From df96abe0876c1fbe29138a84cb87aabb042255c1 Mon Sep 17 00:00:00 2001 From: nobody <> Date: Mon, 30 Sep 2002 15:57:27 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'kseitz_interps-20020528-branch'. Cherrypick from master 2002-09-30 15:57:26 UTC Fernando Nasser ' * disasm.c: New file.': bfd/elf32-i386-fbsd.c bfd/elf64-alpha-fbsd.c bfd/po/da.po gdb/charset.c gdb/charset.h gdb/config/i386/nbsd.mt gdb/cp-support.c gdb/cp-support.h gdb/disasm.c gdb/disasm.h gdb/gdb.c gdb/gdb_mbuild.sh gdb/main.h gdb/objc-exp.y gdb/objc-lang.c gdb/objc-lang.h gdb/testsuite/gdb.base/charset.c gdb/testsuite/gdb.base/charset.exp gdb/testsuite/gdb.base/pc-fp.c gdb/testsuite/gdb.base/pc-fp.exp gdb/testsuite/gdb.c++/m-static.h gdb/testsuite/gdb.c++/m-static1.cc gdb/testsuite/gdb.c++/pr-574.cc gdb/testsuite/gdb.c++/pr-574.exp gdb/testsuite/gdb.c++/printmethod.cc gdb/testsuite/gdb.c++/printmethod.exp gdb/testsuite/gdb.gdb/complaints.exp gdb/testsuite/gdb.mi/gdb669.exp gdb/testsuite/gdb.mi/gdb680.exp gdb/testsuite/gdb.mi/gdb701.c gdb/testsuite/gdb.mi/gdb701.exp gdb/testsuite/gdb.threads/killed.c gdb/testsuite/gdb.threads/killed.exp libiberty/testsuite/test-demangle.c --- bfd/elf32-i386-fbsd.c | 56 + bfd/elf64-alpha-fbsd.c | 56 + bfd/po/da.po | 2745 +++++++++++++++++++++++++ gdb/charset.c | 1274 ++++++++++++ gdb/charset.h | 120 ++ gdb/config/i386/nbsd.mt | 4 + gdb/cp-support.c | 141 ++ gdb/cp-support.h | 25 + gdb/disasm.c | 374 ++++ gdb/disasm.h | 29 + gdb/gdb.c | 34 + gdb/gdb_mbuild.sh | 153 ++ gdb/main.h | 34 + gdb/objc-exp.y | 1841 +++++++++++++++++ gdb/objc-lang.c | 1960 ++++++++++++++++++ gdb/objc-lang.h | 57 + gdb/testsuite/gdb.base/charset.c | 131 ++ gdb/testsuite/gdb.base/charset.exp | 486 +++++ gdb/testsuite/gdb.base/pc-fp.c | 14 + gdb/testsuite/gdb.base/pc-fp.exp | 94 + gdb/testsuite/gdb.c++/m-static.h | 11 + gdb/testsuite/gdb.c++/m-static1.cc | 9 + gdb/testsuite/gdb.c++/pr-574.cc | 22 + gdb/testsuite/gdb.c++/pr-574.exp | 72 + gdb/testsuite/gdb.c++/printmethod.cc | 14 + gdb/testsuite/gdb.c++/printmethod.exp | 69 + gdb/testsuite/gdb.gdb/complaints.exp | 318 +++ gdb/testsuite/gdb.mi/gdb669.exp | 200 ++ gdb/testsuite/gdb.mi/gdb680.exp | 56 + gdb/testsuite/gdb.mi/gdb701.c | 15 + gdb/testsuite/gdb.mi/gdb701.exp | 67 + gdb/testsuite/gdb.threads/killed.c | 24 + gdb/testsuite/gdb.threads/killed.exp | 97 + libiberty/testsuite/test-demangle.c | 175 ++ 34 files changed, 10777 insertions(+) create mode 100644 bfd/elf32-i386-fbsd.c create mode 100644 bfd/elf64-alpha-fbsd.c create mode 100644 bfd/po/da.po create mode 100644 gdb/charset.c create mode 100644 gdb/charset.h create mode 100644 gdb/config/i386/nbsd.mt create mode 100644 gdb/cp-support.c create mode 100644 gdb/cp-support.h create mode 100644 gdb/disasm.c create mode 100644 gdb/disasm.h create mode 100644 gdb/gdb.c create mode 100755 gdb/gdb_mbuild.sh create mode 100644 gdb/main.h create mode 100644 gdb/objc-exp.y create mode 100644 gdb/objc-lang.c create mode 100644 gdb/objc-lang.h create mode 100644 gdb/testsuite/gdb.base/charset.c create mode 100644 gdb/testsuite/gdb.base/charset.exp create mode 100644 gdb/testsuite/gdb.base/pc-fp.c create mode 100644 gdb/testsuite/gdb.base/pc-fp.exp create mode 100644 gdb/testsuite/gdb.c++/m-static.h create mode 100644 gdb/testsuite/gdb.c++/m-static1.cc create mode 100644 gdb/testsuite/gdb.c++/pr-574.cc create mode 100644 gdb/testsuite/gdb.c++/pr-574.exp create mode 100644 gdb/testsuite/gdb.c++/printmethod.cc create mode 100644 gdb/testsuite/gdb.c++/printmethod.exp create mode 100644 gdb/testsuite/gdb.gdb/complaints.exp create mode 100644 gdb/testsuite/gdb.mi/gdb669.exp create mode 100644 gdb/testsuite/gdb.mi/gdb680.exp create mode 100644 gdb/testsuite/gdb.mi/gdb701.c create mode 100644 gdb/testsuite/gdb.mi/gdb701.exp create mode 100644 gdb/testsuite/gdb.threads/killed.c create mode 100644 gdb/testsuite/gdb.threads/killed.exp create mode 100644 libiberty/testsuite/test-demangle.c diff --git a/bfd/elf32-i386-fbsd.c b/bfd/elf32-i386-fbsd.c new file mode 100644 index 00000000000..500e0ebc048 --- /dev/null +++ b/bfd/elf32-i386-fbsd.c @@ -0,0 +1,56 @@ +/* Intel IA-32 specific support for 32-bit ELF on FreeBSD. + Copyright 2002 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define TARGET_LITTLE_SYM bfd_elf32_i386_freebsd_vec +#define TARGET_LITTLE_NAME "elf32-i386-freebsd" +#define ELF_ARCH bfd_arch_i386 +#define ELF_MACHINE_CODE EM_386 +#define ELF_MAXPAGESIZE 0x1000 + +#include "bfd.h" +#include "sysdep.h" +#include "elf-bfd.h" + +/* The kernel recognizes executables as valid only if they carry a + "FreeBSD" label in the ELF header. So we put this label on all + executables and (for simplicity) also all other object files. */ + +static void elf_i386_post_process_headers + PARAMS ((bfd *, struct bfd_link_info *)); + +static void +elf_i386_post_process_headers (abfd, link_info) + bfd * abfd; + struct bfd_link_info * link_info ATTRIBUTE_UNUSED; +{ + Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ + + i_ehdrp = elf_elfheader (abfd); + + /* Put an ABI label supported by FreeBSD >= 4.1. */ + i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; +#ifdef OLD_FREEBSD_ABI_LABEL + /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ + memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); +#endif +} + +#define elf_backend_post_process_headers elf_i386_post_process_headers + +#include "elf32-i386.c" diff --git a/bfd/elf64-alpha-fbsd.c b/bfd/elf64-alpha-fbsd.c new file mode 100644 index 00000000000..061b0b81030 --- /dev/null +++ b/bfd/elf64-alpha-fbsd.c @@ -0,0 +1,56 @@ +/* Alpha specific support for 64-bit ELF on FreeBSD. + Copyright 2002 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define TARGET_LITTLE_SYM bfd_elf64_alpha_freebsd_vec +#define TARGET_LITTLE_NAME "elf64-alpha-freebsd" +#define ELF_ARCH bfd_arch_alpha +#define ELF_MACHINE_CODE EM_ALPHA +#define ELF_MAXPAGESIZE 0x10000 + +#include "bfd.h" +#include "sysdep.h" +#include "elf-bfd.h" + +/* The kernel recognizes executables as valid only if they carry a + "FreeBSD" label in the ELF header. So we put this label on all + executables and (for simplicity) also all other object files. */ + +static void elf_alpha_post_process_headers + PARAMS ((bfd *, struct bfd_link_info *)); + +static void +elf_alpha_post_process_headers (abfd, link_info) + bfd * abfd; + struct bfd_link_info * link_info ATTRIBUTE_UNUSED; +{ + Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ + + i_ehdrp = elf_elfheader (abfd); + + /* Put an ABI label supported by FreeBSD >= 4.1. */ + i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; +#ifdef OLD_FREEBSD_ABI_LABEL + /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ + memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); +#endif +} + +#define elf_backend_post_process_headers elf_alpha_post_process_headers + +#include "elf64-alpha.c" diff --git a/bfd/po/da.po b/bfd/po/da.po new file mode 100644 index 00000000000..6f184849c06 --- /dev/null +++ b/bfd/po/da.po @@ -0,0 +1,2745 @@ +# Danish messages for bfd. +# Copyright (C) 2001, 2002 Free Software Foundation, Inc. +# Keld Simonsen , 2002 +# +msgid "" +msgstr "" +"Project-Id-Version: bfd 2.12.91\n" +"POT-Creation-Date: 2002-07-23 15:55-0400\n" +"PO-Revision-Date: 2002-09-07 21:55+0200\n" +"Last-Translator: Keld Simonsen \n" +"Language-Team: Danish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: aout-adobe.c:197 +#, c-format +msgid "%s: Unknown section type in a.out.adobe file: %x\n" +msgstr "%s: Ukendt sektionstype i a.out.adobe-fil: %x\n" + +#: aout-cris.c:208 +#, c-format +msgid "%s: Invalid relocation type exported: %d" +msgstr "%s: Ugyldig relokaliseringstype eksporteret: %d" + +#: aout-cris.c:252 +#, c-format +msgid "%s: Invalid relocation type imported: %d" +msgstr "%s: Ugyldig relokaliseringstype importeret: %d" + +#: aout-cris.c:263 +#, c-format +msgid "%s: Bad relocation record imported: %d" +msgstr "%s: Fejlagtig relokaliseringstype importeret: %d" + +#: aoutx.h:1282 aoutx.h:1699 +#, c-format +msgid "%s: can not represent section `%s' in a.out object file format" +msgstr "%s: kan ikke representere sektionen \"%s\" i a.out-objektfilformat" + +#: aoutx.h:1669 +#, c-format +msgid "%s: can not represent section for symbol `%s' in a.out object file format" +msgstr "%s: kan ikke representere sektion for symbolet \"%s\" i a.out-objektfilformat" + +#: aoutx.h:1671 +msgid "*unknown*" +msgstr "*ukendt*" + +#: aoutx.h:3732 +#, c-format +msgid "%s: relocateable link from %s to %s not supported" +msgstr "%s: relokaliseringsbar lænke fra %s til %s understøttes inte" + +#: archive.c:1826 +msgid "Warning: writing archive was slow: rewriting timestamp\n" +msgstr "Advarsel: arkivskrivning var langsom: genskriver tidsstempel\n" + +#: archive.c:2093 +msgid "Reading archive file mod timestamp" +msgstr "Læser arkivfilens ændringstidsstempel" + +#. FIXME: bfd can't call perror. +#: archive.c:2120 +msgid "Writing updated armap timestamp" +msgstr "Skriver opdateret armap-tidsstempel" + +#: bfd.c:274 +msgid "No error" +msgstr "Ingen fejl" + +#: bfd.c:275 +msgid "System call error" +msgstr "Systemkaldsfejl" + +#: bfd.c:276 +msgid "Invalid bfd target" +msgstr "Ugyldigt bfd-mål" + +#: bfd.c:277 +msgid "File in wrong format" +msgstr "Filen er i forkert format" + +#: bfd.c:278 +msgid "Archive object file in wrong format" +msgstr "Arkivobjektfil er i forkert format" + +#: bfd.c:279 +msgid "Invalid operation" +msgstr "Ugyldig handling" + +#: bfd.c:280 +msgid "Memory exhausted" +msgstr "Hukommelsen er opbrugt" + +#: bfd.c:281 +msgid "No symbols" +msgstr "Ingen symboler" + +#: bfd.c:282 +msgid "Archive has no index; run ranlib to add one" +msgstr "Arkivet har intet index; kør ranlib for at tilføje ét" + +#: bfd.c:283 +msgid "No more archived files" +msgstr "Ikke flere arkiverede filer" + +#: bfd.c:284 +msgid "Malformed archive" +msgstr "Forvansket arkiv" + +#: bfd.c:285 +msgid "File format not recognized" +msgstr "Filformatet ikke genkendt" + +#: bfd.c:286 +msgid "File format is ambiguous" +msgstr "Filformatet er flertydigt" + +#: bfd.c:287 +msgid "Section has no contents" +msgstr "Sektionen har intet indhold" + +#: bfd.c:288 +msgid "Nonrepresentable section on output" +msgstr "Ikkerepræsenterbar sektion i uddata" + +#: bfd.c:289 +msgid "Symbol needs debug section which does not exist" +msgstr "Symbolet kræver fejlsøgningssektion som ikke eksisterer" + +#: bfd.c:290 +msgid "Bad value" +msgstr "Fejlagtigt værdi" + +#: bfd.c:291 +msgid "File truncated" +msgstr "Filen trunkeret" + +#: bfd.c:292 +msgid "File too big" +msgstr "Filen er for stor" + +#: bfd.c:293 +msgid "#" +msgstr "#" + +#: bfd.c:700 +#, c-format +msgid "BFD %s assertion fail %s:%d" +msgstr "BFD %s-forsikring mislykkedes %s:%d" + +#: bfd.c:719 +#, c-format +msgid "BFD %s internal error, aborting at %s line %d in %s\n" +msgstr "Intern BFD %s-fejl, afbryder ved %s linje %d i %s\n" + +#: bfd.c:723 +#, c-format +msgid "BFD %s internal error, aborting at %s line %d\n" +msgstr "Internt BFD %s-fejl, afbryder ved %s linje %d\n" + +#: bfd.c:725 +msgid "Please report this bug.\n" +msgstr "Rapportér gerne denne fejl.\n" + +#: binary.c:306 +#, c-format +msgid "Warning: Writing section `%s' to huge (ie negative) file offset 0x%lx." +msgstr "Advarsel: Skrivning af sektionen \"%s\" til enorm (dvs negativ) afsætsbyte 0x%lx." + +# src/menus.c:341 +#: coff-a29k.c:119 +msgid "Missing IHCONST" +msgstr "IHCONST mangler" + +# src/menus.c:341 +#: coff-a29k.c:180 +msgid "Missing IHIHALF" +msgstr "IHIHALF mangler" + +#: coff-a29k.c:212 coff-or32.c:229 +msgid "Unrecognized reloc" +msgstr "Ukendt relokalisering" + +#: coff-a29k.c:408 +msgid "missing IHCONST reloc" +msgstr "IHCONST-relokalisering mangler" + +#: coff-a29k.c:498 +msgid "missing IHIHALF reloc" +msgstr "IHIHALF-relokalisering mangler" + +#: coff-alpha.c:881 coff-alpha.c:918 coff-alpha.c:1989 coff-mips.c:1432 +msgid "GP relative relocation used when GP not defined" +msgstr "GP-relativ relokalisering bruges når GP ikke er defineret" + +#: coff-alpha.c:1485 +msgid "using multiple gp values" +msgstr "bruger flere gp-værdier" + +#: coff-arm.c:1066 elf32-arm.h:285 +#, c-format +msgid "%s: unable to find THUMB glue '%s' for `%s'" +msgstr "%s: kunne ikke finde THUMB-klistret \"%s\" til \"%s\"" + +#: coff-arm.c:1096 elf32-arm.h:320 +#, c-format +msgid "%s: unable to find ARM glue '%s' for `%s'" +msgstr "%s: kunne ikke finde ARM-klistret \"%s\" til \"%s\"" + +#: coff-arm.c:1391 coff-arm.c:1486 elf32-arm.h:887 elf32-arm.h:991 +#, c-format +msgid "%s(%s): warning: interworking not enabled." +msgstr "%s(%s): advarsel: samvirken er ikke aktiveret." + +#: coff-arm.c:1395 elf32-arm.h:994 +#, c-format +msgid " first occurrence: %s: arm call to thumb" +msgstr " første forekomst: %s: arm-kald til thumb" + +#: coff-arm.c:1490 elf32-arm.h:890 +#, c-format +msgid " first occurrence: %s: thumb call to arm" +msgstr " første forekomst: %s: thumb-kald til arm" + +#: coff-arm.c:1493 +msgid " consider relinking with --support-old-code enabled" +msgstr " overvej omlænkning med --support-old-code aktiveret" + +#: coff-arm.c:1785 coff-tic80.c:686 cofflink.c:3031 +#, c-format +msgid "%s: bad reloc address 0x%lx in section `%s'" +msgstr "%s: fejlagtig relokaliseringsadresse 0x%lx i sektionen \"%s\"" + +#: coff-arm.c:2127 +#, c-format +msgid "%s: illegal symbol index in reloc: %d" +msgstr "%s: utilladt symbolindex i relokalisering: %d" + +#: coff-arm.c:2255 +#, c-format +msgid "ERROR: %s is compiled for APCS-%d, whereas %s is compiled for APCS-%d" +msgstr "FEJL: %s kompileret for APCS-%d, mens %s er kompileret for APCS-%d" + +#: coff-arm.c:2270 elf32-arm.h:2297 +#, c-format +msgid "ERROR: %s passes floats in float registers, whereas %s passes them in integer registers" +msgstr "FEJL: %s overfører flydende tal i flydende talsregister, mens %s overfører dem i heltalsregister" + +#: coff-arm.c:2273 elf32-arm.h:2302 +#, c-format +msgid "ERROR: %s passes floats in integer registers, whereas %s passes them in float registers" +msgstr "FEJL: %s overfører flydende tal i heltalsregister, mens %s overfører dem i flydendetalsregister" + +#: coff-arm.c:2288 +#, c-format +msgid "ERROR: %s is compiled as position independent code, whereas target %s is absolute position" +msgstr "FEJL: %s er kompileret som positionsuafhængig kode, mens målet %s har absolut position" + +#: coff-arm.c:2291 +#, c-format +msgid "ERROR: %s is compiled as absolute position code, whereas target %s is position independent" +msgstr "FEJL: %s er kompileret som kode med absolut position, mens målet %s er positionsuafhængigt" + +#: coff-arm.c:2320 elf32-arm.h:2358 +#, c-format +msgid "Warning: %s supports interworking, whereas %s does not" +msgstr "Advarsel: %s understøtter samvirken, mens %s derimod ikke gør det" + +#: coff-arm.c:2323 elf32-arm.h:2365 +#, c-format +msgid "Warning: %s does not support interworking, whereas %s does" +msgstr "Advarsel: %s understøtter ikke samvirken, mens %s derimod gør det" + +#: coff-arm.c:2350 +#, c-format +msgid "private flags = %x:" +msgstr "private flag = %x:" + +#: coff-arm.c:2358 elf32-arm.h:2418 +msgid " [floats passed in float registers]" +msgstr " [flydende tal overført i flydendetalsregistre]" + +#: coff-arm.c:2360 +msgid " [floats passed in integer registers]" +msgstr " [flydende tal overført i heltalsregistre]" + +#: coff-arm.c:2363 elf32-arm.h:2421 +msgid " [position independent]" +msgstr " [positionsuafhængigt]" + +#: coff-arm.c:2365 +msgid " [absolute position]" +msgstr " [absolut position]" + +#: coff-arm.c:2369 +msgid " [interworking flag not initialised]" +msgstr " [samvirkendeflag er ikke initieret]" + +#: coff-arm.c:2371 +msgid " [interworking supported]" +msgstr " [samvirken understøttes]" + +#: coff-arm.c:2373 +msgid " [interworking not supported]" +msgstr " [samvirken understøttes ikke]" + +#: coff-arm.c:2421 elf32-arm.h:2124 +#, c-format +msgid "Warning: Not setting interworking flag of %s since it has already been specified as non-interworking" +msgstr "Advarsel: Sætter ikke samvirkeflaget for %s da den allerede er angivet som ikke-samvirkende" + +#: coff-arm.c:2425 elf32-arm.h:2128 +#, c-format +msgid "Warning: Clearing the interworking flag of %s due to outside request" +msgstr "Advarsel: Fjerner samvirkeflaget for %s på grund af anmodning udefra" + +#: coff-i960.c:136 coff-i960.c:485 +msgid "uncertain calling convention for non-COFF symbol" +msgstr "usikker kaldskonvention for ikke-COFF-symbol" + +#: coff-m68k.c:481 coff-mips.c:2429 elf32-m68k.c:2157 elf32-mips.c:1844 +msgid "unsupported reloc type" +msgstr "relokaliseringstypen understøttes ikke" + +#: coff-mips.c:874 elf32-mips.c:1062 elf64-mips.c:1609 +msgid "GP relative relocation when _gp not defined" +msgstr "GP-relativ relokalisering når _gp ikke var defineret" + +#. No other sections should appear in -membedded-pic +#. code. +#: coff-mips.c:2466 +msgid "reloc against unsupported section" +msgstr "relokalisering mod sektion som ikke understøttes" + +#: coff-mips.c:2474 +msgid "reloc not properly aligned" +msgstr "relokalisering ikke på lige grænse" + +#: coff-rs6000.c:2766 +#, c-format +msgid "%s: unsupported relocation type 0x%02x" +msgstr "%s: relokaliseringstypen 0x%02x understøttes ikke" + +#: coff-rs6000.c:2859 +#, c-format +msgid "%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry" +msgstr "%s: TOC-relokalisering ved 0x%x til symbolet \"%s\" uden nogen TOC-post" + +#: coff-rs6000.c:3590 coff64-rs6000.c:2091 +#, c-format +msgid "%s: symbol `%s' has unrecognized smclas %d" +msgstr "%s: symbolet \"%s\" har ukendt smclas %d" + +#: coff-tic54x.c:279 coff-tic80.c:449 +#, c-format +msgid "Unrecognized reloc type 0x%x" +msgstr "Ukendt relokaliseringstype 0x%x" + +#: coff-tic54x.c:390 coffcode.h:4974 +#, c-format +msgid "%s: warning: illegal symbol index %ld in relocs" +msgstr "%s: advarsel: utilladt symbolindex %ld i relokaliseringerne" + +#: coff-w65.c:363 +#, c-format +msgid "ignoring reloc %s\n" +msgstr "ignorerer relokalisering %s\n" + +#: coffcode.h:1086 +#, c-format +msgid "%s (%s): Section flag %s (0x%x) ignored" +msgstr "%s (%s): Sektionsflaget %s (0x%x) ignoreredes" + +#: coffcode.h:2143 +#, c-format +msgid "Unrecognized TI COFF target id '0x%x'" +msgstr "Ukendt TI COFF-mål-id \"0x%x\"" + +#: coffcode.h:4365 +#, c-format +msgid "%s: warning: illegal symbol index %ld in line numbers" +msgstr "%s: advarsel: utilladt symbolindex %ld i linjenummer" + +#: coffcode.h:4379 +#, c-format +msgid "%s: warning: duplicate line number information for `%s'" +msgstr "%s: advarsel: dobbelt linjenummersinformation for \"%s\"" + +#: coffcode.h:4736 +#, c-format +msgid "%s: Unrecognized storage class %d for %s symbol `%s'" +msgstr "%s: Ukendt lagringsklasse %d for %s-symbolet \"%s\"" + +#: coffcode.h:4867 +#, c-format +msgid "warning: %s: local symbol `%s' has no section" +msgstr "advarsel: %s: lokalt symbol \"%s\" har ingen sektion" + +#: coffcode.h:5012 +#, c-format +msgid "%s: illegal relocation type %d at address 0x%lx" +msgstr "%s: utilladt relokaliseringstype %d på adresse 0x%lx" + +#: coffgen.c:1661 +#, c-format +msgid "%s: bad string table size %lu" +msgstr "%s: fejlagtig strengtabelstørrelse %lu" + +#: cofflink.c:534 elflink.h:1912 +#, c-format +msgid "Warning: type of symbol `%s' changed from %d to %d in %s" +msgstr "Advarsel: typen på symbol \"%s\" ændredes fra %d til %d i %s" + +#: cofflink.c:2321 +#, c-format +msgid "%s: relocs in section `%s', but it has no contents" +msgstr "%s: relokaliseringer i sektionen \"%s\", men den har intet indhold" + +#: cofflink.c:2664 coffswap.h:877 +#, c-format +msgid "%s: %s: reloc overflow: 0x%lx > 0xffff" +msgstr "%s: %s: relokalisering giver overløb: 0x%lx > 0xffff" + +#: cofflink.c:2673 coffswap.h:864 +#, c-format +msgid "%s: warning: %s: line number overflow: 0x%lx > 0xffff" +msgstr "%s: advarsel: %s: linjenummer giver overløb: 0x%lx > 0xffff" + +#: dwarf2.c:382 +msgid "Dwarf Error: Can't find .debug_str section." +msgstr "Dwarf-fejl: Kan ikke finde sektionen .debug_str." + +#: dwarf2.c:399 +#, c-format +msgid "Dwarf Error: DW_FORM_strp offset (%lu) greater than or equal to .debug_str size (%lu)." +msgstr "Dwarf-fejl: DW_FORM_strp-afstanden (%lu) større end eller lig med størrelsen på .debug_str (%lu)." + +#: dwarf2.c:543 +msgid "Dwarf Error: Can't find .debug_abbrev section." +msgstr "Dwarf-fejl: Kan ikke finde sektionen .debug_abbrev." + +#: dwarf2.c:560 +#, c-format +msgid "Dwarf Error: Abbrev offset (%lu) greater than or equal to .debug_abbrev size (%lu)." +msgstr "Dwarf-fejl: Forkortningsafstanden (%lu) større end eller lig med størrelsen .debug_abbrev (%lu)." + +#: dwarf2.c:757 +#, c-format +msgid "Dwarf Error: Invalid or unhandled FORM value: %u." +msgstr "Dwarf-fejl: Ugyldig eller ubehandlet FORM-værdi: %u." + +#: dwarf2.c:852 +msgid "Dwarf Error: mangled line number section (bad file number)." +msgstr "Dwarf-fejl: vanskabt linjenummerssektion (fejlagtigt filnummer)." + +#: dwarf2.c:938 +msgid "Dwarf Error: Can't find .debug_line section." +msgstr "Dwarf-fejl: Kan ikke finde sektionen .debug_line." + +#: dwarf2.c:961 +#, c-format +msgid "Dwarf Error: Line offset (%lu) greater than or equal to .debug_line size (%lu)." +msgstr "Dwarf-fejl: Linjeafstanden (%lu) større end eller lig med størrelsen .debug_line (%lu)." + +#: dwarf2.c:1159 +msgid "Dwarf Error: mangled line number section." +msgstr "Dwarf-fejl: vanskabt linjenummerssektion." + +#: dwarf2.c:1355 dwarf2.c:1566 +#, c-format +msgid "Dwarf Error: Could not find abbrev number %u." +msgstr "Dwarf-fejl: Kunne ikke finde forkortningsnumret %u." + +#: dwarf2.c:1527 +#, c-format +msgid "Dwarf Error: found dwarf version '%u', this reader only handles version 2 information." +msgstr "Dwarf-fejl: fandt dwarf version \"%u\", denne læser håndterer kun information fra version 2." + +#: dwarf2.c:1534 +#, c-format +msgid "Dwarf Error: found address size '%u', this reader can not handle sizes greater than '%u'." +msgstr "Dwarf-fejl: fandt adressestørrelsen \"%u\", denne læser kan ikke håndtere størrelser større end \"%u\"." + +#: dwarf2.c:1557 +#, c-format +msgid "Dwarf Error: Bad abbrev number: %u." +msgstr "Dwarf-fejl: Fejlagtigt forkortningsnummer: %u." + +#: ecoff.c:1318 +#, c-format +msgid "Unknown basic type %d" +msgstr "Ukendt grundtype %d" + +#: ecoff.c:1578 +#, c-format +msgid "" +"\n" +" End+1 symbol: %ld" +msgstr "" +"\n" +" Symbol slut+1: %ld" + +#: ecoff.c:1585 ecoff.c:1588 +#, c-format +msgid "" +"\n" +" First symbol: %ld" +msgstr "" +"\n" +" Første symbol: %ld" + +#: ecoff.c:1600 +#, c-format +msgid "" +"\n" +" End+1 symbol: %-7ld Type: %s" +msgstr "" +"\n" +" Symbol slut+1: %-7ld Typ: %s" + +#: ecoff.c:1607 +#, c-format +msgid "" +"\n" +" Local symbol: %ld" +msgstr "" +"\n" +" Lokalt symbol: %ld" + +#: ecoff.c:1615 +#, c-format +msgid "" +"\n" +" struct; End+1 symbol: %ld" +msgstr "" +"\n" +" struct; symbol slut+1: %ld" + +#: ecoff.c:1620 +#, c-format +msgid "" +"\n" +" union; End+1 symbol: %ld" +msgstr "" +"\n" +" union; symbol slut+1: %ld" + +#: ecoff.c:1625 +#, c-format +msgid "" +"\n" +" enum; End+1 symbol: %ld" +msgstr "" +"\n" +" enum; symbol slut+1: %ld" + +#: ecoff.c:1631 +#, c-format +msgid "" +"\n" +" Type: %s" +msgstr "" +"\n" +" Type: %s" + +#: elf-hppa.h:1476 elf-hppa.h:1509 elf32-ppc.c:3091 elf32-sh.c:4213 +#: elf64-sh64.c:1659 +#, c-format +msgid "%s: warning: unresolvable relocation against symbol `%s' from %s section" +msgstr "%s: advarsel: uløselig relokalisering mod symbol \"%s\" fra sektionen %s" + +#: elf-m10200.c:446 elf-m10300.c:656 elf32-arm.h:2084 elf32-avr.c:833 +#: elf32-cris.c:1403 elf32-d10v.c:481 elf32-fr30.c:635 elf32-frv.c:809 +#: elf32-h8300.c:548 elf32-i860.c:1031 elf32-m32r.c:1278 elf32-openrisc.c:439 +#: elf32-v850.c:1691 elf32-xstormy16.c:933 elf64-mmix.c:1302 +msgid "internal error: out of range error" +msgstr "intern fejl: udenfor intervallet" + +#: elf-m10200.c:450 elf-m10300.c:660 elf32-arm.h:2088 elf32-avr.c:837 +#: elf32-cris.c:1407 elf32-d10v.c:485 elf32-fr30.c:639 elf32-frv.c:813 +#: elf32-h8300.c:552 elf32-i860.c:1035 elf32-m32r.c:1282 elf32-openrisc.c:443 +#: elf32-v850.c:1695 elf32-xstormy16.c:937 elf64-mmix.c:1306 elfxx-mips.c:5264 +msgid "internal error: unsupported relocation error" +msgstr "intern fejl: relokaliseringen understøttes ikke" + +#: elf-m10200.c:454 elf-m10300.c:664 elf32-arm.h:2092 elf32-d10v.c:489 +#: elf32-h8300.c:556 elf32-m32r.c:1286 +msgid "internal error: dangerous error" +msgstr "intern fejl: farlig fejl" + +#: elf-m10200.c:458 elf-m10300.c:668 elf32-arm.h:2096 elf32-avr.c:845 +#: elf32-cris.c:1415 elf32-d10v.c:493 elf32-fr30.c:647 elf32-frv.c:821 +#: elf32-h8300.c:560 elf32-i860.c:1043 elf32-m32r.c:1290 elf32-openrisc.c:451 +#: elf32-v850.c:1715 elf32-xstormy16.c:945 elf64-mmix.c:1314 +msgid "internal error: unknown error" +msgstr "intern fejl: ukendt fejl" + +#: elf.c:343 +#, c-format +msgid "%s: invalid string offset %u >= %lu for section `%s'" +msgstr "%s: ugyldig strengafstand %u >= %lu for sektionen \"%s\"" + +#: elf.c:589 +#, c-format +msgid "%s: invalid SHT_GROUP entry" +msgstr "%s: ugyldig SHT_GROUP-post" + +#: elf.c:660 +#, c-format +msgid "%s: no group info for section %s" +msgstr "%s: ingen gruppeinformation for sektionen %s" + +#: elf.c:1023 +msgid "" +"\n" +"Program Header:\n" +msgstr "" +"\n" +"Programhoved:\n" + +#: elf.c:1073 +msgid "" +"\n" +"Dynamic Section:\n" +msgstr "" +"\n" +"Dynamisk sektion:\n" + +#: elf.c:1202 +msgid "" +"\n" +"Version definitions:\n" +msgstr "" +"\n" +"Versionsdefinitioner:\n" + +#: elf.c:1225 +msgid "" +"\n" +"Version References:\n" +msgstr "" +"\n" +"Versionsreferencer:\n" + +#: elf.c:1230 +#, c-format +msgid " required from %s:\n" +msgstr " kræves fra %s:\n" + +#: elf.c:1902 +#, c-format +msgid "%s: invalid link %lu for reloc section %s (index %u)" +msgstr "%s: ugyldig lænke %lu for relokaliseringssektion %s (index %u)" + +#: elf.c:3603 +#, c-format +msgid "%s: Not enough room for program headers (allocated %u, need %u)" +msgstr "%s: Ikke tilstrækkeligt med plads for programhoveder (allokerede %u, behøver %u)" + +#: elf.c:3708 +#, c-format +msgid "%s: Not enough room for program headers, try linking with -N" +msgstr "%s: Ikke tilstrækkeligt med plads for programhoveder, forsøg at lænke med -N" + +#: elf.c:3833 +#, c-format +msgid "Error: First section in segment (%s) starts at 0x%x whereas the segment starts at 0x%x" +msgstr "Fejl: Første sektion i segmentet (%s) begynder ved 0x%x mens segmentet begynder ved 0x%x" + +#: elf.c:4148 +#, c-format +msgid "%s: warning: allocated section `%s' not in segment" +msgstr "%s: advarsel: allokeret sektion \"%s\" ikke i segment" + +#: elf.c:4472 +#, c-format +msgid "%s: symbol `%s' required but not present" +msgstr "%s: symbol \"%s\" kræves men er ikke tilstede" + +#: elf.c:4749 +#, c-format +msgid "%s: warning: Empty loadable segment detected, is this intentional ?\n" +msgstr "%s: advarsel: Tomt indlæsningsbart segment opdaget, er dette meningen?\n" + +#: elf.c:6193 +#, c-format +msgid "%s: unsupported relocation type %s" +msgstr "%s: relokaliseringstypen %s understøttes ikke" + +#: elf32-arm.h:1221 +#, c-format +msgid "%s: Warning: Arm BLX instruction targets Arm function '%s'." +msgstr "%s: Advarsel: Arm BLX-instruktion bruger Arm-funktionen \"%s\" som mål." + +#: elf32-arm.h:1417 +#, c-format +msgid "%s: Warning: Thumb BLX instruction targets thumb function '%s'." +msgstr "%s: Advarsel: Thumb BLX-instruktionen bruger thumb-funktionen \"%s\" som mål." + +#: elf32-arm.h:1914 elf32-sh.c:4125 +#, c-format +msgid "%s(%s+0x%lx): %s relocation against SEC_MERGE section" +msgstr "%s(%s+0x%lx): %s relokalisering mod SEC_MERGE-sektion" + +#: elf32-arm.h:2008 +#, c-format +msgid "%s: warning: unresolvable relocation %d against symbol `%s' from %s section" +msgstr "%s: advarsel: uløselig relokalisering %d mod symbol \"%s\" fra sektionen %s" + +#: elf32-arm.h:2176 +#, c-format +msgid "Warning: Clearing the interworking flag of %s because non-interworking code in %s has been linked with it" +msgstr "Advarsel: Fjerner samvirkendeflaget i %s eftersom ikke-samvirkende kode i %s er lænket med det" + +#: elf32-arm.h:2271 +#, c-format +msgid "ERROR: %s is compiled for EABI version %d, whereas %s is compiled for version %d" +msgstr "FEJL: %s er kompileret for EABI version %d, mens %s er kompileret for version %d" + +#: elf32-arm.h:2285 +#, c-format +msgid "ERROR: %s is compiled for APCS-%d, whereas target %s uses APCS-%d" +msgstr "FEJL: %s er kompileret for APCS-%d, mens målet %s bruger APCS-%d" + +#: elf32-arm.h:2313 +#, c-format +msgid "ERROR: %s uses VFP instructions, whereas %s uses FPA instructions" +msgstr "FEJL: %s bruger VFP-instruktioner, mens %s bruger FPA-instruktioner" + +#: elf32-arm.h:2318 +#, c-format +msgid "ERROR: %s uses FPA instructions, whereas %s uses VFP instructions" +msgstr "FEJL: %s bruger FPA-instruktioner, mens %s bruger VFP-instruktioner" + +#: elf32-arm.h:2338 +#, c-format +msgid "ERROR: %s uses software FP, whereas %s uses hardware FP" +msgstr "FEJL: %s bruger programmeret flydende tal, mens %s bruger maskinens flydende tal" + +#: elf32-arm.h:2343 +#, c-format +msgid "ERROR: %s uses hardware FP, whereas %s uses software FP" +msgstr "FEJL: %s bruger maskinens flydende tal, mens %s bruger programmeret flydende tal" + +#. Ignore init flag - it may not be set, despite the flags field +#. containing valid data. +#: elf32-arm.h:2396 elf32-cris.c:2988 elf32-m68k.c:410 elf32-vax.c:543 +#: elfxx-mips.c:7756 +#, c-format +msgid "private flags = %lx:" +msgstr "private flag = %lx:" + +#: elf32-arm.h:2405 +msgid " [interworking enabled]" +msgstr " [samvirkende er aktiveret]" + +#: elf32-arm.h:2413 +msgid " [VFP float format]" +msgstr " [VFP-flydende talsformat]" + +#: elf32-arm.h:2415 +msgid " [FPA float format]" +msgstr " [FPA-flydende talsformat]" + +#: elf32-arm.h:2424 +msgid " [new ABI]" +msgstr " [nyt ABI]" + +#: elf32-arm.h:2427 +msgid " [old ABI]" +msgstr " [gammelt ABI]" + +#: elf32-arm.h:2430 +msgid " [software FP]" +msgstr " [programmeret FP]" + +#: elf32-arm.h:2438 +msgid " [Version1 EABI]" +msgstr " [Version1 EABI]" + +#: elf32-arm.h:2441 elf32-arm.h:2452 +msgid " [sorted symbol table]" +msgstr " [sorteret symboltabel]" + +#: elf32-arm.h:2443 elf32-arm.h:2454 +msgid " [unsorted symbol table]" +msgstr " [usorteret symboltabel]" + +#: elf32-arm.h:2449 +msgid " [Version2 EABI]" +msgstr " [Version2 EABI]" + +#: elf32-arm.h:2457 +msgid " [dynamic symbols use segment index]" +msgstr " [dynamiske symboler bruger segmentindex]" + +#: elf32-arm.h:2460 +msgid " [mapping symbols precede others]" +msgstr " [mapningssymboler foretrækkes frem for andre]" + +#: elf32-arm.h:2467 +msgid " " +msgstr " " + +#: elf32-arm.h:2474 +msgid " [relocatable executable]" +msgstr " [relokaliseringsbar kørbar fil]" + +#: elf32-arm.h:2477 +msgid " [has entry point]" +msgstr " [har startpunkt]" + +#: elf32-arm.h:2482 +msgid "" +msgstr "" + +#: elf32-avr.c:841 elf32-cris.c:1411 elf32-fr30.c:643 elf32-frv.c:817 +#: elf32-i860.c:1039 elf32-openrisc.c:447 elf32-v850.c:1699 +#: elf32-xstormy16.c:941 elf64-mmix.c:1310 +msgid "internal error: dangerous relocation" +msgstr "intern fejl: farlig relokalisering" + +#: elf32-cris.c:949 +#, c-format +msgid "%s: unresolvable relocation %s against symbol `%s' from %s section" +msgstr "%s: uløselig relokalisering %s mod symbol \"%s\" fra sektionen %s" + +#: elf32-cris.c:1012 +#, c-format +msgid "%s: No PLT nor GOT for relocation %s against symbol `%s' from %s section" +msgstr "%s: Hverken nogen PLT eller GOT for relokalisering %s mod symbol \"%s\" fra sektionen %s" + +#: elf32-cris.c:1015 elf32-cris.c:1141 +msgid "[whose name is lost]" +msgstr "[hvis navn er tabt]" + +#: elf32-cris.c:1130 +#, c-format +msgid "%s: relocation %s with non-zero addend %d against local symbol from %s section" +msgstr "%s: relokalisering %s med ikke-tomt addendum %d mod lokalt symbol fra sektionen %s" + +#: elf32-cris.c:1137 +#, c-format +msgid "%s: relocation %s with non-zero addend %d against symbol `%s' from %s section" +msgstr "%s: relokalisering %s med ikke-tomt addendum %d mod symbol \"%s\" fra sektionen %s" + +#: elf32-cris.c:1155 +#, c-format +msgid "%s: relocation %s is not allowed for global symbol: `%s' from %s section" +msgstr "%s: relokaliseringen %s er ikke tilladt for globalt symbol: \"%s\" fra sektionen %s" + +#: elf32-cris.c:1170 +#, c-format +msgid "%s: relocation %s in section %s with no GOT created" +msgstr "%s: relokalisering %s i sektionen %s uden GOT oprettet" + +#: elf32-cris.c:1288 +#, c-format +msgid "%s: Internal inconsistency; no relocation section %s" +msgstr "%s: Intern inkonsistens; ingen relokaliseringssektion %s" + +#: elf32-cris.c:2514 +#, c-format +msgid "" +"%s, section %s:\n" +" relocation %s should not be used in a shared object; recompile with -fPIC" +msgstr "" +"%s, sektion %s:\n" +" relokaliseringen %s bør ikke bruges i et delt objekt; genoversæt med -fPIC" + +#: elf32-cris.c:2991 +msgid " [symbols have a _ prefix]" +msgstr " [symboler har et _-prefix]" + +#: elf32-cris.c:3030 +#, c-format +msgid "%s: uses _-prefixed symbols, but writing file with non-prefixed symbols" +msgstr "%s: bruger symboler med _-prefix, men skriver fil med symboler uden prefix" + +#: elf32-cris.c:3031 +#, c-format +msgid "%s: uses non-prefixed symbols, but writing file with _-prefixed symbols" +msgstr "%s: bruger symboler uden prefix, men skriver fil med symboler med _-prefix" + +#: elf32-frv.c:1217 +#, c-format +msgid "%s: compiled with %s and linked with modules that use non-pic relocations" +msgstr "%s: kompileret med %s og lænket med moduler som bruger ikke-pic-relokalisering" + +#: elf32-frv.c:1267 +#, c-format +msgid "%s: compiled with %s and linked with modules compiled with %s" +msgstr "%s: kompileret med %s og lænket med moduler som kompileredes med %s" + +#: elf32-frv.c:1279 +#, c-format +msgid "%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)" +msgstr "%s: bruger andre ukendte e_flags-felter (0x%lx) end tidligere moduler (0x%lx)" + +#: elf32-frv.c:1315 +#, c-format +msgid "private flags = 0x%lx:" +msgstr "private flag = 0x%lx:" + +#: elf32-gen.c:82 elf64-gen.c:82 +#, c-format +msgid "%s: Relocations in generic ELF (EM: %d)" +msgstr "%s: Relokalisering i generisk ELF (EM: %d)" + +#: elf32-hppa.c:671 elf64-ppc.c:2323 +#, c-format +msgid "%s: cannot create stub entry %s" +msgstr "%s: kan ikke oprette stubstarten %s" + +#: elf32-hppa.c:956 elf32-hppa.c:3555 +#, c-format +msgid "%s(%s+0x%lx): cannot reach %s, recompile with -ffunction-sections" +msgstr "%s(%s+0x%lx): kan ikke nå %s, genoversæt med -ffunction-sections" + +#: elf32-hppa.c:1338 elf64-x86-64.c:673 +#, c-format +msgid "%s: relocation %s can not be used when making a shared object; recompile with -fPIC" +msgstr "%s: relokaliseringen %s kan ikke bruges når et delt objekt oprettes; genoversæt med -fPIC" + +#: elf32-hppa.c:1358 +#, c-format +msgid "%s: relocation %s should not be used when making a shared object; recompile with -fPIC" +msgstr "%s: relokaliseringen %s bør ikke bruges når et delt objekt oprettes; genoversæt med -fPIC" + +#: elf32-hppa.c:1551 +#, c-format +msgid "Could not find relocation section for %s" +msgstr "Kunne ikke finde relokaliseringssektion for %s" + +#: elf32-hppa.c:2855 +#, c-format +msgid "%s: duplicate export stub %s" +msgstr "%s: dobbelt eksportstub %s" + +#: elf32-hppa.c:3433 +#, c-format +msgid "%s(%s+0x%lx): fixing %s" +msgstr "%s(%s+0x%lx): retter %s" + +#: elf32-hppa.c:4080 +#, c-format +msgid "%s(%s+0x%lx): cannot handle %s for %s" +msgstr "%s(%s+0x%lx): kan ikke håndtere %s for %s" + +#: elf32-hppa.c:4393 +msgid ".got section not immediately after .plt section" +msgstr ".got-sektionen følger ikke umiddelbart efter .plt-sektion" + +#: elf32-i386.c:379 +#, c-format +msgid "%s: invalid relocation type %d" +msgstr "%s: ugyldig relokaliseringstype %d" + +#: elf32-i386.c:876 elf32-s390.c:649 elf64-s390.c:595 elf64-x86-64.c:591 +#, c-format +msgid "%s: bad symbol index: %d" +msgstr "%s: fejlagtigt symbolindex: %d" + +#: elf32-i386.c:948 +#, c-format +msgid "%s: `%s' accessed both as normal and thread local symbol" +msgstr "%s: \"%s\" kaldt både som lokalt normalt symbol og lokalt trådsymbol" + +#: elf32-i386.c:1072 elf32-s390.c:808 elf64-ppc.c:2827 elf64-s390.c:759 +#: elf64-x86-64.c:761 +#, c-format +msgid "%s: bad relocation section name `%s'" +msgstr "%s: fejlagtig relokaliseringssektionsnavn \"%s\"" + +#: elf32-i386.c:1159 elf64-alpha.c:4768 +#, c-format +msgid "%s: TLS local exec code cannot be linked into shared objects" +msgstr "%s: lokal TLS-eksekveringskode kan ikke lænkes ind i delte objekter" + +#: elf32-i386.c:2747 elf32-s390.c:1981 elf32-sparc.c:1571 elf64-ppc.c:5918 +#: elf64-s390.c:1945 elf64-sparc.c:2578 elf64-x86-64.c:1948 +#, c-format +msgid "%s(%s+0x%lx): unresolvable relocation against symbol `%s'" +msgstr "%s(%s+0x%lx): uløselig relokalisering mod symbol \"%s\"" + +#: elf32-i386.c:2784 elf32-s390.c:2019 elf64-ppc.c:5977 elf64-s390.c:1983 +#: elf64-x86-64.c:1986 +#, c-format +msgid "%s(%s+0x%lx): reloc against `%s': error %d" +msgstr "%s(%s+0x%lx): relokalisering mod \"%s\": fejl %d" + +#: elf32-m32r.c:924 +msgid "SDA relocation when _SDA_BASE_ not defined" +msgstr "SDA-relokalisering når _SDA_BASE_ ikke er defineret" + +#: elf32-ia64.c:3687 elf32-m32r.c:1013 elf32-ppc.c:2987 elf64-alpha.c:4185 +#: elf64-alpha.c:4313 elf64-ia64.c:3687 +#, c-format +msgid "%s: unknown relocation type %d" +msgstr "%s: ukendt relokaliseringstype %d" + +#: elf32-m32r.c:1221 +#, c-format +msgid "%s: The target (%s) of an %s relocation is in the wrong section (%s)" +msgstr "%s: Målet (%s) for en %s-relokalisering er i forkert sektion (%s)" + +#: elf32-m32r.c:1947 +#, c-format +msgid "%s: Instruction set mismatch with previous modules" +msgstr "%s: Instruktionsopsætning passer ikke med tidligere moduler" + +#: elf32-m32r.c:1970 +#, c-format +msgid "private flags = %lx" +msgstr "private flag = %lx" + +#: elf32-m32r.c:1975 +msgid ": m32r instructions" +msgstr ": m32r-instruktioner" + +#: elf32-m32r.c:1976 +msgid ": m32rx instructions" +msgstr ": m32rx-instruktioner" + +#: elf32-m68k.c:413 +msgid " [cpu32]" +msgstr " [cpu32]" + +#: elf32-m68k.c:416 +msgid " [m68000]" +msgstr " [m68000]" + +#: elf32-mcore.c:354 elf32-mcore.c:457 +#, c-format +msgid "%s: Relocation %s (%d) is not currently supported.\n" +msgstr "%s: Relokalisering %s (%d) understøttes ikke i øjeblikket.\n" + +#: elf32-mcore.c:442 +#, c-format +msgid "%s: Unknown relocation type %d\n" +msgstr "%s: Ukendt relokaliseringstype %d\n" + +#: elf32-mips.c:1152 elf64-mips.c:1783 +msgid "32bits gp relative relocation occurs for an external symbol" +msgstr "32-bit gp-relativ relokalisering forekom for et eksternt symbol" + +#: elf32-mips.c:1301 +#, c-format +msgid "Linking mips16 objects into %s format is not supported" +msgstr "Lænkning af mips16-objekter til %s-format understøttes ikke" + +#: elf32-ppc.c:1460 +#, c-format +msgid "%s: compiled with -mrelocatable and linked with modules compiled normally" +msgstr "%s: kompileret med -mrelocatable og lænket med moduler som kompileredes normalt" + +#: elf32-ppc.c:1468 +#, c-format +msgid "%s: compiled normally and linked with modules compiled with -mrelocatable" +msgstr "%s: kompileret normalt og lænket med moduler som kompileredes med -mrelocatable" + +#: elf32-ppc.c:1494 elf64-sparc.c:2989 elfxx-mips.c:7713 +#, c-format +msgid "%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)" +msgstr "%s: bruger andre e_flags-felter (0x%lx) end tidligere moduler (0x%lx)" + +#: elf32-ppc.c:1592 +#, c-format +msgid "%s: Unknown special linker type %d" +msgstr "%s: Ukendt speciallænkertype %d" + +#: elf32-ppc.c:2273 elf32-ppc.c:2307 elf32-ppc.c:2342 +#, c-format +msgid "%s: relocation %s cannot be used when making a shared object" +msgstr "%s: relokaliseringen %s kan ikke bruges når et delt objekt oprettes" + +#: elf32-ppc.c:3126 elf64-ppc.c:5473 +#, c-format +msgid "%s: unknown relocation type %d for symbol %s" +msgstr "%s: ukendt relokaliseringstype %d for symbol %s" + +#: elf32-ppc.c:3482 elf32-ppc.c:3503 elf32-ppc.c:3553 +#, c-format +msgid "%s: The target (%s) of a %s relocation is in the wrong output section (%s)" +msgstr "%s: Målet (%s) for en %s-relokalisering er i forkert uddatasektion (%s)" + +#: elf32-ppc.c:3619 +#, c-format +msgid "%s: Relocation %s is not yet supported for symbol %s." +msgstr "%s: Relokaliseringen %s understøttes ikke endnu for symbol %s." + +#: elf32-sh.c:1964 +#, c-format +msgid "%s: 0x%lx: warning: bad R_SH_USES offset" +msgstr "%s: 0x%lx: advarsel: fejlagtig R_SH_USES-afstand" + +#: elf32-sh.c:1976 +#, c-format +msgid "%s: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x" +msgstr "%s: 0x%lx: advarsel: R_SH_USES peger til ukendt instruktion 0x%x" + +#: elf32-sh.c:1993 +#, c-format +msgid "%s: 0x%lx: warning: bad R_SH_USES load offset" +msgstr "%s: 0x%lx: advarsel: fejlagtig R_SH_USES-indlæsningsafstand" + +#: elf32-sh.c:2008 +#, c-format +msgid "%s: 0x%lx: warning: could not find expected reloc" +msgstr "%s: 0x%lx: advarsel: kunne ikke finde forventet relokalisering" + +#: elf32-sh.c:2036 +#, c-format +msgid "%s: 0x%lx: warning: symbol in unexpected section" +msgstr "%s: 0x%lx: advarsel: symbol i uventet sektion" + +#: elf32-sh.c:2153 +#, c-format +msgid "%s: 0x%lx: warning: could not find expected COUNT reloc" +msgstr "%s: 0x%lx: advarsel: kunne ikke finde forventet COUNT-relokalisering" + +#: elf32-sh.c:2162 +#, c-format +msgid "%s: 0x%lx: warning: bad count" +msgstr "%s: 0x%lx: advarsel: fejlagtigt antal" + +#: elf32-sh.c:2550 elf32-sh.c:2926 +#, c-format +msgid "%s: 0x%lx: fatal: reloc overflow while relaxing" +msgstr "%s: 0x%lx: fatalt: relokalisering giver overløb ved forenklingen" + +#: elf32-sh.c:4073 elf64-sh64.c:1576 +msgid "Unexpected STO_SH5_ISA32 on local symbol is not handled" +msgstr "Uventet STO_SH5_ISA32 på lokalt symbol håndteres ikke" + +#: elf32-sh.c:4284 +#, c-format +msgid "%s: 0x%lx: fatal: unaligned branch target for relax-support relocation" +msgstr "%s: 0x%lx: fatalt: ujusteret grenmål for relokalisering for forenklingsunderstøttelse" + +#: elf32-sh64.c:203 elf64-sh64.c:2364 +#, c-format +msgid "%s: compiled as 32-bit object and %s is 64-bit" +msgstr "%s: kompileret som 32-bitsobjekt og %s er 64-bit" + +#: elf32-sh64.c:206 elf64-sh64.c:2367 +#, c-format +msgid "%s: compiled as 64-bit object and %s is 32-bit" +msgstr "%s: kompileret som 64-bitsobjekt og %s er 32-bit" + +#: elf32-sh64.c:208 elf64-sh64.c:2369 +#, c-format +msgid "%s: object size does not match that of target %s" +msgstr "%s: objektstørrelsen stemmer ikke overens med den hos målet %s" + +#: elf32-sh64.c:440 elf64-sh64.c:2941 +#, c-format +msgid "%s: encountered datalabel symbol in input" +msgstr "%s: mødte dataetikettesymbol i inddata" + +#: elf32-sh64.c:523 +msgid "PTB mismatch: a SHmedia address (bit 0 == 1)" +msgstr "PTB passer ikke: en SHmedia-adresse (bit 0 == 1)" + +#: elf32-sh64.c:526 +msgid "PTA mismatch: a SHcompact address (bit 0 == 0)" +msgstr "PTA passer ikke: en SHcompact-adresse (bit 0 == 0)" + +#: elf32-sh64.c:544 +#, c-format +msgid "%s: GAS error: unexpected PTB insn with R_SH_PT_16" +msgstr "%s: GAS-fejl: uventet PTB-instruktion med R_SH_PT_16" + +#: elf32-sh64.c:593 elf64-sh64.c:1703 +#, c-format +msgid "%s: error: unaligned relocation type %d at %08x reloc %08x\n" +msgstr "%s: fejl: ojusteret relokaliseringstype %d på %08x relokalisering %08x\n" + +#: elf32-sh64.c:677 +#, c-format +msgid "%s: could not write out added .cranges entries" +msgstr "%s: kunne ikke udskrive tilføjede .cranges-poster" + +#: elf32-sh64.c:739 +#, c-format +msgid "%s: could not write out sorted .cranges entries" +msgstr "%s: kunne ikke udskrive sorterede cranges-poster" + +#: elf32-sparc.c:1535 elf64-sparc.c:2224 +#, c-format +msgid "%s: probably compiled without -fPIC?" +msgstr "%s: nok kompileret uden -fPIC?" + +#: elf32-sparc.c:2002 +#, c-format +msgid "%s: compiled for a 64 bit system and target is 32 bit" +msgstr "%s: kompileret for et 64-bitssystem og målet er 32-bit" + +#: elf32-sparc.c:2016 +#, c-format +msgid "%s: linking little endian files with big endian files" +msgstr "%s: lænker little endian-filer med big endian-filer" + +#: elf32-v850.c:682 +#, c-format +msgid "Variable `%s' cannot occupy in multiple small data regions" +msgstr "Variabel \"%s\" kan ikke befinde sig i flere små dataområder" + +#: elf32-v850.c:685 +#, c-format +msgid "Variable `%s' can only be in one of the small, zero, and tiny data regions" +msgstr "Variabel \"%s\" kan kun være i et af de små, tomme og bittesmå dataområder" + +#: elf32-v850.c:688 +#, c-format +msgid "Variable `%s' cannot be in both small and zero data regions simultaneously" +msgstr "Variabel \"%s\" kan ikke være i både små og tomme dataområder samtidigt" + +#: elf32-v850.c:691 +#, c-format +msgid "Variable `%s' cannot be in both small and tiny data regions simultaneously" +msgstr "Variabel \"%s\" kan ikke være i både små og bittesmå dataområder samtidigt" + +#: elf32-v850.c:694 +#, c-format +msgid "Variable `%s' cannot be in both zero and tiny data regions simultaneously" +msgstr "Variabel \"%s\" kan ikke være i både tomme og bittesmå dataområder samtidigt" + +#: elf32-v850.c:1072 +msgid "FAILED to find previous HI16 reloc\n" +msgstr "MISLYKKEDES med at finde tidligere HI16-relokalisering\n" + +#: elf32-v850.c:1703 +msgid "could not locate special linker symbol __gp" +msgstr "kunne ikke lokalisere specielt lænkersymbol __gp" + +#: elf32-v850.c:1707 +msgid "could not locate special linker symbol __ep" +msgstr "kunne ikke lokalisere specielt lænkersymbol __ep" + +#: elf32-v850.c:1711 +msgid "could not locate special linker symbol __ctbp" +msgstr "kunne ikke lokalisere specielt lænkersymbol __ctbp" + +#: elf32-v850.c:1875 +#, c-format +msgid "%s: Architecture mismatch with previous modules" +msgstr "%s: Arkitekturen passer ikke sammen med tidligere moduler" + +#: elf32-v850.c:1895 +#, c-format +msgid "private flags = %lx: " +msgstr "private flag = %lx: " + +#: elf32-v850.c:1900 +msgid "v850 architecture" +msgstr "v850-arkitektur" + +#: elf32-v850.c:1901 +msgid "v850e architecture" +msgstr "v850e-arkitektur" + +#: elf32-v850.c:1902 +msgid "v850ea architecture" +msgstr "v850ea-arkitektur" + +#: elf32-vax.c:546 +msgid " [nonpic]" +msgstr " [ikke-pic]" + +#: elf32-vax.c:549 +msgid " [d-float]" +msgstr " [d-flydende tal]" + +#: elf32-vax.c:552 +msgid " [g-float]" +msgstr " [g-flydende tal]" + +#: elf32-vax.c:674 +#, c-format +msgid "%s: warning: GOT addend of %ld to `%s' does not match previous GOT addend of %ld" +msgstr "%s: advarsel: GOT-addendum %ld til \"%s\" stemmer ikke overens med tidligere GOT-addendum %ld" + +#: elf32-vax.c:1679 +#, c-format +msgid "%s: warning: PLT addend of %d to `%s' from %s section ignored" +msgstr "%s: advarsel: PLT-addendum %d til \"%s\" fra sektionen %s ignoreredes" + +#: elf32-vax.c:1814 +#, c-format +msgid "%s: warning: %s relocation against symbol `%s' from %s section" +msgstr "%s: advarsel: %s-relokalisering mod symbol \"%s\" fra sektionen %s" + +#: elf32-vax.c:1820 +#, c-format +msgid "%s: warning: %s relocation to 0x%x from %s section" +msgstr "%s: advarsel: %s-relokalisering til 0x%x fra sektionen %s" + +#: elf32-ia64.c:2280 elf32-xstormy16.c:414 elf64-ia64.c:2280 +msgid "non-zero addend in @fptr reloc" +msgstr "ikke-tomt addendum i @fptr-relokalisering" + +#: elf64-alpha.c:1097 +msgid "GPDISP relocation did not find ldah and lda instructions" +msgstr "GPDISP-relokalisering fandt ingen ldah- og lda-instruktioner" + +#: elf64-alpha.c:3675 +#, c-format +msgid "%s: .got subsegment exceeds 64K (size %d)" +msgstr "%s: .got-subsegment overskrider 64 kB (størrelse %d)" + +#: elf64-alpha.c:4498 elf64-alpha.c:4510 +#, c-format +msgid "%s: gp-relative relocation against dynamic symbol %s" +msgstr "%s: gp-relativ relokalisering mod dynamisk symbol %s" + +#: elf64-alpha.c:4536 elf64-alpha.c:4676 +#, c-format +msgid "%s: pc-relative relocation against dynamic symbol %s" +msgstr "%s: pc-relativ relokalisering mod dynamisk symbol %s" + +#: elf64-alpha.c:4564 +#, c-format +msgid "%s: change in gp: BRSGP %s" +msgstr "%s: ændring i gp: BRSGP %s" + +#: elf64-alpha.c:4589 +msgid "" +msgstr "" + +#: elf64-alpha.c:4594 +#, c-format +msgid "%s: !samegp reloc against symbol without .prologue: %s" +msgstr "%s: !samegp-relokalisering mod symbol uden .prologue: %s" + +#: elf64-alpha.c:4639 +#, c-format +msgid "%s: unhandled dynamic relocation against %s" +msgstr "%s: uhåndteret dynamisk relokalisering mod %s" + +#: elf64-alpha.c:4752 +#, c-format +msgid "%s: dtp-relative relocation against dynamic symbol %s" +msgstr "%s: dtp-relativ relokalisering mod dynamisk symbol %s" + +#: elf64-alpha.c:4775 +#, c-format +msgid "%s: tp-relative relocation against dynamic symbol %s" +msgstr "%s: tp-relativ relokalisering mod dynamisk symbol %s" + +#: elf64-hppa.c:2080 +#, c-format +msgid "stub entry for %s cannot load .plt, dp offset = %ld" +msgstr "stubpost for %s kan ikke læse in .plt, dp-afstand = %ld" + +#: elf64-mmix.c:1002 +#, c-format +msgid "" +"%s: Internal inconsistency error for value for\n" +" linker-allocated global register: linked: 0x%lx%08lx != relaxed: 0x%lx%08lx\n" +msgstr "" +"%s: Intern inkkonsistensfejl for værdien for\n" +" lænkerallokeret globalt register: lænket: 0x%lx%08lx != afslappet: 0x%lx%08lx\n" + +#: elf64-mmix.c:1386 +#, c-format +msgid "%s: base-plus-offset relocation against register symbol: (unknown) in %s" +msgstr "%s: base-plus-afstandsrelokalisering mod registersymbol: (ukendt) i %s" + +#: elf64-mmix.c:1391 +#, c-format +msgid "%s: base-plus-offset relocation against register symbol: %s in %s" +msgstr "%s: base-plus-afstandsrelokalisering mod registersymbol: %s i %s" + +#: elf64-mmix.c:1435 +#, c-format +msgid "%s: register relocation against non-register symbol: (unknown) in %s" +msgstr "%s: registerrelokalisering mod ikke-registersymbol: (ukendt) i %s" + +#: elf64-mmix.c:1440 +#, c-format +msgid "%s: register relocation against non-register symbol: %s in %s" +msgstr "%s: registerrelokalisering mod ikke-registersymbol: %s i %s" + +#: elf64-mmix.c:1477 +#, c-format +msgid "%s: directive LOCAL valid only with a register or absolute value" +msgstr "%s: LOCAL-direktivet er kun gyldigt med et register eller en absolutværdi" + +#: elf64-mmix.c:1505 +#, c-format +msgid "%s: LOCAL directive: Register $%ld is not a local register. First global register is $%ld." +msgstr "%s: LOCAL-direktiv: Register $%ld er ikke et lokalt register. Første globale register er $%ld." + +#: elf64-mmix.c:1965 +#, c-format +msgid "%s: Error: multiple definition of `%s'; start of %s is set in a earlier linked file\n" +msgstr "%s: Fejl: flere definitioner af \"%s\"; begyndelsen på %s er sat i en tidligere lænket fil\n" + +#: elf64-mmix.c:2024 +msgid "Register section has contents\n" +msgstr "Registersektion har indhold\n" + +#: elf64-mmix.c:2186 +#, c-format +msgid "" +"Internal inconsistency: remaining %u != max %u.\n" +" Please report this bug." +msgstr "" +"Intern inkonsekvens: genstående %u != max %u.\n" +" Rapportér gerne denne fejl." + +#: elf64-ppc.c:1669 libbfd.c:1435 +#, c-format +msgid "%s: compiled for a big endian system and target is little endian" +msgstr "%s: kompileret for et big endian-system og målet er little endian" + +#: elf64-ppc.c:1671 libbfd.c:1437 +#, c-format +msgid "%s: compiled for a little endian system and target is big endian" +msgstr "%s: kompileret for et little endian-system og målet er big endian" + +#: elf64-ppc.c:3610 +#, c-format +msgid "%s: unexpected reloc type %u in .opd section" +msgstr "%s: uventet relokaliseringstype %u i .opd-sektion" + +#: elf64-ppc.c:3630 +#, c-format +msgid "%s: .opd is not a regular array of opd entries" +msgstr "%s: .opd er ikke en almindelig vektor med opd-poster" + +#: elf64-ppc.c:3672 +#, c-format +msgid "%s: undefined sym `%s' in .opd section" +msgstr "%s: udefineret symbol \"%s\" i .opd-sektion" + +#: elf64-ppc.c:4397 +#, c-format +msgid "can't find branch stub `%s'" +msgstr "kan ikke finde grenstub \"%s\"" + +#: elf64-ppc.c:4436 elf64-ppc.c:4501 +#, c-format +msgid "linkage table error against `%s'" +msgstr "lænketabelsfejl mod \"%s\"" + +#: elf64-ppc.c:4573 +#, c-format +msgid "can't build branch stub `%s'" +msgstr "kan ikke bygge grenstub \"%s\"" + +#: elf64-ppc.c:5179 +msgid "stubs don't match calculated size" +msgstr "stubbe stemmer ikke overens med beregnet størrelse" + +#: elf64-ppc.c:5828 +#, c-format +msgid "%s: Relocation %s is not supported for symbol %s." +msgstr "%s: Relokaliseringen %s understøttes ikke for symbol %s." + +#: elf64-ppc.c:5872 +#, c-format +msgid "%s: error: relocation %s not a multiple of 4" +msgstr "%s: fejl: relokaliseringen %s er ikke en multipel af 4" + +#: elf64-sparc.c:1280 +#, c-format +msgid "%s: check_relocs: unhandled reloc type %d" +msgstr "%s: check_relocs: uhåndteret relokaliseringstype %d" + +#: elf64-sparc.c:1317 +#, c-format +msgid "%s: Only registers %%g[2367] can be declared using STT_REGISTER" +msgstr "%s: Kun register %%g[2367] kan deklareres med STT_REGISTER" + +#: elf64-sparc.c:1337 +#, c-format +msgid "Register %%g%d used incompatibly: %s in %s, previously %s in %s" +msgstr "Register %%g%d brugt inkompatibelt: %s i %s, tidligere %s i %s" + +#: elf64-sparc.c:1360 +#, c-format +msgid "Symbol `%s' has differing types: REGISTER in %s, previously %s in %s" +msgstr "Symbol \"%s\" har forskellige typer: REGISTER i %s, tidligere %s i %s" + +#: elf64-sparc.c:1406 +#, c-format +msgid "Symbol `%s' has differing types: %s in %s, previously REGISTER in %s" +msgstr "Symbol \"%s\" har forskellige typer: %s i %s, tidligere REGISTER i %s" + +#: elf64-sparc.c:2970 +#, c-format +msgid "%s: linking UltraSPARC specific with HAL specific code" +msgstr "%s: lænker UltraSPARC-specifik med HAL-specifik kode" + +#: elfcode.h:1198 +#, c-format +msgid "%s: version count (%ld) does not match symbol count (%ld)" +msgstr "%s: versionsantal (%ld) stemmer ikke med symbolantal (%ld)" + +#: elflink.c:440 +#, c-format +msgid "%s: Section %s is too large to add hole of %ld bytes" +msgstr "%s: Sektionen %s er for stor til at stoppa hul med %ld byte i" + +#: elflink.h:1090 +#, c-format +msgid "%s: warning: unexpected redefinition of `%s'" +msgstr "%s: advarsel: uventet omdefinition af \"%s\"" + +#: elflink.h:1727 +#, c-format +msgid "%s: %s: invalid version %u (max %d)" +msgstr "%s: %s: ugyldig version %u (max %d)" + +#: elflink.h:1768 +#, c-format +msgid "%s: %s: invalid needed version %d" +msgstr "%s: %s: ugyldig krævet version %d" + +#: elflink.h:1890 +#, c-format +msgid "Warning: size of symbol `%s' changed from %lu to %lu in %s" +msgstr "Advarsel: størrelsen på symbol \"%s\" ændredes fra %lu til %lu i %s" + +#: elflink.h:3174 +#, c-format +msgid "%s: .preinit_array section is not allowed in DSO" +msgstr "%s: .preinit_array-sektionen er ikke tilladt i DSO" + +#: elflink.h:4030 +#, c-format +msgid "warning: type and size of dynamic symbol `%s' are not defined" +msgstr "advarsel: typen og størrelsen på dynamisk symbol \"%s\" er ikke defineret" + +#: elflink.h:4345 +#, c-format +msgid "%s: undefined versioned symbol name %s" +msgstr "%s: udefineret symbolnavn med version %s" + +#: elflink.h:4611 elflink.h:4619 elflink.h:6508 elflink.h:7600 +msgid "Error: out of memory" +msgstr "Fejl: ikke mere hukommelse" + +#: elflink.h:4781 +msgid "Not enough memory to sort relocations" +msgstr "Ikke nok hukommelse til at sortere relokaliseringer" + +#: elflink.h:5682 elflink.h:5725 +#, c-format +msgid "%s: could not find output section %s" +msgstr "%s: kunne ikke finde uddatasektionen %s" + +#: elflink.h:5688 +#, c-format +msgid "warning: %s section has zero size" +msgstr "advarsel: %s-sektionen har nulstørrelse" + +#: elflink.h:6275 +#, c-format +msgid "%s: could not find output section %s for input section %s" +msgstr "%s: kunne ikke finde uddatasektionen %s for inddatasektionen %s" + +#: elflink.h:6486 +#, c-format +msgid "%s: relocation size mismatch in %s section %s" +msgstr "%s: relokaliseringsstørrelsen stemmer ikke overens i %s-sektionen %s" + +#: elflink.h:6849 +msgid "warning: relocation against removed section; zeroing" +msgstr "advarsel: relokalisering mod fjernet sektion; nulstiller" + +#: elflink.h:6879 +msgid "warning: relocation against removed section" +msgstr "advarsel: relokalisering mod fjernet sektion" + +#: elflink.h:6892 +#, c-format +msgid "local symbols in discarded section %s" +msgstr "lokale symboler i bortkastet sektion %s" + +#: elfxx-mips.c:734 +msgid "static procedure (no name)" +msgstr "statisk procedure (intet navn)" + +#: elfxx-mips.c:1601 +msgid "not enough GOT space for local GOT entries" +msgstr "ikke nok med GOT-plads for lokale GOT-poster" + +#: elfxx-mips.c:2750 +#, c-format +msgid "%s: %s+0x%lx: jump to stub routine which is not jal" +msgstr "%s: %s+0x%lx: hop til stubrutine som ikke er jal" + +#: elfxx-mips.c:4270 +#, c-format +msgid "%s: Malformed reloc detected for section %s" +msgstr "%s: Fejlagtig relokalisering for sektion %s opdaget" + +#: elfxx-mips.c:4348 +#, c-format +msgid "%s: CALL16 reloc at 0x%lx not against global symbol" +msgstr "%s: CALL16-relokalisering ved 0x%lx er ikke mod globalt symbol" + +#: elfxx-mips.c:7301 +#, c-format +msgid "%s: illegal section name `%s'" +msgstr "%s: ugyldigt sektionsnavn \"%s\"" + +#: elfxx-mips.c:7615 +#, c-format +msgid "%s: linking PIC files with non-PIC files" +msgstr "%s: lænker PIC-filer med ikke-PIC-filer" + +#: elfxx-mips.c:7625 +#, c-format +msgid "%s: linking abicalls files with non-abicalls files" +msgstr "%s: lænker abicalls-filer med ikke-abicalls-filer" + +#: elfxx-mips.c:7654 +#, c-format +msgid "%s: ISA mismatch (-mips%d) with previous modules (-mips%d)" +msgstr "%s: ISA (-mips%d) passer ikke med tidligere moduler (-mips%d)" + +#: elfxx-mips.c:7676 +#, c-format +msgid "%s: ISA mismatch (%d) with previous modules (%d)" +msgstr "%s: ISA (%d) passer ikke med tidligere moduler (%d)" + +#: elfxx-mips.c:7699 +#, c-format +msgid "%s: ABI mismatch: linking %s module with previous %s modules" +msgstr "%s: ABI passer ikke: lænker %s-modul med tidligere %s-moduler" + +#: elfxx-mips.c:7759 +msgid " [abi=O32]" +msgstr " [abi=O32]" + +#: elfxx-mips.c:7761 +msgid " [abi=O64]" +msgstr " [abi=O64]" + +#: elfxx-mips.c:7763 +msgid " [abi=EABI32]" +msgstr " [abi=EABI32]" + +#: elfxx-mips.c:7765 +msgid " [abi=EABI64]" +msgstr " [abi=EABI64]" + +#: elfxx-mips.c:7767 +msgid " [abi unknown]" +msgstr " [ukendt abi]" + +#: elfxx-mips.c:7769 +msgid " [abi=N32]" +msgstr " [abi=N32]" + +#: elfxx-mips.c:7771 +msgid " [abi=64]" +msgstr " [abi=64]" + +#: elfxx-mips.c:7773 +msgid " [no abi set]" +msgstr " [intet abi sat]" + +#: elfxx-mips.c:7776 +msgid " [mips1]" +msgstr " [mips1]" + +#: elfxx-mips.c:7778 +msgid " [mips2]" +msgstr " [mips2]" + +#: elfxx-mips.c:7780 +msgid " [mips3]" +msgstr " [mips3]" + +#: elfxx-mips.c:7782 +msgid " [mips4]" +msgstr " [mips4]" + +#: elfxx-mips.c:7784 +msgid " [mips5]" +msgstr " [mips5]" + +#: elfxx-mips.c:7786 +msgid " [mips32]" +msgstr " [mips32]" + +#: elfxx-mips.c:7788 +msgid " [mips64]" +msgstr " [mips64]" + +#: elfxx-mips.c:7790 +msgid " [unknown ISA]" +msgstr " [ukendt ISA]" + +#: elfxx-mips.c:7793 +msgid " [mdmx]" +msgstr " [mdmx]" + +#: elfxx-mips.c:7796 +msgid " [mips16]" +msgstr " [mips16]" + +#: elfxx-mips.c:7799 +msgid " [32bitmode]" +msgstr " [32-bittilstand]" + +#: elfxx-mips.c:7801 +msgid " [not 32bitmode]" +msgstr " [ikke 32-bittilstand]" + +#: i386linux.c:458 m68klinux.c:462 sparclinux.c:459 +#, c-format +msgid "Output file requires shared library `%s'\n" +msgstr "Uddatafilen kræver delt bibliotek \"%s\"\n" + +#: i386linux.c:466 m68klinux.c:470 sparclinux.c:467 +#, c-format +msgid "Output file requires shared library `%s.so.%s'\n" +msgstr "Uddatafilen kræver delt bibliotek \"%s.so.%s\"\n" + +#: i386linux.c:655 i386linux.c:705 m68klinux.c:662 m68klinux.c:710 +#: sparclinux.c:657 sparclinux.c:707 +#, c-format +msgid "Symbol %s not defined for fixups\n" +msgstr "Symbol %s er ikke defineret for rettelser\n" + +#: i386linux.c:729 m68klinux.c:734 sparclinux.c:731 +msgid "Warning: fixup count mismatch\n" +msgstr "Advarsel: antal rettelser stemmer ikke\n" + +#: ieee.c:235 +#, c-format +msgid "%s: string too long (%d chars, max 65535)" +msgstr "%s: strengen er for lang (%d tegn, max 65535)" + +#: ieee.c:365 +#, c-format +msgid "%s: unrecognized symbol `%s' flags 0x%x" +msgstr "%s: ukendt symbol \"%s\" flag 0x%x" + +#: ieee.c:877 +#, c-format +msgid "%s: unimplemented ATI record %u for symbol %u" +msgstr "%s: ikke implementeret ATI-post %u for symbol %u" + +#: ieee.c:902 +#, c-format +msgid "%s: unexpected ATN type %d in external part" +msgstr "%s: uventet ATN-type %d i ekstern del" + +#: ieee.c:924 +#, c-format +msgid "%s: unexpected type after ATN" +msgstr "%s: uventet type efter ATN" + +#: ihex.c:258 +#, c-format +msgid "%s:%d: unexpected character `%s' in Intel Hex file\n" +msgstr "%s:%d: uventet tegn \"%s\" i hexadecimal Intel-fil\n" + +#: ihex.c:366 +#, c-format +msgid "%s:%u: bad checksum in Intel Hex file (expected %u, found %u)" +msgstr "%s:%u: fejlagtig kontrolsum i hexadecimal Intel-fil (forventede %u, fandt %u)" + +#: ihex.c:420 +#, c-format +msgid "%s:%u: bad extended address record length in Intel Hex file" +msgstr "%s:%u: fejlagtig længde på post for udvidet adresse i hexadecimal Intel-fil" + +#: ihex.c:437 +#, c-format +msgid "%s:%u: bad extended start address length in Intel Hex file" +msgstr "%s:%u: fejlagtig længde på udvidet startadresse i hexadecimal Intel-fil" + +#: ihex.c:454 +#, c-format +msgid "%s:%u: bad extended linear address record length in Intel Hex file" +msgstr "%s:%u: fejlagtig længde på post for udvidet lineær adresse i hexadecimal Intel-fil" + +#: ihex.c:471 +#, c-format +msgid "%s:%u: bad extended linear start address length in Intel Hex file" +msgstr "%s:%u: fejlagtig længde på post for udvidet lineær startadresse i hexadecimal Intel-fil" + +#: ihex.c:488 +#, c-format +msgid "%s:%u: unrecognized ihex type %u in Intel Hex file\n" +msgstr "%s:%u: ukendt ihex-type %u i hexadecimal Intel-fil\n" + +#: ihex.c:607 +#, c-format +msgid "%s: internal error in ihex_read_section" +msgstr "%s: intern fejl i ihex_read_section" + +#: ihex.c:642 +#, c-format +msgid "%s: bad section length in ihex_read_section" +msgstr "%s: fejlagtig sektionslængde i ihex_read_sektion" + +#: ihex.c:860 +#, c-format +msgid "%s: address 0x%s out of range for Intel Hex file" +msgstr "%s: adressen 0x%s er udenfor intervallet for hexadecimal Intel-fil" + +#: libbfd.c:492 +#, c-format +msgid "not mapping: data=%lx mapped=%d\n" +msgstr "mapper ikke: data=%lx mappet=%d\n" + +#: libbfd.c:495 +msgid "not mapping: env var not set\n" +msgstr "mapper ikke: miljøvariabel er ikke sat\n" + +#: libbfd.c:1466 +#, c-format +msgid "Deprecated %s called at %s line %d in %s\n" +msgstr "Forældet %s kaldt ved %s linje %d i %s\n" + +#: libbfd.c:1469 +#, c-format +msgid "Deprecated %s called\n" +msgstr "Forældet %s kaldt\n" + +#: linker.c:1873 +#, c-format +msgid "%s: indirect symbol `%s' to `%s' is a loop" +msgstr "%s: indirekte symbol \"%s\" til \"%s\" er en løkke" + +#: linker.c:2776 +#, c-format +msgid "Attempt to do relocateable link with %s input and %s output" +msgstr "Forsøg at lave en relokaliseringsbar lænke med %s-inddata og %s-uddata" + +#: merge.c:892 +#, c-format +msgid "%s: access beyond end of merged section (%ld + %ld)" +msgstr "%s: adgang udover slutningen på sammenslagt sektion (%ld + %ld)" + +#: mmo.c:460 +#, c-format +msgid "%s: No core to allocate section name %s\n" +msgstr "%s: Ingen kerne til at allokere sektionsnavn %s\n" + +#: mmo.c:536 +#, c-format +msgid "%s: No core to allocate a symbol %d bytes long\n" +msgstr "%s: Ingen kerne for at allokere et %d byte langt symbol\n" + +#: mmo.c:1245 +#, c-format +msgid "%s: invalid mmo file: initialization value for $255 is not `Main'\n" +msgstr "%s: ugyldig mmo-fil: initieringsværdi for $255 er ikke \"Main\"\n" + +#: mmo.c:1391 +#, c-format +msgid "%s: unsupported wide character sequence 0x%02X 0x%02X after symbol name starting with `%s'\n" +msgstr "%s: bred tegnsekvens som ikke understøttes 0x%02X 0x%02X efter symbolnavnet som begynder med \"%s\"\n" + +#: mmo.c:1633 +#, c-format +msgid "%s: invalid mmo file: unsupported lopcode `%d'\n" +msgstr "%s: ugyldig mmo-fil: lopkod \"%d\" understøttes ikke\n" + +#: mmo.c:1643 +#, c-format +msgid "%s: invalid mmo file: expected YZ = 1 got YZ = %d for lop_quote\n" +msgstr "%s: ugyldig mmo-fil: forventede YZ = 1 fik YZ = %d for lop_quote\n" + +#: mmo.c:1679 +#, c-format +msgid "%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_loc\n" +msgstr "%s: ugyldig mmo-fil: forventede z = 1 eller z = 2, fik z = %d for lop_loc\n" + +#: mmo.c:1725 +#, c-format +msgid "%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_fixo\n" +msgstr "%s: ugyldig mmo-fil: forventede z = 1 eller z = 2, fik z = %d for lop_fixo\n" + +#: mmo.c:1764 +#, c-format +msgid "%s: invalid mmo file: expected y = 0, got y = %d for lop_fixrx\n" +msgstr "%s: ugyldig mmo-fil: forventede y = 0, fik y = %d for lop_fixrx\n" + +#: mmo.c:1773 +#, c-format +msgid "%s: invalid mmo file: expected z = 16 or z = 24, got z = %d for lop_fixrx\n" +msgstr "%s: ugyldig mmo-fil: forventede z = 16 eller z = 24, fik z = %d for lop_fixr\n" + +#: mmo.c:1796 +#, c-format +msgid "%s: invalid mmo file: leading byte of operand word must be 0 or 1, got %d for lop_fixrx\n" +msgstr "%s: ugyldig mmo-fil: indledende byte i operandord skal være 0 eller 1, fik %d for lop_fixrx\n" + +#: mmo.c:1819 +#, c-format +msgid "%s: cannot allocate file name for file number %d, %d bytes\n" +msgstr "%s: kan ikke allokere filnavn for fil nummer %d, %d byte\n" + +#: mmo.c:1839 +#, c-format +msgid "%s: invalid mmo file: file number %d `%s', was already entered as `%s'\n" +msgstr "%s: ugyldig mmo-fil: fil nummer %d \"%s\", var allerede angivet som \"%s\"\n" + +#: mmo.c:1852 +#, c-format +msgid "%s: invalid mmo file: file name for number %d was not specified before use\n" +msgstr "%s: ugyldig mmo-fil: filnavnet for nummer %d blev ikke angivet inden brug\n" + +#: mmo.c:1958 +#, c-format +msgid "%s: invalid mmo file: fields y and z of lop_stab non-zero, y: %d, z: %d\n" +msgstr "%s: ugyldig mmo-fil: felter y og z i lop_stab er ikke-tomme, y: %d, z: %d\n" + +#: mmo.c:1994 +#, c-format +msgid "%s: invalid mmo file: lop_end not last item in file\n" +msgstr "%s: ugyldig mmo-fil: lop_end er ikke sidste objekt i fil\n" + +#: mmo.c:2007 +#, c-format +msgid "%s: invalid mmo file: YZ of lop_end (%ld) not equal to the number of tetras to the preceding lop_stab (%ld)\n" +msgstr "%s: ugyldig mmo-fil: YZ i lop_end (%ld) er ikke lig med antal af tetraer til den foregående lop_stab (%ld)\n" + +#: mmo.c:2670 +#, c-format +msgid "%s: invalid symbol table: duplicate symbol `%s'\n" +msgstr "%s: ugyldig symboltabel: dubletsymbol \"%s\"\n" + +#: mmo.c:2921 +#, c-format +msgid "%s: Bad symbol definition: `Main' set to %s rather than the start address %s\n" +msgstr "%s: Fejlagtig symboldefinition: \"Main\" er sat til %s i stedet for startadressen %s\n" + +#: mmo.c:3011 +#, c-format +msgid "%s: warning: symbol table too large for mmo, larger than 65535 32-bit words: %d. Only `Main' will be emitted.\n" +msgstr "%s: advarsel: symboltabellen er for stor for mmo, større end 65535 32-bit ord: %d. Kun \"Main\" vil blive sendt.\n" + +#: mmo.c:3056 +#, c-format +msgid "%s: internal error, symbol table changed size from %d to %d words\n" +msgstr "%s: intern fejl, symboltabellen ændrede størrelse fra %d til %d ord\n" + +#: mmo.c:3111 +#, c-format +msgid "%s: internal error, internal register section %s had contents\n" +msgstr "%s: intern fejl, den interne registersektion %s havde indhold\n" + +#: mmo.c:3163 +#, c-format +msgid "%s: no initialized registers; section length 0\n" +msgstr "%s: ingen initierede registre; sektionslængde 0\n" + +#: mmo.c:3169 +#, c-format +msgid "%s: too many initialized registers; section length %ld\n" +msgstr "%s: for mange initierede registre; sektionslængde %ld\n" + +#: mmo.c:3174 +#, c-format +msgid "%s: invalid start address for initialized registers of length %ld: 0x%lx%08lx\n" +msgstr "%s: ugyldig startadresse for initierede registre med længden %ld: 0x%lx%08lx\n" + +#: oasys.c:1029 +#, c-format +msgid "%s: can not represent section `%s' in oasys" +msgstr "%s: kan ikke repræsentere sektionen \"%s\" i oasys" + +#: osf-core.c:132 +#, c-format +msgid "Unhandled OSF/1 core file section type %d\n" +msgstr "Uhåndteret sektionstype %d for OSF/1-hukommelsesfil\n" + +#: pe-mips.c:658 +#, c-format +msgid "%s: `ld -r' not supported with PE MIPS objects\n" +msgstr "%s: \"ld -r\" understøttes ikke med PE MIPS-objekt\n" + +#. OK, at this point the following variables are set up: +#. src = VMA of the memory we're fixing up +#. mem = pointer to memory we're fixing up +#. val = VMA of what we need to refer to +#. +#: pe-mips.c:794 +#, c-format +msgid "%s: unimplemented %s\n" +msgstr "%s: uimplementeret %s\n" + +#: pe-mips.c:820 +#, c-format +msgid "%s: jump too far away\n" +msgstr "%s: hop for langt bort\n" + +#: pe-mips.c:847 +#, c-format +msgid "%s: bad pair/reflo after refhi\n" +msgstr "%s: fejlagtigt par/reflo efter refhi\n" + +#. XXX code yet to be written. +#: peicode.h:785 +#, c-format +msgid "%s: Unhandled import type; %x" +msgstr "%s: Uhåndteret importtype; %x" + +#: peicode.h:790 +#, c-format +msgid "%s: Unrecognised import type; %x" +msgstr "%s: Ukendt importtype; %x" + +#: peicode.h:804 +#, c-format +msgid "%s: Unrecognised import name type; %x" +msgstr "%s: Ukendt importnavnstype; %x" + +#: peicode.h:1162 +#, c-format +msgid "%s: Unrecognised machine type (0x%x) in Import Library Format archive" +msgstr "%s: Ukendt maskintype (0x%x) i Import Library Format-arkiv" + +#: peicode.h:1174 +#, c-format +msgid "%s: Recognised but unhandled machine type (0x%x) in Import Library Format archive" +msgstr "%s: Kendt men uhåndteret maskintype (0x%x) i Import Library Format-arkiv" + +#: peicode.h:1191 +#, c-format +msgid "%s: size field is zero in Import Library Format header" +msgstr "%s: størrelsesfeltet er nul i Import Library Format-hoved" + +#: peicode.h:1219 +#, c-format +msgid "%s: string not null terminated in ILF object file." +msgstr "%s: streng ikke nultermineret i ILF-objektfil." + +#: ppcboot.c:416 +msgid "" +"\n" +"ppcboot header:\n" +msgstr "" +"\n" +"ppcboot-hoved:\n" + +#: ppcboot.c:417 +#, c-format +msgid "Entry offset = 0x%.8lx (%ld)\n" +msgstr "Startafstand = 0x%.8lx (%ld)\n" + +#: ppcboot.c:418 +#, c-format +msgid "Length = 0x%.8lx (%ld)\n" +msgstr "Længde = 0x%.8lx (%ld)\n" + +#: ppcboot.c:421 +#, c-format +msgid "Flag field = 0x%.2x\n" +msgstr "Flagfelt = 0x%.2x\n" + +#: ppcboot.c:427 +#, c-format +msgid "Partition name = \"%s\"\n" +msgstr "Partitionsnavn = \"%s\"\n" + +#: ppcboot.c:446 +#, c-format +msgid "" +"\n" +"Partition[%d] start = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n" +msgstr "" +"\n" +"Start på partition[%d] = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n" + +#: ppcboot.c:452 +#, c-format +msgid "Partition[%d] end = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n" +msgstr "Slut på partition[%d] = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n" + +#: ppcboot.c:458 +#, c-format +msgid "Partition[%d] sector = 0x%.8lx (%ld)\n" +msgstr "Sektor for partition[%d] = 0x%.8lx (%ld)\n" + +#: ppcboot.c:459 +#, c-format +msgid "Partition[%d] length = 0x%.8lx (%ld)\n" +msgstr "Længde på partition[%d] = 0x%.8lx (%ld)\n" + +#: som.c:5398 +msgid "som_sizeof_headers unimplemented" +msgstr "som_sizeof_headers er ikke implementeret" + +#: srec.c:301 +#, c-format +msgid "%s:%d: Unexpected character `%s' in S-record file\n" +msgstr "%s:%d: Uventet tegn \"%s\" i S-postfil\n" + +# Vad er stabs? +#: stabs.c:319 +#, c-format +msgid "%s(%s+0x%lx): Stabs entry has invalid string index." +msgstr "%s(%s+0x%lx): Stabpost har ugyldigt strengindex." + +#: syms.c:1044 +msgid "Unsupported .stab relocation" +msgstr ".stab-relokalisering som ikke understøttes" + +#: vms-gsd.c:356 +#, c-format +msgid "bfd_make_section (%s) failed" +msgstr "bfd_make_section (%s) mislykkedes" + +#: vms-gsd.c:371 +#, c-format +msgid "bfd_set_section_flags (%s, %x) failed" +msgstr "bfd_set_section_flags (%s, %x) mislykkedes" + +#: vms-gsd.c:407 +#, c-format +msgid "Size mismatch section %s=%lx, %s=%lx" +msgstr "Størrelsen passer ikke på sektion %s=%lx, %s=%lx" + +#: vms-gsd.c:702 +#, c-format +msgid "unknown gsd/egsd subtype %d" +msgstr "ukendt gsd/egsd-undertype %d" + +#: vms-hdr.c:406 +msgid "Object module NOT error-free !\n" +msgstr "Objektmodulet IKKE fejlfri!\n" + +#: vms-misc.c:543 +#, c-format +msgid "Stack overflow (%d) in _bfd_vms_push" +msgstr "Stakken giver overløb (%d) i _bfd_vms_push" + +#: vms-misc.c:561 +msgid "Stack underflow in _bfd_vms_pop" +msgstr "Stakken giver underløb i _bfd_vms_pop" + +#: vms-misc.c:919 +msgid "_bfd_vms_output_counted called with zero bytes" +msgstr "_bfd_vms_output_counted kaldt med nul byte" + +#: vms-misc.c:924 +msgid "_bfd_vms_output_counted called with too many bytes" +msgstr "_bfd_vms_output_counted called kaldt med for mange byte" + +#: vms-misc.c:1055 +#, c-format +msgid "Symbol %s replaced by %s\n" +msgstr "Symbol %s erstattet med %s\n" + +#: vms-misc.c:1117 +#, c-format +msgid "failed to enter %s" +msgstr "mislykkedes med at gå ind i %s" + +#: vms-tir.c:81 +msgid "No Mem !" +msgstr "Ingen hukommelse!" + +#: vms-tir.c:362 +#, c-format +msgid "bad section index in %s" +msgstr "fejlagtigt sektionsindex i %s" + +#: vms-tir.c:375 +#, c-format +msgid "unsupported STA cmd %s" +msgstr "STA-kommando %s understøttes ikke" + +#: vms-tir.c:380 vms-tir.c:1240 +#, c-format +msgid "reserved STA cmd %d" +msgstr "reserveret STA-kommando %d" + +#: vms-tir.c:491 vms-tir.c:514 +#, c-format +msgid "%s: no symbol \"%s\"" +msgstr "%s: intet symbol \"%s\"" + +#. unsigned shift +#. rotate +#. Redefine symbol to current location. +#. Define a literal. +#: vms-tir.c:581 vms-tir.c:693 vms-tir.c:803 vms-tir.c:821 vms-tir.c:829 +#: vms-tir.c:838 vms-tir.c:1563 +#, c-format +msgid "%s: not supported" +msgstr "%s: understøttes ikke" + +#: vms-tir.c:586 vms-tir.c:1418 +#, c-format +msgid "%s: not implemented" +msgstr "%s: ikke implementeret" + +#: vms-tir.c:590 vms-tir.c:1422 +#, c-format +msgid "reserved STO cmd %d" +msgstr "reserveret STO-kommando %d" + +#: vms-tir.c:708 vms-tir.c:1568 +#, c-format +msgid "reserved OPR cmd %d" +msgstr "reserveret OPR-kommando %d" + +#: vms-tir.c:776 vms-tir.c:1632 +#, c-format +msgid "reserved CTL cmd %d" +msgstr "reserveret CTL-kommando %d" + +#. stack byte from image +#. arg: none. +#: vms-tir.c:1148 +msgid "stack-from-image not implemented" +msgstr "stack-from-image er ikke implementeret" + +#: vms-tir.c:1166 +msgid "stack-entry-mask not fully implemented" +msgstr "stack-entry-mask er ikke helt implementeret" + +#. compare procedure argument +#. arg: cs symbol name +#. by argument index +#. da argument descriptor +#. +#. compare argument descriptor with symbol argument (ARG$V_PASSMECH) +#. and stack TRUE (args match) or FALSE (args dont match) value. +#: vms-tir.c:1180 +msgid "PASSMECH not fully implemented" +msgstr "PASSMECH er ikke helt implementeret" + +#: vms-tir.c:1199 +msgid "stack-local-symbol not fully implemented" +msgstr "stack-local-symbol er ikke helt implementeret" + +#: vms-tir.c:1212 +msgid "stack-literal not fully implemented" +msgstr "stack-literal er ikke helt implementeret" + +#: vms-tir.c:1233 +msgid "stack-local-symbol-entry-point-mask not fully implemented" +msgstr "stack-local-symbol-entry-point-mask er ikke helt implementeret" + +#: vms-tir.c:1510 vms-tir.c:1522 vms-tir.c:1534 vms-tir.c:1546 vms-tir.c:1611 +#: vms-tir.c:1619 vms-tir.c:1627 +#, c-format +msgid "%s: not fully implemented" +msgstr "%s: ikke helt implementeret" + +#: vms-tir.c:1684 +#, c-format +msgid "obj code %d not found" +msgstr "objektkode %d kunne ikke findes" + +#: vms-tir.c:2019 +#, c-format +msgid "SEC_RELOC with no relocs in section %s" +msgstr "SEC_RELOC uden relokaliseringer i sektion %s" + +#: vms-tir.c:2307 +#, c-format +msgid "Unhandled relocation %s" +msgstr "Uhåndteret relokalisering %s" + +#: xcofflink.c:1243 +#, c-format +msgid "%s: `%s' has line numbers but no enclosing section" +msgstr "%s: \"%s\" har linjenumre men ingen omsluttende sektion" + +#: xcofflink.c:1296 +#, c-format +msgid "%s: class %d symbol `%s' has no aux entries" +msgstr "%s: klasse %d-symbol \"%s\" har ingen ydre poster" + +#: xcofflink.c:1319 +#, c-format +msgid "%s: symbol `%s' has unrecognized csect type %d" +msgstr "%s: symbol \"%s\" har ukendt csect-type %d" + +#: xcofflink.c:1331 +#, c-format +msgid "%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d" +msgstr "%s: fejlagtig XTY_ER-symbol \"%s\": klasse %d scnum %d scnlen %d" + +#: xcofflink.c:1367 +#, c-format +msgid "%s: XMC_TC0 symbol `%s' is class %d scnlen %d" +msgstr "%s: XMC_TC0-symbol \"%s\" er klasse %d scnlen %d" + +#: xcofflink.c:1519 +#, c-format +msgid "%s: csect `%s' not in enclosing section" +msgstr "%s: csect \"%s\" er ikke i omsluttende sektion" + +#: xcofflink.c:1626 +#, c-format +msgid "%s: misplaced XTY_LD `%s'" +msgstr "%s: fejlagtigt placeret XTY_LD \"%s\"" + +#: xcofflink.c:1957 +#, c-format +msgid "%s: reloc %s:%d not in csect" +msgstr "%s: relokaliseringen %s:%d er ikke i csect" + +#: xcofflink.c:2092 +#, c-format +msgid "%s: XCOFF shared object when not producing XCOFF output" +msgstr "%s: XCOFF delt objekt når ikke XCOFF-uddata produceres" + +#: xcofflink.c:2113 +#, c-format +msgid "%s: dynamic object with no .loader section" +msgstr "%s: dynamisk objekt uden nogen .loader-sektion" + +#: xcofflink.c:2758 +#, c-format +msgid "%s: no such symbol" +msgstr "%s: intet sådant symbol" + +#: xcofflink.c:2891 +msgid "error: undefined symbol __rtinit" +msgstr "fejl: udefineret symbol __rtinit" + +#: xcofflink.c:3453 +#, c-format +msgid "warning: attempt to export undefined symbol `%s'" +msgstr "advarsel: forsøg på at eksportere udefineret symbol \"%s\"" + +#: xcofflink.c:4447 +#, c-format +msgid "TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling" +msgstr "TOC giver overløb: 0x%lx > 0x10000; prøv -mminimal-toc ved kompilering" + +#: xcofflink.c:5287 xcofflink.c:5756 xcofflink.c:5818 xcofflink.c:6119 +#, c-format +msgid "%s: loader reloc in unrecognized section `%s'" +msgstr "%s: indlæserrelokalisering i ukendt sektion \"%s\"" + +#: xcofflink.c:5309 xcofflink.c:6130 +#, c-format +msgid "%s: `%s' in loader reloc but not loader sym" +msgstr "%s: \"%s\" i indlæserrelokalisering men ikke indlæsersym" + +#: xcofflink.c:5324 +#, c-format +msgid "%s: loader reloc in read-only section %s" +msgstr "%s: indlæserrelokalisering i skrivebeskyttet sektion %s" + +#: elf32-ia64.c:2222 elf64-ia64.c:2222 +msgid "@pltoff reloc against local symbol" +msgstr "@pltoff-relokalisering mod lokalt symbol" + +#: elf32-ia64.c:3562 elf64-ia64.c:3562 +#, c-format +msgid "%s: short data segment overflowed (0x%lx >= 0x400000)" +msgstr "%s: kort datasegment løb over (0x%lx >= 0x400000)" + +#: elf32-ia64.c:3573 elf64-ia64.c:3573 +#, c-format +msgid "%s: __gp does not cover short data segment" +msgstr "%s: __gp dækker ikke kort datasegment" + +#: elf32-ia64.c:3858 elf64-ia64.c:3858 +#, c-format +msgid "%s: linking non-pic code in a shared library" +msgstr "%s: lænker ikke-pic-kode i delt bibliotek" + +#: elf32-ia64.c:3891 elf64-ia64.c:3891 +#, c-format +msgid "%s: @gprel relocation against dynamic symbol %s" +msgstr "%s: @gprel-relokalisering mod dynamisk symbol %s" + +#: elf32-ia64.c:4030 elf64-ia64.c:4030 +#, c-format +msgid "%s: dynamic relocation against speculation fixup" +msgstr "%s: dynamisk relokalisering uden spekulationsrettelser" + +#: elf32-ia64.c:4038 elf64-ia64.c:4038 +#, c-format +msgid "%s: speculation fixup against undefined weak symbol" +msgstr "%s: spekulationsfix mod udefineret svagt symbol" + +#: elf32-ia64.c:4271 elf64-ia64.c:4271 +msgid "unsupported reloc" +msgstr "relokaliseringen understøttes ikke" + +#: elf32-ia64.c:4551 elf64-ia64.c:4551 +#, c-format +msgid "%s: linking trap-on-NULL-dereference with non-trapping files" +msgstr "%s: lænker fang-ved-NULL-dereference med ikkefangende filer" + +#: elf32-ia64.c:4560 elf64-ia64.c:4560 +#, c-format +msgid "%s: linking big-endian files with little-endian files" +msgstr "%s: lænker big endian-filer med little endian-filer" + +#: elf32-ia64.c:4569 elf64-ia64.c:4569 +#, c-format +msgid "%s: linking 64-bit files with 32-bit files" +msgstr "%s: lænker 64-bitfiler med 32-bitfiler" + +#: elf32-ia64.c:4578 elf64-ia64.c:4578 +#, c-format +msgid "%s: linking constant-gp files with non-constant-gp files" +msgstr "%s: lænker konstant-gp-filer med ikke-konstant-gp-filer" + +#: elf32-ia64.c:4588 elf64-ia64.c:4588 +#, c-format +msgid "%s: linking auto-pic files with non-auto-pic files" +msgstr "%s: lænker auto-pic-filer med ikke-auto-pic-filer" + +#: peigen.c:962 pepigen.c:962 +#, c-format +msgid "%s: line number overflow: 0x%lx > 0xffff" +msgstr "%s: linjenummer giver overløb: 0x%lx > 0xffff" + +#: peigen.c:979 pepigen.c:979 +#, c-format +msgid "%s: reloc overflow 1: 0x%lx > 0xffff" +msgstr "%s: relokalisering giver overløb 1: 0x%lx > 0xffff" + +#: peigen.c:993 pepigen.c:993 +msgid "Export Directory [.edata (or where ever we found it)]" +msgstr "Exportkatalog [.edata (eller hvor vi fandt det)]" + +#: peigen.c:994 pepigen.c:994 +msgid "Import Directory [parts of .idata]" +msgstr "Importkatalog [dele af .idata]" + +#: peigen.c:995 pepigen.c:995 +msgid "Resource Directory [.rsrc]" +msgstr "Resursekatalog [.rsrc]" + +#: peigen.c:996 pepigen.c:996 +msgid "Exception Directory [.pdata]" +msgstr "Undtagelseskatalog [.pdata]" + +#: peigen.c:997 pepigen.c:997 +msgid "Security Directory" +msgstr "Sikkerhedskatalog" + +#: peigen.c:998 pepigen.c:998 +msgid "Base Relocation Directory [.reloc]" +msgstr "Baserelokaliseringskatalog [.reloc]" + +#: peigen.c:999 pepigen.c:999 +msgid "Debug Directory" +msgstr "Fejlsøgningskatalog" + +#: peigen.c:1000 pepigen.c:1000 +msgid "Description Directory" +msgstr "Beskrivelseskatalog" + +#: peigen.c:1001 pepigen.c:1001 +msgid "Special Directory" +msgstr "Specialkatalog" + +#: peigen.c:1002 pepigen.c:1002 +msgid "Thread Storage Directory [.tls]" +msgstr "Trådlagringskatalog [.tls]" + +#: peigen.c:1003 pepigen.c:1003 +msgid "Load Configuration Directory" +msgstr "Indlæsningskonfigurationskatalog" + +#: peigen.c:1004 pepigen.c:1004 +msgid "Bound Import Directory" +msgstr "Katalog over bundne importer" + +#: peigen.c:1005 pepigen.c:1005 +msgid "Import Address Table Directory" +msgstr "Importadressetabelkatalog" + +#: peigen.c:1006 pepigen.c:1006 +msgid "Delay Import Directory" +msgstr "Katalog over forskinkede importer" + +#: peigen.c:1007 peigen.c:1008 pepigen.c:1007 pepigen.c:1008 +msgid "Reserved" +msgstr "Reserveret" + +#: peigen.c:1071 pepigen.c:1071 +msgid "" +"\n" +"There is an import table, but the section containing it could not be found\n" +msgstr "" +"\n" +"Der findes en importtabel, men sektionen som indeholder den kunne ikke findes\n" + +#: peigen.c:1076 pepigen.c:1076 +#, c-format +msgid "" +"\n" +"There is an import table in %s at 0x%lx\n" +msgstr "" +"\n" +"Der findes en importtabel i %s på 0x%lx\n" + +#: peigen.c:1113 pepigen.c:1113 +#, c-format +msgid "" +"\n" +"Function descriptor located at the start address: %04lx\n" +msgstr "" +"\n" +"Funktionsidentifikatorer fundet på startadressen: %04lx\n" + +#: peigen.c:1116 pepigen.c:1116 +#, c-format +msgid "\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n" +msgstr "\tkodebase %08lx toc (indlæsningsbar/reelt) %08lx/%08lx\n" + +#: peigen.c:1122 pepigen.c:1122 +msgid "" +"\n" +"No reldata section! Function descriptor not decoded.\n" +msgstr "" +"\n" +"Ingen reldata-sektion! Funktionsidentifikatorer afkodedes ikke.\n" + +#: peigen.c:1127 pepigen.c:1127 +#, c-format +msgid "" +"\n" +"The Import Tables (interpreted %s section contents)\n" +msgstr "" +"\n" +"Importtabellerne (tolket indhold i %s-sektion)\n" + +# Vad er thunk? +#: peigen.c:1130 pepigen.c:1130 +msgid "" +" vma: Hint Time Forward DLL First\n" +" Table Stamp Chain Name Thunk\n" +msgstr "" +" vma: Tips- Tids- Fremad- DLL- Første\n" +" tabel stempel kæde navn thunk\n" + +#: peigen.c:1181 pepigen.c:1181 +#, c-format +msgid "" +"\n" +"\tDLL Name: %s\n" +msgstr "" +"\n" +"\tDLL-navn: %s\n" + +#: peigen.c:1192 pepigen.c:1192 +msgid "\tvma: Hint/Ord Member-Name Bound-To\n" +msgstr "\tvma: Tips/Ordn Medlemsnavn Bundet till\n" + +#: peigen.c:1217 pepigen.c:1217 +msgid "" +"\n" +"There is a first thunk, but the section containing it could not be found\n" +msgstr "" +"\n" +"Der findes en første thunk, men sektionen som indeholder den kunne ikke findes\n" + +#: peigen.c:1357 pepigen.c:1357 +msgid "" +"\n" +"There is an export table, but the section containing it could not be found\n" +msgstr "" +"\n" +"Der findes en eksporttabel, men sektionen som indeholder den kunne ikke findes\n" + +#: peigen.c:1362 pepigen.c:1362 +#, c-format +msgid "" +"\n" +"There is an export table in %s at 0x%lx\n" +msgstr "" +"\n" +"Det findes en eksporttabel i %s ved 0x%lx\n" + +#: peigen.c:1393 pepigen.c:1393 +#, c-format +msgid "" +"\n" +"The Export Tables (interpreted %s section contents)\n" +"\n" +msgstr "" +"\n" +"Eksporttabellerne (tolket indhold i %s-sektion)\n" + +#: peigen.c:1397 pepigen.c:1397 +#, c-format +msgid "Export Flags \t\t\t%lx\n" +msgstr "Eksportflag \t\t\t%lx\n" + +#: peigen.c:1400 pepigen.c:1400 +#, c-format +msgid "Time/Date stamp \t\t%lx\n" +msgstr "Tids/datostempel \t\t%lx\n" + +#: peigen.c:1403 pepigen.c:1403 +#, c-format +msgid "Major/Minor \t\t\t%d/%d\n" +msgstr "Større/mindre \t\t\t%d/%d\n" + +#: peigen.c:1406 pepigen.c:1406 +msgid "Name \t\t\t\t" +msgstr "Navn \t\t\t\t" + +#: peigen.c:1412 pepigen.c:1412 +#, c-format +msgid "Ordinal Base \t\t\t%ld\n" +msgstr "Ordningsbase \t\t\t%ld\n" + +#: peigen.c:1415 pepigen.c:1415 +msgid "Number in:\n" +msgstr "Tal i:\n" + +#: peigen.c:1418 pepigen.c:1418 +#, c-format +msgid "\tExport Address Table \t\t%08lx\n" +msgstr "\tEksportadressetabel \t\t%08lx\n" + +#: peigen.c:1422 pepigen.c:1422 +#, c-format +msgid "\t[Name Pointer/Ordinal] Table\t%08lx\n" +msgstr "\t[Navnepeger/Ordningstal]-tabel\t%08lx\n" + +#: peigen.c:1425 pepigen.c:1425 +msgid "Table Addresses\n" +msgstr "Tabeladresser\n" + +#: peigen.c:1428 pepigen.c:1428 +msgid "\tExport Address Table \t\t" +msgstr "\tEksportadressetabel \t\t" + +#: peigen.c:1433 pepigen.c:1433 +msgid "\tName Pointer Table \t\t" +msgstr "\tNavnepegertabel \t\t" + +#: peigen.c:1438 pepigen.c:1438 +msgid "\tOrdinal Table \t\t\t" +msgstr "\tOrdningstalstabel \t\t\t" + +#: peigen.c:1453 pepigen.c:1453 +#, c-format +msgid "" +"\n" +"Export Address Table -- Ordinal Base %ld\n" +msgstr "" +"\n" +"Eksportadressetabel -- Ordningsbase %ld\n" + +#: peigen.c:1472 pepigen.c:1472 +msgid "Forwarder RVA" +msgstr "Videresender-RVA" + +#: peigen.c:1483 pepigen.c:1483 +msgid "Export RVA" +msgstr "Eksport-RVA" + +#: peigen.c:1490 pepigen.c:1490 +msgid "" +"\n" +"[Ordinal/Name Pointer] Table\n" +msgstr "" +"\n" +"[Ordningstals-/Navnepeger-]tabel\n" + +#: peigen.c:1545 pepigen.c:1545 +#, c-format +msgid "Warning, .pdata section size (%ld) is not a multiple of %d\n" +msgstr "Advarsel, størrelsen på .pdata-sektionen (%ld) er ikke en multipel af %d\n" + +#: peigen.c:1549 pepigen.c:1549 +msgid "" +"\n" +"The Function Table (interpreted .pdata section contents)\n" +msgstr "" +"\n" +"Funktionstabellen (tolket indhold fra .pdata-sektionen)\n" + +#: peigen.c:1552 pepigen.c:1552 +msgid " vma:\t\t\tBegin Address End Address Unwind Info\n" +msgstr " vma:\t\t\tStartadresse Slutadresse Tilbagespolings-information\n" + +#: peigen.c:1554 pepigen.c:1554 +msgid "" +" vma:\t\tBegin End EH EH PrologEnd Exception\n" +" \t\tAddress Address Handler Data Address Mask\n" +msgstr "" +" vma:\t\tStart- Slut- EH- EH- Prologsluts- Undtagelses-\n" +" \t\tadresse adresse håndterere data adresse maske\n" + +#: peigen.c:1624 pepigen.c:1624 +msgid " Register save millicode" +msgstr " Registergemnings millikode" + +#: peigen.c:1627 pepigen.c:1627 +msgid " Register restore millicode" +msgstr " Registergenskabnings millikode" + +#: peigen.c:1630 pepigen.c:1630 +msgid " Glue code sequence" +msgstr " Klisterkodesekvens" + +#: peigen.c:1682 pepigen.c:1682 +msgid "" +"\n" +"\n" +"PE File Base Relocations (interpreted .reloc section contents)\n" +msgstr "" +"\n" +"\n" +"PE-filbaserelokaliseringer (tolket indhold i .reloc-sektionen)\n" + +#: peigen.c:1712 pepigen.c:1712 +#, c-format +msgid "" +"\n" +"Virtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n" +msgstr "" +"\n" +"Virtuel adresse: %08lx Områdesstørrelse %ld (0x%lx) Antal rettelser %ld\n" + +#: peigen.c:1725 pepigen.c:1725 +#, c-format +msgid "\treloc %4d offset %4x [%4lx] %s" +msgstr "\trelokalisering %4d afstand %4x [%4lx] %s" + +#. The MS dumpbin program reportedly ands with 0xff0f before +#. printing the characteristics field. Not sure why. No reason to +#. emulate it here. +#: peigen.c:1765 pepigen.c:1765 +#, c-format +msgid "" +"\n" +"Characteristics 0x%x\n" +msgstr "" +"\n" +"Karakteristik 0x%x\n" diff --git a/gdb/charset.c b/gdb/charset.c new file mode 100644 index 00000000000..00e10659a54 --- /dev/null +++ b/gdb/charset.c @@ -0,0 +1,1274 @@ +/* Character set conversion support for GDB. + Copyright 2001 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "charset.h" +#include "gdbcmd.h" +#include "gdb_assert.h" + +#include +#include +#include + +#ifdef HAVE_ICONV +#include +#endif + + +/* How GDB's character set support works + + GDB has two global settings: + + - The `current host character set' is the character set GDB should + use in talking to the user, and which (hopefully) the user's + terminal knows how to display properly. + + - The `current target character set' is the character set the + program being debugged uses. + + There are commands to set each of these, and mechanisms for + choosing reasonable default values. GDB has a global list of + character sets that it can use as its host or target character + sets. + + The header file `charset.h' declares various functions that + different pieces of GDB need to perform tasks like: + + - printing target strings and characters to the user's terminal + (mostly target->host conversions), + + - building target-appropriate representations of strings and + characters the user enters in expressions (mostly host->target + conversions), + + and so on. + + Now, many of these operations are specific to a particular + host/target character set pair. If GDB supports N character sets, + there are N^2 possible pairs. This means that, the larger GDB's + repertoire of character sets gets, the more expensive it gets to add + new character sets. + + To make sure that GDB can do the right thing for every possible + pairing of host and target character set, while still allowing + GDB's repertoire to scale, we use a two-tiered approach: + + - We maintain a global table of "translations" --- groups of + functions specific to a particular pair of character sets. + + - However, a translation can be incomplete: some functions can be + omitted. Where there is not a translation to specify exactly + what function to use, we provide reasonable defaults. The + default behaviors try to use the "iconv" library functions, which + support a wide range of character sets. However, even if iconv + is not available, there are fallbacks to support trivial + translations: when the host and target character sets are the + same. */ + + +/* The character set and translation structures. */ + + +/* A character set GDB knows about. GDB only supports character sets + with stateless encodings, in which every character is one byte + long. */ +struct charset { + + /* A singly-linked list of all known charsets. */ + struct charset *next; + + /* The name of the character set. Comparisons on character set + names are case-insensitive. */ + const char *name; + + /* Non-zero iff this character set can be used as a host character + set. At present, GDB basically assumes that the host character + set is a superset of ASCII. */ + int valid_host_charset; + + /* Pointers to charset-specific functions that depend only on a + single character set, and data pointers to pass to them. */ + int (*host_char_print_literally) (void *baton, + int host_char); + void *host_char_print_literally_baton; + + int (*target_char_to_control_char) (void *baton, + int target_char, + int *target_ctrl_char); + void *target_char_to_control_char_baton; +}; + + +/* A translation from one character set to another. */ +struct translation { + + /* A singly-linked list of all known translations. */ + struct translation *next; + + /* This structure describes functions going from the FROM character + set to the TO character set. Comparisons on character set names + are case-insensitive. */ + const char *from, *to; + + /* Pointers to translation-specific functions, and data pointers to + pass to them. These pointers can be zero, indicating that GDB + should fall back on the default behavior. We hope the default + behavior will be correct for many from/to pairs, reducing the + number of translations that need to be registered explicitly. */ + + /* TARGET_CHAR is in the `from' charset. + Returns a string in the `to' charset. */ + const char *(*c_target_char_has_backslash_escape) (void *baton, + int target_char); + void *c_target_char_has_backslash_escape_baton; + + /* HOST_CHAR is in the `from' charset. + TARGET_CHAR points to a char in the `to' charset. */ + int (*c_parse_backslash) (void *baton, int host_char, int *target_char); + void *c_parse_backslash_baton; + + /* This is used for the host_char_to_target and target_char_to_host + functions. */ + int (*convert_char) (void *baton, int from, int *to); + void *convert_char_baton; +}; + + + +/* The global lists of character sets and translations. */ + + +/* Character set names are always compared ignoring case. */ +static int +strcmp_case_insensitive (const char *p, const char *q) +{ + while (*p && *q && tolower (*p) == tolower (*q)) + p++, q++; + + return tolower (*p) - tolower (*q); +} + + +/* The global list of all the charsets GDB knows about. */ +static struct charset *all_charsets; + + +static void +register_charset (struct charset *cs) +{ + struct charset **ptr; + + /* Put the new charset on the end, so that the list ends up in the + same order as the registrations in the _initialize function. */ + for (ptr = &all_charsets; *ptr; ptr = &(*ptr)->next) + ; + + cs->next = 0; + *ptr = cs; +} + + +static struct charset * +lookup_charset (const char *name) +{ + struct charset *cs; + + for (cs = all_charsets; cs; cs = cs->next) + if (! strcmp_case_insensitive (name, cs->name)) + return cs; + + return NULL; +} + + +/* The global list of translations. */ +static struct translation *all_translations; + + +static void +register_translation (struct translation *t) +{ + t->next = all_translations; + all_translations = t; +} + + +static struct translation * +lookup_translation (const char *from, const char *to) +{ + struct translation *t; + + for (t = all_translations; t; t = t->next) + if (! strcmp_case_insensitive (from, t->from) + && ! strcmp_case_insensitive (to, t->to)) + return t; + + return 0; +} + + + +/* Constructing charsets. */ + +/* Allocate, initialize and return a straightforward charset. + Use this function, rather than creating the structures yourself, + so that we can add new fields to the structure in the future without + having to tweak all the old charset descriptions. */ +static struct charset * +simple_charset (const char *name, + int valid_host_charset, + int (*host_char_print_literally) (void *baton, int host_char), + void *host_char_print_literally_baton, + int (*target_char_to_control_char) (void *baton, + int target_char, + int *target_ctrl_char), + void *target_char_to_control_char_baton) +{ + struct charset *cs = xmalloc (sizeof (*cs)); + + memset (cs, 0, sizeof (*cs)); + cs->name = name; + cs->valid_host_charset = valid_host_charset; + cs->host_char_print_literally = host_char_print_literally; + cs->host_char_print_literally_baton = host_char_print_literally_baton; + cs->target_char_to_control_char = target_char_to_control_char; + cs->target_char_to_control_char_baton = target_char_to_control_char_baton; + + return cs; +} + + + +/* ASCII functions. */ + +static int +ascii_print_literally (void *baton, int c) +{ + c &= 0xff; + + return (0x20 <= c && c <= 0x7e); +} + + +static int +ascii_to_control (void *baton, int c, int *ctrl_char) +{ + *ctrl_char = (c & 037); + return 1; +} + + +/* ISO-8859 family functions. */ + + +static int +iso_8859_print_literally (void *baton, int c) +{ + c &= 0xff; + + return ((0x20 <= c && c <= 0x7e) /* ascii printables */ + || (! sevenbit_strings && 0xA0 <= c)); /* iso 8859 printables */ +} + + +static int +iso_8859_to_control (void *baton, int c, int *ctrl_char) +{ + *ctrl_char = (c & 0200) | (c & 037); + return 1; +} + + +/* Construct an ISO-8859-like character set. */ +static struct charset * +iso_8859_family_charset (const char *name) +{ + return simple_charset (name, 1, + iso_8859_print_literally, 0, + iso_8859_to_control, 0); +} + + + +/* EBCDIC family functions. */ + + +static int +ebcdic_print_literally (void *baton, int c) +{ + c &= 0xff; + + return (64 <= c && c <= 254); +} + + +static int +ebcdic_to_control (void *baton, int c, int *ctrl_char) +{ + /* There are no control character equivalents in EBCDIC. Use + numeric escapes. */ + return 0; +} + + +/* Construct an EBCDIC-like character set. */ +static struct charset * +ebcdic_family_charset (const char *name) +{ + return simple_charset (name, 0, + ebcdic_print_literally, 0, + ebcdic_to_control, 0); +} + + + + + +/* Fallback functions using iconv. */ + +#if defined(HAVE_ICONV) + +struct cached_iconv { + struct charset *from, *to; + iconv_t i; +}; + + +/* Make sure the iconv cache *CI contains an iconv descriptor + translating from FROM to TO. If it already does, fine; otherwise, + close any existing descriptor, and open up a new one. On success, + return zero; on failure, return -1 and set errno. */ +static int +check_iconv_cache (struct cached_iconv *ci, + struct charset *from, + struct charset *to) +{ + iconv_t i; + + /* Does the cached iconv descriptor match the conversion we're trying + to do now? */ + if (ci->from == from + && ci->to == to + && ci->i != (iconv_t) 0) + return 0; + + /* It doesn't. If we actually had any iconv descriptor open at + all, close it now. */ + if (ci->i != (iconv_t) 0) + { + i = ci->i; + ci->i = (iconv_t) 0; + + if (iconv_close (i) == -1) + error ("Error closing `iconv' descriptor for " + "`%s'-to-`%s' character conversion: %s", + ci->from->name, ci->to->name, safe_strerror (errno)); + } + + /* Open a new iconv descriptor for the required conversion. */ + i = iconv_open (to->name, from->name); + if (i == (iconv_t) -1) + return -1; + + ci->i = i; + ci->from = from; + ci->to = to; + + return 0; +} + + +/* Convert FROM_CHAR using the cached iconv conversion *CI. Return + non-zero if the conversion was successful, zero otherwise. */ +static int +cached_iconv_convert (struct cached_iconv *ci, int from_char, int *to_char) +{ + char from; + ICONV_CONST char *from_ptr = &from; + char to, *to_ptr = &to; + size_t from_left = sizeof (from), to_left = sizeof (to); + + gdb_assert (ci->i != (iconv_t) 0); + + from = from_char; + if (iconv (ci->i, &from_ptr, &from_left, &to_ptr, &to_left) + == (size_t) -1) + { + /* These all suggest that the input or output character sets + have multi-byte encodings of some characters, which means + it's unsuitable for use as a GDB character set. We should + never have selected it. */ + gdb_assert (errno != E2BIG && errno != EINVAL); + + /* This suggests a bug in the code managing *CI. */ + gdb_assert (errno != EBADF); + + /* This seems to mean that there is no equivalent character in + the `to' character set. */ + if (errno == EILSEQ) + return 0; + + /* Anything else is mysterious. */ + internal_error ("Error converting character `%d' from `%s' to `%s' " + "character set: %s", + from_char, ci->from->name, ci->to->name, + safe_strerror (errno)); + } + + /* If the pointers weren't advanced across the input, that also + suggests something was wrong. */ + gdb_assert (from_left == 0 && to_left == 0); + + *to_char = (unsigned char) to; + return 1; +} + + +static void +register_iconv_charsets () +{ + /* Here we should check whether various character sets were + recognized by the local iconv implementation. + + The first implementation registered a bunch of character sets + recognized by iconv, but then we discovered that iconv on Solaris + and iconv on GNU/Linux had no character sets in common. So we + replaced them with the hard-coded tables that appear later in the + file. */ +} + +#endif /* defined (HAVE_ICONV) */ + + +/* Fallback routines for systems without iconv. */ + +#if ! defined (HAVE_ICONV) +struct cached_iconv { char nothing; }; + +static int +check_iconv_cache (struct cached_iconv *ci, + struct charset *from, + struct charset *to) +{ + errno = EINVAL; + return -1; +} + +static int +cached_iconv_convert (struct cached_iconv *ci, int from_char, int *to_char) +{ + /* This function should never be called. */ + gdb_assert (0); +} + +static void +register_iconv_charsets () +{ +} + +#endif /* ! defined(HAVE_ICONV) */ + + +/* Default trivial conversion functions. */ + +static int +identity_either_char_to_other (void *baton, int either_char, int *other_char) +{ + *other_char = either_char; + return 1; +} + + + +/* Default non-trivial conversion functions. */ + + +static char backslashable[] = "abefnrtv"; +static char *backslashed[] = {"a", "b", "e", "f", "n", "r", "t", "v", "0"}; +static char represented[] = "\a\b\e\f\n\r\t\v"; + + +/* Translate TARGET_CHAR into the host character set, and see if it + matches any of our standard escape sequences. */ +static const char * +default_c_target_char_has_backslash_escape (void *baton, int target_char) +{ + int host_char; + const char *ix; + + /* If target_char has no equivalent in the host character set, + assume it doesn't have a backslashed form. */ + if (! target_char_to_host (target_char, &host_char)) + return NULL; + + ix = strchr (represented, host_char); + if (ix) + return backslashed[ix - represented]; + else + return NULL; +} + + +/* Translate the backslash the way we would in the host character set, + and then try to translate that into the target character set. */ +static int +default_c_parse_backslash (void *baton, int host_char, int *target_char) +{ + const char *ix; + + ix = strchr (backslashable, host_char); + + if (! ix) + return 0; + else + return host_char_to_target (represented[ix - backslashable], + target_char); +} + + +/* Convert using a cached iconv descriptor. */ +static int +iconv_convert (void *baton, int from_char, int *to_char) +{ + struct cached_iconv *ci = baton; + return cached_iconv_convert (ci, from_char, to_char); +} + + + +/* Conversion tables. */ + + +/* I'd much rather fall back on iconv whenever possible. But the + character set names you use with iconv aren't standardized at all, + a lot of platforms have really meager character set coverage, etc. + I wanted to have at least something we could use to exercise the + test suite on all platforms. + + In the long run, we should have a configure-time process explore + somehow which character sets the host platform supports, and some + arrangement that allows GDB users to use platform-indepedent names + for character sets. */ + + +/* We generated these tables using iconv on a GNU/Linux machine. */ + + +static int ascii_to_iso_8859_1_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 80 */ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 96 */ + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 112 */ + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 128 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +}; + + +static int ascii_to_ebcdic_us_table[] = { + 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ + 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ + 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ + 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ + 215,216,217,226,227,228,229,230,231,232,233, -1,224, -1, -1,109, /* 96 */ + 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ + 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +}; + + +static int ascii_to_ibm1047_table[] = { + 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ + 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ + 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ + 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ + 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109, /* 96 */ + 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ + 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +}; + + +static int iso_8859_1_to_ascii_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 80 */ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 96 */ + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 112 */ + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 128 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +}; + + +static int iso_8859_1_to_ebcdic_us_table[] = { + 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ + 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ + 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ + 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ + 215,216,217,226,227,228,229,230,231,232,233, -1,224, -1, -1,109, /* 96 */ + 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ + 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ + 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, /* 144 */ + 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255, /* 160 */ + -1, -1, 74, -1, -1, -1,106, -1, -1, -1, -1, -1, 95, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +}; + + +static int iso_8859_1_to_ibm1047_table[] = { + 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ + 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ + 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ + 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ + 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109, /* 96 */ + 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ + 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ + 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, /* 144 */ + 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255, /* 160 */ + 65,170, 74,177,159,178,106,181,187,180,154,138,176,202,175,188, /* 176 */ + 144,143,234,250,190,160,182,179,157,218,155,139,183,184,185,171, /* 192 */ + 100,101, 98,102, 99,103,158,104,116,113,114,115,120,117,118,119, /* 208 */ + 172,105,237,238,235,239,236,191,128,253,254,251,252,186,174, 89, /* 224 */ + 68, 69, 66, 70, 67, 71,156, 72, 84, 81, 82, 83, 88, 85, 86, 87, /* 240 */ + 140, 73,205,206,203,207,204,225,112,221,222,219,220,141,142,223 /* 256 */ +}; + + +static int ebcdic_us_to_ascii_table[] = { + 0, 1, 2, 3, -1, 9, -1,127, -1, -1, -1, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, -1, -1, 8, -1, 24, 25, -1, -1, 28, 29, 30, 31, /* 32 */ + -1, -1, -1, -1, -1, 10, 23, 27, -1, -1, -1, -1, -1, 5, 6, 7, /* 48 */ + -1, -1, 22, -1, -1, -1, -1, 4, -1, -1, -1, -1, 20, 21, -1, 26, /* 64 */ + 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 60, 40, 43,124, /* 80 */ + 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59, -1, /* 96 */ + 45, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 37, 95, 62, 63, /* 112 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ + -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ + -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ + -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ + 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ + 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1 /* 256 */ +}; + + +static int ebcdic_us_to_iso_8859_1_table[] = { + 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, /* 32 */ + 128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, /* 48 */ + 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, /* 64 */ + 32, -1, -1, -1, -1, -1, -1, -1, -1, -1,162, 46, 60, 40, 43,124, /* 80 */ + 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59,172, /* 96 */ + 45, 47, -1, -1, -1, -1, -1, -1, -1, -1,166, 44, 37, 95, 62, 63, /* 112 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ + -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ + -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ + -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ + 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ + 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,159 /* 256 */ +}; + + +static int ebcdic_us_to_ibm1047_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ + 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, /* 80 */ + 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, 92, 93, 94,176, /* 96 */ + 96, 97, -1, -1, -1, -1, -1, -1, -1, -1,106,107,108,109,110,111, /* 112 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1,121,122,123,124,125,126,127, /* 128 */ + -1,129,130,131,132,133,134,135,136,137, -1, -1, -1, -1, -1, -1, /* 144 */ + -1,145,146,147,148,149,150,151,152,153, -1, -1, -1, -1, -1, -1, /* 160 */ + -1,161,162,163,164,165,166,167,168,169, -1, -1, -1, -1, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + 192,193,194,195,196,197,198,199,200,201, -1, -1, -1, -1, -1, -1, /* 208 */ + 208,209,210,211,212,213,214,215,216,217, -1, -1, -1, -1, -1, -1, /* 224 */ + 224, -1,226,227,228,229,230,231,232,233, -1, -1, -1, -1, -1, -1, /* 240 */ + 240,241,242,243,244,245,246,247,248,249, -1, -1, -1, -1, -1,255 /* 256 */ +}; + + +static int ibm1047_to_ascii_table[] = { + 0, 1, 2, 3, -1, 9, -1,127, -1, -1, -1, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, -1, -1, 8, -1, 24, 25, -1, -1, 28, 29, 30, 31, /* 32 */ + -1, -1, -1, -1, -1, 10, 23, 27, -1, -1, -1, -1, -1, 5, 6, 7, /* 48 */ + -1, -1, 22, -1, -1, -1, -1, 4, -1, -1, -1, -1, 20, 21, -1, 26, /* 64 */ + 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 60, 40, 43,124, /* 80 */ + 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59, 94, /* 96 */ + 45, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 37, 95, 62, 63, /* 112 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ + -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ + -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ + -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, 91, -1, -1, /* 176 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, /* 192 */ + 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ + 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ + 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1 /* 256 */ +}; + + +static int ibm1047_to_iso_8859_1_table[] = { + 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, /* 32 */ + 128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, /* 48 */ + 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, /* 64 */ + 32,160,226,228,224,225,227,229,231,241,162, 46, 60, 40, 43,124, /* 80 */ + 38,233,234,235,232,237,238,239,236,223, 33, 36, 42, 41, 59, 94, /* 96 */ + 45, 47,194,196,192,193,195,197,199,209,166, 44, 37, 95, 62, 63, /* 112 */ + 248,201,202,203,200,205,206,207,204, 96, 58, 35, 64, 39, 61, 34, /* 128 */ + 216, 97, 98, 99,100,101,102,103,104,105,171,187,240,253,254,177, /* 144 */ + 176,106,107,108,109,110,111,112,113,114,170,186,230,184,198,164, /* 160 */ + 181,126,115,116,117,118,119,120,121,122,161,191,208, 91,222,174, /* 176 */ + 172,163,165,183,169,167,182,188,189,190,221,168,175, 93,180,215, /* 192 */ + 123, 65, 66, 67, 68, 69, 70, 71, 72, 73,173,244,246,242,243,245, /* 208 */ + 125, 74, 75, 76, 77, 78, 79, 80, 81, 82,185,251,252,249,250,255, /* 224 */ + 92,247, 83, 84, 85, 86, 87, 88, 89, 90,178,212,214,210,211,213, /* 240 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,179,219,220,217,218,159 /* 256 */ +}; + + +static int ibm1047_to_ebcdic_us_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ + 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, /* 80 */ + 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, 92, 93, 94, -1, /* 96 */ + 96, 97, -1, -1, -1, -1, -1, -1, -1, -1,106,107,108,109,110,111, /* 112 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1,121,122,123,124,125,126,127, /* 128 */ + -1,129,130,131,132,133,134,135,136,137, -1, -1, -1, -1, -1, -1, /* 144 */ + -1,145,146,147,148,149,150,151,152,153, -1, -1, -1, -1, -1, -1, /* 160 */ + -1,161,162,163,164,165,166,167,168,169, -1, -1, -1, -1, -1, -1, /* 176 */ + 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ + 192,193,194,195,196,197,198,199,200,201, -1, -1, -1, -1, -1, -1, /* 208 */ + 208,209,210,211,212,213,214,215,216,217, -1, -1, -1, -1, -1, -1, /* 224 */ + 224, -1,226,227,228,229,230,231,232,233, -1, -1, -1, -1, -1, -1, /* 240 */ + 240,241,242,243,244,245,246,247,248,249, -1, -1, -1, -1, -1,255 /* 256 */ +}; + + +static int +table_convert_char (void *baton, int from, int *to) +{ + int *table = (int *) baton; + + if (0 <= from && from <= 255 + && table[from] != -1) + { + *to = table[from]; + return 1; + } + else + return 0; +} + + +static struct translation * +table_translation (const char *from, const char *to, int *table, + const char *(*c_target_char_has_backslash_escape) + (void *baton, int target_char), + void *c_target_char_has_backslash_escape_baton, + int (*c_parse_backslash) (void *baton, + int host_char, + int *target_char), + void *c_parse_backslash_baton) +{ + struct translation *t = xmalloc (sizeof (*t)); + + memset (t, 0, sizeof (*t)); + t->from = from; + t->to = to; + t->c_target_char_has_backslash_escape = c_target_char_has_backslash_escape; + t->c_target_char_has_backslash_escape_baton + = c_target_char_has_backslash_escape_baton; + t->c_parse_backslash = c_parse_backslash; + t->c_parse_backslash_baton = c_parse_backslash_baton; + t->convert_char = table_convert_char; + t->convert_char_baton = (void *) table; + + return t; +} + + +static struct translation * +simple_table_translation (const char *from, const char *to, int *table) +{ + return table_translation (from, to, table, 0, 0, 0, 0); +} + + + +/* Setting and retrieving the host and target charsets. */ + + +/* The current host and target character sets. */ +static struct charset *current_host_charset, *current_target_charset; + +/* The current functions and batons we should use for the functions in + charset.h. */ + +static const char *(*c_target_char_has_backslash_escape_func) + (void *baton, int target_char); +static void *c_target_char_has_backslash_escape_baton; + +static int (*c_parse_backslash_func) (void *baton, + int host_char, + int *target_char); +static void *c_parse_backslash_baton; + +static int (*host_char_to_target_func) (void *baton, + int host_char, + int *target_char); +static void *host_char_to_target_baton; + +static int (*target_char_to_host_func) (void *baton, + int target_char, + int *host_char); +static void *target_char_to_host_baton; + + +/* Cached iconv conversions, that might be useful to fallback + routines. */ +static struct cached_iconv cached_iconv_host_to_target; +static struct cached_iconv cached_iconv_target_to_host; + + +/* Set the host and target character sets to HOST and TARGET. */ +static void +set_host_and_target_charsets (struct charset *host, struct charset *target) +{ + struct translation *h2t, *t2h; + + /* If they're not both initialized yet, then just do nothing for + now. As soon as we're done running our initialize function, + everything will be initialized. */ + if (! host || ! target) + { + current_host_charset = host; + current_target_charset = target; + return; + } + + h2t = lookup_translation (host->name, target->name); + t2h = lookup_translation (target->name, host->name); + + /* If the translations don't provide conversion functions, make sure + iconv can back them up. Do this *before* modifying any state. */ + if (host != target) + { + if (! h2t || ! h2t->convert_char) + { + if (check_iconv_cache (&cached_iconv_host_to_target, host, target) + < 0) + error ("GDB can't convert from the `%s' character set to `%s'.", + host->name, target->name); + } + if (! t2h || ! t2h->convert_char) + { + if (check_iconv_cache (&cached_iconv_target_to_host, target, host) + < 0) + error ("GDB can't convert from the `%s' character set to `%s'.", + target->name, host->name); + } + } + + if (t2h && t2h->c_target_char_has_backslash_escape) + { + c_target_char_has_backslash_escape_func + = t2h->c_target_char_has_backslash_escape; + c_target_char_has_backslash_escape_baton + = t2h->c_target_char_has_backslash_escape_baton; + } + else + c_target_char_has_backslash_escape_func + = default_c_target_char_has_backslash_escape; + + if (h2t && h2t->c_parse_backslash) + { + c_parse_backslash_func = h2t->c_parse_backslash; + c_parse_backslash_baton = h2t->c_parse_backslash_baton; + } + else + c_parse_backslash_func = default_c_parse_backslash; + + if (h2t && h2t->convert_char) + { + host_char_to_target_func = h2t->convert_char; + host_char_to_target_baton = h2t->convert_char_baton; + } + else if (host == target) + host_char_to_target_func = identity_either_char_to_other; + else + { + host_char_to_target_func = iconv_convert; + host_char_to_target_baton = &cached_iconv_host_to_target; + } + + if (t2h && t2h->convert_char) + { + target_char_to_host_func = t2h->convert_char; + target_char_to_host_baton = t2h->convert_char_baton; + } + else if (host == target) + target_char_to_host_func = identity_either_char_to_other; + else + { + target_char_to_host_func = iconv_convert; + target_char_to_host_baton = &cached_iconv_target_to_host; + } + + current_host_charset = host; + current_target_charset = target; +} + + +static struct charset * +lookup_charset_or_error (const char *name) +{ + struct charset *cs = lookup_charset (name); + + if (! cs) + error ("GDB doesn't know of any character set named `%s'.", name); + + return cs; +} + + +static void +check_valid_host_charset (struct charset *cs) +{ + if (! cs->valid_host_charset) + error ("GDB can't use `%s' as its host character set.", cs->name); +} + + +void +set_host_charset (const char *charset) +{ + struct charset *cs = lookup_charset_or_error (charset); + check_valid_host_charset (cs); + set_host_and_target_charsets (cs, current_target_charset); +} + + +const char * +host_charset () +{ + return current_host_charset->name; +} + + +void +set_target_charset (const char *charset) +{ + struct charset *cs = lookup_charset_or_error (charset); + + set_host_and_target_charsets (current_host_charset, cs); +} + + +const char * +target_charset () +{ + return current_target_charset->name; +} + + + +/* Public character management functions. */ + + +const char * +c_target_char_has_backslash_escape (int target_char) +{ + return ((*c_target_char_has_backslash_escape_func) + (c_target_char_has_backslash_escape_baton, target_char)); +} + + +int +c_parse_backslash (int host_char, int *target_char) +{ + return (*c_parse_backslash_func) (c_parse_backslash_baton, + host_char, target_char); +} + + +int +host_char_print_literally (int host_char) +{ + return ((*current_host_charset->host_char_print_literally) + (current_host_charset->host_char_print_literally_baton, + host_char)); +} + + +int +target_char_to_control_char (int target_char, int *target_ctrl_char) +{ + return ((*current_target_charset->target_char_to_control_char) + (current_target_charset->target_char_to_control_char_baton, + target_char, target_ctrl_char)); +} + + +int +host_char_to_target (int host_char, int *target_char) +{ + return ((*host_char_to_target_func) + (host_char_to_target_baton, host_char, target_char)); +} + + +int +target_char_to_host (int target_char, int *host_char) +{ + return ((*target_char_to_host_func) + (target_char_to_host_baton, target_char, host_char)); +} + + + +/* Commands. */ + + +/* List the valid character sets. If HOST_ONLY is non-zero, list only + those character sets which can be used as GDB's host character set. */ +static void +list_charsets (int host_only) +{ + struct charset *cs; + + printf_filtered ("Valid character sets are:\n"); + + for (cs = all_charsets; cs; cs = cs->next) + if (host_only && cs->valid_host_charset) + printf_filtered (" %s\n", cs->name); + else + printf_filtered (" %s %s\n", + cs->name, + cs->valid_host_charset ? "*" : " "); + + if (! host_only) + printf_filtered ("* - can be used as a host character set\n"); +} + + +static void +set_charset_command (char *arg, int from_tty) +{ + if (! arg || arg[0] == '\0') + list_charsets (0); + else + { + struct charset *cs = lookup_charset_or_error (arg); + check_valid_host_charset (cs); + set_host_and_target_charsets (cs, cs); + } +} + + +static void +set_host_charset_command (char *arg, int from_tty) +{ + if (! arg || arg[0] == '\0') + list_charsets (1); + else + { + struct charset *cs = lookup_charset_or_error (arg); + check_valid_host_charset (cs); + set_host_and_target_charsets (cs, current_target_charset); + } +} + + +static void +set_target_charset_command (char *arg, int from_tty) +{ + if (! arg || arg[0] == '\0') + list_charsets (0); + else + { + struct charset *cs = lookup_charset_or_error (arg); + set_host_and_target_charsets (current_host_charset, cs); + } +} + + +static void +show_charset_command (char *arg, int from_tty) +{ + if (current_host_charset == current_target_charset) + { + printf_filtered ("The current host and target character set is `%s'.\n", + host_charset ()); + } + else + { + printf_filtered ("The current host character set is `%s'.\n", + host_charset ()); + printf_filtered ("The current target character set is `%s'.\n", + target_charset ()); + } +} + + + +/* The charset.c module initialization function. */ + +#ifndef GDB_DEFAULT_HOST_CHARSET +#define GDB_DEFAULT_HOST_CHARSET "ISO-8859-1" +#endif + +#ifndef GDB_DEFAULT_TARGET_CHARSET +#define GDB_DEFAULT_TARGET_CHARSET "ISO-8859-1" +#endif + +void +_initialize_charset (void) +{ + /* Register all the character set GDB knows about. + + You should use the same names that iconv does, where possible, to + take advantage of the iconv-based default behaviors. + + CAUTION: if you register a character set, you must also register + as many translations as are necessary to make that character set + interoperate correctly with all the other character sets. We do + provide default behaviors when no translation is available, or + when a translation's function pointer for a particular operation + is zero. Hopefully, these defaults will be correct often enough + that we won't need to provide too many translations. */ + register_charset (simple_charset ("ascii", 1, + ascii_print_literally, 0, + ascii_to_control, 0)); + register_charset (iso_8859_family_charset ("iso-8859-1")); + register_charset (ebcdic_family_charset ("ebcdic-us")); + register_charset (ebcdic_family_charset ("ibm1047")); + register_iconv_charsets (); + + { + struct { char *from; char *to; int *table; } tlist[] = { + { "ascii", "iso-8859-1", ascii_to_iso_8859_1_table }, + { "ascii", "ebcdic-us", ascii_to_ebcdic_us_table }, + { "ascii", "ibm1047", ascii_to_ibm1047_table }, + { "iso-8859-1", "ascii", iso_8859_1_to_ascii_table }, + { "iso-8859-1", "ebcdic-us", iso_8859_1_to_ebcdic_us_table }, + { "iso-8859-1", "ibm1047", iso_8859_1_to_ibm1047_table }, + { "ebcdic-us", "ascii", ebcdic_us_to_ascii_table }, + { "ebcdic-us", "iso-8859-1", ebcdic_us_to_iso_8859_1_table }, + { "ebcdic-us", "ibm1047", ebcdic_us_to_ibm1047_table }, + { "ibm1047", "ascii", ibm1047_to_ascii_table }, + { "ibm1047", "iso-8859-1", ibm1047_to_iso_8859_1_table }, + { "ibm1047", "ebcdic-us", ibm1047_to_ebcdic_us_table } + }; + + int i; + + for (i = 0; i < (sizeof (tlist) / sizeof (tlist[0])); i++) + register_translation (simple_table_translation (tlist[i].from, + tlist[i].to, + tlist[i].table)); + } + + set_host_charset (GDB_DEFAULT_HOST_CHARSET); + set_target_charset (GDB_DEFAULT_TARGET_CHARSET); + + add_cmd ("charset", class_support, set_charset_command, + "Use CHARSET as the host and target character set.\n" + "The `host character set' is the one used by the system GDB is running on.\n" + "The `target character set' is the one used by the program being debugged.\n" + "You may only use supersets of ASCII for your host character set; GDB does\n" + "not support any others.\n" + "To see a list of the character sets GDB supports, type `set charset'\n" + "with no argument.", + &setlist); + + add_cmd ("host-charset", class_support, set_host_charset_command, + "Use CHARSET as the host character set.\n" + "The `host character set' is the one used by the system GDB is running on.\n" + "You may only use supersets of ASCII for your host character set; GDB does\n" + "not support any others.\n" + "To see a list of the character sets GDB supports, type `set host-charset'\n" + "with no argument.", + &setlist); + + add_cmd ("target-charset", class_support, set_target_charset_command, + "Use CHARSET as the target character set.\n" + "The `target character set' is the one used by the program being debugged.\n" + "GDB translates characters and strings between the host and target\n" + "character sets as needed.\n" + "To see a list of the character sets GDB supports, type `set target-charset'\n" + "with no argument.", + &setlist); + + add_cmd ("charset", class_support, show_charset_command, + "Show the current host and target character sets.", + &showlist); + add_alias_cmd ("host-charset", "charset", class_alias, 1, &showlist); + add_alias_cmd ("target-charset", "charset", class_alias, 1, &showlist); +} diff --git a/gdb/charset.h b/gdb/charset.h new file mode 100644 index 00000000000..10578cb9243 --- /dev/null +++ b/gdb/charset.h @@ -0,0 +1,120 @@ +/* Character set conversion support for GDB. + Copyright 2001 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef CHARSET_H +#define CHARSET_H + + +/* If the target program uses a different character set than the host, + GDB has some support for translating between the two; GDB converts + characters and strings to the host character set before displaying + them, and converts characters and strings appearing in expressions + entered by the user to the target character set. + + At the moment, GDB only supports single-byte, stateless character + sets. This includes the ISO-8859 family (ASCII extended with + accented characters, and (I think) Cyrillic, for European + languages), and the EBCDIC family (used on IBM's mainframes). + Unfortunately, it excludes many Asian scripts, the fixed- and + variable-width Unicode encodings, and other desireable things. + Patches are welcome! (For example, it would be nice if the Java + string support could simply get absorbed into some more general + multi-byte encoding support.) + + Furthermore, GDB's code pretty much assumes that the host character + set is some superset of ASCII; there are plenty if ('0' + n) + expressions and the like. + + When the `iconv' library routine supports a character set meeting + the requirements above, it's easy to plug an entry into GDB's table + that uses iconv to handle the details. */ + + +/* Set the host character set to CHARSET. CHARSET must be a superset + of ASCII, since GDB's code assumes this. */ +void set_host_charset (const char *charset); + + +/* Set the target character set to CHARSET. */ +void set_target_charset (const char *charset); + + +/* Return the name of the current host/target character set. The + result is owned by the charset module; the caller should not free + it. */ +const char *host_charset (void); +const char *target_charset (void); + + +/* In general, the set of C backslash escapes (\n, \f) is specific to + the character set. Not all character sets will have form feed + characters, for example. + + The following functions allow GDB to parse and print control + characters in a character-set-independent way. They are both + language-specific (to C and C++) and character-set-specific. + Putting them here is a compromise. */ + + +/* If the target character TARGET_CHAR have a backslash escape in the + C language (i.e., a character like 'n' or 't'), return the host + character string that should follow the backslash. Otherwise, + return zero. + + When this function returns non-zero, the string it returns is + statically allocated; the caller is not responsible for freeing it. */ +const char *c_target_char_has_backslash_escape (int target_char); + + +/* If the host character HOST_CHAR is a valid backslash escape in the + C language for the target character set, return non-zero, and set + *TARGET_CHAR to the target character the backslash escape represents. + Otherwise, return zero. */ +int c_parse_backslash (int host_char, int *target_char); + + +/* Return non-zero if the host character HOST_CHAR can be printed + literally --- that is, if it can be readably printed as itself in a + character or string constant. Return zero if it should be printed + using some kind of numeric escape, like '\031' in C, '^(25)' in + Chill, or #25 in Pascal. */ +int host_char_print_literally (int host_char); + + +/* If the host character HOST_CHAR has an equivalent in the target + character set, set *TARGET_CHAR to that equivalent, and return + non-zero. Otherwise, return zero. */ +int host_char_to_target (int host_char, int *target_char); + + +/* If the target character TARGET_CHAR has an equivalent in the host + character set, set *HOST_CHAR to that equivalent, and return + non-zero. Otherwise, return zero. */ +int target_char_to_host (int target_char, int *host_char); + + +/* If the target character TARGET_CHAR has a corresponding control + character (also in the target character set), set *TARGET_CTRL_CHAR + to the control character, and return non-zero. Otherwise, return + zero. */ +int target_char_to_control_char (int target_char, int *target_ctrl_char); + + +#endif /* CHARSET_H */ diff --git a/gdb/config/i386/nbsd.mt b/gdb/config/i386/nbsd.mt new file mode 100644 index 00000000000..f7f8cd6e70c --- /dev/null +++ b/gdb/config/i386/nbsd.mt @@ -0,0 +1,4 @@ +# Target: Intel 386 running NetBSD +TDEPFILES= i386-tdep.o i387-tdep.o i386bsd-tdep.o i386nbsd-tdep.o corelow.o \ + nbsd-tdep.o solib.o solib-svr4.o +TM_FILE= tm-nbsd.h diff --git a/gdb/cp-support.c b/gdb/cp-support.c new file mode 100644 index 00000000000..46363a8b3bf --- /dev/null +++ b/gdb/cp-support.c @@ -0,0 +1,141 @@ +/* Helper routines for C++ support in GDB. + Copyright 2002 Free Software Foundation, Inc. + + Contributed by MontaVista Software. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "cp-support.h" +#include "gdb_string.h" +#include "demangle.h" + +/* Find the last component of the demangled C++ name NAME. NAME + must be a method name including arguments, in order to correctly + locate the last component. + + This function return a pointer to the first colon before the + last component, or NULL if the name had only one component. */ + +static const char * +find_last_component (const char *name) +{ + const char *p; + int depth; + + /* Functions can have local classes, so we need to find the + beginning of the last argument list, not the end of the first + one. */ + p = name + strlen (name) - 1; + while (p > name && *p != ')') + p--; + + if (p == name) + return NULL; + + /* P now points at the `)' at the end of the argument list. Walk + back to the beginning. */ + p--; + depth = 1; + while (p > name && depth > 0) + { + if (*p == '<' || *p == '(') + depth--; + else if (*p == '>' || *p == ')') + depth++; + p--; + } + + if (p == name) + return NULL; + + while (p > name && *p != ':') + p--; + + if (p == name || p == name + 1 || p[-1] != ':') + return NULL; + + return p - 1; +} + +/* Return the name of the class containing method PHYSNAME. */ + +char * +class_name_from_physname (const char *physname) +{ + char *ret = NULL; + const char *end; + int depth = 0; + char *demangled_name = cplus_demangle (physname, DMGL_ANSI); + + if (demangled_name == NULL) + return NULL; + + end = find_last_component (demangled_name); + if (end != NULL) + { + ret = xmalloc (end - demangled_name + 1); + memcpy (ret, demangled_name, end - demangled_name); + ret[end - demangled_name] = '\0'; + } + + xfree (demangled_name); + return ret; +} + +/* Return the name of the method whose linkage name is PHYSNAME. */ + +char * +method_name_from_physname (const char *physname) +{ + char *ret = NULL; + const char *end; + int depth = 0; + char *demangled_name = cplus_demangle (physname, DMGL_ANSI); + + if (demangled_name == NULL) + return NULL; + + end = find_last_component (demangled_name); + if (end != NULL) + { + char *args; + int len; + + /* Skip "::". */ + end = end + 2; + + /* Find the argument list, if any. */ + args = strchr (end, '('); + if (args == NULL) + len = strlen (end + 2); + else + { + args --; + while (*args == ' ') + args --; + len = args - end + 1; + } + ret = xmalloc (len + 1); + memcpy (ret, end, len); + ret[len] = 0; + } + + xfree (demangled_name); + return ret; +} diff --git a/gdb/cp-support.h b/gdb/cp-support.h new file mode 100644 index 00000000000..a7d333f28b2 --- /dev/null +++ b/gdb/cp-support.h @@ -0,0 +1,25 @@ +/* Helper routines for C++ support in GDB. + Copyright 2002 Free Software Foundation, Inc. + + Contributed by MontaVista Software. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +extern char *class_name_from_physname (const char *physname); + +extern char *method_name_from_physname (const char *physname); diff --git a/gdb/disasm.c b/gdb/disasm.c new file mode 100644 index 00000000000..8ce9a155166 --- /dev/null +++ b/gdb/disasm.c @@ -0,0 +1,374 @@ +/* Disassemble support for GDB. + Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "target.h" +#include "value.h" +#include "ui-out.h" +#include "gdb_string.h" + +#include "disasm.h" + +/* Disassemble functions. + FIXME: We should get rid of all the duplicate code in gdb that does + the same thing: disassemble_command() and the gdbtk variation. */ + +/* This Structure is used to store line number information. + We need a different sort of line table from the normal one cuz we can't + depend upon implicit line-end pc's for lines to do the + reordering in this function. */ + +struct dis_line_entry +{ + int line; + CORE_ADDR start_pc; + CORE_ADDR end_pc; +}; + +/* This variable determines where memory used for disassembly is read from. */ +int gdb_disassemble_from_exec = -1; + +/* This is the memory_read_func for gdb_disassemble when we are + disassembling from the exec file. */ +static int +gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr, + unsigned int len, disassemble_info * info) +{ + extern struct target_ops exec_ops; + int res; + + errno = 0; + res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops); + + if (res == len) + return 0; + else if (errno == 0) + return EIO; + else + return errno; +} + +static int +compare_lines (const PTR mle1p, const PTR mle2p) +{ + struct dis_line_entry *mle1, *mle2; + int val; + + mle1 = (struct dis_line_entry *) mle1p; + mle2 = (struct dis_line_entry *) mle2p; + + val = mle1->line - mle2->line; + + if (val != 0) + return val; + + return mle1->start_pc - mle2->start_pc; +} + +static int +dump_insns (struct ui_out *uiout, disassemble_info * di, + CORE_ADDR low, CORE_ADDR high, + int how_many, struct ui_stream *stb) +{ + int num_displayed = 0; + CORE_ADDR pc; + + /* parts of the symbolic representation of the address */ + int unmapped; + char *filename = NULL; + char *name = NULL; + int offset; + int line; + + for (pc = low; pc < high;) + { + QUIT; + if (how_many >= 0) + { + if (num_displayed >= how_many) + break; + else + num_displayed++; + } + ui_out_tuple_begin (uiout, NULL); + ui_out_field_core_addr (uiout, "address", pc); + + if (!build_address_symbolic (pc, 0, &name, &offset, &filename, + &line, &unmapped)) + { + /* We don't care now about line, filename and + unmapped. But we might in the future. */ + ui_out_text (uiout, " <"); + ui_out_field_string (uiout, "func-name", name); + ui_out_text (uiout, "+"); + ui_out_field_int (uiout, "offset", offset); + ui_out_text (uiout, ">:\t"); + } + if (filename != NULL) + xfree (filename); + if (name != NULL) + xfree (name); + + ui_file_rewind (stb->stream); + pc += TARGET_PRINT_INSN (pc, di); + ui_out_field_stream (uiout, "inst", stb); + ui_file_rewind (stb->stream); + ui_out_tuple_end (uiout); + ui_out_text (uiout, "\n"); + } + return num_displayed; +} + +/* The idea here is to present a source-O-centric view of a + function to the user. This means that things are presented + in source order, with (possibly) out of order assembly + immediately following. */ +static void +do_mixed_source_and_assembly (struct ui_out *uiout, + struct disassemble_info *di, int nlines, + struct linetable_entry *le, + CORE_ADDR low, CORE_ADDR high, + struct symtab *symtab, + int how_many, struct ui_stream *stb) +{ + int newlines = 0; + struct dis_line_entry *mle; + struct symtab_and_line sal; + int i; + int out_of_order = 0; + int next_line = 0; + CORE_ADDR pc; + int num_displayed = 0; + + mle = (struct dis_line_entry *) alloca (nlines + * sizeof (struct dis_line_entry)); + + /* Copy linetable entries for this function into our data + structure, creating end_pc's and setting out_of_order as + appropriate. */ + + /* First, skip all the preceding functions. */ + + for (i = 0; i < nlines - 1 && le[i].pc < low; i++); + + /* Now, copy all entries before the end of this function. */ + + for (; i < nlines - 1 && le[i].pc < high; i++) + { + if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) + continue; /* Ignore duplicates */ + + /* Skip any end-of-function markers. */ + if (le[i].line == 0) + continue; + + mle[newlines].line = le[i].line; + if (le[i].line > le[i + 1].line) + out_of_order = 1; + mle[newlines].start_pc = le[i].pc; + mle[newlines].end_pc = le[i + 1].pc; + newlines++; + } + + /* If we're on the last line, and it's part of the function, + then we need to get the end pc in a special way. */ + + if (i == nlines - 1 && le[i].pc < high) + { + mle[newlines].line = le[i].line; + mle[newlines].start_pc = le[i].pc; + sal = find_pc_line (le[i].pc, 0); + mle[newlines].end_pc = sal.end; + newlines++; + } + + /* Now, sort mle by line #s (and, then by addresses within + lines). */ + + if (out_of_order) + qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); + + /* Now, for each line entry, emit the specified lines (unless + they have been emitted before), followed by the assembly code + for that line. */ + + ui_out_list_begin (uiout, "asm_insns"); + + for (i = 0; i < newlines; i++) + { + int close_list = 1; + /* Print out everything from next_line to the current line. */ + if (mle[i].line >= next_line) + { + if (next_line != 0) + { + /* Just one line to print. */ + if (next_line == mle[i].line) + { + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, next_line, mle[i].line + 1, 0); + } + else + { + /* Several source lines w/o asm instructions associated. */ + for (; next_line < mle[i].line; next_line++) + { + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, next_line, next_line + 1, + 0); + ui_out_list_begin (uiout, "line_asm_insn"); + ui_out_list_end (uiout); + ui_out_tuple_end (uiout); + } + /* Print the last line and leave list open for + asm instructions to be added. */ + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, next_line, mle[i].line + 1, 0); + } + } + else + { + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); + } + + next_line = mle[i].line + 1; + ui_out_list_begin (uiout, "line_asm_insn"); + /* Don't close the list if the lines are not in order. */ + if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line) + close_list = 0; + } + + num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc, + how_many, stb); + if (close_list) + { + ui_out_list_end (uiout); + ui_out_tuple_end (uiout); + ui_out_text (uiout, "\n"); + close_list = 0; + } + if (how_many >= 0) + if (num_displayed >= how_many) + break; + } + ui_out_list_end (uiout); +} + + +static void +do_assembly_only (struct ui_out *uiout, disassemble_info * di, + CORE_ADDR low, CORE_ADDR high, + int how_many, struct ui_stream *stb) +{ + int num_displayed = 0; + + ui_out_list_begin (uiout, "asm_insns"); + + num_displayed = dump_insns (uiout, di, low, high, how_many, stb); + + ui_out_list_end (uiout); +} + +void +gdb_disassembly (struct ui_out *uiout, + char *file_string, + int line_num, + int mixed_source_and_assembly, + int how_many, CORE_ADDR low, CORE_ADDR high) +{ + static disassemble_info di; + static int di_initialized; + /* To collect the instruction outputted from opcodes. */ + static struct ui_stream *stb = NULL; + struct symtab *symtab = NULL; + struct linetable_entry *le = NULL; + int nlines = -1; + + if (!di_initialized) + { + /* We don't add a cleanup for this, because the allocation of + the stream is done once only for each gdb run, and we need to + keep it around until the end. Hopefully there won't be any + errors in the init code below, that make this function bail + out. */ + stb = ui_out_stream_new (uiout); + INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream, + (fprintf_ftype) fprintf_unfiltered); + di.flavour = bfd_target_unknown_flavour; + di.memory_error_func = dis_asm_memory_error; + di.print_address_func = dis_asm_print_address; + di_initialized = 1; + } + + di.mach = TARGET_PRINT_INSN_INFO->mach; + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + di.endian = BFD_ENDIAN_BIG; + else + di.endian = BFD_ENDIAN_LITTLE; + + /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to + determine whether or not to do disassembly from target memory or from the + exec file: + + If we're debugging a local process, read target memory, instead of the + exec file. This makes disassembly of functions in shared libs work + correctly. Also, read target memory if we are debugging native threads. + + Else, we're debugging a remote process, and should disassemble from the + exec file for speed. However, this is no good if the target modifies its + code (for relocation, or whatever). */ + + if (gdb_disassemble_from_exec == -1) + { + if (strcmp (target_shortname, "child") == 0 + || strcmp (target_shortname, "procfs") == 0 + || strcmp (target_shortname, "vxprocess") == 0 + || strstr (target_shortname, "-threads") != NULL) + gdb_disassemble_from_exec = 0; /* It's a child process, read inferior mem */ + else + gdb_disassemble_from_exec = 1; /* It's remote, read the exec file */ + } + + if (gdb_disassemble_from_exec) + di.read_memory_func = gdb_dis_asm_read_memory; + else + di.read_memory_func = dis_asm_read_memory; + + /* Assume symtab is valid for whole PC range */ + symtab = find_pc_symtab (low); + + if (symtab != NULL && symtab->linetable != NULL) + { + /* Convert the linetable to a bunch of my_line_entry's. */ + le = symtab->linetable->item; + nlines = symtab->linetable->nitems; + } + + if (!mixed_source_and_assembly || nlines <= 0 + || symtab == NULL || symtab->linetable == NULL) + do_assembly_only (uiout, &di, low, high, how_many, stb); + + else if (mixed_source_and_assembly) + do_mixed_source_and_assembly (uiout, &di, nlines, le, low, + high, symtab, how_many, stb); + + gdb_flush (gdb_stdout); +} diff --git a/gdb/disasm.h b/gdb/disasm.h new file mode 100644 index 00000000000..beaaf4aaa3d --- /dev/null +++ b/gdb/disasm.h @@ -0,0 +1,29 @@ +/* Disassemble support for GDB. + Copyright 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef DISASM_H +#define DISASM_H + +extern void gdb_disassembly (struct ui_out *uiout, + char *file_string, + int line_num, + int mixed_source_and_assembly, + int how_many, CORE_ADDR low, CORE_ADDR high); +#endif diff --git a/gdb/gdb.c b/gdb/gdb.c new file mode 100644 index 00000000000..c0bc4875b32 --- /dev/null +++ b/gdb/gdb.c @@ -0,0 +1,34 @@ +/* Main function for CLI gdb. + Copyright 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "main.h" +#include "gdb_string.h" + +int +main (int argc, char **argv) +{ + struct captured_main_args args; + memset (&args, 0, sizeof args); + args.argc = argc; + args.argv = argv; + args.use_windows = 0; + return gdb_main (&args); +} diff --git a/gdb/gdb_mbuild.sh b/gdb/gdb_mbuild.sh new file mode 100755 index 00000000000..ae40b02c69a --- /dev/null +++ b/gdb/gdb_mbuild.sh @@ -0,0 +1,153 @@ +#!/bin/sh + +# Multi-build script for testing compilation of all maintained configs of GDB. +# Copyright (C) 2002 Free Software Foundation, Inc. +# Contributed by Richard Earnshaw (rearnsha@arm.com) + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +usage() { + echo "Usage: gdb_mbuild.sh []" + echo " Environment variables examined (with default if not defined):" + echo " AWK (awk) -- must be GNU awk" + echo " MAKE (make)" + echo + echo " Note: Everything in /gdb-allcross will be blown away." + exit 1; +} + +if [ $# -ne 2 -a $# -ne 3 ] ; then + usage +fi + +### COMMAND LINE PARAMETERS + +# Where the sources live +srcdir=$1 + +# Where the builds occur +buildbase=$2 + +# Number of parallel make jobs (you probably want about 2 jobs per cpu for +# maximum throughput) +if [ $# -eq 3 ]; then + par=$3 +else + par="1" +fi + +### ENVIRONMENT PARAMETERS +# Must be GNU awk +awk=${AWK:-awk} + +# Version of make to use +make=${MAKE:-make} + + +# Where builds will live +builddir=${buildbase}/gdb-allcross + +# Where logs will go. NB. Must not be a sub-dir of builddir or you will loose +# them. +logdir=${buildbase}/gdb-logdir + +# Where to look for the list of targets to test +maintainers=${srcdir}/gdb/MAINTAINERS + +# Get the list of targets and the build options +alltarg=`${awk} < "${maintainers}" ' + $2 ~ /--target=.*/ { + targets = gensub (/^.*--target=/, "", 1, $2) + warnings = gensub (/[)]*$/, "", 1, $3) + split (targets, targ, /,/) + for (i in targ) { + print targ[i], warnings + } + }'` + +# Back up the log files +cd ${logdir} + +if [ -f build.out ] +then + mv build.out build.old +fi +if [ -f config.out ] +then + mv config.out config.old +fi +if [ -f fail.sum ] +then + mv fail.sum fail.old +fi + +if [ ! -d ${builddir} ] +then + echo ${builddir} does not exist + exit 1 +fi + +cd ${builddir} +rm -rf * + +MAKE=${make} +export MAKE + +jobs=1 +# For each target, configure and build it. +while read targ opts +do + if [ ${opts} != "broken" ] + then + trap 'echo cleaning up ...; rm -rf ${builddir}/*; exit 1' 1 2 15 + echo ${targ} + mkdir ${targ} + cd ${targ} + ${srcdir}/configure --target=$targ \ + --enable-gdb-build-warnings=$opts \ + >> ${logdir}/config.tout.$targ 2>&1 & + cd .. + jobs=`expr ${jobs} + 1` + if [ ${jobs} -gt ${par} ] + then + wait + jobs=1 + fi + fi +done << EOF +$alltarg +EOF + +wait + +cat ${logdir}/config.tout.* > ${logdir}/config.out +rm -f ${logdir}/config.tout.* + +for targ in * +do + cd $targ + if ${make} -j ${par} all-gdb >> ${logdir}/build.out 2>&1 + then + true + else + echo ">>>>>>>>>>>>>" >> ${logdir}/fail.sum + echo "$targ (${opts})" >> ${logdir}/fail.sum + tail -20 ${logdir}/build.out >> ${logdir}/fail.sum + echo >> ${logdir}/fail.sum + echo $targ build failed + fi + rm -rf * + cd .. +done diff --git a/gdb/main.h b/gdb/main.h new file mode 100644 index 00000000000..8ee189e8a9d --- /dev/null +++ b/gdb/main.h @@ -0,0 +1,34 @@ +/* Main interface for GDB, the GNU debugger. + + Copyright 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef MAIN_H +#define MAIN_H + +struct captured_main_args +{ + int argc; + char **argv; + int use_windows; +}; + +extern int gdb_main (struct captured_main_args *); + +#endif diff --git a/gdb/objc-exp.y b/gdb/objc-exp.y new file mode 100644 index 00000000000..54b99b00610 --- /dev/null +++ b/gdb/objc-exp.y @@ -0,0 +1,1841 @@ +/* YACC parser for C expressions, for GDB. + + Copyright 1986, 1989, 1990, 1991, 1993, 1994, 2002 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Parse a C expression from text in a string, and return the result + as a struct expression pointer. That structure contains arithmetic + operations in reverse polish, with constants represented by + operations that are followed by special data. See expression.h for + the details of the format. What is important here is that it can + be built up sequentially during the process of parsing; the lower + levels of the tree always come first in the result. + + Note that malloc's and realloc's in this file are transformed to + xmalloc and xrealloc respectively by the same sed command in the + makefile that remaps any other malloc/realloc inserted by the + parser generator. Doing this with #defines and trying to control + the interaction with include files ( and for + example) just became too messy, particularly when such includes can + be inserted at random times by the parser generator. */ + +%{ + +#include "defs.h" +#include "gdb_string.h" +#include +#include "expression.h" + +#include "objc-lang.h" /* For objc language constructs. */ + +#include "value.h" +#include "parser-defs.h" +#include "language.h" +#include "c-lang.h" +#include "bfd.h" /* Required by objfiles.h. */ +#include "symfile.h" /* Required by objfiles.h. */ +#include "objfiles.h" /* For have_full_symbols and have_partial_symbols. */ +#include "top.h" +#include "completer.h" /* For skip_quoted(). */ + +/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, + etc), as well as gratuitiously global symbol names, so we can have + multiple yacc generated parsers in gdb. Note that these are only + the variables produced by yacc. If other parser generators (bison, + byacc, etc) produce additional global names that conflict at link + time, then those parser generators need to be fixed instead of + adding those names to this list. */ + +#define yymaxdepth objc_maxdepth +#define yyparse objc_parse +#define yylex objc_lex +#define yyerror objc_error +#define yylval objc_lval +#define yychar objc_char +#define yydebug objc_debug +#define yypact objc_pact +#define yyr1 objc_r1 +#define yyr2 objc_r2 +#define yydef objc_def +#define yychk objc_chk +#define yypgo objc_pgo +#define yyact objc_act +#define yyexca objc_exca +#define yyerrflag objc_errflag +#define yynerrs objc_nerrs +#define yyps objc_ps +#define yypv objc_pv +#define yys objc_s +#define yy_yys objc_yys +#define yystate objc_state +#define yytmp objc_tmp +#define yyv objc_v +#define yy_yyv objc_yyv +#define yyval objc_val +#define yylloc objc_lloc +#define yyreds objc_reds /* With YYDEBUG defined */ +#define yytoks objc_toks /* With YYDEBUG defined */ +#define yyname objc_name /* With YYDEBUG defined */ +#define yyrule objc_rule /* With YYDEBUG defined */ +#define yylhs objc_yylhs +#define yylen objc_yylen +#define yydefred objc_yydefred +#define yydgoto objc_yydgoto +#define yysindex objc_yysindex +#define yyrindex objc_yyrindex +#define yygindex objc_yygindex +#define yytable objc_yytable +#define yycheck objc_yycheck + +#ifndef YYDEBUG +#define YYDEBUG 0 /* Default to no yydebug support. */ +#endif + +int +yyparse PARAMS ((void)); + +static int +yylex PARAMS ((void)); + +void +yyerror PARAMS ((char *)); + +%} + +/* Although the yacc "value" of an expression is not used, + since the result is stored in the structure being created, + other node types do have values. */ + +%union + { + LONGEST lval; + struct { + LONGEST val; + struct type *type; + } typed_val_int; + struct { + DOUBLEST dval; + struct type *type; + } typed_val_float; + struct symbol *sym; + struct type *tval; + struct stoken sval; + struct ttype tsym; + struct symtoken ssym; + int voidval; + struct block *bval; + enum exp_opcode opcode; + struct internalvar *ivar; + struct objc_class_str class; + + struct type **tvec; + int *ivec; + } + +%{ +/* YYSTYPE gets defined by %union. */ +static int +parse_number PARAMS ((char *, int, int, YYSTYPE *)); +%} + +%type exp exp1 type_exp start variable qualified_name lcurly +%type rcurly +%type type typebase +%type nonempty_typelist +/* %type block */ + +/* Fancy type parsing. */ +%type func_mod direct_abs_decl abs_decl +%type ptype +%type array_mod + +%token INT +%token FLOAT + +/* Both NAME and TYPENAME tokens represent symbols in the input, and + both convey their data as strings. But a TYPENAME is a string that + happens to be defined as a typedef or builtin type name (such as + int or char) and a NAME is any other symbol. Contexts where this + distinction is not important can use the nonterminal "name", which + matches either NAME or TYPENAME. */ + +%token STRING +%token NSSTRING /* ObjC Foundation "NSString" literal */ +%token SELECTOR /* ObjC "@selector" pseudo-operator */ +%token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token TYPENAME +%token CLASSNAME /* ObjC Class name */ +%type name +%type name_not_typename +%type typename + +/* A NAME_OR_INT is a symbol which is not known in the symbol table, + but which would parse as a valid number in the current input radix. + E.g. "c" when input_radix==16. Depending on the parse, it will be + turned into a name or into a number. */ + +%token NAME_OR_INT + +%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON +%token TEMPLATE +%token ERROR + +/* Special type cases, put in to allow the parser to distinguish + different legal basetypes. */ +%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD + +%token VARIABLE + +%token ASSIGN_MODIFY + +/* C++ */ +%token THIS + +%left ',' +%left ABOVE_COMMA +%right '=' ASSIGN_MODIFY +%right '?' +%left OROR +%left ANDAND +%left '|' +%left '^' +%left '&' +%left EQUAL NOTEQUAL +%left '<' '>' LEQ GEQ +%left LSH RSH +%left '@' +%left '+' '-' +%left '*' '/' '%' +%right UNARY INCREMENT DECREMENT +%right ARROW '.' '[' '(' +%token BLOCKNAME +%type block +%left COLONCOLON + + +%% + +start : exp1 + | type_exp + ; + +type_exp: type + { write_exp_elt_opcode(OP_TYPE); + write_exp_elt_type($1); + write_exp_elt_opcode(OP_TYPE);} + ; + +/* Expressions, including the comma operator. */ +exp1 : exp + | exp1 ',' exp + { write_exp_elt_opcode (BINOP_COMMA); } + ; + +/* Expressions, not including the comma operator. */ +exp : '*' exp %prec UNARY + { write_exp_elt_opcode (UNOP_IND); } + +exp : '&' exp %prec UNARY + { write_exp_elt_opcode (UNOP_ADDR); } + +exp : '-' exp %prec UNARY + { write_exp_elt_opcode (UNOP_NEG); } + ; + +exp : '!' exp %prec UNARY + { write_exp_elt_opcode (UNOP_LOGICAL_NOT); } + ; + +exp : '~' exp %prec UNARY + { write_exp_elt_opcode (UNOP_COMPLEMENT); } + ; + +exp : INCREMENT exp %prec UNARY + { write_exp_elt_opcode (UNOP_PREINCREMENT); } + ; + +exp : DECREMENT exp %prec UNARY + { write_exp_elt_opcode (UNOP_PREDECREMENT); } + ; + +exp : exp INCREMENT %prec UNARY + { write_exp_elt_opcode (UNOP_POSTINCREMENT); } + ; + +exp : exp DECREMENT %prec UNARY + { write_exp_elt_opcode (UNOP_POSTDECREMENT); } + ; + +exp : SIZEOF exp %prec UNARY + { write_exp_elt_opcode (UNOP_SIZEOF); } + ; + +exp : exp ARROW name + { write_exp_elt_opcode (STRUCTOP_PTR); + write_exp_string ($3); + write_exp_elt_opcode (STRUCTOP_PTR); } + ; + +exp : exp ARROW qualified_name + { /* exp->type::name becomes exp->*(&type::name) */ + /* Note: this doesn't work if name is a + static member! FIXME */ + write_exp_elt_opcode (UNOP_ADDR); + write_exp_elt_opcode (STRUCTOP_MPTR); } + ; +exp : exp ARROW '*' exp + { write_exp_elt_opcode (STRUCTOP_MPTR); } + ; + +exp : exp '.' name + { write_exp_elt_opcode (STRUCTOP_STRUCT); + write_exp_string ($3); + write_exp_elt_opcode (STRUCTOP_STRUCT); } + ; + + +exp : exp '.' qualified_name + { /* exp.type::name becomes exp.*(&type::name) */ + /* Note: this doesn't work if name is a + static member! FIXME */ + write_exp_elt_opcode (UNOP_ADDR); + write_exp_elt_opcode (STRUCTOP_MEMBER); } + ; + +exp : exp '.' '*' exp + { write_exp_elt_opcode (STRUCTOP_MEMBER); } + ; + +exp : exp '[' exp1 ']' + { write_exp_elt_opcode (BINOP_SUBSCRIPT); } + ; +/* + * The rules below parse ObjC message calls of the form: + * '[' target selector {':' argument}* ']' + */ + +exp : '[' TYPENAME + { + CORE_ADDR class; + + class = lookup_objc_class (copy_name ($2.stoken)); + if (class == 0) + error ("%s is not an ObjC Class", + copy_name ($2.stoken)); + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + write_exp_elt_longcst ((LONGEST) class); + write_exp_elt_opcode (OP_LONG); + start_msglist(); + } + msglist ']' + { write_exp_elt_opcode (OP_MSGCALL); + end_msglist(); + write_exp_elt_opcode (OP_MSGCALL); + } + ; + +exp : '[' CLASSNAME + { + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + write_exp_elt_longcst ((LONGEST) $2.class); + write_exp_elt_opcode (OP_LONG); + start_msglist(); + } + msglist ']' + { write_exp_elt_opcode (OP_MSGCALL); + end_msglist(); + write_exp_elt_opcode (OP_MSGCALL); + } + ; + +exp : '[' exp + { start_msglist(); } + msglist ']' + { write_exp_elt_opcode (OP_MSGCALL); + end_msglist(); + write_exp_elt_opcode (OP_MSGCALL); + } + ; + +msglist : name + { add_msglist(&$1, 0); } + | msgarglist + ; + +msgarglist : msgarg + | msgarglist msgarg + ; + +msgarg : name ':' exp + { add_msglist(&$1, 1); } + | ':' exp /* Unnamed arg. */ + { add_msglist(0, 1); } + | ',' exp /* Variable number of args. */ + { add_msglist(0, 0); } + ; + +exp : exp '(' + /* This is to save the value of arglist_len + being accumulated by an outer function call. */ + { start_arglist (); } + arglist ')' %prec ARROW + { write_exp_elt_opcode (OP_FUNCALL); + write_exp_elt_longcst ((LONGEST) end_arglist ()); + write_exp_elt_opcode (OP_FUNCALL); } + ; + +lcurly : '{' + { start_arglist (); } + ; + +arglist : + ; + +arglist : exp + { arglist_len = 1; } + ; + +arglist : arglist ',' exp %prec ABOVE_COMMA + { arglist_len++; } + ; + +rcurly : '}' + { $$ = end_arglist () - 1; } + ; +exp : lcurly arglist rcurly %prec ARROW + { write_exp_elt_opcode (OP_ARRAY); + write_exp_elt_longcst ((LONGEST) 0); + write_exp_elt_longcst ((LONGEST) $3); + write_exp_elt_opcode (OP_ARRAY); } + ; + +exp : lcurly type rcurly exp %prec UNARY + { write_exp_elt_opcode (UNOP_MEMVAL); + write_exp_elt_type ($2); + write_exp_elt_opcode (UNOP_MEMVAL); } + ; + +exp : '(' type ')' exp %prec UNARY + { write_exp_elt_opcode (UNOP_CAST); + write_exp_elt_type ($2); + write_exp_elt_opcode (UNOP_CAST); } + ; + +exp : '(' exp1 ')' + { } + ; + +/* Binary operators in order of decreasing precedence. */ + +exp : exp '@' exp + { write_exp_elt_opcode (BINOP_REPEAT); } + ; + +exp : exp '*' exp + { write_exp_elt_opcode (BINOP_MUL); } + ; + +exp : exp '/' exp + { write_exp_elt_opcode (BINOP_DIV); } + ; + +exp : exp '%' exp + { write_exp_elt_opcode (BINOP_REM); } + ; + +exp : exp '+' exp + { write_exp_elt_opcode (BINOP_ADD); } + ; + +exp : exp '-' exp + { write_exp_elt_opcode (BINOP_SUB); } + ; + +exp : exp LSH exp + { write_exp_elt_opcode (BINOP_LSH); } + ; + +exp : exp RSH exp + { write_exp_elt_opcode (BINOP_RSH); } + ; + +exp : exp EQUAL exp + { write_exp_elt_opcode (BINOP_EQUAL); } + ; + +exp : exp NOTEQUAL exp + { write_exp_elt_opcode (BINOP_NOTEQUAL); } + ; + +exp : exp LEQ exp + { write_exp_elt_opcode (BINOP_LEQ); } + ; + +exp : exp GEQ exp + { write_exp_elt_opcode (BINOP_GEQ); } + ; + +exp : exp '<' exp + { write_exp_elt_opcode (BINOP_LESS); } + ; + +exp : exp '>' exp + { write_exp_elt_opcode (BINOP_GTR); } + ; + +exp : exp '&' exp + { write_exp_elt_opcode (BINOP_BITWISE_AND); } + ; + +exp : exp '^' exp + { write_exp_elt_opcode (BINOP_BITWISE_XOR); } + ; + +exp : exp '|' exp + { write_exp_elt_opcode (BINOP_BITWISE_IOR); } + ; + +exp : exp ANDAND exp + { write_exp_elt_opcode (BINOP_LOGICAL_AND); } + ; + +exp : exp OROR exp + { write_exp_elt_opcode (BINOP_LOGICAL_OR); } + ; + +exp : exp '?' exp ':' exp %prec '?' + { write_exp_elt_opcode (TERNOP_COND); } + ; + +exp : exp '=' exp + { write_exp_elt_opcode (BINOP_ASSIGN); } + ; + +exp : exp ASSIGN_MODIFY exp + { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); + write_exp_elt_opcode ($2); + write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); } + ; + +exp : INT + { write_exp_elt_opcode (OP_LONG); + write_exp_elt_type ($1.type); + write_exp_elt_longcst ((LONGEST)($1.val)); + write_exp_elt_opcode (OP_LONG); } + ; + +exp : NAME_OR_INT + { YYSTYPE val; + parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val); + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (val.typed_val_int.type); + write_exp_elt_longcst ((LONGEST)val.typed_val_int.val); + write_exp_elt_opcode (OP_LONG); + } + ; + + +exp : FLOAT + { write_exp_elt_opcode (OP_DOUBLE); + write_exp_elt_type ($1.type); + write_exp_elt_dblcst ($1.dval); + write_exp_elt_opcode (OP_DOUBLE); } + ; + +exp : variable + ; + +exp : VARIABLE + /* Already written by write_dollar_variable. */ + ; + +exp : SELECTOR + { + write_exp_elt_opcode (OP_SELECTOR); + write_exp_string ($1); + write_exp_elt_opcode (OP_SELECTOR); } + +exp : SIZEOF '(' type ')' %prec UNARY + { write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_int); + CHECK_TYPEDEF ($3); + write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3)); + write_exp_elt_opcode (OP_LONG); } + ; + +exp : STRING + { /* C strings are converted into array + constants with an explicit null byte + added at the end. Thus the array upper + bound is the string length. There is no + such thing in C as a completely empty + string. */ + char *sp = $1.ptr; int count = $1.length; + while (count-- > 0) + { + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_char); + write_exp_elt_longcst ((LONGEST)(*sp++)); + write_exp_elt_opcode (OP_LONG); + } + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type_char); + write_exp_elt_longcst ((LONGEST)'\0'); + write_exp_elt_opcode (OP_LONG); + write_exp_elt_opcode (OP_ARRAY); + write_exp_elt_longcst ((LONGEST) 0); + write_exp_elt_longcst ((LONGEST) ($1.length)); + write_exp_elt_opcode (OP_ARRAY); } + ; + +exp : NSSTRING /* ObjC NextStep NSString constant + * of the form '@' '"' string '"'. + */ + { write_exp_elt_opcode (OP_NSSTRING); + write_exp_string ($1); + write_exp_elt_opcode (OP_NSSTRING); } + ; + +/* C++. */ +exp : THIS + { write_exp_elt_opcode (OP_THIS); + write_exp_elt_opcode (OP_THIS); } + ; + +/* end of C++. */ + +block : BLOCKNAME + { + if ($1.sym != 0) + $$ = SYMBOL_BLOCK_VALUE ($1.sym); + else + { + struct symtab *tem = + lookup_symtab (copy_name ($1.stoken)); + if (tem) + $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), STATIC_BLOCK); + else + error ("No file or function \"%s\".", + copy_name ($1.stoken)); + } + } + ; + +block : block COLONCOLON name + { struct symbol *tem + = lookup_symbol (copy_name ($3), $1, + VAR_NAMESPACE, (int *) NULL, + (struct symtab **) NULL); + if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) + error ("No function \"%s\" in specified context.", + copy_name ($3)); + $$ = SYMBOL_BLOCK_VALUE (tem); } + ; + +variable: block COLONCOLON name + { struct symbol *sym; + sym = lookup_symbol (copy_name ($3), $1, + VAR_NAMESPACE, (int *) NULL, + (struct symtab **) NULL); + if (sym == 0) + error ("No symbol \"%s\" in specified context.", + copy_name ($3)); + + write_exp_elt_opcode (OP_VAR_VALUE); + /* block_found is set by lookup_symbol. */ + write_exp_elt_block (block_found); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_VALUE); } + ; + +qualified_name: typebase COLONCOLON name + { + struct type *type = $1; + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + error ("`%s' is not defined as an aggregate type.", + TYPE_NAME (type)); + + write_exp_elt_opcode (OP_SCOPE); + write_exp_elt_type (type); + write_exp_string ($3); + write_exp_elt_opcode (OP_SCOPE); + } + | typebase COLONCOLON '~' name + { + struct type *type = $1; + struct stoken tmp_token; + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + error ("`%s' is not defined as an aggregate type.", + TYPE_NAME (type)); + + if (!STREQ (type_name_no_tag (type), $4.ptr)) + error ("invalid destructor `%s::~%s'", + type_name_no_tag (type), $4.ptr); + + tmp_token.ptr = (char*) alloca ($4.length + 2); + tmp_token.length = $4.length + 1; + tmp_token.ptr[0] = '~'; + memcpy (tmp_token.ptr+1, $4.ptr, $4.length); + tmp_token.ptr[tmp_token.length] = 0; + write_exp_elt_opcode (OP_SCOPE); + write_exp_elt_type (type); + write_exp_string (tmp_token); + write_exp_elt_opcode (OP_SCOPE); + } + ; + +variable: qualified_name + | COLONCOLON name + { + char *name = copy_name ($2); + struct symbol *sym; + struct minimal_symbol *msymbol; + + sym = + lookup_symbol (name, (const struct block *) NULL, + VAR_NAMESPACE, (int *) NULL, + (struct symtab **) NULL); + if (sym) + { + write_exp_elt_opcode (OP_VAR_VALUE); + write_exp_elt_block (NULL); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_VALUE); + break; + } + + msymbol = lookup_minimal_symbol (name, NULL, NULL); + if (msymbol != NULL) + { + write_exp_msymbol (msymbol, + lookup_function_type (builtin_type_int), + builtin_type_int); + } + else + if (!have_full_symbols () && !have_partial_symbols ()) + error ("No symbol table is loaded. Use the \"file\" command."); + else + error ("No symbol \"%s\" in current context.", name); + } + ; + +variable: name_not_typename + { struct symbol *sym = $1.sym; + + if (sym) + { + if (symbol_read_needs_frame (sym)) + { + if (innermost_block == 0 || + contained_in (block_found, + innermost_block)) + innermost_block = block_found; + } + + write_exp_elt_opcode (OP_VAR_VALUE); + /* We want to use the selected frame, not + another more inner frame which happens to + be in the same block. */ + write_exp_elt_block (NULL); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_VALUE); + } + else if ($1.is_a_field_of_this) + { + /* C++/ObjC: it hangs off of `this'/'self'. + Must not inadvertently convert from a + method call to data ref. */ + if (innermost_block == 0 || + contained_in (block_found, innermost_block)) + innermost_block = block_found; + write_exp_elt_opcode (OP_SELF); + write_exp_elt_opcode (OP_SELF); + write_exp_elt_opcode (STRUCTOP_PTR); + write_exp_string ($1.stoken); + write_exp_elt_opcode (STRUCTOP_PTR); + } + else + { + struct minimal_symbol *msymbol; + register char *arg = copy_name ($1.stoken); + + msymbol = + lookup_minimal_symbol (arg, NULL, NULL); + if (msymbol != NULL) + { + write_exp_msymbol (msymbol, + lookup_function_type (builtin_type_int), + builtin_type_int); + } + else if (!have_full_symbols () && + !have_partial_symbols ()) + error ("No symbol table is loaded. Use the \"file\" command."); + else + error ("No symbol \"%s\" in current context.", + copy_name ($1.stoken)); + } + } + ; + + +ptype : typebase + /* "const" and "volatile" are curently ignored. A type + qualifier before the type is currently handled in the + typebase rule. The reason for recognizing these here + (shift/reduce conflicts) might be obsolete now that some + pointer to member rules have been deleted. */ + | typebase CONST_KEYWORD + | typebase VOLATILE_KEYWORD + | typebase abs_decl + { $$ = follow_types ($1); } + | typebase CONST_KEYWORD abs_decl + { $$ = follow_types ($1); } + | typebase VOLATILE_KEYWORD abs_decl + { $$ = follow_types ($1); } + ; + +abs_decl: '*' + { push_type (tp_pointer); $$ = 0; } + | '*' abs_decl + { push_type (tp_pointer); $$ = $2; } + | '&' + { push_type (tp_reference); $$ = 0; } + | '&' abs_decl + { push_type (tp_reference); $$ = $2; } + | direct_abs_decl + ; + +direct_abs_decl: '(' abs_decl ')' + { $$ = $2; } + | direct_abs_decl array_mod + { + push_type_int ($2); + push_type (tp_array); + } + | array_mod + { + push_type_int ($1); + push_type (tp_array); + $$ = 0; + } + + | direct_abs_decl func_mod + { push_type (tp_function); } + | func_mod + { push_type (tp_function); } + ; + +array_mod: '[' ']' + { $$ = -1; } + | '[' INT ']' + { $$ = $2.val; } + ; + +func_mod: '(' ')' + { $$ = 0; } + | '(' nonempty_typelist ')' + { free ((PTR)$2); $$ = 0; } + ; + +/* We used to try to recognize more pointer to member types here, but + that didn't work (shift/reduce conflicts meant that these rules + never got executed). The problem is that + int (foo::bar::baz::bizzle) + is a function type but + int (foo::bar::baz::bizzle::*) + is a pointer to member type. Stroustrup loses again! */ + +type : ptype + | typebase COLONCOLON '*' + { $$ = lookup_member_type (builtin_type_int, $1); } + ; + +typebase /* Implements (approximately): (type-qualifier)* type-specifier. */ + : TYPENAME + { $$ = $1.type; } + | CLASSNAME + { + if ($1.type == NULL) + error ("No symbol \"%s\" in current context.", + copy_name($1.stoken)); + else + $$ = $1.type; + } + | INT_KEYWORD + { $$ = builtin_type_int; } + | LONG + { $$ = builtin_type_long; } + | SHORT + { $$ = builtin_type_short; } + | LONG INT_KEYWORD + { $$ = builtin_type_long; } + | UNSIGNED LONG INT_KEYWORD + { $$ = builtin_type_unsigned_long; } + | LONG LONG + { $$ = builtin_type_long_long; } + | LONG LONG INT_KEYWORD + { $$ = builtin_type_long_long; } + | UNSIGNED LONG LONG + { $$ = builtin_type_unsigned_long_long; } + | UNSIGNED LONG LONG INT_KEYWORD + { $$ = builtin_type_unsigned_long_long; } + | SHORT INT_KEYWORD + { $$ = builtin_type_short; } + | UNSIGNED SHORT INT_KEYWORD + { $$ = builtin_type_unsigned_short; } + | DOUBLE_KEYWORD + { $$ = builtin_type_double; } + | LONG DOUBLE_KEYWORD + { $$ = builtin_type_long_double; } + | STRUCT name + { $$ = lookup_struct (copy_name ($2), + expression_context_block); } + | CLASS name + { $$ = lookup_struct (copy_name ($2), + expression_context_block); } + | UNION name + { $$ = lookup_union (copy_name ($2), + expression_context_block); } + | ENUM name + { $$ = lookup_enum (copy_name ($2), + expression_context_block); } + | UNSIGNED typename + { $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); } + | UNSIGNED + { $$ = builtin_type_unsigned_int; } + | SIGNED_KEYWORD typename + { $$ = lookup_signed_typename (TYPE_NAME($2.type)); } + | SIGNED_KEYWORD + { $$ = builtin_type_int; } + | TEMPLATE name '<' type '>' + { $$ = lookup_template_type(copy_name($2), $4, + expression_context_block); + } + /* "const" and "volatile" are curently ignored. A type + qualifier after the type is handled in the ptype rule. I + think these could be too. */ + | CONST_KEYWORD typebase { $$ = $2; } + | VOLATILE_KEYWORD typebase { $$ = $2; } + ; + +typename: TYPENAME + | INT_KEYWORD + { + $$.stoken.ptr = "int"; + $$.stoken.length = 3; + $$.type = builtin_type_int; + } + | LONG + { + $$.stoken.ptr = "long"; + $$.stoken.length = 4; + $$.type = builtin_type_long; + } + | SHORT + { + $$.stoken.ptr = "short"; + $$.stoken.length = 5; + $$.type = builtin_type_short; + } + ; + +nonempty_typelist + : type + { $$ = (struct type **) malloc (sizeof (struct type *) * 2); + $$[0] = 1; /* Number of types in vector. */ + $$[1] = $1; + } + | nonempty_typelist ',' type + { int len = sizeof (struct type *) * (++($1[0]) + 1); + $$ = (struct type **) realloc ((char *) $1, len); + $$[$$[0]] = $3; + } + ; + +name : NAME { $$ = $1.stoken; } + | BLOCKNAME { $$ = $1.stoken; } + | TYPENAME { $$ = $1.stoken; } + | CLASSNAME { $$ = $1.stoken; } + | NAME_OR_INT { $$ = $1.stoken; } + ; + +name_not_typename : NAME + | BLOCKNAME +/* These would be useful if name_not_typename was useful, but it is + just a fake for "variable", so these cause reduce/reduce conflicts + because the parser can't tell whether NAME_OR_INT is a + name_not_typename (=variable, =exp) or just an exp. If + name_not_typename was ever used in an lvalue context where only a + name could occur, this might be useful. */ + | NAME_OR_INT */ + ; + +%% + +/* Take care of parsing a number (anything that starts with a digit). + Set yylval and return the token type; update lexptr. LEN is the + number of characters in it. */ + +/*** Needs some error checking for the float case. ***/ + +static int +parse_number (p, len, parsed_float, putithere) + register char *p; + register int len; + int parsed_float; + YYSTYPE *putithere; +{ + /* FIXME: Shouldn't these be unsigned? We don't deal with negative + values here, and we do kind of silly things like cast to + unsigned. */ + register LONGEST n = 0; + register LONGEST prevn = 0; + unsigned LONGEST un; + + register int i = 0; + register int c; + register int base = input_radix; + int unsigned_p = 0; + + /* Number of "L" suffixes encountered. */ + int long_p = 0; + + /* We have found a "L" or "U" suffix. */ + int found_suffix = 0; + + unsigned LONGEST high_bit; + struct type *signed_type; + struct type *unsigned_type; + + if (parsed_float) + { + char c; + + /* It's a float since it contains a point or an exponent. */ + + if (sizeof (putithere->typed_val_float.dval) <= sizeof (float)) + sscanf (p, "%g", &putithere->typed_val_float.dval); + else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double)) + sscanf (p, "%lg", &putithere->typed_val_float.dval); + else + { +#ifdef PRINTF_HAS_LONG_DOUBLE + sscanf (p, "%Lg", &putithere->typed_val_float.dval); +#else + /* Scan it into a double, then assign it to the long double. + This at least wins with values representable in the range + of doubles. */ + double temp; + sscanf (p, "%lg", &temp); + putithere->typed_val_float.dval = temp; +#endif + } + + /* See if it has `f' or `l' suffix (float or long double). */ + + c = tolower (p[len - 1]); + + if (c == 'f') + putithere->typed_val_float.type = builtin_type_float; + else if (c == 'l') + putithere->typed_val_float.type = builtin_type_long_double; + else if (isdigit (c) || c == '.') + putithere->typed_val_float.type = builtin_type_double; + else + return ERROR; + + return FLOAT; + } + + /* Handle base-switching prefixes 0x, 0t, 0d, and 0. */ + if (p[0] == '0') + switch (p[1]) + { + case 'x': + case 'X': + if (len >= 3) + { + p += 2; + base = 16; + len -= 2; + } + break; + + case 't': + case 'T': + case 'd': + case 'D': + if (len >= 3) + { + p += 2; + base = 10; + len -= 2; + } + break; + + default: + base = 8; + break; + } + + while (len-- > 0) + { + c = *p++; + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + if (c != 'l' && c != 'u') + n *= base; + if (c >= '0' && c <= '9') + { + if (found_suffix) + return ERROR; + n += i = c - '0'; + } + else + { + if (base > 10 && c >= 'a' && c <= 'f') + { + if (found_suffix) + return ERROR; + n += i = c - 'a' + 10; + } + else if (c == 'l') + { + ++long_p; + found_suffix = 1; + } + else if (c == 'u') + { + unsigned_p = 1; + found_suffix = 1; + } + else + return ERROR; /* Char not a digit. */ + } + if (i >= base) + return ERROR; /* Invalid digit in this base. */ + + /* Portably test for overflow (only works for nonzero values, so + make a second check for zero). FIXME: Can't we just make n + and prevn unsigned and avoid this? */ + if (c != 'l' && c != 'u' && (prevn >= n) && n != 0) + unsigned_p = 1; /* Try something unsigned. */ + + /* Portably test for unsigned overflow. + FIXME: This check is wrong; for example it doesn't find + overflow on 0x123456789 when LONGEST is 32 bits. */ + if (c != 'l' && c != 'u' && n != 0) + { + if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n)) + error ("Numeric constant too large."); + } + prevn = n; + } + + /* An integer constant is an int, a long, or a long long. An L + suffix forces it to be long; an LL suffix forces it to be long + long. If not forced to a larger size, it gets the first type of + the above that it fits in. To figure out whether it fits, we + shift it right and see whether anything remains. Note that we + can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one + operation, because many compilers will warn about such a shift + (which always produces a zero result). Sometimes TARGET_INT_BIT + or TARGET_LONG_BIT will be that big, sometimes not. To deal with + the case where it is we just always shift the value more than + once, with fewer bits each time. */ + + un = (unsigned LONGEST)n >> 2; + if (long_p == 0 + && (un >> (TARGET_INT_BIT - 2)) == 0) + { + high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1); + + /* A large decimal (not hex or octal) constant (between INT_MAX + and UINT_MAX) is a long or unsigned long, according to ANSI, + never an unsigned int, but this code treats it as unsigned + int. This probably should be fixed. GCC gives a warning on + such constants. */ + + unsigned_type = builtin_type_unsigned_int; + signed_type = builtin_type_int; + } + else if (long_p <= 1 + && (un >> (TARGET_LONG_BIT - 2)) == 0) + { + high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1); + unsigned_type = builtin_type_unsigned_long; + signed_type = builtin_type_long; + } + else + { + high_bit = (((unsigned LONGEST)1) + << (TARGET_LONG_LONG_BIT - 32 - 1) + << 16 + << 16); + if (high_bit == 0) + /* A long long does not fit in a LONGEST. */ + high_bit = + (unsigned LONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1); + unsigned_type = builtin_type_unsigned_long_long; + signed_type = builtin_type_long_long; + } + + putithere->typed_val_int.val = n; + + /* If the high bit of the worked out type is set then this number + has to be unsigned. */ + + if (unsigned_p || (n & high_bit)) + { + putithere->typed_val_int.type = unsigned_type; + } + else + { + putithere->typed_val_int.type = signed_type; + } + + return INT; +} + +struct token +{ + char *operator; + int token; + enum exp_opcode opcode; +}; + +static const struct token tokentab3[] = + { + {">>=", ASSIGN_MODIFY, BINOP_RSH}, + {"<<=", ASSIGN_MODIFY, BINOP_LSH} + }; + +static const struct token tokentab2[] = + { + {"+=", ASSIGN_MODIFY, BINOP_ADD}, + {"-=", ASSIGN_MODIFY, BINOP_SUB}, + {"*=", ASSIGN_MODIFY, BINOP_MUL}, + {"/=", ASSIGN_MODIFY, BINOP_DIV}, + {"%=", ASSIGN_MODIFY, BINOP_REM}, + {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR}, + {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND}, + {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR}, + {"++", INCREMENT, BINOP_END}, + {"--", DECREMENT, BINOP_END}, + {"->", ARROW, BINOP_END}, + {"&&", ANDAND, BINOP_END}, + {"||", OROR, BINOP_END}, + {"::", COLONCOLON, BINOP_END}, + {"<<", LSH, BINOP_END}, + {">>", RSH, BINOP_END}, + {"==", EQUAL, BINOP_END}, + {"!=", NOTEQUAL, BINOP_END}, + {"<=", LEQ, BINOP_END}, + {">=", GEQ, BINOP_END} + }; + +/* Read one token, getting characters through lexptr. */ + +static int +yylex () +{ + int c, tokchr; + int namelen; + unsigned int i; + char *tokstart; + char *tokptr; + int tempbufindex; + static char *tempbuf; + static int tempbufsize; + + retry: + + tokstart = lexptr; + /* See if it is a special token of length 3. */ + for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++) + if (STREQN (tokstart, tokentab3[i].operator, 3)) + { + lexptr += 3; + yylval.opcode = tokentab3[i].opcode; + return tokentab3[i].token; + } + + /* See if it is a special token of length 2. */ + for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++) + if (STREQN (tokstart, tokentab2[i].operator, 2)) + { + lexptr += 2; + yylval.opcode = tokentab2[i].opcode; + return tokentab2[i].token; + } + + switch (tokchr = *tokstart) + { + case 0: + return 0; + + case ' ': + case '\t': + case '\n': + lexptr++; + goto retry; + + case '\'': + /* We either have a character constant ('0' or '\177' for + example) or we have a quoted symbol reference ('foo(int,int)' + in C++ for example). */ + lexptr++; + c = *lexptr++; + if (c == '\\') + c = parse_escape (&lexptr); + else if (c == '\'') + error ("Empty character constant."); + + yylval.typed_val_int.val = c; + yylval.typed_val_int.type = builtin_type_char; + + c = *lexptr++; + if (c != '\'') + { + namelen = skip_quoted (tokstart, + get_gdb_completer_word_break_characters()) + - tokstart; + if (namelen > 2) + { + lexptr = tokstart + namelen; + if (lexptr[-1] != '\'') + error ("Unmatched single quote."); + namelen -= 2; + tokstart++; + goto tryname; + } + error ("Invalid character constant."); + } + return INT; + + case '(': + paren_depth++; + lexptr++; + return '('; + + case ')': + if (paren_depth == 0) + return 0; + paren_depth--; + lexptr++; + return ')'; + + case ',': + if (comma_terminates && paren_depth == 0) + return 0; + lexptr++; + return ','; + + case '.': + /* Might be a floating point number. */ + if (lexptr[1] < '0' || lexptr[1] > '9') + goto symbol; /* Nope, must be a symbol. */ + /* FALL THRU into number case. */ + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + /* It's a number. */ + int got_dot = 0, got_e = 0, toktype = FLOAT; + /* Initialize toktype to anything other than ERROR. */ + register char *p = tokstart; + int hex = input_radix > 10; + int local_radix = input_radix; + if (tokchr == '0' && (p[1] == 'x' || p[1] == 'X')) + { + p += 2; + hex = 1; + local_radix = 16; + } + else if (tokchr == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D')) + { + p += 2; + hex = 0; + local_radix = 10; + } + + for (;; ++p) + { + /* This test includes !hex because 'e' is a valid hex digit + and thus does not indicate a floating point number when + the radix is hex. */ + + if (!hex && (*p == 'e' || *p == 'E')) + if (got_e) + toktype = ERROR; /* Only one 'e' in a float. */ + else + got_e = 1; + /* This test does not include !hex, because a '.' always + indicates a decimal floating point number regardless of + the radix. */ + else if (*p == '.') + if (got_dot) + toktype = ERROR; /* Only one '.' in a float. */ + else + got_dot = 1; + else if (got_e && (p[-1] == 'e' || p[-1] == 'E') && + (*p == '-' || *p == '+')) + /* This is the sign of the exponent, not the end of the + number. */ + continue; + /* Always take decimal digits; parse_number handles radix + error. */ + else if (*p >= '0' && *p <= '9') + continue; + /* We will take letters only if hex is true, and only up + to what the input radix would permit. FSF was content + to rely on parse_number to validate; but it leaks. */ + else if (*p >= 'a' && *p <= 'z') + { + if (!hex || *p >= ('a' + local_radix - 10)) + toktype = ERROR; + } + else if (*p >= 'A' && *p <= 'Z') + { + if (!hex || *p >= ('A' + local_radix - 10)) + toktype = ERROR; + } + else break; + } + if (toktype != ERROR) + toktype = parse_number (tokstart, p - tokstart, + got_dot | got_e, &yylval); + if (toktype == ERROR) + { + char *err_copy = (char *) alloca (p - tokstart + 1); + + memcpy (err_copy, tokstart, p - tokstart); + err_copy[p - tokstart] = 0; + error ("Invalid number \"%s\".", err_copy); + } + lexptr = p; + return toktype; + } + + case '+': + case '-': + case '*': + case '/': + case '%': + case '|': + case '&': + case '^': + case '~': + case '!': +#if 0 + case '@': /* Moved out below. */ +#endif + case '<': + case '>': + case '[': + case ']': + case '?': + case ':': + case '=': + case '{': + case '}': + symbol: + lexptr++; + return tokchr; + + case '@': + if (strncmp(tokstart, "@selector", 9) == 0) + { + tokptr = strchr(tokstart, '('); + if (tokptr == NULL) + { + error ("Missing '(' in @selector(...)"); + } + tempbufindex = 0; + tokptr++; /* Skip the '('. */ + do { + /* Grow the static temp buffer if necessary, including + allocating the first one on demand. */ + if (tempbufindex + 1 >= tempbufsize) + { + tempbuf = (char *) realloc (tempbuf, tempbufsize += 64); + } + tempbuf[tempbufindex++] = *tokptr++; + } while ((*tokptr != ')') && (*tokptr != '\0')); + if (*tokptr++ != ')') + { + error ("Missing ')' in @selector(...)"); + } + tempbuf[tempbufindex] = '\0'; + yylval.sval.ptr = tempbuf; + yylval.sval.length = tempbufindex; + lexptr = tokptr; + return SELECTOR; + } + if (tokstart[1] != '"') + { + lexptr++; + return tokchr; + } + /* ObjC NextStep NSString constant: fall thru and parse like + STRING. */ + tokstart++; + + case '"': + + /* Build the gdb internal form of the input string in tempbuf, + translating any standard C escape forms seen. Note that the + buffer is null byte terminated *only* for the convenience of + debugging gdb itself and printing the buffer contents when + the buffer contains no embedded nulls. Gdb does not depend + upon the buffer being null byte terminated, it uses the + length string instead. This allows gdb to handle C strings + (as well as strings in other languages) with embedded null + bytes. */ + + tokptr = ++tokstart; + tempbufindex = 0; + + do { + /* Grow the static temp buffer if necessary, including + allocating the first one on demand. */ + if (tempbufindex + 1 >= tempbufsize) + { + tempbuf = (char *) realloc (tempbuf, tempbufsize += 64); + } + switch (*tokptr) + { + case '\0': + case '"': + /* Do nothing, loop will terminate. */ + break; + case '\\': + tokptr++; + c = parse_escape (&tokptr); + if (c == -1) + { + continue; + } + tempbuf[tempbufindex++] = c; + break; + default: + tempbuf[tempbufindex++] = *tokptr++; + break; + } + } while ((*tokptr != '"') && (*tokptr != '\0')); + if (*tokptr++ != '"') + { + error ("Unterminated string in expression."); + } + tempbuf[tempbufindex] = '\0'; /* See note above. */ + yylval.sval.ptr = tempbuf; + yylval.sval.length = tempbufindex; + lexptr = tokptr; + return (tokchr == '@' ? NSSTRING : STRING); + } + + if (!(tokchr == '_' || tokchr == '$' || + (tokchr >= 'a' && tokchr <= 'z') || (tokchr >= 'A' && tokchr <= 'Z'))) + /* We must have come across a bad character (e.g. ';'). */ + error ("Invalid character '%c' in expression.", c); + + /* It's a name. See how long it is. */ + namelen = 0; + for (c = tokstart[namelen]; + (c == '_' || c == '$' || (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');) + { + if (c == '<') + { + int i = namelen; + while (tokstart[++i] && tokstart[i] != '>'); + if (tokstart[i] == '>') + namelen = i; + } + c = tokstart[++namelen]; + } + + /* The token "if" terminates the expression and is NOT + removed from the input stream. */ + if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f') + { + return 0; + } + + lexptr += namelen; + + tryname: + + /* Catch specific keywords. Should be done with a data structure. */ + switch (namelen) + { + case 8: + if (STREQN (tokstart, "unsigned", 8)) + return UNSIGNED; + if (current_language->la_language == language_cplus + && STREQN (tokstart, "template", 8)) + return TEMPLATE; + if (STREQN (tokstart, "volatile", 8)) + return VOLATILE_KEYWORD; + break; + case 6: + if (STREQN (tokstart, "struct", 6)) + return STRUCT; + if (STREQN (tokstart, "signed", 6)) + return SIGNED_KEYWORD; + if (STREQN (tokstart, "sizeof", 6)) + return SIZEOF; + if (STREQN (tokstart, "double", 6)) + return DOUBLE_KEYWORD; + break; + case 5: + if ((current_language->la_language == language_cplus) + && STREQN (tokstart, "class", 5)) + return CLASS; + if (STREQN (tokstart, "union", 5)) + return UNION; + if (STREQN (tokstart, "short", 5)) + return SHORT; + if (STREQN (tokstart, "const", 5)) + return CONST_KEYWORD; + break; + case 4: + if (STREQN (tokstart, "enum", 4)) + return ENUM; + if (STREQN (tokstart, "long", 4)) + return LONG; + if (current_language->la_language == language_cplus + && STREQN (tokstart, "this", 4)) + { + static const char this_name[] = { + CPLUS_MARKER, 't', 'h', 'i', 's', '\0' + }; + + if (lookup_symbol (this_name, expression_context_block, + VAR_NAMESPACE, (int *) NULL, + (struct symtab **) NULL)) + return THIS; + } + break; + case 3: + if (STREQN (tokstart, "int", 3)) + return INT_KEYWORD; + break; + default: + break; + } + + yylval.sval.ptr = tokstart; + yylval.sval.length = namelen; + + if (*tokstart == '$') + { + write_dollar_variable (yylval.sval); + return VARIABLE; + } + + /* Use token-type BLOCKNAME for symbols that happen to be defined as + functions or symtabs. If this is not so, then ... + Use token-type TYPENAME for symbols that happen to be defined + currently as names of types; NAME for other symbols. + The caller is not constrained to care about the distinction. */ + { + char *tmp = copy_name (yylval.sval); + struct symbol *sym; + int is_a_field_of_this = 0, *need_this; + int hextype; + + if (current_language->la_language == language_cplus || + current_language->la_language == language_objc) + need_this = &is_a_field_of_this; + else + need_this = (int *) NULL; + + sym = lookup_symbol (tmp, expression_context_block, + VAR_NAMESPACE, + need_this, + (struct symtab **) NULL); + /* Call lookup_symtab, not lookup_partial_symtab, in case there + are no psymtabs (coff, xcoff, or some future change to blow + away the psymtabs once symbols are read). */ + if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) || + lookup_symtab (tmp)) + { + yylval.ssym.sym = sym; + yylval.ssym.is_a_field_of_this = is_a_field_of_this; + return BLOCKNAME; + } + if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF) + { +#if 1 + /* Despite the following flaw, we need to keep this code + enabled. Because we can get called from + check_stub_method, if we don't handle nested types then + it screws many operations in any program which uses + nested types. */ + /* In "A::x", if x is a member function of A and there + happens to be a type (nested or not, since the stabs + don't make that distinction) named x, then this code + incorrectly thinks we are dealing with nested types + rather than a member function. */ + + char *p; + char *namestart; + struct symbol *best_sym; + + /* Look ahead to detect nested types. This probably should + be done in the grammar, but trying seemed to introduce a + lot of shift/reduce and reduce/reduce conflicts. It's + possible that it could be done, though. Or perhaps a + non-grammar, but less ad hoc, approach would work well. */ + + /* Since we do not currently have any way of distinguishing + a nested type from a non-nested one (the stabs don't tell + us whether a type is nested), we just ignore the + containing type. */ + + p = lexptr; + best_sym = sym; + while (1) + { + /* Skip whitespace. */ + while (*p == ' ' || *p == '\t' || *p == '\n') + ++p; + if (*p == ':' && p[1] == ':') + { + /* Skip the `::'. */ + p += 2; + /* Skip whitespace. */ + while (*p == ' ' || *p == '\t' || *p == '\n') + ++p; + namestart = p; + while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9') + || (*p >= 'a' && *p <= 'z') + || (*p >= 'A' && *p <= 'Z')) + ++p; + if (p != namestart) + { + struct symbol *cur_sym; + /* As big as the whole rest of the expression, + which is at least big enough. */ + char *ncopy = alloca (strlen (tmp) + + strlen (namestart) + 3); + char *tmp1; + + tmp1 = ncopy; + memcpy (tmp1, tmp, strlen (tmp)); + tmp1 += strlen (tmp); + memcpy (tmp1, "::", 2); + tmp1 += 2; + memcpy (tmp1, namestart, p - namestart); + tmp1[p - namestart] = '\0'; + cur_sym = lookup_symbol (ncopy, + expression_context_block, + VAR_NAMESPACE, (int *) NULL, + (struct symtab **) NULL); + if (cur_sym) + { + if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF) + { + best_sym = cur_sym; + lexptr = p; + } + else + break; + } + else + break; + } + else + break; + } + else + break; + } + + yylval.tsym.type = SYMBOL_TYPE (best_sym); +#else /* not 0 */ + yylval.tsym.type = SYMBOL_TYPE (sym); +#endif /* not 0 */ + return TYPENAME; + } + if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0) + return TYPENAME; + + /* See if it's an ObjC classname. */ + if (!sym) + { + CORE_ADDR Class = lookup_objc_class(tmp); + if (Class) + { + extern struct symbol *lookup_struct_typedef(); + yylval.class.class = Class; + if ((sym = lookup_struct_typedef (tmp, + expression_context_block, + 1))) + yylval.class.type = SYMBOL_TYPE (sym); + return CLASSNAME; + } + } + + /* Input names that aren't symbols but ARE valid hex numbers, + when the input radix permits them, can be names or numbers + depending on the parse. Note we support radixes > 16 here. */ + if (!sym && + ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) || + (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10))) + { + YYSTYPE newlval; /* Its value is ignored. */ + hextype = parse_number (tokstart, namelen, 0, &newlval); + if (hextype == INT) + { + yylval.ssym.sym = sym; + yylval.ssym.is_a_field_of_this = is_a_field_of_this; + return NAME_OR_INT; + } + } + + /* Any other kind of symbol. */ + yylval.ssym.sym = sym; + yylval.ssym.is_a_field_of_this = is_a_field_of_this; + return NAME; + } +} + +void +yyerror (msg) + char *msg; +{ + if (*lexptr == '\0') + error("A %s near end of expression.", (msg ? msg : "error")); + else + error ("A %s in expression, near `%s'.", (msg ? msg : "error"), + lexptr); +} diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c new file mode 100644 index 00000000000..dc839518b24 --- /dev/null +++ b/gdb/objc-lang.c @@ -0,0 +1,1960 @@ +/* Objective-C language support routines for GDB, the GNU debugger. + + Copyright 2002 Free Software Foundation, Inc. + + Contributed by Apple Computer, Inc. + Written by Michael Snyder. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "parser-defs.h" +#include "language.h" +#include "c-lang.h" +#include "objc-lang.h" +#include "complaints.h" +#include "value.h" +#include "symfile.h" +#include "objfiles.h" +#include "string.h" /* for strchr */ +#include "target.h" /* for target_has_execution */ +#include "gdbcore.h" +#include "gdbcmd.h" +#include "frame.h" +#include "gdb_regex.h" +#include "regcache.h" + +#include + +struct objc_object { + CORE_ADDR isa; +}; + +struct objc_class { + CORE_ADDR isa; + CORE_ADDR super_class; + CORE_ADDR name; + long version; + long info; + long instance_size; + CORE_ADDR ivars; + CORE_ADDR methods; + CORE_ADDR cache; + CORE_ADDR protocols; +}; + +struct objc_super { + CORE_ADDR receiver; + CORE_ADDR class; +}; + +struct objc_method { + CORE_ADDR name; + CORE_ADDR types; + CORE_ADDR imp; +}; + +/* Complaints about ObjC classes, selectors, etc. */ + +static struct complaint noclass_lookup_complaint = { + "no way to lookup Objective-C classes", 0, 0 +}; + +static struct complaint nosel_lookup_complaint = { + "no way to lookup Objective-C selectors", 0, 0 +}; + + +#if (!defined __GNUC__ || __GNUC__ < 2 || __GNUC_MINOR__ < (defined __cplusplus ? 6 : 4)) +#define __CHECK_FUNCTION ((__const char *) 0) +#else +#define __CHECK_FUNCTION __PRETTY_FUNCTION__ +#endif + +#define CHECK(expression) \ + ((void) ((expression) ? 0 : gdb_check (#expression, __FILE__, __LINE__, \ + __CHECK_FUNCTION))) + +#define CHECK_FATAL(expression) \ + ((void) ((expression) ? 0 : gdb_check_fatal (#expression, __FILE__, \ + __LINE__, __CHECK_FUNCTION))) + +static void +gdb_check (const char *str, const char *file, + unsigned int line, const char *func) +{ + error ("assertion failure on line %u of \"%s\" in function \"%s\": %s\n", + line, file, func, str); +} + +static void +gdb_check_fatal (const char *str, const char *file, + unsigned int line, const char *func) +{ + internal_error (file, line, + "assertion failure in function \"%s\": %s\n", func, str); +} + +/* Lookup a structure type named "struct NAME", visible in lexical + block BLOCK. If NOERR is nonzero, return zero if NAME is not + suitably defined. */ + +struct symbol * +lookup_struct_typedef (char *name, struct block *block, int noerr) +{ + register struct symbol *sym; + + sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0, + (struct symtab **) NULL); + + if (sym == NULL) + { + if (noerr) + return 0; + else + error ("No struct type named %s.", name); + } + if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT) + { + if (noerr) + return 0; + else + error ("This context has class, union or enum %s, not a struct.", + name); + } + return sym; +} + +CORE_ADDR +lookup_objc_class (char *classname) +{ + struct value * function, *classval; + + if (! target_has_execution) + { + /* Can't call into inferior to lookup class. */ + return 0; + } + + if (lookup_minimal_symbol("objc_lookUpClass", 0, 0)) + function = find_function_in_inferior("objc_lookUpClass"); + else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0)) + function = find_function_in_inferior("objc_lookup_class"); + else + { + complain (&noclass_lookup_complaint, 0); + return 0; + } + + classval = value_string (classname, strlen (classname) + 1); + classval = value_coerce_array (classval); + return (CORE_ADDR) value_as_long (call_function_by_hand (function, + 1, &classval)); +} + +int +lookup_child_selector (char *selname) +{ + struct value * function, *selstring; + + if (! target_has_execution) + { + /* Can't call into inferior to lookup selector. */ + return 0; + } + + if (lookup_minimal_symbol("sel_getUid", 0, 0)) + function = find_function_in_inferior("sel_getUid"); + else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0)) + function = find_function_in_inferior("sel_get_any_uid"); + else + { + complain (&nosel_lookup_complaint, 0); + return 0; + } + + selstring = value_coerce_array (value_string (selname, + strlen (selname) + 1)); + return value_as_long (call_function_by_hand (function, 1, &selstring)); +} + +struct value * +value_nsstring (char *ptr, int len) +{ + struct value *stringValue[3]; + struct value *function, *nsstringValue; + struct symbol *sym; + struct type *type; + + if (!target_has_execution) + return 0; /* Can't call into inferior to create NSString. */ + + if (!(sym = lookup_struct_typedef("NSString", 0, 1)) && + !(sym = lookup_struct_typedef("NXString", 0, 1))) + type = lookup_pointer_type(builtin_type_void); + else + type = lookup_pointer_type(SYMBOL_TYPE (sym)); + + stringValue[2] = value_string(ptr, len); + stringValue[2] = value_coerce_array(stringValue[2]); + /* _NSNewStringFromCString replaces "istr" after Lantern2A. */ + if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0)) + { + function = find_function_in_inferior("_NSNewStringFromCString"); + nsstringValue = call_function_by_hand(function, 1, &stringValue[2]); + } + else if (lookup_minimal_symbol("istr", 0, 0)) + { + function = find_function_in_inferior("istr"); + nsstringValue = call_function_by_hand(function, 1, &stringValue[2]); + } + else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0)) + { + function = find_function_in_inferior("+[NSString stringWithCString:]"); + stringValue[0] = value_from_longest + (builtin_type_long, lookup_objc_class ("NSString")); + stringValue[1] = value_from_longest + (builtin_type_long, lookup_child_selector ("stringWithCString:")); + nsstringValue = call_function_by_hand(function, 3, &stringValue[0]); + } + else + error ("NSString: internal error -- no way to create new NSString"); + + VALUE_TYPE(nsstringValue) = type; + return nsstringValue; +} + +/* Objective-C name demangling. */ + +char * +objc_demangle (const char *mangled) +{ + char *demangled, *cp; + + if (mangled[0] == '_' && + (mangled[1] == 'i' || mangled[1] == 'c') && + mangled[2] == '_') + { + cp = demangled = xmalloc(strlen(mangled) + 2); + + if (mangled[1] == 'i') + *cp++ = '-'; /* for instance method */ + else + *cp++ = '+'; /* for class method */ + + *cp++ = '['; /* opening left brace */ + strcpy(cp, mangled+3); /* tack on the rest of the mangled name */ + + while (*cp && *cp == '_') + cp++; /* skip any initial underbars in class name */ + + if (!(cp = strchr(cp, '_'))) /* find first non-initial underbar */ + { + free(demangled); /* not mangled name */ + return NULL; + } + if (cp[1] == '_') { /* easy case: no category name */ + *cp++ = ' '; /* replace two '_' with one ' ' */ + strcpy(cp, mangled + (cp - demangled) + 2); + } + else { + *cp++ = '('; /* less easy case: category name */ + if (!(cp = strchr(cp, '_'))) + { + free(demangled); /* not mangled name */ + return NULL; + } + *cp++ = ')'; + *cp++ = ' '; /* overwriting 1st char of method name... */ + strcpy(cp, mangled + (cp - demangled)); /* get it back */ + } + + while (*cp && *cp == '_') + cp++; /* skip any initial underbars in method name */ + + for (; *cp; cp++) + if (*cp == '_') + *cp = ':'; /* replace remaining '_' with ':' */ + + *cp++ = ']'; /* closing right brace */ + *cp++ = 0; /* string terminator */ + return demangled; + } + else + return NULL; /* Not an objc mangled name. */ +} + +/* Print the character C on STREAM as part of the contents of a + literal string whose delimiter is QUOTER. Note that that format + for printing characters and strings is language specific. */ + +static void +objc_emit_char (register int c, struct ui_file *stream, int quoter) +{ + + c &= 0xFF; /* Avoid sign bit follies. */ + + if (PRINT_LITERAL_FORM (c)) + { + if (c == '\\' || c == quoter) + { + fputs_filtered ("\\", stream); + } + fprintf_filtered (stream, "%c", c); + } + else + { + switch (c) + { + case '\n': + fputs_filtered ("\\n", stream); + break; + case '\b': + fputs_filtered ("\\b", stream); + break; + case '\t': + fputs_filtered ("\\t", stream); + break; + case '\f': + fputs_filtered ("\\f", stream); + break; + case '\r': + fputs_filtered ("\\r", stream); + break; + case '\033': + fputs_filtered ("\\e", stream); + break; + case '\007': + fputs_filtered ("\\a", stream); + break; + default: + fprintf_filtered (stream, "\\%.3o", (unsigned int) c); + break; + } + } +} + +static void +objc_printchar (int c, struct ui_file *stream) +{ + fputs_filtered ("'", stream); + objc_emit_char (c, stream, '\''); + fputs_filtered ("'", stream); +} + +/* Print the character string STRING, printing at most LENGTH + characters. Printing stops early if the number hits print_max; + repeat counts are printed as appropriate. Print ellipses at the + end if we had to stop before printing LENGTH characters, or if + FORCE_ELLIPSES. */ + +static void +objc_printstr (struct ui_file *stream, char *string, + unsigned int length, int force_ellipses) +{ + register unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; + extern int inspect_it; + extern int repeat_count_threshold; + extern int print_max; + + /* If the string was not truncated due to `set print elements', and + the last byte of it is a null, we don't print that, in + traditional C style. */ + if ((!force_ellipses) && length > 0 && string[length-1] == '\0') + length--; + + if (length == 0) + { + fputs_filtered ("\"\"", stream); + return; + } + + for (i = 0; i < length && things_printed < print_max; ++i) + { + /* Position of the character we are examining to see whether it + is repeated. */ + unsigned int rep1; + /* Number of repetitions we have detected so far. */ + unsigned int reps; + + QUIT; + + if (need_comma) + { + fputs_filtered (", ", stream); + need_comma = 0; + } + + rep1 = i + 1; + reps = 1; + while (rep1 < length && string[rep1] == string[i]) + { + ++rep1; + ++reps; + } + + if (reps > repeat_count_threshold) + { + if (in_quotes) + { + if (inspect_it) + fputs_filtered ("\\\", ", stream); + else + fputs_filtered ("\", ", stream); + in_quotes = 0; + } + objc_printchar (string[i], stream); + fprintf_filtered (stream, " ", reps); + i = rep1 - 1; + things_printed += repeat_count_threshold; + need_comma = 1; + } + else + { + if (!in_quotes) + { + if (inspect_it) + fputs_filtered ("\\\"", stream); + else + fputs_filtered ("\"", stream); + in_quotes = 1; + } + objc_emit_char (string[i], stream, '"'); + ++things_printed; + } + } + + /* Terminate the quotes if necessary. */ + if (in_quotes) + { + if (inspect_it) + fputs_filtered ("\\\"", stream); + else + fputs_filtered ("\"", stream); + } + + if (force_ellipses || i < length) + fputs_filtered ("...", stream); +} + +/* Create a fundamental C type using default reasonable for the + current target. + + Some object/debugging file formats (DWARF version 1, COFF, etc) do + not define fundamental types such as "int" or "double". Others + (stabs or DWARF version 2, etc) do define fundamental types. For + the formats which don't provide fundamental types, gdb can create + such types using this function. + + FIXME: Some compilers distinguish explicitly signed integral types + (signed short, signed int, signed long) from "regular" integral + types (short, int, long) in the debugging information. There is + some disagreement as to how useful this feature is. In particular, + gcc does not support this. Also, only some debugging formats allow + the distinction to be passed on to a debugger. For now, we always + just use "short", "int", or "long" as the type name, for both the + implicit and explicitly signed types. This also makes life easier + for the gdb test suite since we don't have to account for the + differences in output depending upon what the compiler and + debugging format support. We will probably have to re-examine the + issue when gdb starts taking it's fundamental type information + directly from the debugging information supplied by the compiler. + fnf@cygnus.com */ + +static struct type * +objc_create_fundamental_type (struct objfile *objfile, int typeid) +{ + register struct type *type = NULL; + + switch (typeid) + { + default: + /* FIXME: For now, if we are asked to produce a type not in + this language, create the equivalent of a C integer type + with the name "". When all the dust settles from + the type reconstruction work, this should probably become + an error. */ + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "", objfile); + warning ("internal error: no C/C++ fundamental type %d", typeid); + break; + case FT_VOID: + type = init_type (TYPE_CODE_VOID, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "void", objfile); + break; + case FT_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "char", objfile); + break; + case FT_SIGNED_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, "signed char", objfile); + break; + case FT_UNSIGNED_CHAR: + type = init_type (TYPE_CODE_INT, + TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned char", objfile); + break; + case FT_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + 0, "short", objfile); + break; + case FT_SIGNED_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + 0, "short", objfile); /* FIXME-fnf */ + break; + case FT_UNSIGNED_SHORT: + type = init_type (TYPE_CODE_INT, + TARGET_SHORT_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned short", objfile); + break; + case FT_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "int", objfile); + break; + case FT_SIGNED_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + 0, "int", objfile); /* FIXME -fnf */ + break; + case FT_UNSIGNED_INTEGER: + type = init_type (TYPE_CODE_INT, + TARGET_INT_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned int", objfile); + break; + case FT_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + 0, "long", objfile); + break; + case FT_SIGNED_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + 0, "long", objfile); /* FIXME -fnf */ + break; + case FT_UNSIGNED_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long", objfile); + break; + case FT_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + 0, "long long", objfile); + break; + case FT_SIGNED_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + 0, "signed long long", objfile); + break; + case FT_UNSIGNED_LONG_LONG: + type = init_type (TYPE_CODE_INT, + TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long long", objfile); + break; + case FT_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_FLOAT_BIT / TARGET_CHAR_BIT, + 0, "float", objfile); + break; + case FT_DBL_PREC_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "double", objfile); + break; + case FT_EXT_PREC_FLOAT: + type = init_type (TYPE_CODE_FLT, + TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, + 0, "long double", objfile); + break; + } + return (type); +} + + +/* Table mapping opcodes into strings for printing operators + and precedences of the operators. */ + +static const struct op_print objc_op_print_tab[] = + { + {",", BINOP_COMMA, PREC_COMMA, 0}, + {"=", BINOP_ASSIGN, PREC_ASSIGN, 1}, + {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0}, + {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0}, + {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0}, + {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0}, + {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0}, + {"==", BINOP_EQUAL, PREC_EQUAL, 0}, + {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0}, + {"<=", BINOP_LEQ, PREC_ORDER, 0}, + {">=", BINOP_GEQ, PREC_ORDER, 0}, + {">", BINOP_GTR, PREC_ORDER, 0}, + {"<", BINOP_LESS, PREC_ORDER, 0}, + {">>", BINOP_RSH, PREC_SHIFT, 0}, + {"<<", BINOP_LSH, PREC_SHIFT, 0}, + {"+", BINOP_ADD, PREC_ADD, 0}, + {"-", BINOP_SUB, PREC_ADD, 0}, + {"*", BINOP_MUL, PREC_MUL, 0}, + {"/", BINOP_DIV, PREC_MUL, 0}, + {"%", BINOP_REM, PREC_MUL, 0}, + {"@", BINOP_REPEAT, PREC_REPEAT, 0}, + {"-", UNOP_NEG, PREC_PREFIX, 0}, + {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0}, + {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0}, + {"*", UNOP_IND, PREC_PREFIX, 0}, + {"&", UNOP_ADDR, PREC_PREFIX, 0}, + {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0}, + {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0}, + {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}, + {NULL, 0, 0, 0} +}; + +struct type ** const (objc_builtin_types[]) = +{ + &builtin_type_int, + &builtin_type_long, + &builtin_type_short, + &builtin_type_char, + &builtin_type_float, + &builtin_type_double, + &builtin_type_void, + &builtin_type_long_long, + &builtin_type_signed_char, + &builtin_type_unsigned_char, + &builtin_type_unsigned_short, + &builtin_type_unsigned_int, + &builtin_type_unsigned_long, + &builtin_type_unsigned_long_long, + &builtin_type_long_double, + &builtin_type_complex, + &builtin_type_double_complex, + 0 +}; + +const struct language_defn objc_language_defn = { + "objective-c", /* Language name */ + language_objc, + objc_builtin_types, + range_check_off, + type_check_off, + case_sensitive_on, + objc_parse, + objc_error, + evaluate_subexp_standard, + objc_printchar, /* Print a character constant */ + objc_printstr, /* Function to print string constant */ + objc_emit_char, + objc_create_fundamental_type, /* Create fundamental type in this language */ + c_print_type, /* Print a type using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ + c_value_print, /* Print a top-level value */ + {"", "", "", ""}, /* Binary format info */ + {"0%lo", "0", "o", ""}, /* Octal format info */ + {"%ld", "", "d", ""}, /* Decimal format info */ + {"0x%lx", "0x", "x", ""}, /* Hex format info */ + objc_op_print_tab, /* Expression operators for printing */ + 1, /* C-style arrays */ + 0, /* String lower bound */ + &builtin_type_char, /* Type of string elements */ + LANG_MAGIC +}; + +/* + * ObjC: + * Following functions help construct Objective-C message calls + */ + +struct selname /* For parsing Objective-C. */ + { + struct selname *next; + char *msglist_sel; + int msglist_len; + }; + +static int msglist_len; +static struct selname *selname_chain; +static char *msglist_sel; + +void +start_msglist(void) +{ + register struct selname *new = + (struct selname *) xmalloc (sizeof (struct selname)); + + new->next = selname_chain; + new->msglist_len = msglist_len; + new->msglist_sel = msglist_sel; + msglist_len = 0; + msglist_sel = (char *)xmalloc(1); + *msglist_sel = 0; + selname_chain = new; +} + +void +add_msglist(struct stoken *str, int addcolon) +{ + char *s, *p; + int len, plen; + + if (str == 0) { /* Unnamed arg, or... */ + if (addcolon == 0) { /* variable number of args. */ + msglist_len++; + return; + } + p = ""; + plen = 0; + } else { + p = str->ptr; + plen = str->length; + } + len = plen + strlen(msglist_sel) + 2; + s = (char *)xmalloc(len); + strcpy(s, msglist_sel); + strncat(s, p, plen); + free(msglist_sel); + msglist_sel = s; + if (addcolon) { + s[len-2] = ':'; + s[len-1] = 0; + msglist_len++; + } else + s[len-2] = '\0'; +} + +int +end_msglist(void) +{ + register int val = msglist_len; + register struct selname *sel = selname_chain; + register char *p = msglist_sel; + int selid; + + selname_chain = sel->next; + msglist_len = sel->msglist_len; + msglist_sel = sel->msglist_sel; + selid = lookup_child_selector(p); + if (!selid) + error("Can't find selector \"%s\"", p); + write_exp_elt_longcst (selid); + free(p); + write_exp_elt_longcst (val); /* Number of args */ + free(sel); + + return val; +} + +/* + * Function: specialcmp (char *a, char *b) + * + * Special strcmp: treats ']' and ' ' as end-of-string. + * Used for qsorting lists of objc methods (either by class or selector). + */ + +int specialcmp(char *a, char *b) +{ + while (*a && *a != ' ' && *a != ']' && *b && *b != ' ' && *b != ']') + { + if (*a != *b) + return *a - *b; + a++, b++; + } + if (*a && *a != ' ' && *a != ']') + return 1; /* a is longer therefore greater */ + if (*b && *b != ' ' && *b != ']') + return -1; /* a is shorter therefore lesser */ + return 0; /* a and b are identical */ +} + +/* + * Function: compare_selectors (void *, void *) + * + * Comparison function for use with qsort. Arguments are symbols or + * msymbols Compares selector part of objc method name alphabetically. + */ + +static int +compare_selectors (void *a, void *b) +{ + char *aname, *bname; + + if ((aname = SYMBOL_SOURCE_NAME (*(struct symbol **) a)) == NULL || + (bname = SYMBOL_SOURCE_NAME (*(struct symbol **) b)) == NULL) + error ("internal: compare_selectors(1)"); + + if ((aname = strchr(aname, ' ')) == NULL || + (bname = strchr(bname, ' ')) == NULL) + error ("internal: compare_selectors(2)"); + + return specialcmp (aname+1, bname+1); +} + +/* + * Function: selectors_info (regexp, from_tty) + * + * Implements the "Info selectors" command. Takes an optional regexp + * arg. Lists all objective c selectors that match the regexp. Works + * by grepping thru all symbols for objective c methods. Output list + * is sorted and uniqued. + */ + +static void +selectors_info (char *regexp, int from_tty) +{ + struct objfile *objfile; + struct minimal_symbol *msymbol; + char *name; + char *val; + int matches = 0; + int maxlen = 0; + int ix; + char myregexp[2048]; + char asel[256]; + struct symbol **sym_arr; + int plusminus = 0; + + if (regexp == NULL) + strcpy(myregexp, ".*]"); /* Null input, match all objc methods. */ + else + { + if (*regexp == '+' || *regexp == '-') + { /* User wants only class methods or only instance methods. */ + plusminus = *regexp++; + while (*regexp == ' ' || *regexp == '\t') + regexp++; + } + if (*regexp == '\0') + strcpy(myregexp, ".*]"); + else + { + strcpy(myregexp, regexp); + if (myregexp[strlen(myregexp) - 1] == '$') /* end of selector */ + myregexp[strlen(myregexp) - 1] = ']'; /* end of method name */ + else + strcat(myregexp, ".*]"); + } + } + + if (regexp != NULL) + if (0 != (val = re_comp (myregexp))) + error ("Invalid regexp (%s): %s", val, regexp); + + /* First time thru is JUST to get max length and count. */ + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL) + name = SYMBOL_NAME (msymbol); + if (name && + (name[0] == '-' || name[0] == '+') && + name[1] == '[') /* Got a method name. */ + { + /* Filter for class/instance methods. */ + if (plusminus && name[0] != plusminus) + continue; + /* Find selector part. */ + name = (char *) strchr(name+2, ' '); + if (regexp == NULL || re_exec(++name) != 0) + { + char *mystart = name; + char *myend = (char *) strchr(mystart, ']'); + + if (myend && (myend - mystart > maxlen)) + maxlen = myend - mystart; /* Get longest selector. */ + matches++; + } + } + } + if (matches) + { + printf_filtered ("Selectors matching \"%s\":\n\n", + regexp ? regexp : "*"); + + sym_arr = alloca (matches * sizeof (struct symbol *)); + matches = 0; + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL) + name = SYMBOL_NAME (msymbol); + if (name && + (name[0] == '-' || name[0] == '+') && + name[1] == '[') /* Got a method name. */ + { + /* Filter for class/instance methods. */ + if (plusminus && name[0] != plusminus) + continue; + /* Find selector part. */ + name = (char *) strchr(name+2, ' '); + if (regexp == NULL || re_exec(++name) != 0) + sym_arr[matches++] = (struct symbol *) msymbol; + } + } + + qsort (sym_arr, matches, sizeof (struct minimal_symbol *), + compare_selectors); + /* Prevent compare on first iteration. */ + asel[0] = 0; + for (ix = 0; ix < matches; ix++) /* Now do the output. */ + { + char *p = asel; + + QUIT; + if ((name = SYMBOL_DEMANGLED_NAME (sym_arr[ix])) == NULL) + name = SYMBOL_NAME (sym_arr[ix]); + name = strchr (name, ' ') + 1; + if (p[0] && specialcmp(name, p) == 0) + continue; /* Seen this one already (not unique). */ + + /* Copy selector part. */ + while (*name && *name != ']') + *p++ = *name++; + *p++ = '\0'; + /* Print in columns. */ + puts_filtered_tabular(asel, maxlen + 1, 0); + } + begin_line(); + } + else + printf_filtered ("No selectors matching \"%s\"\n", regexp ? regexp : "*"); +} + +/* + * Function: compare_classes (void *, void *) + * + * Comparison function for use with qsort. Arguments are symbols or + * msymbols Compares class part of objc method name alphabetically. + */ + +static int +compare_classes (void *a, void *b) +{ + char *aname, *bname; + + if ((aname = SYMBOL_SOURCE_NAME (*(struct symbol **) a)) == NULL || + (bname = SYMBOL_SOURCE_NAME (*(struct symbol **) b)) == NULL) + error ("internal: compare_classes(1)"); + + return specialcmp (aname+1, bname+1); +} + +/* + * Function: classes_info(regexp, from_tty) + * + * Implements the "info classes" command for objective c classes. + * Lists all objective c classes that match the optional regexp. + * Works by grepping thru the list of objective c methods. List will + * be sorted and uniqued (since one class may have many methods). + * BUGS: will not list a class that has no methods. + */ + +static void +classes_info (char *regexp, int from_tty) +{ + struct objfile *objfile; + struct minimal_symbol *msymbol; + char *name; + char *val; + int matches = 0; + int maxlen = 0; + int ix; + char myregexp[2048]; + char aclass[256]; + struct symbol **sym_arr; + + if (regexp == NULL) + strcpy(myregexp, ".* "); /* Null input: match all objc classes. */ + else + { + strcpy(myregexp, regexp); + if (myregexp[strlen(myregexp) - 1] == '$') + /* In the method name, the end of the class name is marked by ' '. */ + myregexp[strlen(myregexp) - 1] = ' '; + else + strcat(myregexp, ".* "); + } + + if (regexp != NULL) + if (0 != (val = re_comp (myregexp))) + error ("Invalid regexp (%s): %s", val, regexp); + + /* First time thru is JUST to get max length and count. */ + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL) + name = SYMBOL_NAME (msymbol); + if (name && + (name[0] == '-' || name[0] == '+') && + name[1] == '[') /* Got a method name. */ + if (regexp == NULL || re_exec(name+2) != 0) + { + /* Compute length of classname part. */ + char *mystart = name + 2; + char *myend = (char *) strchr(mystart, ' '); + + if (myend && (myend - mystart > maxlen)) + maxlen = myend - mystart; + matches++; + } + } + if (matches) + { + printf_filtered ("Classes matching \"%s\":\n\n", + regexp ? regexp : "*"); + sym_arr = alloca (matches * sizeof (struct symbol *)); + matches = 0; + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL) + name = SYMBOL_NAME (msymbol); + if (name && + (name[0] == '-' || name[0] == '+') && + name[1] == '[') /* Got a method name. */ + if (regexp == NULL || re_exec(name+2) != 0) + sym_arr[matches++] = (struct symbol *) msymbol; + } + + qsort (sym_arr, matches, sizeof (struct minimal_symbol *), + compare_classes); + /* Prevent compare on first iteration. */ + aclass[0] = 0; + for (ix = 0; ix < matches; ix++) /* Now do the output. */ + { + char *p = aclass; + + QUIT; + if ((name = SYMBOL_DEMANGLED_NAME (sym_arr[ix])) == NULL) + name = SYMBOL_NAME (sym_arr[ix]); + name += 2; + if (p[0] && specialcmp(name, p) == 0) + continue; /* Seen this one already (not unique). */ + + /* Copy class part of method name. */ + while (*name && *name != ' ') + *p++ = *name++; + *p++ = '\0'; + /* Print in columns. */ + puts_filtered_tabular(aclass, maxlen + 1, 0); + } + begin_line(); + } + else + printf_filtered ("No classes matching \"%s\"\n", regexp ? regexp : "*"); +} + +/* + * Function: find_imps (char *selector, struct symbol **sym_arr) + * + * Input: a string representing a selector + * a pointer to an array of symbol pointers + * possibly a pointer to a symbol found by the caller. + * + * Output: number of methods that implement that selector. Side + * effects: The array of symbol pointers is filled with matching syms. + * + * By analogy with function "find_methods" (symtab.c), builds a list + * of symbols matching the ambiguous input, so that "decode_line_2" + * (symtab.c) can list them and ask the user to choose one or more. + * In this case the matches are objective c methods + * ("implementations") matching an objective c selector. + * + * Note that it is possible for a normal (c-style) function to have + * the same name as an objective c selector. To prevent the selector + * from eclipsing the function, we allow the caller (decode_line_1) to + * search for such a function first, and if it finds one, pass it in + * to us. We will then integrate it into the list. We also search + * for one here, among the minsyms. + * + * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided + * into two parts: debuggable (struct symbol) syms, and + * non_debuggable (struct minimal_symbol) syms. The debuggable + * ones will come first, before NUM_DEBUGGABLE (which will thus + * be the index of the first non-debuggable one). + */ + +/* + * Function: total_number_of_imps (char *selector); + * + * Input: a string representing a selector + * Output: number of methods that implement that selector. + * + * By analogy with function "total_number_of_methods", this allows + * decode_line_1 (symtab.c) to detect if there are objective c methods + * matching the input, and to allocate an array of pointers to them + * which can be manipulated by "decode_line_2" (also in symtab.c). + */ + +char * +parse_selector (char *method, char **selector) +{ + char *s1 = NULL; + char *s2 = NULL; + int found_quote = 0; + + char *nselector = NULL; + + CHECK (selector != NULL); + + s1 = method; + + while (isspace (*s1)) + s1++; + if (*s1 == '\'') + { + found_quote = 1; + s1++; + } + while (isspace (*s1)) + s1++; + + nselector = s1; + s2 = s1; + + for (;;) { + if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':')) + *s1++ = *s2; + else if (isspace (*s2)) + ; + else if ((*s2 == '\0') || (*s2 == '\'')) + break; + else + return NULL; + s2++; + } + *s1++ = '\0'; + + while (isspace (*s2)) + s2++; + if (found_quote) + { + if (*s2 == '\'') + s2++; + while (isspace (*s2)) + s2++; + } + + if (selector != NULL) + *selector = nselector; + + return s2; +} + +char * +parse_method (char *method, char *type, char **class, + char **category, char **selector) +{ + char *s1 = NULL; + char *s2 = NULL; + int found_quote = 0; + + char ntype = '\0'; + char *nclass = NULL; + char *ncategory = NULL; + char *nselector = NULL; + + CHECK (type != NULL); + CHECK (class != NULL); + CHECK (category != NULL); + CHECK (selector != NULL); + + s1 = method; + + while (isspace (*s1)) + s1++; + if (*s1 == '\'') + { + found_quote = 1; + s1++; + } + while (isspace (*s1)) + s1++; + + if ((s1[0] == '+') || (s1[0] == '-')) + ntype = *s1++; + + while (isspace (*s1)) + s1++; + + if (*s1 != '[') + return NULL; + s1++; + + nclass = s1; + while (isalnum (*s1) || (*s1 == '_')) + s1++; + + s2 = s1; + while (isspace (*s2)) + s2++; + + if (*s2 == '(') + { + s2++; + while (isspace (*s2)) + s2++; + ncategory = s2; + while (isalnum (*s2) || (*s2 == '_')) + s2++; + *s2++ = '\0'; + } + + /* Truncate the class name now that we're not using the open paren. */ + *s1++ = '\0'; + + nselector = s2; + s1 = s2; + + for (;;) { + if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':')) + *s1++ = *s2; + else if (isspace (*s2)) + ; + else if (*s2 == ']') + break; + else + return NULL; + s2++; + } + *s1++ = '\0'; + s2++; + + while (isspace (*s2)) + s2++; + if (found_quote) + { + if (*s2 != '\'') + return NULL; + s2++; + while (isspace (*s2)) + s2++; + } + + if (type != NULL) + *type = ntype; + if (class != NULL) + *class = nclass; + if (category != NULL) + *category = ncategory; + if (selector != NULL) + *selector = nselector; + + return s2; +} + +void +find_methods (struct symtab *symtab, char type, + const char *class, const char *category, + const char *selector, struct symbol **syms, + unsigned int *nsym, unsigned int *ndebug) +{ + struct objfile *objfile = NULL; + struct minimal_symbol *msymbol = NULL; + struct block *block = NULL; + struct symbol *sym = NULL; + + char *symname = NULL; + + char ntype = '\0'; + char *nclass = NULL; + char *ncategory = NULL; + char *nselector = NULL; + + unsigned int csym = 0; + unsigned int cdebug = 0; + + static char *tmp = NULL; + static unsigned int tmplen = 0; + + CHECK (nsym != NULL); + CHECK (ndebug != NULL); + + if (symtab) + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK); + + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + + if ((msymbol->type != mst_text) && (msymbol->type != mst_file_text)) + /* Not a function or method. */ + continue; + + if (symtab) + if ((SYMBOL_VALUE_ADDRESS (msymbol) < block->startaddr) || + (SYMBOL_VALUE_ADDRESS (msymbol) >= block->endaddr)) + /* Not in the specified symtab. */ + continue; + + symname = SYMBOL_DEMANGLED_NAME (msymbol); + if (symname == NULL) + symname = SYMBOL_NAME (msymbol); + if (symname == NULL) + continue; + + if ((symname[0] != '-' && symname[0] != '+') || (symname[1] != '[')) + /* Not a method name. */ + continue; + + while ((strlen (symname) + 1) >= tmplen) + { + tmplen = (tmplen == 0) ? 1024 : tmplen * 2; + tmp = xrealloc (tmp, tmplen); + } + strcpy (tmp, symname); + + if (parse_method (tmp, &ntype, &nclass, &ncategory, &nselector) == NULL) + continue; + + if ((type != '\0') && (ntype != type)) + continue; + + if ((class != NULL) + && ((nclass == NULL) || (strcmp (class, nclass) != 0))) + continue; + + if ((category != NULL) && + ((ncategory == NULL) || (strcmp (category, ncategory) != 0))) + continue; + + if ((selector != NULL) && + ((nselector == NULL) || (strcmp (selector, nselector) != 0))) + continue; + + sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol)); + if (sym != NULL) + { + const char *newsymname = SYMBOL_DEMANGLED_NAME (sym); + + if (newsymname == NULL) + newsymname = SYMBOL_NAME (sym); + if (strcmp (symname, newsymname) == 0) + { + /* Found a high-level method sym: swap it into the + lower part of sym_arr (below num_debuggable). */ + if (syms != NULL) + { + syms[csym] = syms[cdebug]; + syms[cdebug] = sym; + } + csym++; + cdebug++; + } + else + { + warning ( +"debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring", + newsymname, symname); + if (syms != NULL) + syms[csym] = (struct symbol *) msymbol; + csym++; + } + } + else + { + /* Found a non-debuggable method symbol. */ + if (syms != NULL) + syms[csym] = (struct symbol *) msymbol; + csym++; + } + } + + if (nsym != NULL) + *nsym = csym; + if (ndebug != NULL) + *ndebug = cdebug; +} + +char *find_imps (struct symtab *symtab, struct block *block, + char *method, struct symbol **syms, + unsigned int *nsym, unsigned int *ndebug) +{ + char type = '\0'; + char *class = NULL; + char *category = NULL; + char *selector = NULL; + + unsigned int csym = 0; + unsigned int cdebug = 0; + + unsigned int ncsym = 0; + unsigned int ncdebug = 0; + + char *buf = NULL; + char *tmp = NULL; + + CHECK (nsym != NULL); + CHECK (ndebug != NULL); + + if (nsym != NULL) + *nsym = 0; + if (ndebug != NULL) + *ndebug = 0; + + buf = (char *) alloca (strlen (method) + 1); + strcpy (buf, method); + tmp = parse_method (buf, &type, &class, &category, &selector); + + if (tmp == NULL) { + + struct symtab *sym_symtab = NULL; + struct symbol *sym = NULL; + struct minimal_symbol *msym = NULL; + + strcpy (buf, method); + tmp = parse_selector (buf, &selector); + + if (tmp == NULL) + return NULL; + + sym = lookup_symbol (selector, block, VAR_NAMESPACE, 0, &sym_symtab); + if (sym != NULL) + { + if (syms) + syms[csym] = sym; + csym++; + cdebug++; + } + + if (sym == NULL) + msym = lookup_minimal_symbol (selector, 0, 0); + + if (msym != NULL) + { + if (syms) + syms[csym] = msym; + csym++; + } + } + + if (syms != NULL) + find_methods (symtab, type, class, category, selector, + syms + csym, &ncsym, &ncdebug); + else + find_methods (symtab, type, class, category, selector, + NULL, &ncsym, &ncdebug); + + /* If we didn't find any methods, just return. */ + if (ncsym == 0 && ncdebug == 0) + return method; + + /* Take debug symbols from the second batch of symbols and swap them + * with debug symbols from the first batch. Repeat until either the + * second section is out of debug symbols or the first section is + * full of debug symbols. Either way we have all debug symbols + * packed to the beginning of the buffer. + */ + + if (syms != NULL) + { + while ((cdebug < csym) && (ncdebug > 0)) + { + struct symbol *s = NULL; + /* First non-debugging symbol. */ + unsigned int i = cdebug; + /* Last of second batch of debug symbols. */ + unsigned int j = csym + ncdebug - 1; + + s = syms[j]; + syms[j] = syms[i]; + syms[i] = s; + + /* We've moved a symbol from the second debug section to the + first one. */ + cdebug++; + ncdebug--; + } + } + + csym += ncsym; + cdebug += ncdebug; + + if (nsym != NULL) + *nsym = csym; + if (ndebug != NULL) + *ndebug = cdebug; + + if (syms == NULL) + return method + (tmp - buf); + + if (csym > 1) + { + /* Sort debuggable symbols. */ + if (cdebug > 1) + qsort (syms, cdebug, sizeof (struct minimal_symbol *), + compare_classes); + + /* Sort minimal_symbols. */ + if ((csym - cdebug) > 1) + qsort (&syms[cdebug], csym - cdebug, + sizeof (struct minimal_symbol *), compare_classes); + } + /* Terminate the sym_arr list. */ + syms[csym] = 0; + + return method + (tmp - buf); +} + +void +print_object_command (char *args, int from_tty) +{ + struct value *object, *function, *description; + CORE_ADDR string_addr; + int i = 0; + char c = -1; + + if (!args || !*args) + error ( +"The 'print-object' command requires an argument (an Objective-C object)"); + + { + struct expression *expr = parse_expression (args); + register struct cleanup *old_chain = + make_cleanup (free_current_contents, &expr); + int pc = 0; + +#if 1 + object = expr->language_defn->evaluate_exp (builtin_type_void_data_ptr, + expr, &pc, EVAL_NORMAL); +#else + object = evaluate_subexp (builtin_type_void_data_ptr, + expr, &pc, EVAL_NORMAL); +#endif + do_cleanups (old_chain); + } + + if (!(function = find_function_in_inferior ("_NSPrintForDebugger"))) + error ("Unable to locate _NSPrintForDebugger in child process"); + + description = call_function_by_hand (function, 1, &object); + + if ((string_addr = value_as_long (description)) == 0) + error ("object returns null description"); + + read_memory (string_addr + i++, &c, 1); + if (c != '\0') + do + { /* Read and print characters up to EOS. */ + QUIT; + printf_filtered ("%c", c); + read_memory (string_addr + i++, &c, 1); + } while (c != 0); + else + printf_filtered(""); + printf_filtered ("\n"); +} + +/* The data structure 'methcalls' is used to detect method calls (thru + * ObjC runtime lib functions objc_msgSend, objc_msgSendSuper, etc.), + * and ultimately find the method being called. + */ + +struct objc_methcall { + char *name; + /* Return instance method to be called. */ + CORE_ADDR (*stop_at) (CORE_ADDR); + /* Start of pc range corresponding to method invocation. */ + CORE_ADDR begin; + /* End of pc range corresponding to method invocation. */ + CORE_ADDR end; +}; + +static int resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc); +static int resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc); +static int resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc); +static int resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc); + +static struct objc_methcall methcalls[] = { + { "_objc_msgSend", resolve_msgsend, 0, 0}, + { "_objc_msgSend_stret", resolve_msgsend_stret, 0, 0}, + { "_objc_msgSendSuper", resolve_msgsend_super, 0, 0}, + { "_objc_msgSendSuper_stret", resolve_msgsend_super_stret, 0, 0}, + { "_objc_getClass", NULL, 0, 0}, + { "_objc_getMetaClass", NULL, 0, 0} +}; + +#define nmethcalls (sizeof (methcalls) / sizeof (methcalls[0])) + +/* The following function, "find_objc_msgsend", fills in the data + * structure "objc_msgs" by finding the addresses of each of the + * (currently four) functions that it holds (of which objc_msgSend is + * the first). This must be called each time symbols are loaded, in + * case the functions have moved for some reason. + */ + +void +find_objc_msgsend (void) +{ + unsigned int i; + for (i = 0; i < nmethcalls; i++) { + + struct minimal_symbol *func; + + /* Try both with and without underscore. */ + func = lookup_minimal_symbol (methcalls[i].name, NULL, NULL); + if ((func == NULL) && (methcalls[i].name[0] == '_')) { + func = lookup_minimal_symbol (methcalls[i].name + 1, NULL, NULL); + } + if (func == NULL) { + methcalls[i].begin = 0; + methcalls[i].end = 0; + continue; + } + + methcalls[i].begin = SYMBOL_VALUE_ADDRESS (func); + do { + methcalls[i].end = SYMBOL_VALUE_ADDRESS (++func); + } while (methcalls[i].begin == methcalls[i].end); + } +} + +/* find_objc_msgcall (replaces pc_off_limits) + * + * ALL that this function now does is to determine whether the input + * address ("pc") is the address of one of the Objective-C message + * dispatch functions (mainly objc_msgSend or objc_msgSendSuper), and + * if so, it returns the address of the method that will be called. + * + * The old function "pc_off_limits" used to do a lot of other things + * in addition, such as detecting shared library jump stubs and + * returning the address of the shlib function that would be called. + * That functionality has been moved into the SKIP_TRAMPOLINE_CODE and + * IN_SOLIB_TRAMPOLINE macros, which are resolved in the target- + * dependent modules. + */ + +struct objc_submethod_helper_data { + CORE_ADDR (*f) (CORE_ADDR, CORE_ADDR *); + CORE_ADDR pc; + CORE_ADDR *new_pc; +}; + +int +find_objc_msgcall_submethod_helper (PTR arg) +{ + struct objc_submethod_helper_data *s = + (struct objc_submethod_helper_data *) arg; + + if (s->f (s->pc, s->new_pc) == 0) + return 1; + else + return 0; +} + +int +find_objc_msgcall_submethod (CORE_ADDR (*f) (CORE_ADDR, CORE_ADDR *), + CORE_ADDR pc, + CORE_ADDR *new_pc) +{ + struct objc_submethod_helper_data s; + + s.f = f; + s.pc = pc; + s.new_pc = new_pc; + + if (catch_errors (find_objc_msgcall_submethod_helper, + (PTR) &s, + "Unable to determine target of Objective-C method call (ignoring):\n", + RETURN_MASK_ALL) == 0) + return 1; + else + return 0; +} + +int +find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc) +{ + unsigned int i; + + find_objc_msgsend (); + if (new_pc != NULL) { *new_pc = 0; } + + for (i = 0; i < nmethcalls; i++) + if ((pc >= methcalls[i].begin) && (pc < methcalls[i].end)) + { + if (methcalls[i].stop_at != NULL) + return find_objc_msgcall_submethod (methcalls[i].stop_at, + pc, new_pc); + else + return 0; + } + + return 0; +} + +void +_initialize_objc_language (void) +{ + add_language (&objc_language_defn); + add_info ("selectors", selectors_info, /* INFO SELECTORS command. */ + "All Objective-C selectors, or those matching REGEXP."); + add_info ("classes", classes_info, /* INFO CLASSES command. */ + "All Objective-C classes, or those matching REGEXP."); + add_com ("print-object", class_vars, print_object_command, + "Ask an Objective-C object to print itself.\n"); + add_com_alias ("po", "print-object", class_vars, 1); +} + +#if defined (__powerpc__) || defined (__ppc__) +static unsigned long FETCH_ARGUMENT (int i) +{ + return read_register (3 + i); +} +#elif defined (__i386__) +static unsigned long FETCH_ARGUMENT (int i) +{ + CORE_ADDR stack = read_register (SP_REGNUM); + return read_memory_unsigned_integer (stack + (4 * (i + 1)), 4); +} +#elif defined (__sparc__) +static unsigned long FETCH_ARGUMENT (int i) +{ + return read_register (O0_REGNUM + i); +} +#elif defined (__hppa__) || defined (__hppa) +static unsigned long FETCH_ARGUMENT (int i) +{ + return read_register (R0_REGNUM + 26 - i); +} +#else +#error unknown architecture +#endif + +#if defined (__hppa__) || defined (__hppa) +static CORE_ADDR CONVERT_FUNCPTR (CORE_ADDR pc) +{ + if (pc & 0x2) + pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, 4); + + return pc; +} +#else +static CORE_ADDR CONVERT_FUNCPTR (CORE_ADDR pc) +{ + return pc; +} +#endif + +static void +read_objc_method (CORE_ADDR addr, struct objc_method *method) +{ + method->name = read_memory_unsigned_integer (addr + 0, 4); + method->types = read_memory_unsigned_integer (addr + 4, 4); + method->imp = read_memory_unsigned_integer (addr + 8, 4); +} + +static +unsigned long read_objc_methlist_nmethods (CORE_ADDR addr) +{ + return read_memory_unsigned_integer (addr + 4, 4); +} + +static void +read_objc_methlist_method (CORE_ADDR addr, unsigned long num, + struct objc_method *method) +{ + CHECK_FATAL (num < read_objc_methlist_nmethods (addr)); + read_objc_method (addr + 8 + (12 * num), method); +} + +static void +read_objc_object (CORE_ADDR addr, struct objc_object *object) +{ + object->isa = read_memory_unsigned_integer (addr, 4); +} + +static void +read_objc_super (CORE_ADDR addr, struct objc_super *super) +{ + super->receiver = read_memory_unsigned_integer (addr, 4); + super->class = read_memory_unsigned_integer (addr + 4, 4); +}; + +static void +read_objc_class (CORE_ADDR addr, struct objc_class *class) +{ + class->isa = read_memory_unsigned_integer (addr, 4); + class->super_class = read_memory_unsigned_integer (addr + 4, 4); + class->name = read_memory_unsigned_integer (addr + 8, 4); + class->version = read_memory_unsigned_integer (addr + 12, 4); + class->info = read_memory_unsigned_integer (addr + 16, 4); + class->instance_size = read_memory_unsigned_integer (addr + 18, 4); + class->ivars = read_memory_unsigned_integer (addr + 24, 4); + class->methods = read_memory_unsigned_integer (addr + 28, 4); + class->cache = read_memory_unsigned_integer (addr + 32, 4); + class->protocols = read_memory_unsigned_integer (addr + 36, 4); +} + +CORE_ADDR +find_implementation_from_class (CORE_ADDR class, CORE_ADDR sel) +{ + CORE_ADDR subclass = class; + + while (subclass != 0) + { + + struct objc_class class_str; + unsigned mlistnum = 0; + + read_objc_class (subclass, &class_str); + + for (;;) + { + CORE_ADDR mlist; + unsigned long nmethods; + unsigned long i; + + mlist = read_memory_unsigned_integer (class_str.methods + + (4 * mlistnum), 4); + if (mlist == 0) + break; + + nmethods = read_objc_methlist_nmethods (mlist); + + for (i = 0; i < nmethods; i++) + { + struct objc_method meth_str; + read_objc_methlist_method (mlist, i, &meth_str); + +#if 0 + fprintf (stderr, + "checking method 0x%lx against selector 0x%lx\n", + meth_str.name, sel); +#endif + + if (meth_str.name == sel) + return CONVERT_FUNCPTR (meth_str.imp); + } + mlistnum++; + } + subclass = class_str.super_class; + } + + return 0; +} + +CORE_ADDR +find_implementation (CORE_ADDR object, CORE_ADDR sel) +{ + struct objc_object ostr; + + if (object == 0) + return 0; + read_objc_object (object, &ostr); + if (ostr.isa == 0) + return 0; + + return find_implementation_from_class (ostr.isa, sel); +} + +static int +resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc) +{ + CORE_ADDR object; + CORE_ADDR sel; + CORE_ADDR res; + + object = FETCH_ARGUMENT (0); + sel = FETCH_ARGUMENT (1); + + res = find_implementation (object, sel); + if (new_pc != 0) + *new_pc = res; + if (res == 0) + return 1; + return 0; +} + +static int +resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc) +{ + CORE_ADDR object; + CORE_ADDR sel; + CORE_ADDR res; + + object = FETCH_ARGUMENT (1); + sel = FETCH_ARGUMENT (2); + + res = find_implementation (object, sel); + if (new_pc != 0) + *new_pc = res; + if (res == 0) + return 1; + return 0; +} + +static int +resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc) +{ + struct objc_super sstr; + + CORE_ADDR super; + CORE_ADDR sel; + CORE_ADDR res; + + super = FETCH_ARGUMENT (0); + sel = FETCH_ARGUMENT (1); + + read_objc_super (super, &sstr); + if (sstr.class == 0) + return 0; + + res = find_implementation_from_class (sstr.class, sel); + if (new_pc != 0) + *new_pc = res; + if (res == 0) + return 1; + return 0; +} + +static int +resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc) +{ + struct objc_super sstr; + + CORE_ADDR super; + CORE_ADDR sel; + CORE_ADDR res; + + super = FETCH_ARGUMENT (1); + sel = FETCH_ARGUMENT (2); + + read_objc_super (super, &sstr); + if (sstr.class == 0) + return 0; + + res = find_implementation_from_class (sstr.class, sel); + if (new_pc != 0) + *new_pc = res; + if (res == 0) + return 1; + return 0; +} diff --git a/gdb/objc-lang.h b/gdb/objc-lang.h new file mode 100644 index 00000000000..87e315b5c06 --- /dev/null +++ b/gdb/objc-lang.h @@ -0,0 +1,57 @@ +/* Objective-C language support definitions for GDB, the GNU debugger. + + Copyright 1992 Free Software Foundation, Inc. + + Contributed by Apple Computer, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef __STDC__ /* Forward decls for prototypes. */ +struct value; +#endif + +extern int objc_parse (void); /* Defined in c-exp.y */ + +extern void objc_error (char *); /* Defined in c-exp.y */ + +extern int c_val_print (struct type *, char *, int, + CORE_ADDR, struct ui_file *, int, + int, int, enum val_prettyprint); + +extern int c_value_print (struct value *, struct ui_file *, + int, enum val_prettyprint); + +extern CORE_ADDR lookup_objc_class (char *classname); +extern int lookup_child_selector (char *methodname); + +char *objc_demangle (const char *mangled); + +int find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc); + +char *parse_selector (char *method, char **selector); + +char *parse_method (char *method, char *type, + char **class, char **category, + char **selector); + +void find_methods (struct symtab *symtab, char type, + const char *class, const char *category, + const char *selector, struct symbol **syms, + unsigned int *nsym, unsigned int *ndebug); + +char *find_imps (struct symtab *symtab, struct block *block, + char *method, struct symbol **syms, + unsigned int *nsym, unsigned int *ndebug); diff --git a/gdb/testsuite/gdb.base/charset.c b/gdb/testsuite/gdb.base/charset.c new file mode 100644 index 00000000000..ece684a1ef9 --- /dev/null +++ b/gdb/testsuite/gdb.base/charset.c @@ -0,0 +1,131 @@ +/* Test GDB's character set support + Jim Blandy --- December 2001 */ + +#include + + +/* X_string is a null-terminated string in the X charset whose + elements are as follows. X should be the name the `set charset' + command uses for the character set, in lower-case, with any + non-identifier characters replaced with underscores. Where a + character set doesn't have the given character, the string should + contain the character 'x'. + + [0] --- the `alert' character, '\a' + [1] --- the `backspace' character, '\b' + [2] --- the `escape' character, '\e' + [3] --- the `form feed' character, '\f' + [4] --- the `line feed' character, '\n' + [5] --- the `carriage return' character, '\r' + [6] --- the `horizontal tab' character, '\t' + [7] --- the `vertical tab' character, '\v' + [8 .. 33] --- the uppercase letters A-Z + [34 .. 59] --- the lowercase letters a-z + [60 .. 69] --- the digits 0-9 + [70] --- the `cent' character + [71] --- a control character with no defined backslash escape + + Feel free to extend these as you like. */ + +#define NUM_CHARS (72) + +char ascii_string[NUM_CHARS]; +char iso_8859_1_string[NUM_CHARS]; +char ebcdic_us_string[NUM_CHARS]; +char ibm1047_string[NUM_CHARS]; + + +void +init_string (char string[], + char x, + char alert, char backspace, char escape, char form_feed, + char line_feed, char carriage_return, char horizontal_tab, + char vertical_tab, char cent, char misc_ctrl) +{ + memset (string, x, NUM_CHARS); + string[0] = alert; + string[1] = backspace; + string[2] = escape; + string[3] = form_feed; + string[4] = line_feed; + string[5] = carriage_return; + string[6] = horizontal_tab; + string[7] = vertical_tab; + string[70] = cent; + string[71] = misc_ctrl; +} + + +void +fill_run (char string[], int start, int len, int first) +{ + int i; + + for (i = 0; i < len; i++) + string[start + i] = first + i; +} + + +int main () +{ +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif + (void) malloc (1); + /* Initialize ascii_string. */ + init_string (ascii_string, + 120, + 7, 8, 27, 12, + 10, 13, 9, + 11, 120, 17); + fill_run (ascii_string, 8, 26, 65); + fill_run (ascii_string, 34, 26, 97); + fill_run (ascii_string, 60, 10, 48); + + /* Initialize iso_8859_1_string. */ + init_string (iso_8859_1_string, + 120, + 7, 8, 27, 12, + 10, 13, 9, + 11, 162, 17); + fill_run (iso_8859_1_string, 8, 26, 65); + fill_run (iso_8859_1_string, 34, 26, 97); + fill_run (iso_8859_1_string, 60, 10, 48); + + /* Initialize ebcdic_us_string. */ + init_string (ebcdic_us_string, + 167, + 47, 22, 39, 12, + 37, 13, 5, + 11, 74, 17); + /* In EBCDIC, the upper-case letters are broken into three separate runs. */ + fill_run (ebcdic_us_string, 8, 9, 193); + fill_run (ebcdic_us_string, 17, 9, 209); + fill_run (ebcdic_us_string, 26, 8, 226); + /* The lower-case letters are, too. */ + fill_run (ebcdic_us_string, 34, 9, 129); + fill_run (ebcdic_us_string, 43, 9, 145); + fill_run (ebcdic_us_string, 52, 8, 162); + /* The digits, at least, are contiguous. */ + fill_run (ebcdic_us_string, 60, 10, 240); + + /* Initialize ibm1047_string. */ + init_string (ibm1047_string, + 167, + 47, 22, 39, 12, + 37, 13, 5, + 11, 74, 17); + /* In EBCDIC, the upper-case letters are broken into three separate runs. */ + fill_run (ibm1047_string, 8, 9, 193); + fill_run (ibm1047_string, 17, 9, 209); + fill_run (ibm1047_string, 26, 8, 226); + /* The lower-case letters are, too. */ + fill_run (ibm1047_string, 34, 9, 129); + fill_run (ibm1047_string, 43, 9, 145); + fill_run (ibm1047_string, 52, 8, 162); + /* The digits, at least, are contiguous. */ + fill_run (ibm1047_string, 60, 10, 240); + + puts ("All set!"); /* all strings initialized */ +} diff --git a/gdb/testsuite/gdb.base/charset.exp b/gdb/testsuite/gdb.base/charset.exp new file mode 100644 index 00000000000..8e765aa3a95 --- /dev/null +++ b/gdb/testsuite/gdb.base/charset.exp @@ -0,0 +1,486 @@ +# Copyright 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# Test GDB's character set support. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "charset" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +# Start with a fresh gdb. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Parse the output from a `show charset' command. Return the host +# and target charset as a two-element list. +proc parse_show_charset_output {testname} { + global gdb_prompt + + gdb_expect { + -re "The current host and target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" { + set host_charset $expect_out(1,string) + set target_charset $expect_out(1,string) + pass $testname + } + -re "The current host character set is `(.*)'\\.\[\r\n\]+The current target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" { + set host_charset $expect_out(1,string) + set target_charset $expect_out(2,string) + pass $testname + } + -re ".*$gdb_prompt $" { + fail $testname + } + timeout { + fail "$testname (timeout)" + } + } + + return [list $host_charset $target_charset] +} + + +# Try the various `show charset' commands. These are all aliases of each +# other; `show target-charset' and `show host-charset' actually print +# both the host and target charsets. + +send_gdb "show charset\n" +set show_charset [parse_show_charset_output "show charset"] + +send_gdb "show target-charset\n" +set show_target_charset [parse_show_charset_output "show target-charset"] + +if {! [string compare $show_charset $show_target_charset]} { + pass "check `show target-charset' against `show charset'" +} else { + fail "check `show target-charset' against `show charset'" +} + +send_gdb "show host-charset\n" +set show_host_charset [parse_show_charset_output "show host-charset"] + +if {! [string compare $show_charset $show_host_charset]} { + pass "check `show host-charset' against `show charset'" +} else { + fail "check `show host-charset' against `show charset'" +} + + +# Get the list of supported charsets. +send_gdb "set charset\n" + +# True iff we've seen the "Valid character sets are:" message. +set seen_valid 0 + +# True iff we've seen the "can be used as a host character set" message. +set seen_can_host 0 + +# A Tcl array mapping the names of all the character sets we've seen +# to "1" if the character set can be used as a host character set, or +# "0" otherwise. We can use `array names charsets' just to get a list +# of all character sets. +array set charsets {} + +proc all_charset_names {} { + global charsets + return [array names charsets] +} + +proc charset_exists {charset} { + global charsets + return [info exists charsets($charset)] +} + +proc valid_host_charset {charset} { + global charsets + return $charsets($charset) +} + +gdb_expect { + -re "Valid character sets are:\[\r\n\]+" { + # There's no ^ at the beginning of the pattern above, so that + # expect can skip the echoed `set charset' command. + set seen_valid 1 + exp_continue + } + -re "^ (\[^ \t\n\]*) \\*\[\r\n\]+" { + set charsets($expect_out(1,string)) 1 + exp_continue + } + -re "^ (\[^ \t\n\]*)\[ \t\]*\[\r\n\]+" { + set charsets($expect_out(1,string)) 0 + exp_continue + } + -re "^\\* - can be used as a host character set\[\r\n\]+" { + set seen_can_host 1 + exp_continue + } + -re ".*${gdb_prompt} $" { + # We don't do an exp_continue here. + } + timeout { + fail "get valid character sets (timeout)" + } +} + + +# Check that we've seen all the right pieces of the output, and that +# we can at least use ASCII as a host character set. +if {$seen_valid && $seen_can_host && [charset_exists ascii]} { + # We can't do the below as part of the test above, since all the + # [] substitution takes place before any expression evaluation + # takes place; && doesn't really short circuit things the way + # you'd like. We'd get an "can't read $charsets(ascii)" error + # even when `info exists' had returned zero. + if {[valid_host_charset ascii]} { + pass "get valid character sets" + } else { + fail "get valid character sets" + } +} else { + fail "get valid character sets (no ascii charset)" +} + + +# Try using `set host-charset' on an invalid character set. +gdb_test "set host-charset my_grandma_bonnie" \ + "GDB doesn't know of any character set named `my_grandma_bonnie'." \ + "try `set host-charset' with invalid charset" + + +# Try using `set target-charset' on an invalid character set. +gdb_test "set target-charset my_grandma_bonnie" \ + "GDB doesn't know of any character set named `my_grandma_bonnie'." \ + "try `set target-charset' with invalid charset" + + +# Make sure that GDB supports every host/target charset combination. +foreach host_charset [all_charset_names] { + if {[valid_host_charset $host_charset]} { + + set testname "try `set host-charset $host_charset'" + send_gdb "set host-charset $host_charset\n" + gdb_expect { + -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" { + # How did it get into `charsets' then? + fail "$testname (didn't recognize name)" + } + -re "GDB can't use `.*' as its host character set\\.\[\r\n]+${gdb_prompt} $" { + # Well, then why does its `charsets' entry say it can? + fail $testname + } + -re "${gdb_prompt} $" { + pass $testname + } + timeout { + fail "$testname (timeout)" + } + } + + # Check that the command actually had its intended effect: + # $host_charset should now be the host character set. + send_gdb "show charset\n" + set result [parse_show_charset_output "parse `show charset' after `set host-charset $host_charset'"] + if {! [string compare [lindex $result 0] $host_charset]} { + pass "check effect of `set host-charset $host_charset'" + } else { + fail "check effect of `set host-charset $host_charset'" + } + + # Now try setting every possible target character set, + # given that host charset. + foreach target_charset [all_charset_names] { + set testname "try `set target-charset $target_charset'" + send_gdb "set target-charset $target_charset\n" + gdb_expect { + -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" { + fail "$testname (didn't recognize name)" + } + -re "GDB can't convert from the .* character set to .*\\.\[\r\n\]+${gdb_prompt} $" { + # This is a serious problem. GDB should be able to convert + # between any arbitrary pair of character sets. + fail "$testname (can't convert)" + } + -re "${gdb_prompt} $" { + pass $testname + } + timeout { + fail "$testname (timeout)" + } + } + + # Check that the command actually had its intended effect: + # $target_charset should now be the target charset. + send_gdb "show charset\n" + set result [parse_show_charset_output "parse `show charset' after `set target-charset $target_charset'"] + if {! [string compare $result [list $host_charset $target_charset]]} { + pass "check effect of `set target-charset $target_charset'" + } else { + fail "check effect of `set target-charset $target_charset'" + } + + # Test handling of characters in the host charset which + # can't be translated into the target charset. \xA2 is + # `cent' in ISO-8859-1, which has no equivalent in ASCII. + # + # On some systems, the pseudo-tty through which we + # communicate with GDB insists on stripping the high bit + # from input characters, meaning that `cent' turns into + # `"'. Since ISO-8859-1 and ASCII are identical in the + # lower 128 characters, it's tough to see how we can test + # this behavior on such systems, so we just xfail it. + # + # Note: the \x16 (Control-V) is an escape to allow \xA2 to + # get past readline. + if {! [string compare $host_charset iso-8859-1] && ! [string compare $target_charset ascii]} { + + set testname "untranslatable character in character literal" + send_gdb "print '\x16\xA2'\n" + gdb_expect { + -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" { + pass $testname + } + -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" { + xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)" + } + -re "$gdb_prompt $" { + fail $testname + } + timeout { + fail "$testname (timeout)" + } + } + + set testname "untranslatable character in string literal" + # If the PTTY zeros bit seven, then this turns into + # print """ + # which gets us a syntax error. We don't care. + send_gdb "print \"\x16\xA2\"\n" + gdb_expect { + -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" { + pass $testname + } + -re "Unterminated string in expression.\[\r\n\]+$gdb_prompt $" { + xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)" + } + -re "$gdb_prompt $" { + fail $testname + } + timeout { + fail "$testname (timeout)" + } + } + + set testname "untranslatable characters in backslash escape" + send_gdb "print '\\\x16\xA2'\n" + gdb_expect { + -re "The escape sequence .* is equivalent to plain .*, which has no equivalent\[\r\n\]+in the .* character set\\.\[\r\n\]+$gdb_prompt $" { + pass $testname + } + -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" { + xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)" + } + -re "$gdb_prompt $" { + fail $testname + } + timeout { + fail "$testname (timeout)" + } + } + } + } + } +} + + +# Set the host character set to plain ASCII, and try actually printing +# some strings in various target character sets. We need to run the +# test program to the point at which the strings have been +# initialized. +gdb_test "break [gdb_get_line_number "all strings initialized"]" \ + ".*Breakpoint.* at .*" \ + "set breakpoint after all strings have been initialized" +gdb_run_cmd +gdb_expect { + -re "Breakpoint.*all strings initialized.*$gdb_prompt $" { + pass "run until all strings have been initialized" + } + -re "$gdb_prompt $" { + fail "run until all strings have been initialized" + } + timeout { + fail "run until all strings have been initialized (timeout)" + } +} + + +gdb_test "set host-charset ascii" "" +foreach target_charset [all_charset_names] { + send_gdb "set target-charset $target_charset\n" + gdb_expect { + -re "$gdb_prompt $" { + pass "set target-charset $target_charset" + } + timeout { + fail "set target-charset $target_charset (timeout)" + } + } + + # Try printing the null character. There seems to be a bug in + # gdb_test that requires us to use gdb_expect here. + send_gdb "print '\\0'\n" + gdb_expect { + -re "\\\$${decimal} = 0 '\\\\0'\[\r\n\]+$gdb_prompt $" { + pass "print the null character in ${target_charset}" + } + -re "$gdb_prompt $" { + fail "print the null character in ${target_charset}" + } + timeout { + fail "print the null character in ${target_charset} (timeout)" + } + } + + # Compute the name of the variable in the test program that holds + # a string in $target_charset. The variable's name is the + # character set's name, in lower-case, with all non-identifier + # characters replaced with '_', with "_string" stuck on the end. + set var_name [string tolower "${target_charset}_string"] + regsub -all -- "\[^a-z0-9_\]" $var_name "_" var_name + + # Compute a regexp matching the results we expect. This is static, + # but it's easier than writing it out. + regsub -all "." "abefnrtv" "(\\\\&|x)" escapes + set uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + set lowercase "abcdefghijklmnopqrstuvwxyz" + set digits "0123456789" + set octal_escape "\\\\\[0-9\]\[0-9\]\[0-9\]" + + send_gdb "print $var_name\n" + # ${escapes}${uppercase}${lowercase}${digits}${octal}${octal} + gdb_expect { + -re ".* = \"(\\\\a|x)(\\\\b|x)(\\\\e|x)(\\\\f|x)(\\\\n|x)(\\\\r|x)(\\\\t|x)(\\\\v|x)${uppercase}${lowercase}${digits}(\\\\\[0-9\]\[0-9\]\[0-9\]|x)(\\\\\[0-9\]\[0-9\]\[0-9\]|x).*\"\[\r\n\]+$gdb_prompt $" { + pass "print string in $target_charset" + } + -re "$gdb_prompt $" { + fail "print string in $target_charset" + } + timeout { + fail "print string in $target_charset (timeout)" + } + } + + # Try entering a character literal, and see if it comes back unchanged. + gdb_test "print 'A'" \ + " = \[0-9-\]+ 'A'" \ + "parse character literal in ${target_charset}" + + # Check that the character literal was encoded correctly. + gdb_test "print 'A' == $var_name\[8\]" \ + " = 1" \ + "check value of parsed character literal in ${target_charset}" + + # Try entering a string literal, and see if it comes back unchanged. + gdb_test "print \"abcdefABCDEF012345\"" \ + " = \"abcdefABCDEF012345\"" \ + "parse string literal in ${target_charset}" + + # Check that the string literal was encoded correctly. + gdb_test "print \"q\"\[0\] == $var_name\[50\]" \ + " = 1" \ + "check value of parsed string literal in ${target_charset}" + + # Test handling of characters in the target charset which + # can't be translated into the host charset. + if {! [string compare $target_charset iso-8859-1]} { + gdb_test "print iso_8859_1_string\[70\]" \ + " = \[0-9-\]+ '\\\\242'" \ + "print character with no equivalent in host character set" + gdb_test "print iso_8859_1_string + 70" \ + " = ${hex} \"\\\\242.*\"" \ + "print string with no equivalent in host character set" + } + + # Make sure that we don't apply the ISO-8859-1 `print_literally' + # function to ASCII. + if {! [string compare $target_charset ascii]} { + gdb_test "print iso_8859_1_string\[70\]" \ + " = \[0-9-\]+ '\\\\242'" \ + "print ASCII unprintable character" + gdb_test "print iso_8859_1_string + 70" \ + " = ${hex} \"\\\\242.*\"" \ + "print ASCII unprintable string" + } + + # Try printing characters with backslash escape equivalents. + set escapees {a b e f n r t v} + for {set i 0} {$i < [llength $escapees]} {incr i} { + set escape [lindex $escapees $i] + send_gdb "print $var_name\[$i\]\n" + set have_escape 1 + gdb_expect { + -re "= \[0-9-\]+ '\\\\${escape}'\[\r\n\]+$gdb_prompt $" { + pass "try printing '\\${escape}' in ${target_charset}" + } + -re "= \[0-9-\]+ 'x'\[\r\n\]+$gdb_prompt $" { + xfail "try printing '\\${escape}' in ${target_charset} (no such escape)" + set have_escape 0 + } + -re "$gdb_prompt $" { + fail "try printing '\\${escape}' in ${target_charset}" + } + timeout { + fail "try printing '\\${escape}' in ${target_charset} (timeout)" + } + } + + if {$have_escape} { + + # Try parsing a backslash escape in a character literal. + gdb_test "print '\\${escape}' == $var_name\[$i\]" \ + " = 1" \ + "check value of '\\${escape}' in ${target_charset}" + + # Try parsing a backslash escape in a string literal. + gdb_test "print \"\\${escape}\"\[0\] == $var_name\[$i\]" \ + " = 1" \ + "check value of \"\\${escape}\" in ${target_charset}" + } + } + + # Try printing a character escape that doesn't exist. We should + # get the unescaped character, in the target character set. + gdb_test "print '\\q'" " = \[0-9-\]+ 'q'" \ + "print escape that doesn't exist in $target_charset" + gdb_test "print '\\q' == $var_name\[50\]" " = 1" \ + "check value of escape that doesn't exist in $target_charset" +} + +gdb_exit diff --git a/gdb/testsuite/gdb.base/pc-fp.c b/gdb/testsuite/gdb.base/pc-fp.c new file mode 100644 index 00000000000..8c89a0f0b81 --- /dev/null +++ b/gdb/testsuite/gdb.base/pc-fp.c @@ -0,0 +1,14 @@ +#include + +void +foo (int i) +{ + i++; + printf ("In foo %d\n", i); +} + +int +main () +{ + foo (1); +} diff --git a/gdb/testsuite/gdb.base/pc-fp.exp b/gdb/testsuite/gdb.base/pc-fp.exp new file mode 100644 index 00000000000..f94e3314388 --- /dev/null +++ b/gdb/testsuite/gdb.base/pc-fp.exp @@ -0,0 +1,94 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# The doco makes reference to built-in registers -- $pc and $fp. If +# the ISA contains registers by that name then they should be +# displayed. If the ISA contains registers identified as being +# equivalent, but have different names, then GDB will provide these as +# aliases. If the ISA doesn't provide any equivalent registers, then +# GDB will provide registers that map onto the frame's PC and FP. + +if $tracelevel then { + strace $tracelevel +} + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "pc-fp" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +proc get_valueofx { fmt exp default } { + global gdb_prompt + send_gdb "print${fmt} ${exp}\n" + gdb_expect { + -re "\\$\[0-9\]* = (0x\[0-9a-zA-Z\]+).*$gdb_prompt $" { + set val $expect_out(1,string) + pass "get value of ${exp} ($val)" + } + timeout { + set size ${default} + fail "get value of ${exp} (timeout)" + } + } + return ${val} +} + +# Get the value of PC and FP + +set valueof_pc [get_valueofx "/x" "\$pc" "0"] +set valueof_fp [get_valueofx "/x" "\$fp" "0"] + +# Check that the sequence $REGNAME -> REGNUM -> $REGNAME works. Use +# display since that encodes and then decodes the expression parameter +# (and hence uses the mechanisms we're trying to test). + +gdb_test "display/i \$pc" "1: x/i +\\\$pc +${valueof_pc}.*" +gdb_test "display/w \$fp" "2: x/xw +\\\$fp +${valueof_fp}.*" + +# FIXME: cagney/2002-09-04: Should also check that ``info registers +# $pc'' et.al.'' come back with the same value as the above displays +# and a print --- assuming that is that people agree to such behavour. +# Need to re-write default_print_registers_info() for it to work (and +# such a rewrite is on the reggroups branch). + +# gdb_test "info registers \$pc" "${valueof_pc}" +# gdb_test "info registers \$fp" "${valueof_fp}" diff --git a/gdb/testsuite/gdb.c++/m-static.h b/gdb/testsuite/gdb.c++/m-static.h new file mode 100644 index 00000000000..137d3b75c50 --- /dev/null +++ b/gdb/testsuite/gdb.c++/m-static.h @@ -0,0 +1,11 @@ +// 2002-08-16 + +class gnu_obj_4 +{ + public: + static const int elsewhere; + static const int nowhere; + // At some point, perhaps: + // static const int everywhere = 317; +}; + diff --git a/gdb/testsuite/gdb.c++/m-static1.cc b/gdb/testsuite/gdb.c++/m-static1.cc new file mode 100644 index 00000000000..f88c9ce2522 --- /dev/null +++ b/gdb/testsuite/gdb.c++/m-static1.cc @@ -0,0 +1,9 @@ +// 2002-08-16 + +namespace __gnu_test { +#include "m-static.h" +} + +using namespace __gnu_test; + +const int gnu_obj_4::elsewhere = 221; diff --git a/gdb/testsuite/gdb.c++/pr-574.cc b/gdb/testsuite/gdb.c++/pr-574.cc new file mode 100644 index 00000000000..eb06b61b7ae --- /dev/null +++ b/gdb/testsuite/gdb.c++/pr-574.cc @@ -0,0 +1,22 @@ +/* + An attempt to replicate PR gdb/574 with a shorter program. + + Printing out *theB failed if the program was compiled with GCC 2.95. +*/ + +class A { +public: + virtual void foo() {}; // Stick in a virtual function. + int a; // Stick in a data member. +}; + +class B : public A { + static int b; // Stick in a static data member. +}; + +int main() +{ + B *theB = new B; + + return 0; // breakpoint: constructs-done +} diff --git a/gdb/testsuite/gdb.c++/pr-574.exp b/gdb/testsuite/gdb.c++/pr-574.exp new file mode 100644 index 00000000000..5beacd10fee --- /dev/null +++ b/gdb/testsuite/gdb.c++/pr-574.exp @@ -0,0 +1,72 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Tests for the bug mentioned in PR gdb/574. It's a bit +# idiosyncratic, so I gave it its own file. + +# 2002-08-16 David Carlton + +# This file is part of the gdb testsuite + +if $tracelevel then { + strace $tracelevel + } + +if { [skip_cplus_tests] } { continue } + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "pr-574" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile} "c++"] { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +# First, run to after we've constructed the object: + +gdb_breakpoint [gdb_get_line_number "constructs-done"] +gdb_continue_to_breakpoint "end of constructors" + +# This failed, as long as the code was compiled with GCC v. 2. + +# Different compilers order the data for differently, so I'm not +# matching the result exactly. + +gdb_test "print *theB" "\\$\[0-9\]* = { = {\[^}\]*}, static b = }" "PR gdb/574" + +gdb_exit +return 0 diff --git a/gdb/testsuite/gdb.c++/printmethod.cc b/gdb/testsuite/gdb.c++/printmethod.cc new file mode 100644 index 00000000000..d32e1b1d1c4 --- /dev/null +++ b/gdb/testsuite/gdb.c++/printmethod.cc @@ -0,0 +1,14 @@ +/* Create some objects, and try to print out their methods. */ + +class A { +public: + virtual void virt() {}; + void nonvirt() {}; +}; + +int main() +{ + A *theA = new A; + + return 0; // breakpoint: constructs-done +} diff --git a/gdb/testsuite/gdb.c++/printmethod.exp b/gdb/testsuite/gdb.c++/printmethod.exp new file mode 100644 index 00000000000..9b96cbfc468 --- /dev/null +++ b/gdb/testsuite/gdb.c++/printmethod.exp @@ -0,0 +1,69 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This tries to print out methods of classes. + +# 2002-08-16 David Carlton + +# This file is part of the gdb testsuite + +if $tracelevel then { + strace $tracelevel + } + +if { [skip_cplus_tests] } { continue } + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "printmethod" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile} "c++"] { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +# First, run to after we've constructed the object: + +gdb_breakpoint [gdb_get_line_number "constructs-done"] +gdb_continue_to_breakpoint "end of constructors" + +# The first of these is for PR gdb/653. + +gdb_test "print theA->virt" "\\$\[0-9\]* = &A::virt\\(\\)" "print virtual method." +gdb_test "print theA->nonvirt" "Cannot take address of a method" "print nonvirtual method." + +gdb_exit +return 0 diff --git a/gdb/testsuite/gdb.gdb/complaints.exp b/gdb/testsuite/gdb.gdb/complaints.exp new file mode 100644 index 00000000000..3d3426f2474 --- /dev/null +++ b/gdb/testsuite/gdb.gdb/complaints.exp @@ -0,0 +1,318 @@ +# Copyright 2002 +# Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Andrew Cagney (cagney at redhat dot com), +# derived from xfullpath.exp (written by Joel Brobecker), derived from +# selftest.exp (written by Rob Savoye). + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# are we on a target board +if [is_remote target] { + return +} + +proc setup_test { executable } { + global gdb_prompt + global timeout + + # load yourself into the debugger + # This can take a relatively long time, particularly for testing where + # the executable is being accessed over a network, or where gdb does not + # support partial symbols for a particular target and has to load the + # entire symbol table. Set the timeout to 10 minutes, which should be + # adequate for most environments (it *has* timed out with 5 min on a + # SPARCstation SLC under moderate load, so this isn't unreasonable). + # After gdb is started, set the timeout to 30 seconds for the duration + # of this test, and then back to the original value. + + set oldtimeout $timeout + set timeout 600 + verbose "Timeout is now $timeout seconds" 2 + if {[gdb_load $executable] <0} then { + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + return -1 + } + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + + # Set a breakpoint at main + gdb_test "break captured_command_loop" \ + "Breakpoint.*at.* file.*, line.*" \ + "breakpoint in captured_command_loop" + + # run yourself + # It may take a very long time for the inferior gdb to start (lynx), + # so we bump it back up for the duration of this command. + set timeout 600 + + set description "run until breakpoint at captured_command_loop" + send_gdb "run -nw\n" + gdb_expect { + -re "Starting program.*Breakpoint \[0-9\]+,.*captured_command_loop .data.* at .*main.c:.*$gdb_prompt $" { + pass "$description" + } + -re "Starting program.*Breakpoint \[0-9\]+,.*captured_command_loop .data.*$gdb_prompt $" { + xfail "$description (line numbers scrambled?)" + } + -re "vfork: No more processes.*$gdb_prompt $" { + fail "$description (out of virtual memory)" + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + return -1 + } + -re ".*$gdb_prompt $" { + fail "$description" + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + return -1 + } + timeout { + fail "$description (timeout)" + } + } + + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + + return 0 +} + +proc test_initial_complaints { } { + + global gdb_prompt + + # Unsupress complaints + gdb_test "set stop_whining = 2" + + # Prime the system + gdb_test "call complaint (&symfile_complaints, \"Register a complaint\")" \ + "During symbol reading, Register a complaint." + + # Check that the complaint was inserted and where + gdb_test "print symfile_complaints->root->fmt" \ + ".\[0-9\]+ =.*\"Register a complaint\"" + + # Re-issue the first message #1 + gdb_test "call complaint (&symfile_complaints, symfile_complaints->root->fmt)" \ + "During symbol reading, Register a complaint." + + # Check that there is only one thing in the list + gdb_test "print symfile_complaints->root->next == &complaint_sentinel" \ + ".\[0-9\]+ = 1" "list has one entry" + + # Add a second complaint, expect it + gdb_test "call complaint (&symfile_complaints, \"Testing! Testing! Testing!\")" \ + "During symbol reading, Testing. Testing. Testing.." + + return 0 +} + +proc test_serial_complaints { } { + + global gdb_prompt + + gdb_test_exact "call clear_complaints (&symfile_complaints, 1, 0)" "" "serial start" + + # Prime the system + send_gdb "call complaint (&symfile_complaints, \"serial line 1\")\n" + gdb_expect { + -re "During symbol reading...serial line 1...$gdb_prompt " { + pass "serial line 1" + } + "$gdb_prompt" { + fail "serial line 1" + } + timeout { + fail "serial line 1 (timeout)" + } + } + + # Add a second complaint, expect it + send_gdb "call complaint (&symfile_complaints, \"serial line 2\")\n" + gdb_expect { + -re "serial line 2...$gdb_prompt " { + pass "serial line 2" + } + "$gdb_prompt" { + fail "serial line 2" + } + timeout { + fail "serial line 2 (timeout)" + } + } + + send_gdb "call clear_complaints (&symfile_complaints, 1, 0)\n" + gdb_expect { + -re "\r\n\r\n$gdb_prompt " { + pass "serial end" + } + "$gdb_prompt" { + fail "serial end" + } + timeout { + fail "serial end (timeout)" + } + } + + return 0 +} + +# For short complaints, all are the same + +proc test_short_complaints { } { + + global gdb_prompt + + gdb_test_exact "call clear_complaints (&symfile_complaints, 1, 1)" "" "short start" + + # Prime the system + send_gdb "call complaint (&symfile_complaints, \"short line 1\")\n" + gdb_expect { + -re "short line 1...$gdb_prompt " { + pass "short line 1" + } + "$gdb_prompt" { + fail "short line 1" + } + timeout { + fail "short line 1 (timeout)" + } + } + + # Add a second complaint, expect it + send_gdb "call complaint (&symfile_complaints, \"short line 2\")\n" + gdb_expect { + -re "short line 2...$gdb_prompt " { + pass "short line 2" + } + "$gdb_prompt" { + fail "short line 2" + } + timeout { + fail "short line 2 (timeout)" + } + } + + send_gdb "call clear_complaints (&symfile_complaints, 1, 0)\n" + gdb_expect { + -re "\r\n\r\n$gdb_prompt " { + pass "short end" + } + "$gdb_prompt" { + fail "short end" + } + timeout { + fail "short end (timeout)" + } + } + + return 0 +} + +# Check that nothing comes out when there haven't been any real +# complaints. Note that each test is really checking the previous +# command. + +proc test_empty_complaint { cmd msg } { + global gdb_prompt + send_gdb $cmd + gdb_expect { + -re "\r\n\r\n$gdb_prompt " { + fail $msg + } + "\r\n$gdb_prompt" { + pass $msg + } + timeout { + fail "$msg (timeout)" + } + } + +} + +proc test_empty_complaints { } { + + test_empty_complaint "call clear_complaints(&symfile_complaints,0,0)\n" \ + "empty non-verbose non-noisy clear" + test_empty_complaint "call clear_complaints(&symfile_complaints,1,0)\n" \ + "empty verbose non-noisy clear" + test_empty_complaint "call clear_complaints(&symfile_complaints,1,1)\n" \ + "empty verbose noisy clear" + test_empty_complaint "call clear_complaints(&symfile_complaints,0,1)\n" \ + "empty non-verbose noisy clear" + + return 0 +} + +# Find a pathname to a file that we would execute if the shell was asked +# to run $arg using the current PATH. + +proc find_gdb { arg } { + + # If the arg directly specifies an existing executable file, then + # simply use it. + + if [file executable $arg] then { + return $arg + } + + set result [which $arg] + if [string match "/" [ string range $result 0 0 ]] then { + return $result + } + + # If everything fails, just return the unqualified pathname as default + # and hope for best. + + return $arg +} + +# Run the test with self. +# Copy the file executable file in case this OS doesn't like to edit its own +# text space. + +set GDB_FULLPATH [find_gdb $GDB] + +# Remove any old copy lying around. +remote_file host delete x$tool + +gdb_start + +set file [remote_download host $GDB_FULLPATH x$tool] + +set setup_result [setup_test $file ] +if {$setup_result <0} then { + return -1 +} + +test_initial_complaints +test_serial_complaints +test_short_complaints +test_empty_complaints + +gdb_exit; +catch "remote_file host delete $file"; diff --git a/gdb/testsuite/gdb.mi/gdb669.exp b/gdb/testsuite/gdb.mi/gdb669.exp new file mode 100644 index 00000000000..4f294b964ea --- /dev/null +++ b/gdb/testsuite/gdb.mi/gdb669.exp @@ -0,0 +1,200 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file checks for the bug gdb/669, where the console +# command "info threads" and the MI command "-thread-list-ids" +# return different threads in the system. + +# This only works with native configurations +if {![isnative]} { + return +} + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +gdb_exit +if {[mi_gdb_start]} { + continue +} + +# The procs below are all stolen from mi-pthreads.exp. Any updates +# should also be made to the procs there. + +proc get_mi_thread_list {name} { + global expect_out + + # MI will return a list of thread ids: + # + # -thread-list-ids + # ^done,thread-ids=[thread-id="1",thread-id="2",...],number-of-threads="N" + # (gdb) + mi_gdb_test "-thread-list-ids" \ + {\^done,thread-ids={(thread-id="[0-9]+"(,)?)+},number-of-threads="[0-9]+"} \ + "-thread_list_ids ($name)" + + set output {} + if {[info exists expect_out(buffer)]} { + set output $expect_out(buffer) + } + set thread_list {} + if {![regexp {thread-ids=\{(thread-id="[0-9]+"(,)?)*\}} $output threads]} { + fail "finding threads in MI output ($name)" + } else { + pass "finding threads in MI output ($name)" + + # Make list of console threads + set start [expr {[string first \{ $threads] + 1}] + set end [expr {[string first \} $threads] - 1}] + set threads [string range $threads $start $end] + foreach thread [split $threads ,] { + if {[scan $thread {thread-id="%d"} num]} { + lappend thread_list $num + } + } + } + + return $thread_list +} + +# Check that MI and the console know of the same threads. +# Appends NAME to all test names. +proc check_mi_and_console_threads {name} { + global expect_out + + mi_gdb_test "-thread-list-ids" \ + {\^done,thread-ids={(thread-id="[0-9]+"(,)*)+},number-of-threads="[0-9]+"} \ + "-thread-list-ids ($name)" + set mi_output {} + if {[info exists expect_out(buffer)]} { + set mi_output $expect_out(buffer) + } + + # GDB will return a list of thread ids and some more info: + # + # (gdb) + # -interpreter-exec console "info threads" + # ~" 4 Thread 2051 (LWP 7734) 0x401166b1 in __libc_nanosleep () at __libc_nanosleep:-1" + # ~" 3 Thread 1026 (LWP 7733) () at __libc_nanosleep:-1" + # ~" 2 Thread 2049 (LWP 7732) 0x401411f8 in __poll (fds=0x804bb24, nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:63" + # ~"* 1 Thread 1024 (LWP 7731) main (argc=1, argv=0xbfffdd94) at ../../../src/gdb/testsuite/gdb.mi/pthreads.c:160" + # FIXME: kseitz/2002-09-05: Don't use the hack-cli method. + mi_gdb_test "info threads" \ + {.*(~".*"[\r\n]*)+.*} \ + "info threads ($name)" + set console_output {} + if {[info exists expect_out(buffer)]} { + set console_output $expect_out(buffer) + } + + # Make a list of all known threads to console (gdb's thread IDs) + set console_thread_list {} + foreach line [split $console_output \n] { + if {[string index $line 0] == "~"} { + # This is a line from the console; trim off "~", " ", "*", and "\"" + set line [string trim $line ~\ \"\*] + if {[scan $line "%d" id] == 1} { + lappend console_thread_list $id + } + } + } + + # Now find the result string from MI + set mi_result "" + foreach line [split $mi_output \n] { + if {[string range $line 0 4] == "^done"} { + set mi_result $line + } + } + if {$mi_result == ""} { + fail "finding MI result string ($name)" + } else { + pass "finding MI result string ($name)" + } + + # Finally, extract the thread ids and compare them to the console + set num_mi_threads_str "" + if {![regexp {number-of-threads="[0-9]+"} $mi_result num_mi_threads_str]} { + fail "finding number of threads in MI output ($name)" + } else { + pass "finding number of threads in MI output ($name)" + + # Extract the number of threads from the MI result + if {![scan $num_mi_threads_str {number-of-threads="%d"} num_mi_threads]} { + fail "got number of threads from MI ($name)" + } else { + pass "got number of threads from MI ($name)" + + # Check if MI and console have same number of threads + if {$num_mi_threads != [llength $console_thread_list]} { + fail "console and MI have same number of threads ($name)" + } else { + pass "console and MI have same number of threads ($name)" + + # Get MI thread list + set mi_thread_list [get_mi_thread_list $name] + + # Check if MI and console have the same threads + set fails 0 + foreach ct [lsort $console_thread_list] mt [lsort $mi_thread_list] { + if {$ct != $mt} { + incr fails + } + } + if {$fails > 0} { + fail "MI and console have same threads ($name)" + + # Send a list of failures to the log + send_log "Console has thread ids: $console_thread_list\n" + send_log "MI has thread ids: $mi_thread_list\n" + } else { + pass "MI and console have same threads ($name)" + } + } + } + } +} + +# +# Start here +# +set testfile "pthreads" +set srcfile "$testfile.c" +set binfile "$objdir/$subdir/$testfile" + +set options [list debug incdir=$subdir] +if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] + != "" } { + gdb_suppress_entire_file \ + "Testcase compile failed, so all tests in this file will automatically fail." +} + +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_load $binfile + +mi_run_to_main +check_mi_and_console_threads "at main" + +for {set i 0} {$i < 4} {incr i} { + mi_next "next, try $i" + check_mi_and_console_threads "try $i" +} + +mi_gdb_exit + diff --git a/gdb/testsuite/gdb.mi/gdb680.exp b/gdb/testsuite/gdb.mi/gdb680.exp new file mode 100644 index 00000000000..eee96a69ac1 --- /dev/null +++ b/gdb/testsuite/gdb.mi/gdb680.exp @@ -0,0 +1,56 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# +# test gdb/680 +# + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +gdb_exit +if [mi_gdb_start] { + continue +} + +proc do_test {count} { + mi_gdb_test "-data-list-register-names -1" \ + {\^error,msg=\"bad register number\"} \ + "-data-list-register-names -1, try $count" +} + +# Tests a bug with ui-out and nested uiout types. When +# an error is encountered building a nest typed, like +# lists or tuples, the uiout is not reset to some sane +# state. As a result, uiout still thinks it is building +# this nested type. Execute enough of these errors and +# an assertion failure occurs. This is most obvious +# with invalid register number and the register commands. + +# MAX_UIOUT_LEVELS is set to 5. +set counter 0 +for {set i 0} {$i < 4} {incr i} { + do_test $i +} + +#setup_kfail "gdb/680" +do_test $i + +mi_gdb_exit +return 0 diff --git a/gdb/testsuite/gdb.mi/gdb701.c b/gdb/testsuite/gdb.mi/gdb701.c new file mode 100644 index 00000000000..16e5c297340 --- /dev/null +++ b/gdb/testsuite/gdb.mi/gdb701.c @@ -0,0 +1,15 @@ +struct _foo +{ + int x; + int y; + int z; +}; + +typedef struct _foo Foo; + +int +main (int argc, char *argv[]) +{ + Foo *foo = 0; + exit (0); +} diff --git a/gdb/testsuite/gdb.mi/gdb701.exp b/gdb/testsuite/gdb.mi/gdb701.exp new file mode 100644 index 00000000000..703ec6a9fc3 --- /dev/null +++ b/gdb/testsuite/gdb.mi/gdb701.exp @@ -0,0 +1,67 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# +# test gdb/701 +# + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +gdb_exit +if [mi_gdb_start] { + continue +} + +set testfile gdb701 +set srcfile "$testfile.c" +set binfile $objdir/$subdir/$testfile +if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable debug] != ""} { + gdb_suppress_entire_file "Testcase compile failed, so all test in this file will automatically fail." +} + +# When varobj reports the types of objects, it often isn't really reporting +# the type as GDB knows it. For example, in this testcase, we have a +# structure which has been typedefed. A varobj of this type would really have +# a type of "TYPE_CODE_TYPEDEF". It's target type is "TYPE_CODE_STRUCT". Varobj +# should skip over the TYPEDEF type when figuring out the varobj's children. +# If it doesn't, Bad Things Happen(TM). + +# Run to main +mi_run_to_main + +# Step over "foo = 0" +mi_next "step over \"foo = 0\"" + +mi_gdb_test "-var-create fooPtr * foo" \ + "(&\".*\"\r\n)*\\^done,name=\"fooPtr\",numchild=\"3\",type=\"Foo \\*\"" \ + "create fooPtr" + +mi_gdb_test "-var-list-children fooPtr" \ + "(&\".*\"\r\n)*\\^done,numchild=\"3\",.*" \ + "list children of fooPtr" + +foreach i [list x y z] { + mi_gdb_test "-var-list-children fooPtr.$i" \ + "(&\".*\"\r\n)*\\^done,numchild=\"0\"" \ + "list children of fooPtr.$i" +} + +mi_gdb_exit +return 0 diff --git a/gdb/testsuite/gdb.threads/killed.c b/gdb/testsuite/gdb.threads/killed.c new file mode 100644 index 00000000000..6cb3928a346 --- /dev/null +++ b/gdb/testsuite/gdb.threads/killed.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +int pid; + +void * +child_func (void *dummy) +{ + kill (pid, SIGKILL); + exit (1); +} + +int +main () +{ + pthread_t child; + + pid = getpid (); + pthread_create (&child, 0, child_func, 0); + for (;;) + sleep (10000); +} diff --git a/gdb/testsuite/gdb.threads/killed.exp b/gdb/testsuite/gdb.threads/killed.exp new file mode 100644 index 00000000000..21e03aab5ec --- /dev/null +++ b/gdb/testsuite/gdb.threads/killed.exp @@ -0,0 +1,97 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# This is a regression test for gdb/568 in the sources.redhat.com +# GNATS database. As of early June 2002, GDB could get sort of wedged +# debugging the program `killed.c': +# +# $ $D6/gdb/gdb -nw killed +# GNU gdb 2002-06-11-cvs +# Copyright 2002 Free Software Foundation, Inc. +# GDB is free software, covered by the GNU General Public License, and you are +# welcome to change it and/or distribute copies of it under certain conditions. +# Type "show copying" to see the conditions. +# There is absolutely no warranty for GDB. Type "show warranty" for details. +# This GDB was configured as "i686-pc-linux-gnu"... +# (gdb) run +# Starting program: /home/jimb/foo/play/killed +# [New Thread 1024 (LWP 6487)] +# [New Thread 2049 (LWP 6488)] +# [New Thread 1026 (LWP 6489)] +# Cannot find user-level thread for LWP 6487: generic error +# (gdb) quit +# The program is running. Exit anyway? (y or n) y +# Cannot find thread 2049: generic error +# (gdb) kill +# Kill the program being debugged? (y or n) y +# Cannot find thread 2049: generic error +# (gdb) The program is running. Exit anyway? (y or n) y +# Cannot find thread 2049: generic error +# (gdb) +# [7]+ Stopped $D6/gdb/gdb -nw killed +# $ kill %7 +# +# [7]+ Stopped $D6/gdb/gdb -nw killed +# $ kill -9 %7 +# +# [7]+ Stopped $D6/gdb/gdb -nw killed +# $ +# [7]+ Killed $D6/gdb/gdb -nw killed +# $ + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "killed" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}/${subdir}"]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "run" "" "run program to completion" + +# Try to quit. +send_gdb "quit\n" +gdb_expect { + -re "The program is running. Exit anyway\\? \\(y or n\\) $" { + send_gdb "y\n" + exp_continue + } + eof { + pass "GDB exits after multi-threaded program exits messily" + } + -re "Cannot find thread ${decimal}: generic error\[\r\n\]*$gdb_prompt $" { + # setup_kfail "gdb/568" + fail "GDB exits after multi-threaded program exits messily (not a regression; gdb/568)" + } + timeout { + fail "GDB exits after multi-threaded program exits messily (timeout)" + } +} diff --git a/libiberty/testsuite/test-demangle.c b/libiberty/testsuite/test-demangle.c new file mode 100644 index 00000000000..82f263e88af --- /dev/null +++ b/libiberty/testsuite/test-demangle.c @@ -0,0 +1,175 @@ +/* Demangler test program, + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Zack Weinberg +#include "libiberty.h" +#include "demangle.h" + +struct line +{ + size_t alloced; + char *data; +}; + +static unsigned int lineno; + +/* Safely read a single line of arbitrary length from standard input. */ + +#define LINELEN 80 + +static void +getline(buf) + struct line *buf; +{ + char *data = buf->data; + size_t alloc = buf->alloced; + size_t count = 0; + int c; + + if (data == 0) + { + data = xmalloc (LINELEN); + alloc = LINELEN; + } + + /* Skip comment lines. */ + while ((c = getchar()) == '#') + { + while ((c = getchar()) != EOF && c != '\n'); + lineno++; + } + + /* c is the first character on the line, and it's not a comment + line: copy this line into the buffer and return. */ + while (c != EOF && c != '\n') + { + if (count >= alloc) + { + alloc *= 2; + data = xrealloc (data, alloc); + } + data[count++] = c; + c = getchar(); + } + lineno++; + data[count] = '\0'; + + buf->data = data; + buf->alloced = alloc; +} + +/* The tester operates on a data file consisting of triples of lines: + format switch + input to be demangled + expected output + + The format switch is expected to be either the empty string, a + line of the form --format=, or just by itself. */ + +#define FORMATS "--format=" +#define FORMATL (sizeof FORMATS - 1) + +int +main(argc, argv) + int argc; + char **argv; +{ + enum demangling_styles style; + struct line format; + struct line input; + struct line expect; + char *fstyle; + char *result; + int failures = 0; + int tests = 0; + + if (argc > 1) + { + fprintf (stderr, "usage: %s < test-set\n", argv[0]); + return 2; + } + + format.data = 0; + input.data = 0; + expect.data = 0; + + for (;;) + { + getline (&format); + if (feof (stdin)) + break; + + getline (&input); + getline (&expect); + + tests++; + + fstyle = format.data; + if (!strncmp (fstyle, FORMATS, FORMATL)) + fstyle += FORMATL; + + if (fstyle[0] == '\0') + style = auto_demangling; + else + style = cplus_demangle_name_to_style (fstyle); + + if (style == unknown_demangling) + { + printf ("FAIL at line %d: unknown demangling style %s\n", + lineno, fstyle); + failures++; + continue; + } + + cplus_demangle_set_style (style); + + result = cplus_demangle (input.data, + DMGL_PARAMS|DMGL_ANSI|DMGL_VERBOSE|DMGL_TYPES); + + if (result + ? strcmp (result, expect.data) + : strcmp (input.data, expect.data)) + { + printf ("\ +FAIL at line %d, style %s:\n\ +in: %s\n\ +out: %s\n\ +exp: %s\n", + lineno, fstyle, + input.data, + result, + expect.data); + failures++; + } + free (result); + } + + free (format.data); + free (input.data); + free (expect.data); + + printf ("%s: %d tests, %d failures\n", argv[0], tests, failures); + return failures ? 1 : 0; +} -- 2.47.2