diff options
-rw-r--r-- | libiberty/ChangeLog | 193 | ||||
-rw-r--r-- | libiberty/Makefile.in | 50 | ||||
-rw-r--r-- | libiberty/aclocal.m4 | 71 | ||||
-rw-r--r-- | libiberty/choose-temp.c | 10 | ||||
-rw-r--r-- | libiberty/config.in | 9 | ||||
-rw-r--r-- | libiberty/config.table | 1 | ||||
-rwxr-xr-x | libiberty/configure | 585 | ||||
-rw-r--r-- | libiberty/configure.in | 25 | ||||
-rw-r--r-- | libiberty/cp-demangle.c | 3015 | ||||
-rw-r--r-- | libiberty/cplus-dem.c | 186 | ||||
-rw-r--r-- | libiberty/dyn-string.c | 333 | ||||
-rw-r--r-- | libiberty/hashtab.c | 169 | ||||
-rw-r--r-- | libiberty/memcmp.c | 4 | ||||
-rw-r--r-- | libiberty/mkstemps.c | 2 | ||||
-rw-r--r-- | libiberty/partition.c | 8 | ||||
-rw-r--r-- | libiberty/setenv.c | 12 | ||||
-rw-r--r-- | libiberty/strncmp.c | 28 | ||||
-rw-r--r-- | libiberty/xmalloc.c | 3 |
18 files changed, 4421 insertions, 283 deletions
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index c375430291a..e7bac6d4758 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,11 +1,83 @@ -2000-06-06 DJ Delorie <dj@cygnus.com> +2000-06-09 Zack Weinberg <zack@wolery.cumb.org> - * Makefile.in: add EXTRA_INCS - * configure.in: if with-newlib, point to it for includes - rather than using the installed includes, for target builds. - If cygwin, override function list only for target builds. - * configure: regenerate + * cp-demangle.c (demangle_operator_name): Add spaces before + names beginning with a letter: delete, delete[], new, new[], + sizeof. + (demangle_special_name): Handle TF <type> and TJ <type>. + +Thu Jun 8 18:52:24 2000 Philippe De Muyter <phdm@macqel.be> + + * cp-demangle.c (template_arg_list_new): Revert previous PARAMS patch. + +Thu Jun 8 09:25:54 2000 Philippe De Muyter <phdm@macqel.be> + + * cp-demangle.c (stdio.h): File included unconditionaly. + (template_arg_list_new): Parameter list is PARAMS ((void)), not (). + * dyn-string.c (stdio.h): File included. + * partition.c (partition_print): No `&' needed to take the address of + a function. + +2000-06-07 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * configure.in (ac_libiberty_warn_cflags): Add -pedantic. + + * choose-temp.c (try, choose_temp_base, make_temp_file): Constify. + + * cp-demangle.c (demangle_char): Change parameter from char to int. + (demangle_expression, demangle_expr_primary): Remove extra + semi-colon in prototype. + + * dyn-string.c (dyn_string_append_char): Change parameter from + char to int. + + * memcmp.c (memcmp): Constify. + + * mkstemps.c (gcc_uint64_t): Mark GNUC `long long' case with + __extension__. + + * partition.c (elem_compare): Prototype. Don't cast away + const-ness. + + * setenv.c (setenv): Use braces to avoid ambiguous `else'. + +2000-06-07 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + * Makefile.in (cp-demangle.o): Depend on $(INCDIR)/demangle.h. + + * cp-demangle.c: Include demangle.h. + (template_arg_list_new): DeANSIfy. + (cp_demangle): Make static and add prototype. + (operator_code, operators): Constify. + (demangle_operator_name): Likewise for variables `p1', `p2' and `p'. + +2000-06-05 Alex Samuel <samuel@codesourcery.com> + + * cp-demangle.c (demangle_prefix): Cast argument to isdigit to + unsigned char. + (demangle_unqualified_name): Likewise. + (demangle_number_literally): Likewise. + (demangle_type): Likewise. + (demangle_substitution): Likewise. + (is_mangled_char): Likewise, for isalnum. + +2000-06-04 Alex Samuel <samuel@codesourcery.com> + + * Makefile.in (CFILES): Add cp-demangle.c and dyn-string.c. + (REQUIRED_OFILES): Add cp-demangle.o and dyn-string.o. + (cp-demangle.o): New dependency. + (dyn-string.o): Likewise. + + * dyn-string.c: Move here from gcc/dyn-string.c. Add new functions. + + * cplus-dem.c (libiberty_demanglers): Add initializer for new-ABI + demangler. + (cplus_demangle): Call cplus_demangle_new_abi if in new-ABI + demangling mode. + (gnu_new_abi_symbol_characters): New function. + (main): Use gnu_new_abi_symbol_characters. * cp-demangle.c: New + file. + * cp-demangle.c: New file. + Tue May 30 16:45:25 2000 Andrew Cagney <cagney@b1.cygnus.com> * floatformat.c: Add name to each floatformat field. @@ -16,7 +88,7 @@ Tue May 30 15:07:52 2000 Jeffrey A Law (law@cygnus.com) 2000-05-29 Zack Weinberg <zack@wolery.cumb.org> - * hashtab.c, partition.c, xmemdup.c: Include string.h + * hashtab.c, partition.c, sort.c, xmemdup.c: Include string.h if HAVE_STRING_H. * pexecute.c, xexit.c: Include stdlib.h if HAVE_STDLIB_H. * objalloc.c: Include config.h. Include stdlib.h and don't @@ -26,22 +98,125 @@ Tue May 30 15:07:52 2000 Jeffrey A Law (law@cygnus.com) HAVE_STRING_H, else declare memset without prototype. Don't include stddef.h. - * sort.c: Bring over from GCC. +2000-05-23 Mike Stump <mrs@wrs.com> + + * Makefile.in (xmalloc.o): Add dependency for config.h, fixes make + -j3. + +2000-05-18 J. David Anglin <dave@hiauly1.hia.nrc.ca> + + * xmalloc.c: Include config.h for HAVE_SBRK definition. + +2000-05-16 Horst von Brand <vonbrand@sleipnir.valparaiso.cl> + + * hashtab.c (hash_pointer): Delete low-order bits which are + probably zero, also eliminate a warning on alpha. + +2000-05-15 David Edelsohn <edelsohn@gnu.org> + + * Makefile.in: Change "pic" to depend on $(PICFLAG), not + on $(enable_shared). + +2000-05-10 Jakub Jelinek <jakub@redhat.com> + + * config.table: Use mh-sparcpic for sparc*-*-*. -2000-05-26 Alexandre Oliva <aoliva@cygnus.com> +2000-05-08 Nick Clifton <nickc@cygnus.com> + + * Makefile.in (CFILES): Add strncmp.c. + (NEEDED): Add strncmp. + +2000-05-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * cplus-dem.c (cplus_demangle_opname, demangle_function_name): + Cast the arguments to `islower' to `unsigned char'. + (print_demangler_list): Prototype. + +Thu May 4 17:14:41 2000 Philippe De Muyter <phdm@macqel.be> + + * sort.c (UCHAR_MAX): Provide fallback definition. + +2000-04-29 Alexandre Oliva <aoliva@cygnus.com> * Makefile.in (maintainer-clean-subdir): Fix handling of empty SUBDIRS. +2000-04-28 Kenneth Block <block@zk3.dec.com> + Jason Merrill <jason@casey.cygnus.com> + + * cplus-dem.c (libiberty_demanglers): New table for demangle styles. + (cplus_demangle_set_style): New function for setting style. + (cplus_demangle_name_to_style): New function to translate name. + +2000-04-27 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * aclocal.m4: New file with new test libiberty_AC_FUNC_STRNCMP. + + * configure.in (AC_CHECK_HEADERS): Add sys/mman.h fcntl.h. + (libiberty_AC_FUNC_STRNCMP): Invoke. + + * strncmp.c: New file. + +Thu Apr 27 16:58:43 MET DST 2000 Jan Hubicka <jh@suse.cz> + + * hashtab.c (htab_expand): Add prototype. + (find_empty_slot_for_expand): Likewise. + +2000-04-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * hashtab.c (hash_pointer, eq_pointer): Make definition static to + match prototype. + (htab_expand): Cast the return value of xcalloc. + +2000-04-24 Mark Mitchell <mark@codesourcery.com> + + * hashtab.c (hash_pointer): New function. + (eq_pointer): Likewise. + (htab_hash_pointer): New variable. + (htab_eq_pointer): Likewise. + +2000-04-23 Mark Mitchell <mark@codesourcery.com> + + * sort.c (sort_pointers): Fix endianness bugs. + + * sort.c: New file. + * Makefile.in (CFILES): Add sort.c + (REQUIRED_OFILES): Add sort.o. + (sort.o): New target. + 2000-04-21 Michael Sokolov <msokolov@ivan.Harhan.ORG> * Makefile.in (*-subdir): Revamp slightly to avoid losing on 4.3BSD systems. +Tue Apr 18 16:23:31 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * hashtab.c: Various minor cleanups. + (htab_find_slot_with_hash): INSERT is now enum insert_option. + (htab_find_slot): Likewise. + +2000-04-16 Dave Pitts <dpitts@cozx.com> + + * cplus-dem.c (cplus_demangle_opname): Changed to use islower. + 2000-04-05 Richard Henderson <rth@cygnus.com> * splay-tree.c (splay_tree_remove): New. +2000-03-30 Mark Mitchell <mark@codesourcery.com> + + * hashtab.c (find_empty_slot_for_expand): Use hashval_t for hash + codes. + (htab_find_with_hash): Likewise. + (htab_find_slot_with_hash): Likewise. + +2000-03-29 Zack Weinberg <zack@wolery.cumb.org> + + * hashtab.c (htab_find_with_hash): Avoid calculating hash2 + unless it will be used. Rearrange loop for better + optimization. + (higher_prime_number): Add static prototype. + Thu Mar 16 01:33:58 2000 Jeffrey A Law (law@cygnus.com) * Makefile.in (partition.o): Depend on config.h diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in index f9c1621fcc9..a95adcdccc0 100644 --- a/libiberty/Makefile.in +++ b/libiberty/Makefile.in @@ -1,6 +1,6 @@ # # Makefile -# Copyright (C) 1990, 91 - 99, 2000 +# Copyright (C) 1990, 91-99, 2000 # Free Software Foundation # # This file is part of the libiberty library. @@ -106,10 +106,11 @@ installcheck: installcheck-subdir INCDIR=$(srcdir)/$(MULTISRCTOP)../include -COMPILE.c = $(CC) -c @DEFS@ $(LIBCFLAGS) -I. -I$(INCDIR) @EXTRA_INCS@ $(HDEFINES) @ac_libiberty_warn_cflags@ +COMPILE.c = $(CC) -c @DEFS@ $(LIBCFLAGS) -I. -I$(INCDIR) $(HDEFINES) @ac_libiberty_warn_cflags@ .c.o: - test x"$(enable_shared)" != xyes || \ - $(COMPILE.c) $(PICFLAG) $< -o pic/$@ + if [ x"$(PICFLAG)" != x ]; then \ + $(COMPILE.c) $(PICFLAG) $< -o pic/$@; \ + else true; fi $(COMPILE.c) $< info: info-subdir @@ -124,23 +125,25 @@ HFILES = alloca-conf.h # (alphabetical), and add them to REQUIRED_OFILES or funcs in # configure.in. CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c \ - bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c fdmatch.c \ - fnmatch.c getcwd.c getpwd.c getopt.c getopt1.c getpagesize.c \ - getruntime.c floatformat.c hashtab.c hex.c index.c insque.c memchr.c \ - memcmp.c memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c \ - partition.c pexecute.c putenv.c random.c rename.c rindex.c \ - setenv.c sigsetmask.c spaces.c splay-tree.c strcasecmp.c \ - strncasecmp.c strchr.c strdup.c strerror.c strrchr.c \ - strsignal.c strstr.c strtod.c strtol.c strtoul.c tmpnam.c \ - vasprintf.c vfork.c vfprintf.c vprintf.c vsprintf.c waitpid.c \ - xatexit.c xexit.c xmalloc.c xmemdup.c xstrdup.c xstrerror.c + bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c \ + cp-demangle.c dyn-string.c fdmatch.c fnmatch.c getcwd.c \ + getpwd.c getopt.c getopt1.c getpagesize.c getruntime.c \ + floatformat.c hashtab.c hex.c index.c insque.c memchr.c memcmp.c \ + memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c \ + partition.c pexecute.c putenv.c random.c rename.c rindex.c setenv.c \ + sigsetmask.c sort.c spaces.c splay-tree.c strcasecmp.c strncasecmp.c \ + strchr.c strdup.c strerror.c strncmp.c strrchr.c strsignal.c strstr.c \ + strtod.c strtol.c strtoul.c tmpnam.c vasprintf.c vfork.c vfprintf.c \ + vprintf.c vsprintf.c waitpid.c xatexit.c xexit.c xmalloc.c \ + xmemdup.c xstrdup.c xstrerror.c # These are always included in the library. -REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o \ - fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o getruntime.o hashtab.o \ - hex.o floatformat.o objalloc.o obstack.o partition.o pexecute.o spaces.o \ - splay-tree.o strerror.o strsignal.o xatexit.o xexit.o xmalloc.o \ - xmemdup.o xstrdup.o xstrerror.o +REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o cp-demangle.o \ + dyn-string.o fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o \ + getruntime.o hashtab.o hex.o floatformat.o objalloc.o obstack.o \ + partition.o pexecute.o sort.o spaces.o splay-tree.o strerror.o \ + strsignal.o xatexit.o xexit.o xmalloc.o xmemdup.o xstrdup.o \ + xstrerror.o $(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS) $(ALLOCA) rm -f $(TARGETLIB) @@ -167,7 +170,7 @@ install_to_tooldir: all # to include there. Do not add anything LGPL to this list; libstdc++ # can't use anything encumbering. NEEDED = atexit calloc memchr memcmp memcpy memmove memset rename strchr \ - strerror strrchr strstr strtol strtoul tmpnam vfprintf vprintf \ + strerror strncmp strrchr strstr strtol strtoul tmpnam vfprintf vprintf \ vfork waitpid bcmp bcopy bzero needed-list: Makefile rm -f needed-list; touch needed-list; \ @@ -185,7 +188,7 @@ required-list: Makefile echo $(REQUIRED_OFILES) > required-list stamp-picdir: - if [ x"$(enable_shared)" = xyes ] && [ ! -d pic ]; then \ + if [ x"$(PICFLAG)" != x ] && [ ! -d pic ]; then \ mkdir pic; \ else true; fi touch stamp-picdir @@ -260,6 +263,8 @@ choose-temp.o: config.h clock.o: config.h concat.o: $(INCDIR)/libiberty.h cplus-dem.o: config.h $(INCDIR)/demangle.h +cp-demangle.o: config.h $(INCDIR)/dyn-string.h $(INCDIR)/demangle.h +dyn-string.o: config.h $(INCDIR)/dyn-string.h fdmatch.o: $(INCDIR)/libiberty.h fnmatch.o: config.h $(INCDIR)/fnmatch.h getcwd.o: config.h @@ -276,13 +281,14 @@ obstack.o: config.h $(INCDIR)/obstack.h partition.o: config.h $(INCDIR)/partition.h pexecute.o: config.h $(INCDIR)/libiberty.h setenv.o: config.h +sort.o: config.h $(INCDIR)/sort.h $(INCDIR)/ansidecl.h spaces.o: $(INCDIR)/libiberty.h splay-tree.o: config.h $(INCDIR)/libiberty.h $(INCDIR)/splay-tree.h $(INCDIR)/ansidecl.h strerror.o: config.h $(INCDIR)/libiberty.h strsignal.o: config.h $(INCDIR)/libiberty.h xatexit.o: $(INCDIR)/libiberty.h xexit.o: $(INCDIR)/libiberty.h -xmalloc.o: $(INCDIR)/libiberty.h +xmalloc.o: config.h $(INCDIR)/libiberty.h xmemdup.o: config.h $(INCDIR)/libiberty.h xstrdup.o: config.h $(INCDIR)/libiberty.h xstrerror.o: config.h $(INCDIR)/libiberty.h diff --git a/libiberty/aclocal.m4 b/libiberty/aclocal.m4 new file mode 100644 index 00000000000..b6a38d60522 --- /dev/null +++ b/libiberty/aclocal.m4 @@ -0,0 +1,71 @@ +dnl See whether strncmp reads past the end of its string parameters. +dnl On some versions of SunOS4 at least, strncmp reads a word at a time +dnl but erroneously reads past the end of strings. This can cause +dnl a SEGV in some cases. +AC_DEFUN(libiberty_AC_FUNC_STRNCMP, +[AC_REQUIRE([AC_FUNC_MMAP]) +AC_CACHE_CHECK([for working strncmp], ac_cv_func_strncmp_works, +[AC_TRY_RUN([ +/* Test by Jim Wilson and Kaveh Ghazi. + Check whether strncmp reads past the end of its string parameters. */ +#include <sys/types.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +#ifndef MAP_ANON +#ifdef MAP_ANONYMOUS +#define MAP_ANON MAP_ANONYMOUS +#else +#define MAP_ANON MAP_FILE +#endif +#endif + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif + +#define MAP_LEN 0x10000 + +main () +{ +#if defined(HAVE_MMAP) || defined(HAVE_MMAP_ANYWHERE) + char *p; + int dev_zero; + + dev_zero = open ("/dev/zero", O_RDONLY); + if (dev_zero < 0) + exit (1); + + p = (char *) mmap (0, MAP_LEN, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, dev_zero, 0); + if (p == (char *)-1) + exit (2); + else + { + char *string = "__si_type_info"; + char *q = (char *) p + MAP_LEN - strlen (string) - 2; + char *r = (char *) p + 0xe; + + strcpy (q, string); + strcpy (r, string); + strncmp (r, q, 14); + } +#endif /* HAVE_MMAP || HAVE_MMAP_ANYWHERE */ + exit (0); +} +], ac_cv_func_strncmp_works=yes, ac_cv_func_strncmp_works=no, + ac_cv_func_strncmp_works=no) +rm -f core core.* *.core]) +if test $ac_cv_func_strncmp_works = no ; then + LIBOBJS="$LIBOBJS strncmp.o" +fi +]) diff --git a/libiberty/choose-temp.c b/libiberty/choose-temp.c index 826d818ed62..1a475dd6fb9 100644 --- a/libiberty/choose-temp.c +++ b/libiberty/choose-temp.c @@ -79,9 +79,11 @@ extern int mkstemps (); If success, DIR is returned. Otherwise NULL is returned. */ -static char * +static const char *try PARAMS ((const char *, const char *)); + +static const char * try (dir, base) - char *dir, *base; + const char *dir, *base; { if (base != 0) return base; @@ -102,7 +104,7 @@ try (dir, base) char * choose_temp_base () { - char *base = 0; + const char *base = 0; char *temp_filename; int len; static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 }; @@ -147,7 +149,7 @@ char * make_temp_file (suffix) const char *suffix; { - char *base = 0; + const char *base = 0; char *temp_filename; int base_len, suffix_len; int fd; diff --git a/libiberty/config.in b/libiberty/config.in index 6e64208da92..bc0c7291a8c 100644 --- a/libiberty/config.in +++ b/libiberty/config.in @@ -13,6 +13,9 @@ /* Define if you have <alloca.h> and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + /* Define if you have <sys/wait.h> that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H @@ -196,6 +199,9 @@ /* Define if you have the waitpid function. */ #undef HAVE_WAITPID +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + /* Define if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H @@ -208,6 +214,9 @@ /* Define if you have the <sys/file.h> header file. */ #undef HAVE_SYS_FILE_H +/* Define if you have the <sys/mman.h> header file. */ +#undef HAVE_SYS_MMAN_H + /* Define if you have the <sys/param.h> header file. */ #undef HAVE_SYS_PARAM_H diff --git a/libiberty/config.table b/libiberty/config.table index 4e33746164c..ea3312bc072 100644 --- a/libiberty/config.table +++ b/libiberty/config.table @@ -27,6 +27,7 @@ if [ "${shared}" = "yes" ]; then i[3456]86-*-*) frags="${frags} ../../config/mh-x86pic" ;; powerpc*-*-aix*) ;; powerpc*-*-*) frags="${frags} ../../config/mh-ppcpic" ;; + sparc*-*-*) frags="${frags} ../../config/mh-sparcpic" ;; *-*-*) frags="${frags} ../../config/mh-${host_cpu}pic" ;; esac fi diff --git a/libiberty/configure b/libiberty/configure index e16dc845bce..ef375bbcccd 100755 --- a/libiberty/configure +++ b/libiberty/configure @@ -34,7 +34,6 @@ program_suffix=NONE program_transform_name=s,x,x, silent= site= -sitefile= srcdir= target=NONE verbose= @@ -149,7 +148,6 @@ Configuration: --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages - --site-file=FILE use FILE as the site file --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX @@ -320,11 +318,6 @@ EOF -site=* | --site=* | --sit=*) site="$ac_optarg" ;; - -site-file | --site-file | --site-fil | --site-fi | --site-f) - ac_prev=sitefile ;; - -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*) - sitefile="$ac_optarg" ;; - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) @@ -490,16 +483,12 @@ fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. -if test -z "$sitefile"; then - if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi -else - CONFIG_SITE="$sitefile" fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then @@ -598,7 +587,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:602: checking host system type" >&5 +echo "configure:591: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -621,7 +610,7 @@ echo "$ac_t""$host" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:625: checking build system type" >&5 +echo "configure:614: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -647,7 +636,7 @@ fi # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:651: checking for $ac_word" >&5 +echo "configure:640: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -679,7 +668,7 @@ fi # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:683: checking for $ac_word" >&5 +echo "configure:672: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -711,7 +700,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:715: checking for $ac_word" >&5 +echo "configure:704: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -757,7 +746,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:761: checking for $ac_word" >&5 +echo "configure:750: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -787,7 +776,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:791: checking for $ac_word" >&5 +echo "configure:780: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -836,7 +825,7 @@ fi fi echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:840: checking whether we are using GNU C" >&5 +echo "configure:829: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -845,7 +834,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:838: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -856,12 +845,12 @@ echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes - ac_libiberty_warn_cflags='-W -Wall -Wtraditional' + ac_libiberty_warn_cflags='-W -Wall -Wtraditional -pedantic' ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:865: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:854: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -891,7 +880,7 @@ fi echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 -echo "configure:895: checking for POSIXized ISC" >&5 +echo "configure:884: checking for POSIXized ISC" >&5 if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 then @@ -929,7 +918,7 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:933: checking for a BSD compatible install" >&5 +echo "configure:922: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -990,7 +979,7 @@ host_makefile_frag=${frag} # able to link anything, it had better be able to at least compile # something. echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:994: checking how to run the C preprocessor" >&5 +echo "configure:983: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1005,13 +994,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 1009 "configure" +#line 998 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1015: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1004: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1022,13 +1011,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 1026 "configure" +#line 1015 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1032: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1021: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1039,13 +1028,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext <<EOF -#line 1043 "configure" +#line 1032 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1049: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1038: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1069,21 +1058,21 @@ else fi echo "$ac_t""$CPP" 1>&6 -for ac_hdr in sys/file.h sys/param.h stdlib.h string.h unistd.h strings.h sys/time.h sys/resource.h sys/stat.h +for ac_hdr in sys/file.h sys/param.h stdlib.h string.h unistd.h strings.h sys/time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1077: checking for $ac_hdr" >&5 +echo "configure:1066: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1082 "configure" +#line 1071 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1087: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1076: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1110,12 +1099,12 @@ fi done echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:1114: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo "configure:1103: checking for sys/wait.h that is POSIX.1 compatible" >&5 if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1119 "configure" +#line 1108 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/wait.h> @@ -1131,7 +1120,7 @@ wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:1135: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1124: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -1207,12 +1196,12 @@ if test "x" = "y"; then for ac_func in asprintf atexit basename bcmp bcopy bzero calloc clock getcwd do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1211: checking for $ac_func" >&5 +echo "configure:1200: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1216 "configure" +#line 1205 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1235,7 +1224,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1239: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1228: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1262,12 +1251,12 @@ done for ac_func in getpagesize index insque mkstemps memchr memcmp memcpy memmove do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1266: checking for $ac_func" >&5 +echo "configure:1255: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1271 "configure" +#line 1260 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1290,7 +1279,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1294: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1317,12 +1306,12 @@ done for ac_func in memset putenv random rename rindex sigsetmask strcasecmp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1321: checking for $ac_func" >&5 +echo "configure:1310: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1326 "configure" +#line 1315 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1345,7 +1334,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1349: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1338: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1372,12 +1361,12 @@ done for ac_func in setenv strchr strdup strncasecmp strrchr strstr strtod strtol do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1376: checking for $ac_func" >&5 +echo "configure:1365: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1381 "configure" +#line 1370 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1400,7 +1389,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1393: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1427,12 +1416,12 @@ done for ac_func in strtoul tmpnam vasprintf vfprintf vprintf vsprintf waitpid do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1431: checking for $ac_func" >&5 +echo "configure:1420: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1436 "configure" +#line 1425 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1455,7 +1444,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1448: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1494,12 +1483,12 @@ EOF for ac_func in getrusage on_exit psignal strerror strsignal sysconf times do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1498: checking for $ac_func" >&5 +echo "configure:1487: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1503 "configure" +#line 1492 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1522,7 +1511,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1526: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1515: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1549,12 +1538,12 @@ done for ac_func in sbrk gettimeofday do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1553: checking for $ac_func" >&5 +echo "configure:1542: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1558 "configure" +#line 1547 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1577,7 +1566,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1581: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1570: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1649,11 +1638,6 @@ EOF setobjs=yes - if test -d ${libiberty_topdir}/newlib - then - EXTRA_INCS="-I${libiberty_topdir}/newlib/libc/include" - fi - fi else @@ -1665,7 +1649,6 @@ fi - if test -z "${setobjs}"; then case "${host}" in @@ -1722,15 +1705,10 @@ if test -z "${setobjs}"; then # provides from our shell variables, so that they appear to be # missing. - # DJ - only if we're *building* cygwin, not just building *with* cygwin - - if test -n "${with_target_subdir}" - then - funcs="`echo $funcs | sed -e 's/random//'`" - LIBOBJS="$LIBOBJS random.o" - vars="`echo $vars | sed -e 's/sys_siglist//'`" - checkfuncs="`echo $checkfuncs | sed -e 's/strsignal//' -e 's/psignal//'`" - fi + funcs="`echo $funcs | sed -e 's/random//'`" + LIBOBJS="$LIBOBJS random.o" + vars="`echo $vars | sed -e 's/sys_siglist//'`" + checkfuncs="`echo $checkfuncs | sed -e 's/strsignal//' -e 's/psignal//'`" ;; *-*-mingw32*) @@ -1770,7 +1748,7 @@ EOF # We haven't set the list of objects yet. Use the standard autoconf # tests. This will only work if the compiler works. echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1774: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1752: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1781,12 +1759,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 1785 "configure" +#line 1763 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1768: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1812,19 +1790,19 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1816: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1794: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross for ac_func in $funcs do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1823: checking for $ac_func" >&5 +echo "configure:1801: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1828 "configure" +#line 1806 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1847,7 +1825,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1829: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1894,19 +1872,19 @@ EOF # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:1898: checking for working alloca.h" >&5 +echo "configure:1876: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1903 "configure" +#line 1881 "configure" #include "confdefs.h" #include <alloca.h> int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:1910: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1888: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -1927,12 +1905,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:1931: checking for alloca" >&5 +echo "configure:1909: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1936 "configure" +#line 1914 "configure" #include "confdefs.h" #ifdef __GNUC__ @@ -1960,7 +1938,7 @@ int main() { char *p = (char *) alloca(1); ; return 0; } EOF -if { (eval echo configure:1964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1942: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -1992,12 +1970,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:1996: checking whether alloca needs Cray hooks" >&5 +echo "configure:1974: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2001 "configure" +#line 1979 "configure" #include "confdefs.h" #if defined(CRAY) && ! defined(CRAY2) webecray @@ -2022,12 +2000,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2026: checking for $ac_func" >&5 +echo "configure:2004: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2031 "configure" +#line 2009 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -2050,7 +2028,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:2054: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2077,7 +2055,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:2081: checking stack direction for C alloca" >&5 +echo "configure:2059: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2085,7 +2063,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <<EOF -#line 2089 "configure" +#line 2067 "configure" #include "confdefs.h" find_stack_direction () { @@ -2104,7 +2082,7 @@ main () exit (find_stack_direction() < 0); } EOF -if { (eval echo configure:2108: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -2129,12 +2107,12 @@ fi esac echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2133: checking for ANSI C header files" >&5 +echo "configure:2111: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2138 "configure" +#line 2116 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> @@ -2142,7 +2120,7 @@ else #include <float.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2146: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2124: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2159,7 +2137,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 2163 "configure" +#line 2141 "configure" #include "confdefs.h" #include <string.h> EOF @@ -2177,7 +2155,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 2181 "configure" +#line 2159 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -2198,7 +2176,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 2202 "configure" +#line 2180 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2209,7 +2187,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2213: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2233,12 +2211,12 @@ EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:2237: checking for pid_t" >&5 +echo "configure:2215: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2242 "configure" +#line 2220 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -2267,17 +2245,17 @@ fi ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for vfork.h""... $ac_c" 1>&6 -echo "configure:2271: checking for vfork.h" >&5 +echo "configure:2249: checking for vfork.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2276 "configure" +#line 2254 "configure" #include "confdefs.h" #include <vfork.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2281: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2259: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2302,18 +2280,18 @@ else fi echo $ac_n "checking for working vfork""... $ac_c" 1>&6 -echo "configure:2306: checking for working vfork" >&5 +echo "configure:2284: checking for working vfork" >&5 if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then echo $ac_n "checking for vfork""... $ac_c" 1>&6 -echo "configure:2312: checking for vfork" >&5 +echo "configure:2290: checking for vfork" >&5 if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2317 "configure" +#line 2295 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char vfork(); below. */ @@ -2336,7 +2314,7 @@ vfork(); ; return 0; } EOF -if { (eval echo configure:2340: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vfork=yes" else @@ -2358,7 +2336,7 @@ fi ac_cv_func_vfork_works=$ac_cv_func_vfork else cat > conftest.$ac_ext <<EOF -#line 2362 "configure" +#line 2340 "configure" #include "confdefs.h" /* Thanks to Paul Eggert for this test. */ #include <stdio.h> @@ -2453,7 +2431,7 @@ main() { } } EOF -if { (eval echo configure:2457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2435: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_vfork_works=yes else @@ -2480,19 +2458,19 @@ fi fi for v in $vars; do echo $ac_n "checking for $v""... $ac_c" 1>&6 -echo "configure:2484: checking for $v" >&5 +echo "configure:2462: checking for $v" >&5 if eval "test \"`echo '$''{'libiberty_cv_var_$v'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2489 "configure" +#line 2467 "configure" #include "confdefs.h" int *p; int main() { extern int $v; p = &$v; ; return 0; } EOF -if { (eval echo configure:2496: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2474: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "libiberty_cv_var_$v=yes" else @@ -2518,12 +2496,109 @@ EOF for ac_func in $checkfuncs do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2522: checking for $ac_func" >&5 +echo "configure:2500: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2505 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +fi + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2558: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2563 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2568: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2597: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2527 "configure" +#line 2602 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -2546,7 +2621,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:2550: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2625: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2570,8 +2645,269 @@ else fi done +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:2650: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext <<EOF +#line 2658 "configure" +#include "confdefs.h" + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the filesystem buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propogated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ +#include <sys/types.h> +#include <fcntl.h> +#include <sys/mman.h> + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:2798: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + fi + +echo $ac_n "checking for working strncmp""... $ac_c" 1>&6 +echo "configure:2822: checking for working strncmp" >&5 +if eval "test \"`echo '$''{'ac_cv_func_strncmp_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_strncmp_works=no +else + cat > conftest.$ac_ext <<EOF +#line 2830 "configure" +#include "confdefs.h" + +/* Test by Jim Wilson and Kaveh Ghazi. + Check whether strncmp reads past the end of its string parameters. */ +#include <sys/types.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +#ifndef MAP_ANON +#ifdef MAP_ANONYMOUS +#define MAP_ANON MAP_ANONYMOUS +#else +#define MAP_ANON MAP_FILE +#endif +#endif + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif + +#define MAP_LEN 0x10000 + +main () +{ +#if defined(HAVE_MMAP) || defined(HAVE_MMAP_ANYWHERE) + char *p; + int dev_zero; + + dev_zero = open ("/dev/zero", O_RDONLY); + if (dev_zero < 0) + exit (1); + + p = (char *) mmap (0, MAP_LEN, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, dev_zero, 0); + if (p == (char *)-1) + exit (2); + else + { + char *string = "__si_type_info"; + char *q = (char *) p + MAP_LEN - strlen (string) - 2; + char *r = (char *) p + 0xe; + + strcpy (q, string); + strcpy (r, string); + strncmp (r, q, 14); + } +#endif /* HAVE_MMAP || HAVE_MMAP_ANYWHERE */ + exit (0); +} + +EOF +if { (eval echo configure:2891: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_strncmp_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_strncmp_works=no +fi +rm -fr conftest* +fi + +rm -f core core.* *.core +fi + +echo "$ac_t""$ac_cv_func_strncmp_works" 1>&6 +if test $ac_cv_func_strncmp_works = no ; then + LIBOBJS="$LIBOBJS strncmp.o" +fi + + # Install a library built with a cross compiler in $(tooldir) rather # than $(libdir). if test -z "${with_cross_host}"; then @@ -2735,7 +3071,6 @@ s%@INSTALL_DATA@%$INSTALL_DATA%g /@host_makefile_frag@/r $host_makefile_frag s%@host_makefile_frag@%%g s%@CPP@%$CPP%g -s%@EXTRA_INCS@%$EXTRA_INCS%g s%@CHECK@%$CHECK%g s%@LIBOBJS@%$LIBOBJS%g s%@ALLOCA@%$ALLOCA%g diff --git a/libiberty/configure.in b/libiberty/configure.in index cc30251514d..6ad054a6448 100644 --- a/libiberty/configure.in +++ b/libiberty/configure.in @@ -55,7 +55,7 @@ AC_PROG_CC_GNU if test $ac_cv_prog_gcc = yes; then GCC=yes - ac_libiberty_warn_cflags='-W -Wall -Wtraditional' + ac_libiberty_warn_cflags='-W -Wall -Wtraditional -pedantic' dnl Check whether -g works, even if CFLAGS is set, in case the package dnl plays around with CFLAGS (such as to build both debugging and dnl normal versions of a library), tasteless as that idea is. @@ -109,7 +109,7 @@ AC_SUBST_FILE(host_makefile_frag) # It's OK to check for header files. Although the compiler may not be # able to link anything, it had better be able to at least compile # something. -AC_CHECK_HEADERS(sys/file.h sys/param.h stdlib.h string.h unistd.h strings.h sys/time.h sys/resource.h sys/stat.h) +AC_CHECK_HEADERS(sys/file.h sys/param.h stdlib.h string.h unistd.h strings.h sys/time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h) AC_HEADER_SYS_WAIT # This is the list of functions which libiberty will provide if they @@ -216,11 +216,6 @@ if test -n "${with_target_subdir}"; then setobjs=yes - if test -d ${libiberty_topdir}/newlib - then - EXTRA_INCS="-I${libiberty_topdir}/newlib/libc/include" - fi - fi else @@ -230,7 +225,6 @@ else fi -AC_SUBST(EXTRA_INCS) AC_SUBST(CHECK) if test -z "${setobjs}"; then @@ -283,15 +277,10 @@ if test -z "${setobjs}"; then # provides from our shell variables, so that they appear to be # missing. - # DJ - only if we're *building* cygwin, not just building *with* cygwin - - if test -n "${with_target_subdir}" - then - funcs="`echo $funcs | sed -e 's/random//'`" - LIBOBJS="$LIBOBJS random.o" - vars="`echo $vars | sed -e 's/sys_siglist//'`" - checkfuncs="`echo $checkfuncs | sed -e 's/strsignal//' -e 's/psignal//'`" - fi + funcs="`echo $funcs | sed -e 's/random//'`" + LIBOBJS="$LIBOBJS random.o" + vars="`echo $vars | sed -e 's/sys_siglist//'`" + checkfuncs="`echo $checkfuncs | sed -e 's/strsignal//' -e 's/psignal//'`" ;; *-*-mingw32*) @@ -363,6 +352,8 @@ EOF AC_CHECK_FUNCS($checkfuncs) fi +libiberty_AC_FUNC_STRNCMP + # Install a library built with a cross compiler in $(tooldir) rather # than $(libdir). if test -z "${with_cross_host}"; then diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c new file mode 100644 index 00000000000..b1c405549ec --- /dev/null +++ b/libiberty/cp-demangle.c @@ -0,0 +1,3015 @@ +/* Demangler for IA64 / g++ standard C++ ABI. + Copyright (C) 2000 CodeSourcery LLC. + Written by Alex Samuel <samuel@codesourcery.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. +*/ + +/* This file implements demangling of C++ names mangled according to + the IA64 / g++ standard C++ ABI. Use the cp_demangle function to + demangle a mangled name, or compile with the preprocessor macro + STANDALONE_DEMANGLER defined to create a demangling filter + executable. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ctype.h> + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#include <stdio.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "ansidecl.h" +#include "libiberty.h" +#include "dyn-string.h" +#include "demangle.h" + +/* If CP_DEMANGLE_DEBUG is defined, a trace of the grammar evaluation, + and other debugging output, will be generated. */ +#ifdef CP_DEMANGLE_DEBUG +#define DEMANGLE_TRACE(PRODUCTION, DM) \ + fprintf (stderr, " -> %-24s at position %3d\n", \ + (PRODUCTION), current_position (DM)); +#else +#define DEMANGLE_TRACE(PRODUCTION, DM) +#endif + +/* If flag_verbose is zero, some simplifications will be made to the + output to make it easier to read and supress details that are + generally not of interest to the average C++ programmer. + Otherwise, the demangled representation will attempt to convey as + much information as the mangled form. */ +static int flag_verbose; + +/* If flag_strict is non-zero, demangle strictly according to the + specification -- don't demangle special g++ manglings. */ +static int flag_strict; + +/* String_list_t is an extended form of dyn_string_t which provides a link + field. A string_list_t may safely be cast to and used as a + dyn_string_t. */ + +struct string_list_def +{ + struct dyn_string string; + struct string_list_def *next; +}; + +typedef struct string_list_def *string_list_t; + +/* Data structure representing a potential substitution. */ + +struct substitution_def +{ + /* The demangled text of the substitution. */ + dyn_string_t text; + + /* The template parameter that this represents, indexed from zero. + If this is not a template paramter number, the value is + NOT_TEMPLATE_PARM. */ + int template_parm_number; + + /* Whether this substitution represents a template item. */ + int template_p : 1; +}; + +#define NOT_TEMPLATE_PARM (-1) + +/* Data structure representing a template argument list. */ + +struct template_arg_list_def +{ + /* The next (lower) template argument list in the stack of currently + active template arguments. */ + struct template_arg_list_def *next; + + /* The first element in the list of template arguments in + left-to-right order. */ + string_list_t first_argument; + + /* The last element in the arguments lists. */ + string_list_t last_argument; +}; + +typedef struct template_arg_list_def *template_arg_list_t; + +/* Data structure to maintain the state of the current demangling. */ + +struct demangling_def +{ + /* The full mangled name being mangled. */ + char *name; + + /* Pointer into name at the current position. */ + char *next; + + /* Stack for strings containing demangled result generated so far. + Text is emitted to the topmost (first) string. */ + string_list_t result; + + /* The number of presently available substitutions. */ + int num_substitutions; + + /* The allocated size of the substitutions array. */ + int substitutions_allocated; + + /* An array of available substitutions. The number of elements in + the array is given by num_substitions, and the allocated array + size in substitutions_size. + + The most recent substition is at the end, so + + - `S_' corresponds to substititutions[num_substitutions - 1] + - `S0_' corresponds to substititutions[num_substitutions - 2] + + etc. */ + struct substitution_def *substitutions; + + /* The stack of template argument lists. */ + template_arg_list_t template_arg_lists; + + /* The most recently demangled source-name. */ + dyn_string_t last_source_name; +}; + +typedef struct demangling_def *demangling_t; + +/* This type is the standard return code from most functions. Values + other than STATUS_OK contain descriptive messages. */ +typedef const char *status_t; + +/* Special values that can be used as a status_t. */ +#define STATUS_OK NULL +#define STATUS_ERROR "Error." +#define STATUS_UNIMPLEMENTED "Unimplemented." +#define STATUS_INTERNAL_ERROR "Internal error." + +static void int_to_dyn_string + PARAMS ((int, dyn_string_t)); +static string_list_t string_list_new + PARAMS ((int)); +static void string_list_delete + PARAMS ((string_list_t)); +static void result_close_template_list + PARAMS ((demangling_t)); +static void result_push + PARAMS ((demangling_t)); +static string_list_t result_pop + PARAMS ((demangling_t)); +static int substitution_start + PARAMS ((demangling_t)); +static void substitution_add + PARAMS ((demangling_t, int, int, int)); +static dyn_string_t substitution_get + PARAMS ((demangling_t, int, int *)); +#ifdef CP_DEMANGLE_DEBUG +static void substitutions_print + PARAMS ((demangling_t, FILE *)); +#endif +static template_arg_list_t template_arg_list_new + PARAMS ((void)); +static void template_arg_list_delete + PARAMS ((template_arg_list_t)); +static void template_arg_list_add_arg + PARAMS ((template_arg_list_t, string_list_t)); +static string_list_t template_arg_list_get_arg + PARAMS ((template_arg_list_t, int)); +static void push_template_arg_list + PARAMS ((demangling_t, template_arg_list_t)); +static void pop_to_template_arg_list + PARAMS ((demangling_t, template_arg_list_t)); +#ifdef CP_DEMANGLE_DEBUG +static void template_arg_list_print + PARAMS ((template_arg_list_t, FILE *)); +#endif +static template_arg_list_t current_template_arg_list + PARAMS ((demangling_t)); +static demangling_t demangling_new + PARAMS ((char *)); +static void demangling_delete + PARAMS ((demangling_t)); + +/* The last character of DS. Warning: DS is evaluated twice. */ +#define dyn_string_last_char(DS) \ + (dyn_string_buf (DS)[dyn_string_length (DS) - 1]) + +/* Append a space character (` ') to DS if it does not already end + with one. */ +#define dyn_string_append_space(DS) \ + do \ + { \ + if (dyn_string_length (DS) > 0 \ + && dyn_string_last_char (DS) != ' ') \ + dyn_string_append_char ((DS), ' '); \ + } \ + while (0) + +/* Returns the index of the current position in the mangled name. */ +#define current_position(DM) ((DM)->next - (DM)->name) + +/* Returns the character at the current position of the mangled name. */ +#define peek_char(DM) (*((DM)->next)) + +/* Returns the character one past the current position of the mangled + name. */ +#define peek_char_next(DM) \ + (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1))) + +/* Returns the character at the current position, and advances the + current position to the next character. */ +#define next_char(DM) (*((DM)->next)++) + +/* Returns non-zero if the current position is the end of the mangled + name, i.e. one past the last character. */ +#define end_of_name_p(DM) (peek_char (DM) == '\0') + +/* Advances the current position by one character. */ +#define advance_char(DM) (++(DM)->next) + +/* Returns the string containing the current demangled result. */ +#define result_string(DM) (&(DM)->result->string) + +/* Appends a dyn_string_t to the demangled result. */ +#define result_append_string(DM, STRING) \ + dyn_string_append (&(DM)->result->string, (STRING)) + +/* Appends NUL-terminated string CSTR to the demangled result. */ +#define result_append(DM, CSTR) \ + dyn_string_append_cstr (&(DM)->result->string, (CSTR)) + +/* Appends character CHAR to the demangled result. */ +#define result_append_char(DM, CHAR) \ + dyn_string_append_char (&(DM)->result->string, (CHAR)) + +/* The length of the current demangled result. */ +#define result_length(DM) \ + dyn_string_length (&(DM)->result->string) + +/* Appends a space to the demangled result if the last character is + not a space. */ +#define result_append_space(DM) \ + dyn_string_append_space (&(DM)->result->string) + +/* Evaluate EXPR, which must produce a status_t. If the status code + indicates an error, return from the current function with that + status code. */ +#define RETURN_IF_ERROR(EXPR) \ + do \ + { \ + status_t s = EXPR; \ + if (s != STATUS_OK) \ + return s; \ + } \ + while (0) + +/* Appends a base 10 representation of VALUE to DS. */ + +static void +int_to_dyn_string (value, ds) + int value; + dyn_string_t ds; +{ + int i; + int mask = 1; + + /* Handle zero up front. */ + if (value == 0) + { + dyn_string_append_char (ds, '0'); + return; + } + + /* For negative numbers, emit a minus sign. */ + if (value < 0) + { + dyn_string_append_char (ds, '-'); + value = -value; + } + + /* Find the power of 10 of the first digit. */ + i = value; + while (i > 9) + { + mask *= 10; + i /= 10; + } + + /* Write the digits. */ + while (mask > 0) + { + int digit = value / mask; + dyn_string_append_char (ds, '0' + digit); + value -= digit * mask; + mask /= 10; + } +} + +/* Creates a new string list node. The contents of the string are + empty, but the initial buffer allocation is LENGTH. The string + list node should be deleted with string_list_delete. */ + +static string_list_t +string_list_new (length) + int length; +{ + string_list_t s = + (string_list_t) xmalloc (sizeof (struct string_list_def)); + dyn_string_init ((dyn_string_t) s, length); + return s; +} + +/* Deletes the entire string list starting at NODE. */ + +static void +string_list_delete (node) + string_list_t node; +{ + while (node != NULL) + { + string_list_t next = node->next; + free (node); + node = next; + } +} + +/* Appends a greater-than character to the demangled result. If the + last character is a greater-than character, a space is inserted + first, so that the two greater-than characters don't look like a + right shift token. */ + +static void +result_close_template_list (dm) + demangling_t dm; +{ + dyn_string_t s = &dm->result->string; + if (dyn_string_last_char (s) == '>') + dyn_string_append_char (s, ' '); + dyn_string_append_char (s, '>'); +} + +/* Allocates and pushes a new string onto the demangled results stack + for DM. Subsequent demangling with DM will emit to the new string. */ + +static void +result_push (dm) + demangling_t dm; +{ + string_list_t new_string = string_list_new (0); + new_string->next = (string_list_t) dm->result; + dm->result = new_string; +} + +/* Removes and returns the topmost element on the demangled results + stack for DM. The caller assumes ownership for the returned + string. */ + +static string_list_t +result_pop (dm) + demangling_t dm; +{ + string_list_t top = dm->result; + dm->result = top->next; + return top; +} + +/* Returns the start position of a fragment of the demangled result + that will be a substitution candidate. Should be called at the + start of productions that can add substitutions. */ + +static int +substitution_start (dm) + demangling_t dm; +{ + return result_length (dm); +} + +/* Adds the suffix of the current demangled result of DM starting at + START_POSITION as a potential substitution. If TEMPLATE_P is + non-zero, this potential substitution is a template-id. + + If TEMPLATE_PARM_NUMBER is not NOT_TEMPLATE_PARM, the substitution + is for that particular <template-param>, and is distinct from other + otherwise-identical types and other <template-param>s with + different indices. */ + +static void +substitution_add (dm, start_position, template_p, template_parm_number) + demangling_t dm; + int start_position; + int template_p; + int template_parm_number; +{ + dyn_string_t result = result_string (dm); + dyn_string_t substitution = dyn_string_new (0); + int i; + + dyn_string_substring (substitution, + result, start_position, result_length (dm)); + + /* Check whether SUBSTITUTION already occurs. */ + for (i = 0; i < dm->num_substitutions; ++i) + if (dyn_string_eq (dm->substitutions[i].text, substitution) + && dm->substitutions[i].template_parm_number == template_parm_number) + /* Found SUBSTITUTION already present. */ + { + /* Callers expect this function to take ownership of + SUBSTITUTION, so delete it. */ + dyn_string_delete (substitution); + return; + } + + /* If there's no room for the new entry, grow the array. */ + if (dm->substitutions_allocated == dm->num_substitutions) + { + dm->substitutions_allocated *= 2; + dm->substitutions = (struct substitution_def *) + xrealloc (dm->substitutions, + sizeof (struct substitution_def) + * dm->substitutions_allocated); + } + + /* Add the substitution to the array. */ + dm->substitutions[i].text = substitution; + dm->substitutions[i].template_p = template_p; + dm->substitutions[i].template_parm_number = template_parm_number; + ++dm->num_substitutions; + +#ifdef CP_DEMANGLE_DEBUG + substitutions_print (dm, stderr); +#endif +} + +/* Returns the Nth-most-recent substitution. Sets *TEMPLATE_P to + non-zero if the substitution is a template-id, zero otherwise. + N is numbered from zero. DM retains ownership of the returned + string. If N is negative, or equal to or greater than the current + number of substitution candidates, returns NULL. */ + +static dyn_string_t +substitution_get (dm, n, template_p) + demangling_t dm; + int n; + int *template_p; +{ + struct substitution_def *sub; + + /* Make sure N is in the valid range. */ + if (n < 0 || n >= dm->num_substitutions) + return NULL; + + sub = &(dm->substitutions[n]); + *template_p = sub->template_p; + return sub->text; +} + +#ifdef CP_DEMANGLE_DEBUG +/* Debugging routine to print the current substitutions to FP. */ + +static void +substitutions_print (dm, fp) + demangling_t dm; + FILE *fp; +{ + int seq_id; + int num = dm->num_substitutions; + + fprintf (fp, "SUBSTITUTIONS:\n"); + for (seq_id = -1; seq_id < num - 1; ++seq_id) + { + int template_p; + dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p); + + if (seq_id == -1) + fprintf (fp, " S_ "); + else + fprintf (fp, " S%d_", seq_id); + fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text)); + } +} + +#endif /* CP_DEMANGLE_DEBUG */ + +/* Creates a new template argument list. */ + +static template_arg_list_t +template_arg_list_new () +{ + template_arg_list_t new_list + = (template_arg_list_t) xmalloc (sizeof (struct template_arg_list_def)); + /* Initialize the new list to have no arguments. */ + new_list->first_argument = NULL; + new_list->last_argument = NULL; + /* Return the new list. */ + return new_list; +} + +/* Deletes a template argument list and the template arguments it + contains. */ + +static void +template_arg_list_delete (list) + template_arg_list_t list; +{ + /* If there are any arguments on LIST, delete them. */ + if (list->first_argument != NULL) + string_list_delete (list->first_argument); + /* Delete LIST. */ + free (list); +} + +/* Adds ARG to the template argument list ARG_LIST. */ + +static void +template_arg_list_add_arg (arg_list, arg) + template_arg_list_t arg_list; + string_list_t arg; +{ + if (arg_list->first_argument == NULL) + /* If there were no arguments before, ARG is the first one. */ + arg_list->first_argument = arg; + else + /* Make ARG the last argument on the list. */ + arg_list->last_argument->next = arg; + /* Make ARG the last on the list. */ + arg_list->last_argument = arg; + arg->next = NULL; +} + +/* Returns the template arugment at position INDEX in template + argument list ARG_LIST. */ + +static string_list_t +template_arg_list_get_arg (arg_list, index) + template_arg_list_t arg_list; + int index; +{ + string_list_t arg = arg_list->first_argument; + /* Scan down the list of arguments to find the one at position + INDEX. */ + while (index--) + { + arg = arg->next; + if (arg == NULL) + /* Ran out of arguments before INDEX hit zero. That's an + error. */ + return NULL; + } + /* Return the argument at position INDEX. */ + return arg; +} + +/* Pushes ARG_LIST onto the top of the template argument list stack. */ + +static void +push_template_arg_list (dm, arg_list) + demangling_t dm; + template_arg_list_t arg_list; +{ + arg_list->next = dm->template_arg_lists; + dm->template_arg_lists = arg_list; +#ifdef CP_DEMANGLE_DEBUG + fprintf (stderr, " ** pushing template arg list\n"); + template_arg_list_print (arg_list, stderr); +#endif +} + +/* Pops and deletes elements on the template argument list stack until + arg_list is the topmost element. If arg_list is NULL, all elements + are popped and deleted. */ + +static void +pop_to_template_arg_list (dm, arg_list) + demangling_t dm; + template_arg_list_t arg_list; +{ + while (dm->template_arg_lists != arg_list) + { + template_arg_list_t top = dm->template_arg_lists; + /* Disconnect the topmost element from the list. */ + dm->template_arg_lists = top->next; + /* Delete the popped element. */ + template_arg_list_delete (top); +#ifdef CP_DEMANGLE_DEBUG + fprintf (stderr, " ** removing template arg list\n"); +#endif + } +} + +#ifdef CP_DEMANGLE_DEBUG + +/* Prints the contents of ARG_LIST to FP. */ + +static void +template_arg_list_print (arg_list, fp) + template_arg_list_t arg_list; + FILE *fp; +{ + string_list_t arg; + int index = -1; + + fprintf (fp, "TEMPLATE ARGUMENT LIST:\n"); + for (arg = arg_list->first_argument; arg != NULL; arg = arg->next) + { + if (index == -1) + fprintf (fp, " T_ : "); + else + fprintf (fp, " T%d_ : ", index); + ++index; + fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg)); + } +} + +#endif /* CP_DEMANGLE_DEBUG */ + +/* Returns the topmost element on the stack of template argument + lists. If there is no list of template arguments, returns NULL. */ + +static template_arg_list_t +current_template_arg_list (dm) + demangling_t dm; +{ + return dm->template_arg_lists; +} + +/* Allocates a demangling_t object for demangling mangled NAME. A new + result must be pushed before the returned object can be used. */ + +static demangling_t +demangling_new (name) + char *name; +{ + demangling_t dm = (demangling_t) + xmalloc (sizeof (struct demangling_def)); + + dm->name = name; + dm->next = name; + dm->result = NULL; + dm->last_source_name = dyn_string_new (0); + dm->num_substitutions = 0; + dm->substitutions_allocated = 10; + dm->substitutions = (struct substitution_def *) + xmalloc (dm->substitutions_allocated * sizeof (struct substitution_def)); + dm->template_arg_lists = NULL; + + return dm; +} + +/* Deallocates a demangling_t object and all memory associated with + it. */ + +static void +demangling_delete (dm) + demangling_t dm; +{ + int i; + template_arg_list_t arg_list = dm->template_arg_lists; + + /* Delete the stack of template argument lists. */ + while (arg_list != NULL) + { + template_arg_list_t next = arg_list->next; + template_arg_list_delete (arg_list); + arg_list = next; + } + /* Delete the list of substitutions. */ + for (i = dm->num_substitutions; --i >= 0; ) + dyn_string_delete (dm->substitutions[i].text); + free (dm->substitutions); + /* Delete the demangled result. */ + string_list_delete (dm->result); + /* Delete the stored identifier name. */ + dyn_string_delete (dm->last_source_name); + /* Delete the context object itself. */ + free (dm); +} + +/* These functions demangle an alternative of the corresponding + production in the mangling spec. The first argument of each is a + demangling context structure for the current demangling + operation. Most emit demangled text directly to the topmost result + string on the result string stack in the demangling context + structure. */ + +static status_t demangle_char + PARAMS ((demangling_t, int)); +static status_t demangle_mangled_name + PARAMS ((demangling_t)); +static status_t demangle_encoding + PARAMS ((demangling_t)); +static status_t demangle_name + PARAMS ((demangling_t, int *)); +static status_t demangle_nested_name + PARAMS ((demangling_t, int *)); +static status_t demangle_prefix + PARAMS ((demangling_t, int *)); +static status_t demangle_unqualified_name + PARAMS ((demangling_t)); +static status_t demangle_source_name + PARAMS ((demangling_t)); +static status_t demangle_number + PARAMS ((demangling_t, int *, int, int)); +static status_t demangle_number_literally + PARAMS ((demangling_t, dyn_string_t, int, int)); +static status_t demangle_identifier + PARAMS ((demangling_t, int, dyn_string_t)); +static status_t demangle_operator_name + PARAMS ((demangling_t, int, int *)); +static status_t demangle_special_name + PARAMS ((demangling_t)); +static status_t demangle_ctor_dtor_name + PARAMS ((demangling_t)); +static status_t demangle_type_ptr + PARAMS ((demangling_t)); +static status_t demangle_type + PARAMS ((demangling_t)); +static status_t demangle_CV_qualifiers + PARAMS ((demangling_t, dyn_string_t)); +static status_t demangle_builtin_type + PARAMS ((demangling_t)); +static status_t demangle_function_type + PARAMS ((demangling_t, int)); +static status_t demangle_bare_function_type + PARAMS ((demangling_t, int)); +static status_t demangle_class_enum_type + PARAMS ((demangling_t, int *)); +static status_t demangle_array_type + PARAMS ((demangling_t)); +static status_t demangle_template_param + PARAMS ((demangling_t, int *)); +static status_t demangle_template_args + PARAMS ((demangling_t)); +static status_t demangle_literal + PARAMS ((demangling_t)); +static status_t demangle_template_arg + PARAMS ((demangling_t)); +static status_t demangle_expression + PARAMS ((demangling_t)); +static status_t demangle_scope_expression + PARAMS ((demangling_t)); +static status_t demangle_expr_primary + PARAMS ((demangling_t)); +static status_t demangle_substitution + PARAMS ((demangling_t, int *, int *)); +static status_t demangle_local_name + PARAMS ((demangling_t)); +static status_t demangle_discriminator + PARAMS ((demangling_t, int)); +static status_t cp_demangle + PARAMS ((char *, dyn_string_t)); + +/* When passed to demangle_bare_function_type, indicates that the + function's return type is not encoded before its parameter types. */ +#define BFT_NO_RETURN_TYPE -1 + +/* Check that the next character is C. If so, consume it. If not, + return an error. */ + +static status_t +demangle_char (dm, c) + demangling_t dm; + int c; +{ + static char *error_message = NULL; + + if (peek_char (dm) == c) + { + advance_char (dm); + return STATUS_OK; + } + else + { + if (error_message == NULL) + error_message = strdup ("Expected ?"); + error_message[9] = c; + return error_message; + } +} + +/* Demangles and emits a <mangled-name>. + + <mangled-name> ::= _Z <encoding> */ + +static status_t +demangle_mangled_name (dm) + demangling_t dm; +{ + DEMANGLE_TRACE ("mangled-name", dm); + RETURN_IF_ERROR (demangle_char (dm, '_')); + RETURN_IF_ERROR (demangle_char (dm, 'Z')); + RETURN_IF_ERROR (demangle_encoding (dm)); + return STATUS_OK; +} + +/* Demangles and emits an <encoding>. + + <encoding> ::= <function name> <bare-function-type> + ::= <data name> + ::= <substitution> */ + +static status_t +demangle_encoding (dm) + demangling_t dm; +{ + int template_p; + int special_std_substitution; + int start_position; + int start = substitution_start (dm); + template_arg_list_t old_arg_list = current_template_arg_list (dm); + char peek = peek_char (dm); + + DEMANGLE_TRACE ("encoding", dm); + + /* Remember where the name starts. If it turns out to be a template + function, we'll have to insert the return type here. */ + start_position = result_length (dm); + + if (peek == 'S') + { + RETURN_IF_ERROR (demangle_substitution (dm, &template_p, + &special_std_substitution)); + if (special_std_substitution) + { + /* This was the magic `std::' substitution. */ + result_append (dm, "::"); + RETURN_IF_ERROR (demangle_encoding (dm)); + } + } + else if (peek == 'G' || peek == 'T') + RETURN_IF_ERROR (demangle_special_name (dm)); + else + { + /* Now demangle the name. */ + RETURN_IF_ERROR (demangle_name (dm, &template_p)); + + /* If there's anything left, the name was a function name, with + maybe its return type, and its parameters types, following. */ + if (!end_of_name_p (dm) + && peek_char (dm) != 'E') + { + if (template_p) + /* Template functions have their return type encoded. The + return type should be inserted at start_position. */ + RETURN_IF_ERROR + (demangle_bare_function_type (dm, start_position)); + else + /* Non-template functions don't have their return type + encoded. */ + RETURN_IF_ERROR + (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE)); + } + + substitution_add (dm, start, template_p, NOT_TEMPLATE_PARM); + } + + /* Pop off template argument lists that were built during the + mangling of this name, to restore the old template context. */ + pop_to_template_arg_list (dm, old_arg_list); + + return STATUS_OK; +} + +/* Demangles and emits a <name>. + + <name> ::= <unscoped-name> + ::= <unscoped-template-name> <template-args> + ::= <nested-name> + ::= <local-name> + + <unscoped-name> ::= <unqualified-name> + ::= St <unqualified-name> # ::std:: + + <unscoped-template-name> + ::= <unscoped-name> + ::= <substitution> */ + +static status_t +demangle_name (dm, template_p) + demangling_t dm; + int *template_p; +{ + int special_std_substitution; + int start = substitution_start (dm); + + DEMANGLE_TRACE ("name", dm); + + switch (peek_char (dm)) + { + case 'N': + /* This is a <nested-name>. */ + RETURN_IF_ERROR (demangle_nested_name (dm, template_p)); + break; + + case 'Z': + RETURN_IF_ERROR (demangle_local_name (dm)); + break; + + case 'S': + /* The `St' substitution allows a name nested in std:: to appear + without being enclosed in a nested name. + <name> ::= St <unqualified-name> # ::std:: */ + if (peek_char_next (dm) == 't') + { + (void) next_char (dm); + (void) next_char (dm); + result_append (dm, "std::"); + RETURN_IF_ERROR (demangle_unqualified_name (dm)); + } + else + { + RETURN_IF_ERROR (demangle_substitution (dm, template_p, + &special_std_substitution)); + if (special_std_substitution) + { + /* This was the magic `std::' substitution. We can have + a <nested-name> or one of the unscoped names + following. */ + result_append (dm, "::"); + RETURN_IF_ERROR (demangle_name (dm, template_p)); + } + } + break; + + default: + /* This is an <unscoped-name> or <unscoped-template-name>. */ + RETURN_IF_ERROR (demangle_unqualified_name (dm)); + + /* If the <unqualified-name> is followed by template args, this + is an <unscoped-template-name>. */ + if (peek_char (dm) == 'I') + { + /* Add a substitution for the unqualified template name. */ + substitution_add (dm, start, 0, NOT_TEMPLATE_PARM); + + RETURN_IF_ERROR (demangle_template_args (dm)); + *template_p = 1; + } + else + *template_p = 0; + + break; + } + + return STATUS_OK; +} + +/* Demangles and emits a <nested-name>. + + <nested-name> ::= N [<CV-qualifiers>] <prefix> <component> E */ + +static status_t +demangle_nested_name (dm, template_p) + demangling_t dm; + int *template_p; +{ + char peek; + + DEMANGLE_TRACE ("nested-name", dm); + + RETURN_IF_ERROR (demangle_char (dm, 'N')); + + peek = peek_char (dm); + if (peek == 'r' || peek == 'V' || peek == 'K') + { + /* Snarf up and emit CV qualifiers. */ + dyn_string_t cv_qualifiers = dyn_string_new (24); + demangle_CV_qualifiers (dm, cv_qualifiers); + result_append_string (dm, cv_qualifiers); + dyn_string_delete (cv_qualifiers); + result_append_space (dm); + } + + RETURN_IF_ERROR (demangle_prefix (dm, template_p)); + /* No need to demangle the final <component>; demangle_prefix will + handle it. */ + RETURN_IF_ERROR (demangle_char (dm, 'E')); + + return STATUS_OK; +} + +/* Demangles and emits a <prefix>. + + <prefix> ::= <prefix> <component> + ::= <template-prefix> <template-args> + ::= # empty + ::= <substitution> + + <template-prefix> ::= <prefix> + ::= <substitution> + + <component> ::= <unqualified-name> + ::= <local-name> */ + +static status_t +demangle_prefix (dm, template_p) + demangling_t dm; + int *template_p; +{ + int start = substitution_start (dm); + int nested = 0; + + /* TEMPLATE_P is updated as we decend the nesting chain. After + <template-args>, it is set to non-zero; after everything else it + is set to zero. */ + + DEMANGLE_TRACE ("prefix", dm); + + while (1) + { + char peek; + int unused; + + if (end_of_name_p (dm)) + return "Unexpected end of name in <compound-name>."; + + peek = peek_char (dm); + + if (isdigit ((unsigned char) peek) + || (peek >= 'a' && peek <= 'z') + || peek == 'C' || peek == 'D' + || peek == 'S') + { + /* We have another level of scope qualification. */ + if (nested) + result_append (dm, "::"); + else + nested = 1; + + if (peek == 'S') + /* The substitution determines whether this is a + template-id. */ + RETURN_IF_ERROR (demangle_substitution (dm, template_p, + &unused)); + else + { + RETURN_IF_ERROR (demangle_unqualified_name (dm)); + *template_p = 0; + } + } + else if (peek == 'Z') + RETURN_IF_ERROR (demangle_local_name (dm)); + else if (peek == 'I') + { + if (*template_p) + return STATUS_INTERNAL_ERROR; + /* The template name is a substitution candidate. */ + substitution_add (dm, start, 0, NOT_TEMPLATE_PARM); + RETURN_IF_ERROR (demangle_template_args (dm)); + *template_p = 1; + } + else if (peek == 'E') + /* All done. */ + return STATUS_OK; + else + return "Unexpected character in <compound-name>."; + + /* Add a new substitution for the prefix thus far. */ + substitution_add (dm, start, *template_p, NOT_TEMPLATE_PARM); + } +} + +/* Demangles and emits an <unqualified-name>. If the + <unqualified-name> is a function and the first element in the + argument list should be taken to be its return type, + ENCODE_RETURN_TYPE is non-zero. + + <unqualified-name> ::= <operator-name> + ::= <special-name> + ::= <source-name> */ + +static status_t +demangle_unqualified_name (dm) + demangling_t dm; +{ + char peek = peek_char (dm); + + DEMANGLE_TRACE ("unqualified-name", dm); + + if (isdigit ((unsigned char) peek)) + RETURN_IF_ERROR (demangle_source_name (dm)); + else if (peek >= 'a' && peek <= 'z') + { + int num_args; + RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args)); + } + else if (peek == 'C' || peek == 'D') + RETURN_IF_ERROR (demangle_ctor_dtor_name (dm)); + else + return "Unexpected character in <unqualified-name>."; + + return STATUS_OK; +} + +/* Demangles and emits <source-name>. + + <source-name> ::= <length number> <identifier> */ + +static status_t +demangle_source_name (dm) + demangling_t dm; +{ + int length; + + DEMANGLE_TRACE ("source-name", dm); + + /* Decode the length of the identifier. */ + RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0)); + if (length == 0) + return "Zero length in <source-name>."; + + /* Now the identifier itself. It's placed into last_source_name, + where it can be used to build a constructor or destructor name. */ + RETURN_IF_ERROR (demangle_identifier (dm, length, + dm->last_source_name)); + + /* Emit it. */ + result_append_string (dm, dm->last_source_name); + + return STATUS_OK; +} + +/* Demangles a number, either a <number> or a <positive-number> at the + current position, consuming all consecutive digit characters. Sets + *VALUE to the resulting numberand returns STATUS_OK. The number is + interpreted as BASE, which must be either 10 or 36. If IS_SIGNED + is non-zero, negative numbers -- prefixed with `n' -- are accepted. + + <number> ::= [n] <positive-number> + + <positive-number> ::= <decimal integer> */ + +static status_t +demangle_number (dm, value, base, is_signed) + demangling_t dm; + int *value; + int base; + int is_signed; +{ + dyn_string_t number = dyn_string_new (10); + + DEMANGLE_TRACE ("number", dm); + + demangle_number_literally (dm, number, base, is_signed); + *value = strtol (dyn_string_buf (number), NULL, base); + dyn_string_delete (number); + + return STATUS_OK; +} + +/* Demangles a number at the current position. The digits (and minus + sign, if present) that make up the number are appended to STR. + Only base-BASE digits are accepted; BASE must be either 10 or 36. + If IS_SIGNED, negative numbers -- prefixed with `n' -- are + accepted. Does not consume a trailing underscore or other + terminating character. */ + +static status_t +demangle_number_literally (dm, str, base, is_signed) + demangling_t dm; + dyn_string_t str; + int base; + int is_signed; +{ + DEMANGLE_TRACE ("number*", dm); + + if (base != 10 && base != 36) + return STATUS_INTERNAL_ERROR; + + /* An `n' denotes a negative number. */ + if (is_signed && peek_char (dm) == 'n') + { + /* Skip past the n. */ + advance_char (dm); + /* The normal way to write a negative number is with a minus + sign. */ + dyn_string_append_char (str, '-'); + } + + /* Loop until we hit a non-digit. */ + while (1) + { + char peek = peek_char (dm); + if (isdigit ((unsigned char) peek) + || (base == 36 && peek >= 'A' && peek <= 'Z')) + /* Accumulate digits. */ + dyn_string_append_char (str, next_char (dm)); + else + /* Not a digit? All done. */ + break; + } + + return STATUS_OK; +} + +/* Demangles an identifier at the current position of LENGTH + characters and places it in IDENTIFIER. */ + +static status_t +demangle_identifier (dm, length, identifier) + demangling_t dm; + int length; + dyn_string_t identifier; +{ + DEMANGLE_TRACE ("identifier", dm); + + dyn_string_clear (identifier); + dyn_string_resize (identifier, length); + while (length-- > 0) + { + if (end_of_name_p (dm)) + return "Unexpected end of name in <identifier>."; + dyn_string_append_char (identifier, next_char (dm)); + } + + return STATUS_OK; +} + +/* Demangles and emits an <operator-name>. If SHORT_NAME is non-zero, + the short form is emitted; otherwise the full source form + (`operator +' etc.) is emitted. *NUM_ARGS is set to the number of + operands that the operator takes. + + <operator-name> + ::= nw # new + ::= na # new[] + ::= dl # delete + ::= da # delete[] + ::= ps # + (unary) + ::= ng # - (unary) + ::= ad # & (unary) + ::= de # * (unary) + ::= co # ~ + ::= pl # + + ::= mi # - + ::= ml # * + ::= dv # / + ::= rm # % + ::= an # & + ::= or # | + ::= eo # ^ + ::= aS # = + ::= pL # += + ::= mI # -= + ::= mL # *= + ::= dV # /= + ::= rM # %= + ::= aN # &= + ::= oR # |= + ::= eO # ^= + ::= ls # << + ::= rs # >> + ::= lS # <<= + ::= rS # >>= + ::= eq # == + ::= ne # != + ::= lt # < + ::= gt # > + ::= le # <= + ::= ge # >= + ::= nt # ! + ::= aa # && + ::= oo # || + ::= pp # ++ + ::= mm # -- + ::= cm # , + ::= pm # ->* + ::= pt # -> + ::= cl # () + ::= ix # [] + ::= qu # ? + ::= sz # sizeof + ::= cv <type> # cast + ::= vx <source-name> # vendor extended operator */ + +static status_t +demangle_operator_name (dm, short_name, num_args) + demangling_t dm; + int short_name; + int *num_args; +{ + struct operator_code + { + /* The mangled code for this operator. */ + const char *code; + /* The source name of this operator. */ + const char *name; + /* The number of arguments this operator takes. */ + int num_args; + }; + + static const struct operator_code operators[] = + { + { "aN", "&=" , 2 }, + { "aS", "=" , 2 }, + { "aa", "&&" , 2 }, + { "ad", "&" , 1 }, + { "an", "&" , 2 }, + { "cl", "()" , 0 }, + { "cm", "," , 2 }, + { "co", "~" , 1 }, + { "dV", "/=" , 2 }, + { "da", " delete[]", 1 }, + { "de", "*" , 1 }, + { "dl", " delete" , 1 }, + { "dv", "/" , 2 }, + { "eO", "^=" , 2 }, + { "eo", "^" , 2 }, + { "eq", "==" , 2 }, + { "ge", ">=" , 2 }, + { "gt", ">" , 2 }, + { "ix", "[]" , 2 }, + { "lS", "<<=" , 2 }, + { "le", "<=" , 2 }, + { "ls", "<<" , 2 }, + { "lt", "<" , 2 }, + { "mI", "-=" , 2 }, + { "mL", "*=" , 2 }, + { "mi", "-" , 2 }, + { "ml", "*" , 2 }, + { "mm", "--" , 1 }, + { "na", " new[]" , 1 }, + { "ne", "!=" , 2 }, + { "ng", "-" , 1 }, + { "nt", "!" , 1 }, + { "nw", " new" , 1 }, + { "oR", "|=" , 2 }, + { "oo", "||" , 2 }, + { "or", "|" , 2 }, + { "pL", "+=" , 2 }, + { "pl", "+" , 2 }, + { "pm", "->*" , 2 }, + { "pp", "++" , 1 }, + { "ps", "+" , 1 }, + { "qu", "?" , 3 }, + { "rM", "%=" , 2 }, + { "rS", ">>=" , 2 }, + { "rm", "%" , 2 }, + { "rs", ">>" , 2 }, + { "sz", " sizeof" , 1 } + }; + + const int num_operators = + sizeof (operators) / sizeof (struct operator_code); + + int c0 = next_char (dm); + int c1 = next_char (dm); + const struct operator_code* p1 = operators; + const struct operator_code* p2 = operators + num_operators; + + DEMANGLE_TRACE ("operator-name", dm); + + /* Is this a vendor extended operator? */ + if (c0 == 'v' && c1 == 'x') + { + result_append (dm, "operator"); + RETURN_IF_ERROR (demangle_source_name (dm)); + *num_args = 0; + return STATUS_OK; + } + + /* Is this a conversion operator? */ + if (c0 == 'c' && c1 == 'v') + { + result_append (dm, "operator "); + /* Demangle the converted-to type. */ + RETURN_IF_ERROR (demangle_type (dm)); + *num_args = 0; + return STATUS_OK; + } + + /* Perform a binary search for the operator code. */ + while (1) + { + const struct operator_code* p = p1 + (p2 - p1) / 2; + char match0 = p->code[0]; + char match1 = p->code[1]; + + if (c0 == match0 && c1 == match1) + /* Found it. */ + { + if (!short_name) + result_append (dm, "operator"); + result_append (dm, p->name); + *num_args = p->num_args; + + return STATUS_OK; + } + + if (p == p1) + /* Couldn't find it. */ + return "Unknown code in <operator-name>."; + + /* Try again. */ + if (c0 < match0 || (c0 == match0 && c1 < match1)) + p2 = p; + else + p1 = p; + } +} + +/* Demangles and emits a <special-name>. + + <special-name> ::= GV <object name> # Guard variable + ::= Th[n] <offset number> _ <base name> <base encoding> + # non-virtual base override thunk + ::= Tv[n] <offset number> _ <vcall offset number> + _ <base encoding> + # virtual base override thunk + ::= TV <type> # virtual table + ::= TT <type> # VTT + ::= TI <type> # typeinfo structure + ::= TS <type> # typeinfo name + + Also demangles the special g++ manglings, + + <special-name> ::= CT <type> <offset number> _ <base type> + # construction vtable + ::= TF <type> # typeinfo function (old ABI only) + ::= TJ <type> # java Class structure */ + +static status_t +demangle_special_name (dm) + demangling_t dm; +{ + dyn_string_t number; + int unused; + char peek = peek_char (dm); + + DEMANGLE_TRACE ("special-name", dm); + + if (peek == 'G') + { + /* A guard variable name. Consume the G. */ + advance_char (dm); + RETURN_IF_ERROR (demangle_char (dm, 'V')); + result_append (dm, "guard variable for "); + RETURN_IF_ERROR (demangle_name (dm, &unused)); + } + else if (peek == 'T') + { + /* Other C++ implementation miscellania. Consume the T. */ + advance_char (dm); + + switch (peek_char (dm)) + { + case 'V': + /* Virtual table. */ + advance_char (dm); + result_append (dm, "vtable for "); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'T': + /* VTT structure. */ + advance_char (dm); + result_append (dm, "VTT for "); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'I': + /* Typeinfo structure. */ + advance_char (dm); + result_append (dm, "typeinfo for "); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'F': + /* Typeinfo function. Used only in old ABI with new mangling. */ + advance_char (dm); + result_append (dm, "typeinfo fn for "); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'S': + /* Character string containing type name, used in typeinfo. */ + advance_char (dm); + result_append (dm, "typeinfo name for "); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'J': + /* The java Class variable corresponding to a C++ class. */ + advance_char (dm); + result_append (dm, "java Class for "); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'h': + /* Non-virtual thunk. */ + advance_char (dm); + result_append (dm, "non-virtual thunk"); + /* Demangle and emit the offset. */ + number = dyn_string_new (4); + demangle_number_literally (dm, number, 10, 1); + /* Don't display the offset unless in verbose mode. */ + if (flag_verbose) + { + result_append_char (dm, ' '); + result_append_string (dm, number); + } + dyn_string_delete (number); + /* Demangle the separator. */ + RETURN_IF_ERROR (demangle_char (dm, '_')); + /* Demangle and emit the target name and function type. */ + result_append (dm, " to "); + RETURN_IF_ERROR (demangle_encoding (dm)); + break; + + case 'v': + /* Virtual thunk. */ + advance_char (dm); + result_append (dm, "virtual thunk "); + /* Demangle and emit the offset. */ + number = dyn_string_new (4); + demangle_number_literally (dm, number, 10, 1); + /* Don't display the offset unless in verbose mode. */ + if (flag_verbose) + { + result_append_string (dm, number); + result_append_char (dm, ' '); + } + dyn_string_delete (number); + /* Demangle the separator. */ + RETURN_IF_ERROR (demangle_char (dm, '_')); + /* Demangle and emit the vcall offset. */ + number = dyn_string_new (4); + demangle_number_literally (dm, number, 10, 1); + /* Don't display the vcall offset unless in verbose mode. */ + if (flag_verbose) + { + result_append_string (dm, number); + result_append_char (dm, ' '); + } + dyn_string_delete (number); + /* Demangle the separator. */ + RETURN_IF_ERROR (demangle_char (dm, '_')); + /* Demangle and emit the target function. */ + result_append (dm, "to "); + RETURN_IF_ERROR (demangle_encoding (dm)); + break; + + case 'C': + /* TC is a special g++ mangling for a construction vtable. */ + if (!flag_strict) + { + advance_char (dm); + result_append (dm, "construction vtable for "); + RETURN_IF_ERROR (demangle_type (dm)); + /* Demangle the offset. */ + number = dyn_string_new (4); + demangle_number_literally (dm, number, 10, 1); + /* Demangle the underscore separator. */ + RETURN_IF_ERROR (demangle_char (dm, '_')); + /* Demangle the base type. */ + result_append (dm, "-in-"); + RETURN_IF_ERROR (demangle_type (dm)); + /* Don't display the offset unless in verbose mode. */ + if (flag_verbose) + { + result_append_char (dm, ' '); + result_append_string (dm, number); + } + dyn_string_delete (number); + break; + } + /* If flag_strict, fall through. */ + + default: + return "Unrecognized <special-name>."; + } + } + else + return STATUS_ERROR; + + return STATUS_OK; +} + +/* Demangles and emits a <ctor-dtor-name>. + + <ctor-dtor-name> + ::= C1 # complete object (in-charge) ctor + ::= C2 # base object (not-in-charge) ctor + ::= C3 # complete object (in-charge) allocating ctor + ::= C4 # base object (not-in-charge) allocating ctor + ::= D0 # deleting (in-charge) dtor + ::= D1 # complete object (in-charge) dtor + ::= D2 # base object (not-in-charge) dtor */ + +static status_t +demangle_ctor_dtor_name (dm) + demangling_t dm; +{ + static const char *const ctor_flavors[] = + { + "in-charge", + "not-in-charge", + "in-charge allocating", + "not-in-charge allocating" + }; + static const char *const dtor_flavors[] = + { + "in-charge deleting", + "in-charge", + "not-in-charge" + }; + + int flavor; + char peek = peek_char (dm); + + DEMANGLE_TRACE ("ctor-dtor-name", dm); + + if (peek == 'C') + { + /* A constructor name. Consume the C. */ + advance_char (dm); + if (peek_char (dm) < '1' || peek_char (dm) > '4') + return "Unrecognized constructor."; + result_append_string (dm, dm->last_source_name); + /* Print the flavor of the constructor if in verbose mode. */ + flavor = next_char (dm) - '1'; + if (flag_verbose) + { + result_append (dm, "["); + result_append (dm, ctor_flavors[flavor]); + result_append_char (dm, ']'); + } + } + else if (peek == 'D') + { + /* A destructor name. Consume the D. */ + advance_char (dm); + if (peek_char (dm) < '0' || peek_char (dm) > '2') + return "Unrecognized destructor."; + result_append_char (dm, '~'); + result_append_string (dm, dm->last_source_name); + /* Print the flavor of the destructor if in verbose mode. */ + flavor = next_char (dm) - '0'; + if (flag_verbose) + { + result_append (dm, " ["); + result_append (dm, dtor_flavors[flavor]); + result_append_char (dm, ']'); + } + } + else + return STATUS_ERROR; + + return STATUS_OK; +} + +/* Handle pointer, reference, and pointer-to-member cases for + demangle_type. All consecutive `P's, `R's, and 'M's are joined to + build a pointer/reference type. We snarf all these, plus the + following <type>, all at once since we need to know whether we have + a pointer to data or pointer to function to construct the right + output syntax. C++'s pointer syntax is hairy. + + <type> ::= P <type> + ::= R <type> + ::= <pointer-to-member-type> + + <pointer-to-member-type> ::= M </class/ type> </member/ type> */ + +static status_t +demangle_type_ptr (dm) + demangling_t dm; +{ + char next; + status_t status; + + /* Collect pointer symbols into this string. */ + dyn_string_t symbols = dyn_string_new (10); + + DEMANGLE_TRACE ("type*", dm); + + /* Scan forward, collecting pointers and references into symbols, + until we hit something else. Then emit the type. */ + while (1) + { + next = peek_char (dm); + if (next == 'P') + { + dyn_string_append_char (symbols, '*'); + advance_char (dm); + } + else if (next == 'R') + { + dyn_string_append_char (symbols, '&'); + advance_char (dm); + } + else if (next == 'M') + { + /* Pointer-to-member. */ + dyn_string_t class_type; + + /* Eat the 'M'. */ + advance_char (dm); + + /* Capture the type of which this is a pointer-to-member. */ + result_push (dm); + RETURN_IF_ERROR (demangle_type (dm)); + class_type = (dyn_string_t) result_pop (dm); + + /* Build the pointer-to-member notation. It comes before + other pointer and reference qualifiers -- */ + dyn_string_prepend_cstr (symbols, "::*"); + dyn_string_prepend (symbols, class_type); + dyn_string_delete (class_type); + + if (peek_char (dm) == 'F') + continue; + + /* Demangle the type of the pointed-to member. */ + status = demangle_type (dm); + /* Make it pretty. */ + result_append_space (dm); + /* Add the pointer-to-member syntax, and other pointer and + reference symbols. */ + result_append_string (dm, symbols); + /* Clean up. */ + dyn_string_delete (symbols); + + RETURN_IF_ERROR (status); + return STATUS_OK; + } + else if (next == 'F') + { + /* Ooh, tricky, a pointer-to-function. */ + int position = result_length (dm); + result_append_char (dm, '('); + result_append_string (dm, symbols); + result_append_char (dm, ')'); + dyn_string_delete (symbols); + + RETURN_IF_ERROR (demangle_function_type (dm, position)); + return STATUS_OK; + } + else + { + /* No more pointe or reference tokens. Finish up. */ + status = demangle_type (dm); + + result_append_string (dm, symbols); + dyn_string_delete (symbols); + + RETURN_IF_ERROR (status); + return STATUS_OK; + } + } +} + +/* Demangles and emits a <type>. + + <type> ::= <builtin-type> + ::= <function-type> + ::= <class-enum-type> + ::= <array-type> + ::= <pointer-to-member-type> + ::= <template-param> + ::= <CV-qualifiers> <type> + ::= P <type> # pointer-to + ::= R <type> # reference-to + ::= C <type> # complex pair (C 2000) + ::= G <type> # imaginary (C 2000) + ::= U <source-name> <type> # vendor extended type qualifier + ::= <substitution> */ + +static status_t +demangle_type (dm) + demangling_t dm; +{ + int start = substitution_start (dm); + char peek = peek_char (dm); + int template_p = 0; + int special_std_substitution; + int is_builtin_type = 0; + template_arg_list_t old_arg_list = current_template_arg_list (dm); + int template_parm = NOT_TEMPLATE_PARM; + + DEMANGLE_TRACE ("type", dm); + + /* A <class-enum-type> can start with a digit (a <source-name>), an + N (a <nested-name>), or a Z (a <local-name>). */ + if (isdigit ((unsigned char) peek) || peek == 'N' || peek == 'Z') + RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p)); + else if (peek >= 'a' && peek <= 'z') + { + RETURN_IF_ERROR (demangle_builtin_type (dm)); + is_builtin_type = 1; + } + else + switch (peek) + { + case 'r': + case 'V': + case 'K': + { + status_t status; + dyn_string_t cv_qualifiers = dyn_string_new (24); + demangle_CV_qualifiers (dm, cv_qualifiers); + + /* If the qualifiers apply to a pointer or reference, they + need to come after the whole qualified type. */ + if (peek_char (dm) == 'P' || peek_char (dm) == 'R') + { + status = demangle_type (dm); + result_append_space (dm); + result_append_string (dm, cv_qualifiers); + } + /* Otherwise, the qualifiers come first. */ + else + { + result_append_string (dm, cv_qualifiers); + result_append_space (dm); + status = demangle_type (dm); + } + + dyn_string_delete (cv_qualifiers); + RETURN_IF_ERROR (status); + } + break; + + case 'F': + return "Non-pointer or -reference function type."; + + case 'A': + RETURN_IF_ERROR (demangle_array_type (dm)); + break; + + case 'T': + RETURN_IF_ERROR (demangle_template_param (dm, &template_parm)); + break; + + case 'S': + RETURN_IF_ERROR (demangle_substitution (dm, &template_p, + &special_std_substitution)); + if (special_std_substitution) + { + /* This was the magic `std::' substitution. What follows + must be a class name in that namespace. */ + result_append (dm, "::"); + RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p)); + } + break; + + case 'P': + case 'R': + case 'M': + RETURN_IF_ERROR (demangle_type_ptr (dm)); + break; + + case 'C': + /* A C99 complex type. */ + result_append (dm, "complex "); + advance_char (dm); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'G': + /* A C99 imaginary type. */ + result_append (dm, "imaginary "); + advance_char (dm); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + case 'U': + /* Vendor extended type qualifier. */ + advance_char (dm); + RETURN_IF_ERROR (demangle_source_name (dm)); + result_append_char (dm, ' '); + RETURN_IF_ERROR (demangle_type (dm)); + break; + + default: + return "Unexpected character in <type>."; + } + + /* Unqualified builin types are not substitution candidates. */ + if (!is_builtin_type) + /* Add a new substitution for the type. If this type was a + <template-param>, pass its index since from the point of + substitutions, a <template-param> token is a substitution + candidate distinct from the type that is substituted for it. */ + substitution_add (dm, start, template_p, template_parm); + + /* Pop off template argument lists added during mangling of this + type. */ + pop_to_template_arg_list (dm, old_arg_list); + + return STATUS_OK; +} + +/* C++ source names of builtin types, indexed by the mangled code + letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc). */ +static const char *const builtin_type_names[26] = +{ + "signed char", /* a */ + "bool", /* b */ + "char", /* c */ + "double", /* d */ + "long double", /* e */ + "float", /* f */ + "__float128", /* g */ + "unsigned char", /* h */ + "int", /* i */ + "unsigned", /* j */ + NULL, /* k */ + "long", /* l */ + "unsigned long", /* m */ + "__int128", /* n */ + "unsigned __int128", /* o */ + NULL, /* p */ + NULL, /* q */ + NULL, /* r */ + "short", /* s */ + "unsigned short", /* t */ + NULL, /* u */ + "void", /* v */ + "wchar_t", /* w */ + "long long", /* x */ + "unsigned long long", /* y */ + "..." /* z */ +}; + +/* Demangles and emits a <builtin-type>. + + <builtin-type> ::= v # void + ::= w # wchar_t + ::= b # bool + ::= c # char + ::= a # signed char + ::= h # unsigned char + ::= s # short + ::= t # unsigned short + ::= i # int + ::= j # unsigned int + ::= l # long + ::= m # unsigned long + ::= x # long long, __int64 + ::= y # unsigned long long, __int64 + ::= n # __int128 + ::= o # unsigned __int128 + ::= f # float + ::= d # double + ::= e # long double, __float80 + ::= g # __float128 + ::= z # ellipsis + ::= u <source-name> # vendor extended type */ + +static status_t +demangle_builtin_type (dm) + demangling_t dm; +{ + + char code = peek_char (dm); + + DEMANGLE_TRACE ("builtin-type", dm); + + if (code == 'u') + { + advance_char (dm); + RETURN_IF_ERROR (demangle_source_name (dm)); + return STATUS_OK; + } + else if (code >= 'a' && code <= 'z') + { + const char *type_name = builtin_type_names[code - 'a']; + if (type_name == NULL) + return "Unrecognized <builtin-type> code."; + + result_append (dm, type_name); + advance_char (dm); + return STATUS_OK; + } + else + return "Non-alphabetic <builtin-type> code."; +} + +/* Demangles all consecutive CV-qualifiers (const, volatile, and + restrict) at the current position. The qualifiers are appended to + QUALIFIERS. Returns STATUS_OK. */ + +static status_t +demangle_CV_qualifiers (dm, qualifiers) + demangling_t dm; + dyn_string_t qualifiers; +{ + DEMANGLE_TRACE ("CV-qualifiers", dm); + + while (1) + { + switch (peek_char (dm)) + { + case 'r': + dyn_string_append_space (qualifiers); + dyn_string_append_cstr (qualifiers, "restrict"); + break; + + case 'V': + dyn_string_append_space (qualifiers); + dyn_string_append_cstr (qualifiers, "volatile"); + break; + + case 'K': + dyn_string_append_space (qualifiers); + dyn_string_append_cstr (qualifiers, "const"); + break; + + default: + return STATUS_OK; + } + + advance_char (dm); + } +} + +/* Demangles and emits a <function-type> FUNCTION_NAME_POS is the + position in the result string of the start of the function + identifier, at which the function's return type will be inserted. + + <function-type> ::= F [Y] <bare-function-type> E */ + +static status_t +demangle_function_type (dm, function_name_pos) + demangling_t dm; + int function_name_pos; +{ + DEMANGLE_TRACE ("function-type", dm); + RETURN_IF_ERROR (demangle_char (dm, 'F')); + if (peek_char (dm) == 'Y') + { + /* Indicate this function has C linkage if in verbose mode. */ + if (flag_verbose) + result_append (dm, " [extern \"C\"] "); + advance_char (dm); + } + RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos)); + RETURN_IF_ERROR (demangle_char (dm, 'E')); + return STATUS_OK; +} + +/* Demangles and emits a <bare-function-type>. RETURN_TYPE_POS is the + position in the result string at which the function return type + should be inserted. If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the + function's return type is assumed not to be encoded. + + <bare-function-type> ::= <signature type>+ */ + +static status_t +demangle_bare_function_type (dm, return_type_pos) + demangling_t dm; + int return_type_pos; +{ + /* Sequence is the index of the current function parameter, counting + from zero. The value -1 denotes the return type. */ + int sequence = + (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1); + + DEMANGLE_TRACE ("bare-function-type", dm); + + result_append_char (dm, '('); + while (!end_of_name_p (dm) && peek_char (dm) != 'E') + { + if (sequence == -1) + /* We're decoding the function's return type. */ + { + dyn_string_t return_type; + + /* Decode the return type off to the side. */ + result_push (dm); + RETURN_IF_ERROR (demangle_type (dm)); + return_type = (dyn_string_t) result_pop (dm); + + /* Add a space to the end of the type. */ + dyn_string_append_space (return_type); + + /* Insert the return type where we've been asked to. */ + dyn_string_insert (result_string (dm), return_type_pos, + return_type); + dyn_string_delete (return_type); + } + else + { + /* Skip `void' parameter types. One should only occur as + the only type in a parameter list; in that case, we want + to print `foo ()' instead of `foo (void)'. */ + if (peek_char (dm) == 'v') + { + /* Consume the v. */ + advance_char (dm); + continue; + } + /* Separate parameter types by commas. */ + if (sequence > 0) + result_append (dm, ", "); + /* Demangle the type. */ + RETURN_IF_ERROR (demangle_type (dm)); + } + + ++sequence; + } + result_append_char (dm, ')'); + + return STATUS_OK; +} + +/* Demangles and emits a <class-enum-type>. *TEMPLATE_P is set to + non-zero if the type is a template-id, zero otherwise. + + <class-enum-type> ::= <name> */ + +static status_t +demangle_class_enum_type (dm, template_p) + demangling_t dm; + int *template_p; +{ + DEMANGLE_TRACE ("class-enum-type", dm); + + RETURN_IF_ERROR (demangle_name (dm, template_p)); + return STATUS_OK; +} + +/* Demangles and emits an <array-type>. + + <array-type> ::= A [<dimension number>] _ <element type> */ + +static status_t +demangle_array_type (dm) + demangling_t dm; +{ + dyn_string_t array_size = dyn_string_new (10); + + RETURN_IF_ERROR (demangle_char (dm, 'A')); + + /* Demangle the array size into array_size. */ + RETURN_IF_ERROR (demangle_number_literally (dm, array_size, 10, 0)); + + /* Demangle the base type of the array. */ + RETURN_IF_ERROR (demangle_char (dm, '_')); + RETURN_IF_ERROR (demangle_type (dm)); + + /* Emit the array dimension syntax. */ + result_append_char (dm, '['); + result_append_string (dm, array_size); + result_append_char (dm, ']'); + dyn_string_delete (array_size); + + return STATUS_OK; +} + +/* Demangles and emits a <template-param>. The zero-indexed position + in the parameter list is placed in *TEMPLATE_PARM_NUMBER. + + <template-param> ::= T_ # first template parameter + ::= T <parameter-2 number> _ */ + +static status_t +demangle_template_param (dm, template_parm_number) + demangling_t dm; + int *template_parm_number; +{ + int parm_number; + template_arg_list_t current_arg_list = current_template_arg_list (dm); + string_list_t arg; + + DEMANGLE_TRACE ("template-param", dm); + + /* Make sure there is a template argmust list in which to look up + this parameter reference. */ + if (current_arg_list == NULL) + return "Template parameter outside of template."; + + RETURN_IF_ERROR (demangle_char (dm, 'T')); + if (peek_char (dm) == '_') + parm_number = 0; + else + { + RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0)); + ++parm_number; + } + RETURN_IF_ERROR (demangle_char (dm, '_')); + + arg = template_arg_list_get_arg (current_arg_list, parm_number); + if (arg == NULL) + /* parm_number exceeded the number of arguments in the current + template argument list. */ + return "Template parameter number out of bounds."; + result_append_string (dm, (dyn_string_t) arg); + + if (peek_char (dm) == 'I') + RETURN_IF_ERROR (demangle_template_args (dm)); + + *template_parm_number = parm_number; + return STATUS_OK; +} + +/* Demangles and emits a <template-args>. + + <template-args> ::= I <template-arg>+ E */ + +static status_t +demangle_template_args (dm) + demangling_t dm; +{ + int first = 1; + template_arg_list_t arg_list = template_arg_list_new (); + + /* Preserve the most recently demangled source name. */ + dyn_string_t old_last_source_name = dm->last_source_name; + dm->last_source_name = dyn_string_new (0); + + DEMANGLE_TRACE ("template-args", dm); + + RETURN_IF_ERROR (demangle_char (dm, 'I')); + result_append_char (dm, '<'); + do + { + string_list_t arg; + + if (first) + first = 0; + else + result_append (dm, ", "); + + /* Capture the template arg. */ + result_push (dm); + RETURN_IF_ERROR (demangle_template_arg (dm)); + arg = result_pop (dm); + + /* Emit it in the demangled name. */ + result_append_string (dm, (dyn_string_t) arg); + + /* Save it for use in expanding <template-param>s. */ + template_arg_list_add_arg (arg_list, arg); + } + while (peek_char (dm) != 'E'); + /* Append the '>'. */ + result_close_template_list (dm); + + /* Consume the 'E'. */ + advance_char (dm); + + /* Restore the most recent demangled source name. */ + dyn_string_delete (dm->last_source_name); + dm->last_source_name = old_last_source_name; + + /* Push the list onto the top of the stack of template argument + lists, so that arguments from it are used from now on when + expanding <template-param>s. */ + push_template_arg_list (dm, arg_list); + + return STATUS_OK; +} + +/* This function, which does not correspond to a production in the + mangling spec, handles the `literal' production for both + <template-arg> and <expr-primary>. It does not expect or consume + the initial `L' or final `E'. The demangling is given by: + + <literal> ::= <type> </value/ number> + + and the emitted output is `(type)number'. */ + +static status_t +demangle_literal (dm) + demangling_t dm; +{ + dyn_string_t value = dyn_string_new (0); + char peek = peek_char (dm); + + DEMANGLE_TRACE ("literal", dm); + + if (!flag_verbose && peek >= 'a' && peek <= 'z') + { + /* If not in verbose mode and this is a builtin type, see if we + can produce simpler numerical output. In particular, for + integer types shorter than `long', just write the number + without type information; for bools, write `true' or `false'. + Other refinements could be made here too. */ + + /* This constant string is used to map from <builtin-type> codes + (26 letters of the alphabet) to codes that determine how the + value will be displayed. The codes are: + b: display as bool + i: display as int + l: display as long + A space means the value will be represented using cast + notation. */ + static const char *const code_map = "ibi iii ll ii i "; + + char code = code_map[peek - 'a']; + /* FIXME: Implement demangling of floats and doubles. */ + if (code == 'u') + return STATUS_UNIMPLEMENTED; + if (code == 'b') + { + /* It's a boolean. */ + char value; + + /* Consume the b. */ + advance_char (dm); + /* Look at the next character. It should be 0 or 1, + corresponding to false or true, respectively. */ + value = peek_char (dm); + if (value == '0') + result_append (dm, "false"); + else if (value == '1') + result_append (dm, "true"); + else + return "Unrecognized bool constant."; + /* Consume the 0 or 1. */ + advance_char (dm); + return STATUS_OK; + } + else if (code == 'i' || code == 'l') + { + /* It's an integer or long. */ + + /* Consume the type character. */ + advance_char (dm); + /* Demangle the number and write it out. */ + RETURN_IF_ERROR (demangle_number_literally (dm, value, 10, 1)); + result_append_string (dm, value); + /* For long integers, append an l. */ + if (code == 'l') + result_append_char (dm, code); + return STATUS_OK; + } + /* ...else code == ' ', so fall through to represent this + literal's type explicitly using cast syntax. */ + } + + result_append_char (dm, '('); + RETURN_IF_ERROR (demangle_type (dm)); + result_append_char (dm, ')'); + + RETURN_IF_ERROR (demangle_number_literally (dm, value, 10, 1)); + result_append_string (dm, value); + dyn_string_delete (value); + + return STATUS_OK; +} + +/* Demangles and emits a <template-arg>. + + <template-arg> ::= <type> # type + ::= L <type> <value number> E # literal + ::= LZ <encoding> E # external name + ::= X <expression> E # expression */ + +static status_t +demangle_template_arg (dm) + demangling_t dm; +{ + DEMANGLE_TRACE ("template-arg", dm); + + switch (peek_char (dm)) + { + case 'L': + advance_char (dm); + + if (peek_char (dm) == 'Z') + { + /* External name. */ + advance_char (dm); + /* FIXME: Standard is contradictory here. */ + RETURN_IF_ERROR (demangle_encoding (dm)); + } + else + RETURN_IF_ERROR (demangle_literal (dm)); + RETURN_IF_ERROR (demangle_char (dm, 'E')); + break; + + case 'X': + /* Expression. */ + advance_char (dm); + RETURN_IF_ERROR (demangle_expression (dm)); + break; + + default: + RETURN_IF_ERROR (demangle_type (dm)); + break; + } + + return STATUS_OK; +} + +/* Demangles and emits an <expression>. + + <expression> ::= <unary operator-name> <expression> + ::= <binary operator-name> <expression> <expression> + ::= <expr-primary> + ::= <scope-expression> */ + +static status_t +demangle_expression (dm) + demangling_t dm; +{ + char peek = peek_char (dm); + + DEMANGLE_TRACE ("expression", dm); + + if (peek == 'L' || peek == 'T') + RETURN_IF_ERROR (demangle_expr_primary (dm)); + else if (peek == 's' && peek_char_next (dm) == 'r') + RETURN_IF_ERROR (demangle_scope_expression (dm)); + else + /* An operator expression. */ + { + int num_args; + dyn_string_t operator_name; + + /* We have an operator name. Since we want to output binary + operations in infix notation, capture the operator name + first. */ + result_push (dm); + RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args)); + operator_name = (dyn_string_t) result_pop (dm); + + /* If it's binary, do an operand first. */ + if (num_args > 1) + { + result_append_char (dm, '('); + RETURN_IF_ERROR (demangle_expression (dm)); + result_append_char (dm, ')'); + } + + /* Now emit the operator, followed by its second (if binary) or + only (if unary) operand. */ + result_append_string (dm, operator_name); + dyn_string_delete (operator_name); + result_append_char (dm, '('); + RETURN_IF_ERROR (demangle_expression (dm)); + result_append_char (dm, ')'); + + /* The ternary operator takes a third operand. */ + if (num_args == 3) + { + result_append (dm, ":("); + RETURN_IF_ERROR (demangle_expression (dm)); + result_append_char (dm, ')'); + } + } + + return STATUS_OK; +} + +/* Demangles and emits a <scope-expression>. + + <scope-expression> ::= sr <qualifying type> <source-name> + ::= sr <qualifying type> <encoding> */ + +static status_t +demangle_scope_expression (dm) + demangling_t dm; +{ + RETURN_IF_ERROR (demangle_char (dm, 's')); + RETURN_IF_ERROR (demangle_char (dm, 'r')); + RETURN_IF_ERROR (demangle_type (dm)); + result_append (dm, "::"); + RETURN_IF_ERROR (demangle_encoding (dm)); + return STATUS_OK; +} + +/* Demangles and emits an <expr-primary>. + + <expr-primary> ::= <template-param> + ::= L <type> <value number> E # literal + ::= L <mangled-name> E # external name */ + +static status_t +demangle_expr_primary (dm) + demangling_t dm; +{ + char peek = peek_char (dm); + int unused; + + DEMANGLE_TRACE ("expr-primary", dm); + + if (peek == 'T') + RETURN_IF_ERROR (demangle_template_param (dm, &unused)); + else if (peek == 'L') + { + /* Consume the `L'. */ + advance_char (dm); + peek = peek_char (dm); + + if (peek == '_') + RETURN_IF_ERROR (demangle_mangled_name (dm)); + else + RETURN_IF_ERROR (demangle_literal (dm)); + + RETURN_IF_ERROR (demangle_char (dm, 'E')); + } + else + return STATUS_ERROR; + + return STATUS_OK; +} + +/* Demangles and emits a <substitution>. Sets *TEMPLATE_P to non-zero + if the substitution is the name of a template, zero otherwise. If + the substitution token is St, which corresponds to the `::std::' + namespace and can appear in a non-nested name, sets + *SPECIAL_STD_SUBSTITUTION to non-zero; zero otherwise. + + <substitution> ::= S <seq-id> _ + ::= S_ + + ::= St # ::std:: + ::= Sa # ::std::allocator + ::= Sb # ::std::basic_string + ::= Ss # ::std::basic_string<char, + ::std::char_traits<char>, + ::std::allocator<char> > + ::= Si # ::std::basic_istream<char, + std::char_traits<char> > + ::= So # ::std::basic_ostream<char, + std::char_traits<char> > + ::= Sd # ::std::basic_iostream<char, + std::char_traits<char> > +*/ + +static status_t +demangle_substitution (dm, template_p, special_std_substitution) + demangling_t dm; + int *template_p; + int *special_std_substitution; +{ + int seq_id; + int peek; + dyn_string_t text; + + DEMANGLE_TRACE ("substitution", dm); + + RETURN_IF_ERROR (demangle_char (dm, 'S')); + *special_std_substitution = 0; + + /* Scan the substitution sequence index. A missing number denotes + the first index. */ + peek = peek_char (dm); + if (peek == '_') + seq_id = -1; + /* If the following character is 0-9 or a capital letter, interpret + the sequence up to the next underscore as a base-36 substitution + index. */ + else if (isdigit ((unsigned char) peek) + || (peek >= 'A' && peek <= 'Z')) + RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0)); + else + { + switch (peek) + { + case 't': + result_append (dm, "std"); + *special_std_substitution = 1; + break; + + case 'a': + result_append (dm, "std::allocator"); + dyn_string_copy_cstr (dm->last_source_name, "allocator"); + break; + + case 'b': + result_append (dm, "std::basic_string"); + dyn_string_copy_cstr (dm->last_source_name, "basic_string"); + break; + + case 's': + if (!flag_verbose) + { + result_append (dm, "std::string"); + dyn_string_copy_cstr (dm->last_source_name, "string"); + } + else + { + result_append (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"); + dyn_string_copy_cstr (dm->last_source_name, "basic_string"); + } + break; + + case 'i': + if (!flag_verbose) + { + result_append (dm, "std::istream"); + dyn_string_copy_cstr (dm->last_source_name, "istream"); + } + else + { + result_append (dm, "std::basic_istream<char, std::char_traints<char> >"); + dyn_string_copy_cstr (dm->last_source_name, "basic_istream"); + } + break; + + case 'o': + if (!flag_verbose) + { + result_append (dm, "std::ostream"); + dyn_string_copy_cstr (dm->last_source_name, "ostream"); + } + else + { + result_append (dm, "std::basic_ostream<char, std::char_traits<char> >"); + dyn_string_copy_cstr (dm->last_source_name, "basic_ostream"); + } + break; + + case 'd': + if (!flag_verbose) + { + result_append (dm, "std::iostream"); + dyn_string_copy_cstr (dm->last_source_name, "iostream"); + } + else + { + result_append (dm, "std::basic_iostream<char, std::char_traits<char> >"); + dyn_string_copy_cstr (dm->last_source_name, "basic_iostream"); + } + break; + + default: + return "Unrecognized <substitution>."; + } + + advance_char (dm); + return STATUS_OK; + } + + /* Look up the substitution text. Since `S_' is the most recent + substitution, `S0_' is the second-most-recent, etc., shift the + numbering by one. */ + text = substitution_get (dm, seq_id + 1, template_p); + if (text == NULL) + return "Substitution number out of range."; + + /* Emit the substitution text. */ + result_append_string (dm, text); + + RETURN_IF_ERROR (demangle_char (dm, '_')); + return STATUS_OK; +} + +/* Demangles and emits a <local-name>. + + <local-name> := Z <function encoding> E <entity name> [<discriminator>] + := Z <function encoding> E s [<discriminator>] */ + +static status_t +demangle_local_name (dm) + demangling_t dm; +{ + DEMANGLE_TRACE ("local-name", dm); + + RETURN_IF_ERROR (demangle_char (dm, 'Z')); + RETURN_IF_ERROR (demangle_encoding (dm)); + RETURN_IF_ERROR (demangle_char (dm, 'E')); + result_append (dm, "'s "); + + if (peek_char (dm) == 's') + { + /* Local character string literal. */ + result_append (dm, "string literal"); + /* Consume the s. */ + advance_char (dm); + RETURN_IF_ERROR (demangle_discriminator (dm, 0)); + } + else + { + int unused; + result_append (dm, "local "); + /* Local name for some other entity. Demangle its name. */ + RETURN_IF_ERROR (demangle_name (dm, &unused)); + RETURN_IF_ERROR (demangle_discriminator (dm, 1)); + } + + return STATUS_OK; + } + + /* Optimonally demangles and emits a <discriminator>. If there is no + <discriminator> at the current position in the mangled string, the + descriminator is assumed to be zero. Emit the discriminator number + in parentheses, unless SUPPRESS_FIRST is non-zero and the + discriminator is zero. + + <discriminator> ::= _ <number> */ + +static status_t +demangle_discriminator (dm, suppress_first) + demangling_t dm; + int suppress_first; +{ + /* Output for <discriminator>s to the demangled name is completely + supressed if not in verbose mode. */ + + if (peek_char (dm) == '_') + { + /* Consume the underscore. */ + advance_char (dm); + if (flag_verbose) + result_append (dm, " [#"); + /* Check if there's a number following the underscore. */ + if (isdigit ((unsigned char) peek_char (dm))) + { + int discriminator; + /* Demangle the number. */ + RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0)); + if (flag_verbose) + /* Write the discriminator. The mangled number is two + less than the discriminator ordinal, counting from + zero. */ + int_to_dyn_string (discriminator + 2, + (dyn_string_t) dm->result); + } + else + { + if (flag_verbose) + /* A missing digit correspond to one. */ + result_append_char (dm, '1'); + } + if (flag_verbose) + result_append_char (dm, ']'); + } + else if (!suppress_first) + { + if (flag_verbose) + result_append (dm, " [#0]"); + } + + return STATUS_OK; +} + +/* Demangle NAME into RESULT, which must be an initialized + dyn_string_t. On success, returns STATUS_OK. On failure, returns + an error message, and the contents of RESULT are unchanged. */ + +static status_t +cp_demangle (name, result) + char *name; + dyn_string_t result; +{ + status_t status; + int length = strlen (name); + + if (length > 2 && name[0] == '_' && name[1] == 'Z') + { + demangling_t dm = demangling_new (name); + + result_push (dm); + status = demangle_mangled_name (dm); + + if (status == STATUS_OK) + { + dyn_string_t demangled = (dyn_string_t) result_pop (dm); + dyn_string_copy (result, demangled); + dyn_string_delete (demangled); + } + + demangling_delete (dm); + } + else + { + /* It's evidently not a mangled C++ name. It could be the name + of something with C linkage, though, so just copy NAME into + RESULT. */ + dyn_string_copy_cstr (result, name); + status = STATUS_OK; + } + + return status; +} + +/* Variant entry point for integration with the existing cplus-dem + demangler. Attempts to demangle MANGLED. If the demangling + succeeds, returns a buffer, allocated with malloc, containing the + demangled name. The caller must deallocate the buffer using free. + If the demangling failes, returns NULL. */ + +char * +cplus_demangle_new_abi (mangled) + const char* mangled; +{ + /* Create a dyn_string to hold the demangled name. */ + dyn_string_t demangled = dyn_string_new (0); + /* Attempt the demangling. */ + status_t status = cp_demangle ((char *) mangled, demangled); + if (status == STATUS_OK) + /* Demangling succeeded. */ + { + /* Grab the demangled result from the dyn_string. It was + allocated with malloc, so we can return it directly. */ + char *return_value = dyn_string_release (demangled); + /* The dyn_string can go away. */ + dyn_string_delete (demangled); + /* Hand back the demangled name. */ + return return_value; + } + else + /* Demangling failed. */ + { + dyn_string_delete (demangled); + return NULL; + } +} + +#ifdef STANDALONE_DEMANGLER + +#include "getopt.h" + +static void print_usage + PARAMS ((FILE* fp, int exit_value)); + +/* Non-zero if CHAR is a character than can occur in a mangled name. */ +#define is_mangled_char(CHAR) \ + (isalnum ((unsigned char) (CHAR)) || (CHAR) == '_') + +/* The name of this program, as invoked. */ +const char* program_name; + +/* Prints usage summary to FP and then exits with EXIT_VALUE. */ + +static void +print_usage (fp, exit_value) + FILE* fp; + int exit_value; +{ + fprintf (fp, "Usage: %s [options] [names ...]\n", program_name); + fprintf (fp, "Options:\n", program_name); + fprintf (fp, " -h,--help Display this message.\n"); + fprintf (fp, " -s,--strict Demangle standard names only.\n"); + fprintf (fp, " -v,--verbose Produce verbose demanglings.\n"); + fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n"); + + exit (exit_value); +} + +/* Option specification for getopt_long. */ +static struct option long_options[] = +{ + { "help", no_argument, NULL, 'h' }, + { "strict", no_argument, NULL, 's' }, + { "verbose", no_argument, NULL, 'v' }, + { NULL, no_argument, NULL, 0 }, +}; + +/* Main entry for a demangling filter executable. It will demangle + its command line arguments, if any. If none are provided, it will + filter stdin to stdout, replacing any recognized mangled C++ names + with their demangled equivalents. */ + +int +main (argc, argv) + int argc; + char *argv[]; +{ + status_t status; + int i; + int opt_char; + + /* Use the program name of this program, as invoked. */ + program_name = argv[0]; + + /* Parse options. */ + do + { + opt_char = getopt_long (argc, argv, "hsv", long_options, NULL); + switch (opt_char) + { + case '?': /* Unrecognized option. */ + print_usage (stderr, 1); + break; + + case 'h': + print_usage (stdout, 0); + break; + + case 's': + flag_strict = 1; + break; + + case 'v': + flag_verbose = 1; + break; + } + } + while (opt_char != -1); + + if (optind == argc) + /* No command line arguments were provided. Filter stdin. */ + { + dyn_string_t mangled = dyn_string_new (3); + dyn_string_t demangled = dyn_string_new (0); + status_t status; + + /* Read all of input. */ + while (!feof (stdin)) + { + char c = getchar (); + + /* The first character of a mangled name is an underscore. */ + if (feof (stdin)) + break; + if (c != '_') + { + /* It's not a mangled name. Print the character and go + on. */ + putchar (c); + continue; + } + c = getchar (); + + /* The second character of a mangled name is a capital `Z'. */ + if (feof (stdin)) + break; + if (c != 'Z') + { + /* It's not a mangled name. Print the previous + underscore, the `Z', and go on. */ + putchar ('_'); + putchar (c); + continue; + } + + /* Start keeping track of the candidate mangled name. */ + dyn_string_append_char (mangled, '_'); + dyn_string_append_char (mangled, 'Z'); + + /* Pile characters into mangled until we hit one that can't + occur in a mangled name. */ + c = getchar (); + while (!feof (stdin) && is_mangled_char (c)) + { + dyn_string_append_char (mangled, c); + if (feof (stdin)) + break; + c = getchar (); + } + + /* Attempt to demangle the name. */ + status = cp_demangle (dyn_string_buf (mangled), demangled); + + /* If the demangling succeeded, great! Print out the + demangled version. */ + if (status == STATUS_OK) + fputs (dyn_string_buf (demangled), stdout); + /* Otherwise, it might not have been a mangled name. Just + print out the original text. */ + else + fputs (dyn_string_buf (mangled), stdout); + + /* If we haven't hit EOF yet, we've read one character that + can't occur in a mangled name, so print it out. */ + if (!feof (stdin)) + putchar (c); + + /* Clear the candidate mangled name, to start afresh next + time we hit a `_Z'. */ + dyn_string_clear (mangled); + } + + dyn_string_delete (mangled); + dyn_string_delete (demangled); + } + else + /* Demangle command line arguments. */ + { + dyn_string_t result = dyn_string_new (0); + + /* Loop over command line arguments. */ + for (i = optind; i < argc; ++i) + { + /* Attempt to demangle. */ + status = cp_demangle (argv[i], result); + + /* If it worked, print the demangled name. */ + if (status == STATUS_OK) + printf ("%s\n", dyn_string_buf (result)); + /* If not, print the error message to stderr instead. */ + else + fprintf (stderr, "%s\n", status); + } + dyn_string_delete (result); + } + + return 0; +} + +#endif /* STANDALONE_DEMANGLER */ diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index 52249d2b580..44d11968162 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -252,6 +252,55 @@ typedef enum type_kind_t tk_real } type_kind_t; +struct demangler_engine libiberty_demanglers[] = +{ + { + AUTO_DEMANGLING_STYLE_STRING, + auto_demangling, + "Automatic selection based on executable" + } + , + { + GNU_DEMANGLING_STYLE_STRING, + gnu_demangling, + "GNU (g++) style demangling" + } + , + { + LUCID_DEMANGLING_STYLE_STRING, + lucid_demangling, + "Lucid (lcc) style demangling" + } + , + { + ARM_DEMANGLING_STYLE_STRING, + arm_demangling, + "ARM style demangling" + } + , + { + HP_DEMANGLING_STYLE_STRING, + hp_demangling, + "HP (aCC) style demangling" + } + , + { + EDG_DEMANGLING_STYLE_STRING, + edg_demangling, + "EDG style demangling" + } + , + { + GNU_NEW_ABI_DEMANGLING_STYLE_STRING, + gnu_new_abi_demangling, + "GNU (g++) new-ABI-style demangling" + } + , + { + NULL, unknown_demangling, NULL + } +}; + #define STRING_EMPTY(str) ((str) -> b == (str) -> p) #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ string_prepend(str, " ");} @@ -636,8 +685,8 @@ cplus_demangle_opname (opname, result, options) } } else if (opname[0] == '_' && opname[1] == '_' - && opname[2] >= 'a' && opname[2] <= 'z' - && opname[3] >= 'a' && opname[3] <= 'z') + && islower((unsigned char)opname[2]) + && islower((unsigned char)opname[3])) { if (opname[4] == '\0') { @@ -733,6 +782,7 @@ cplus_demangle_opname (opname, result, options) return ret; } + /* Takes operator name as e.g. "++" and returns mangled operator name (e.g. "postincrement_expr"), or NULL if not found. @@ -758,6 +808,40 @@ cplus_mangle_opname (opname, options) return (0); } +/* Add a routine to set the demangling style to be sure it is valid and + allow for any demangler initialization that maybe necessary. */ + +enum demangling_styles +cplus_demangle_set_style (style) + enum demangling_styles style; +{ + struct demangler_engine *demangler = libiberty_demanglers; + + for (; demangler->demangling_style != unknown_demangling; ++demangler) + if (style == demangler->demangling_style) + { + current_demangling_style = style; + return current_demangling_style; + } + + return unknown_demangling; +} + +/* Do string name to style translation */ + +enum demangling_styles +cplus_demangle_name_to_style (name) + const char *name; +{ + struct demangler_engine *demangler = libiberty_demanglers; + + for (; demangler->demangling_style != unknown_demangling; ++demangler) + if (strcmp (name, demangler->demangling_style_name) == 0) + return demangler->demangling_style; + + return unknown_demangling; +} + /* char *cplus_demangle (const char *mangled, int options) If MANGLED is a mangled function name produced by GNU C++, then @@ -798,6 +882,10 @@ cplus_demangle (mangled, options) if ((work -> options & DMGL_STYLE_MASK) == 0) work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK; + /* The new-ABI demangling is implemented elsewhere. */ + if (GNU_NEW_ABI_DEMANGLING) + return cplus_demangle_new_abi (mangled); + ret = internal_cplus_demangle (work, mangled); squangle_mop_up (work); return (ret); @@ -4188,8 +4276,8 @@ demangle_function_name (work, mangled, declp, scan) } } else if (declp->b[0] == '_' && declp->b[1] == '_' - && declp->b[2] >= 'a' && declp->b[2] <= 'z' - && declp->b[3] >= 'a' && declp->b[3] <= 'z') + && islower((unsigned char)declp->b[2]) + && islower((unsigned char)declp->b[3])) { if (declp->b[4] == '\0') { @@ -4402,6 +4490,7 @@ static int flags = DMGL_PARAMS | DMGL_ANSI; static void demangle_it PARAMS ((char *)); static void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN; static void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN; +static void print_demangler_list PARAMS ((FILE *)); static void demangle_it (mangled_name) @@ -4421,16 +4510,43 @@ demangle_it (mangled_name) } } +static void +print_demangler_list (stream) + FILE *stream; +{ + struct demangler_engine *demangler; + + fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name); + + for (demangler = libiberty_demanglers + 1; + demangler->demangling_style != unknown_demangling; + ++demangler) + fprintf (stream, ",%s", demangler->demangling_style_name); + + fprintf (stream, "}"); +} + static void usage (stream, status) FILE *stream; int status; { fprintf (stream, "\ -Usage: %s [-_] [-n] [-s {gnu,lucid,arm,hp,edg}] [--strip-underscores]\n\ - [--no-strip-underscores] [--format={gnu,lucid,arm,hp,edg}]\n\ - [--help] [--version] [arg...]\n", +Usage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n", program_name); + + fprintf (stream, "\ + [-s "); + print_demangler_list (stream); + fprintf (stream, "]\n"); + + fprintf (stream, "\ + [--format "); + print_demangler_list (stream); + fprintf (stream, "]\n"); + + fprintf (stream, "\ + [--help] [--version] [arg...]\n"); exit (status); } @@ -4468,6 +4584,9 @@ standard_symbol_characters PARAMS ((void)); static const char * hp_symbol_characters PARAMS ((void)); +static const char * +gnu_new_abi_symbol_characters PARAMS ((void)); + /* Return the string of non-alnum characters that may occur as a valid symbol component, in the standard assembler symbol syntax. */ @@ -4516,6 +4635,17 @@ hp_symbol_characters () } +/* Return the string of non-alnum characters that may occur + as a valid symbol component in the GNU standard C++ ABI mangling + scheme. */ + +static const char * +gnu_new_abi_symbol_characters () +{ + return "_"; +} + + extern int main PARAMS ((int, char **)); int @@ -4553,32 +4683,19 @@ main (argc, argv) flags |= DMGL_JAVA; break; case 's': - if (strcmp (optarg, "gnu") == 0) - { - current_demangling_style = gnu_demangling; - } - else if (strcmp (optarg, "lucid") == 0) - { - current_demangling_style = lucid_demangling; - } - else if (strcmp (optarg, "arm") == 0) - { - current_demangling_style = arm_demangling; - } - else if (strcmp (optarg, "hp") == 0) - { - current_demangling_style = hp_demangling; - } - else if (strcmp (optarg, "edg") == 0) - { - current_demangling_style = edg_demangling; - } - else - { - fprintf (stderr, "%s: unknown demangling style `%s'\n", - program_name, optarg); - return (1); - } + { + enum demangling_styles style; + + style = cplus_demangle_name_to_style (optarg); + if (style == unknown_demangling) + { + fprintf (stderr, "%s: unknown demangling style `%s'\n", + program_name, optarg); + return (1); + } + else + cplus_demangle_set_style (style); + } break; } } @@ -4603,6 +4720,9 @@ main (argc, argv) case hp_demangling: valid_symbols = hp_symbol_characters (); break; + case gnu_new_abi_demangling: + valid_symbols = gnu_new_abi_symbol_characters (); + break; default: /* Folks should explicitly indicate the appropriate alphabet for each demangling. Providing a default would allow the diff --git a/libiberty/dyn-string.c b/libiberty/dyn-string.c new file mode 100644 index 00000000000..f4a9d9a74f8 --- /dev/null +++ b/libiberty/dyn-string.c @@ -0,0 +1,333 @@ +/* An abstract string datatype. + Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + Contributed by Mark Mitchell (mark@markmitchell.com). + +This file is part of GNU CC. + +GNU CC 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, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#include "libiberty.h" +#include "dyn-string.h" + +/* Performs in-place initialization of a dyn_string struct. This + function can be used with a dyn_string struct on the stack or + embedded in another object. The contents of of the string itself + are still dynamically allocated. The string initially is capable + of holding at least SPACE characeters, including the terminating + NUL. If SPACE is 0, it will silently be increated to 1. */ + +void +dyn_string_init (ds_struct_ptr, space) + struct dyn_string *ds_struct_ptr; + int space; +{ + /* We need at least one byte in which to store the terminating NUL. */ + if (space == 0) + space = 1; + + ds_struct_ptr->allocated = space; + ds_struct_ptr->s = (char *) xmalloc (space); + ds_struct_ptr->length = 0; + ds_struct_ptr->s[0] = '\0'; +} + +/* Create a new dynamic string capable of holding at least SPACE characters, + including the terminating NUL. If SPACE is 0, it will be silently + increased to 1. */ + +dyn_string_t +dyn_string_new (space) + int space; +{ + dyn_string_t result = (dyn_string_t) xmalloc (sizeof (struct dyn_string)); + dyn_string_init (result, space); + return result; +} + +/* Free the memory used by DS. */ + +void +dyn_string_delete (ds) + dyn_string_t ds; +{ + free (ds->s); + free (ds); +} + +/* Returns the contents of DS in a buffer allocated with malloc. It + is the caller's responsibility to deallocate the buffer using free. + DS is then set to the empty string. */ + +char* +dyn_string_release (ds) + dyn_string_t ds; +{ + /* Store the old buffer. */ + char* result = ds->s; + /* The buffer is no longer owned by DS. */ + ds->s = NULL; + /* Reinitialize DS to the empty string. */ + dyn_string_init (ds, 0); + /* Return the old buffer. */ + return result; +} + +/* Increase the capacity of DS so it can hold at least SPACE + characters, plus the terminating NUL. This function will not (at + present) reduce the capacity of DS. */ + +dyn_string_t +dyn_string_resize (ds, space) + dyn_string_t ds; + int space; +{ + int new_allocated = ds->allocated; + + /* Increase SPACE to hold the NUL termination. */ + ++space; + + while (space > new_allocated) + new_allocated *= 2; + + if (new_allocated != ds->allocated) + { + /* We actually need more space. */ + ds->allocated = new_allocated; + ds->s = (char *) xrealloc (ds->s, ds->allocated); + } + + return ds; +} + +/* Sets the contents of DS to the empty string. */ + +void +dyn_string_clear (ds) + dyn_string_t ds; +{ + /* A dyn_string always has room for at least the NUL terminator. */ + ds->s[0] = '\0'; + ds->length = 0; +} + +/* Makes the contents of DEST the same as the contents of SRC. DEST + and SRC must be distinct. */ + +void +dyn_string_copy (dest, src) + dyn_string_t dest; + dyn_string_t src; +{ + if (dest == src) + abort (); + + /* Make room in DEST. */ + dyn_string_resize (dest, src->length); + /* Copy DEST into SRC. */ + strcpy (dest->s, src->s); + /* Update the size of DEST. */ + dest->length = src->length; +} + +/* Copies SRC, a NUL-terminated string, into DEST. */ + +void +dyn_string_copy_cstr (dest, src) + dyn_string_t dest; + const char *src; +{ + int length = strlen (src); + /* Make room in DEST. */ + dyn_string_resize (dest, length); + /* Copy DEST into SRC. */ + strcpy (dest->s, src); + /* Update the size of DEST. */ + dest->length = length; +} + +/* Inserts SRC at the beginning of DEST. DEST is expanded as + necessary. SRC and DEST must be distinct. */ + +void +dyn_string_prepend (dest, src) + dyn_string_t dest; + dyn_string_t src; +{ + dyn_string_insert (dest, 0, src); +} + +/* Inserts SRC, a NUL-terminated string, at the beginning of DEST. + DEST is expanded as necessary. */ + +void +dyn_string_prepend_cstr (dest, src) + dyn_string_t dest; + const char *src; +{ + dyn_string_insert_cstr (dest, 0, src); +} + +/* Inserts SRC into DEST starting at position POS. DEST is expanded as + necessary. SRC and DEST must be distinct. */ + +void +dyn_string_insert (dest, pos, src) + dyn_string_t dest; + int pos; + dyn_string_t src; +{ + int i; + + if (src == dest) + abort (); + + dyn_string_resize (dest, dest->length + src->length); + /* Make room for the insertion. Be sure to copy the NUL. */ + for (i = dest->length; i >= pos; --i) + dest->s[i + src->length] = dest->s[i]; + /* Splice in the new stuff. */ + strncpy (dest->s + pos, src->s, src->length); + /* Compute the new length. */ + dest->length += src->length; +} + +/* Inserts SRC, a NUL-terminated string, into DEST starting at + position POS. DEST is expanded as necessary. */ + +void +dyn_string_insert_cstr (dest, pos, src) + dyn_string_t dest; + int pos; + const char *src; +{ + int i; + int length = strlen (src); + + dyn_string_resize (dest, dest->length + length); + /* Make room for the insertion. Be sure to copy the NUL. */ + for (i = dest->length; i >= pos; --i) + dest->s[i + length] = dest->s[i]; + /* Splice in the new stuff. */ + strncpy (dest->s + pos, src, length); + /* Compute the new length. */ + dest->length += length; +} + +/* Append S to DS, resizing DS if necessary. Returns DS. */ + +dyn_string_t +dyn_string_append (ds, s) + dyn_string_t ds; + dyn_string_t s; +{ + dyn_string_resize (ds, ds->length + s->length); + strcpy (ds->s + ds->length, s->s); + ds->length += s->length; + return ds; +} + +/* Append the NUL-terminated string S to DS, resizing DS if necessary. + Returns DS. */ + +dyn_string_t +dyn_string_append_cstr (ds, s) + dyn_string_t ds; + const char *s; +{ + int len = strlen (s); + + /* The new length is the old length plus the size of our string, plus + one for the null at the end. */ + dyn_string_resize (ds, ds->length + len); + strcpy (ds->s + ds->length, s); + ds->length += len; + + return ds; +} + +/* Appends C to the end of DS. */ + +dyn_string_t +dyn_string_append_char (ds, c) + dyn_string_t ds; + int c; +{ + /* Make room for the extra character. */ + dyn_string_resize (ds, ds->length + 1); + /* Append the character; it will overwrite the old NUL. */ + ds->s[ds->length] = c; + /* Add a new NUL at the end. */ + ds->s[ds->length + 1] = '\0'; + /* Update the length. */ + ++(ds->length); + return ds; +} + +/* Sets the contents of DEST to the substring of SRC starting at START + and ending before END. START must be less than or equal to END, + and both must be between zero and the length of SRC, inclusive. */ + +void +dyn_string_substring (dest, src, start, end) + dyn_string_t dest; + dyn_string_t src; + int start; + int end; +{ + int i; + int length = end - start; + + if (start > end || start > src->length || end > src->length) + abort (); + + /* Make room for the substring. */ + dyn_string_resize (dest, length); + /* Copy the characters in the substring, */ + for (i = length; --i >= 0; ) + dest->s[i] = src->s[start + i]; + /* NUL-terimate the result. */ + dest->s[length] = '\0'; + /* Record the length of the substring. */ + dest->length = length; +} + +/* Returns non-zero if DS1 and DS2 have the same contents. */ + +int +dyn_string_eq (ds1, ds2) + dyn_string_t ds1; + dyn_string_t ds2; +{ + /* If DS1 and DS2 have different lengths, they must not be the same. */ + if (ds1->length != ds2->length) + return 0; + else + return !strcmp (ds1->s, ds2->s); +} diff --git a/libiberty/hashtab.c b/libiberty/hashtab.c index 6ae34aab0f1..57b40417c95 100644 --- a/libiberty/hashtab.c +++ b/libiberty/hashtab.c @@ -1,5 +1,5 @@ /* An expandable hash tables datatype. - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. Contributed by Vladimir Makarov (vmakarov@cygnus.com). This file is part of the libiberty library. @@ -59,8 +59,20 @@ Boston, MA 02111-1307, USA. */ #define DELETED_ENTRY ((void *) 1) +static unsigned long higher_prime_number PARAMS ((unsigned long)); +static hashval_t hash_pointer PARAMS ((const void *)); +static int eq_pointer PARAMS ((const void *, const void *)); +static void htab_expand PARAMS ((htab_t)); +static void **find_empty_slot_for_expand PARAMS ((htab_t, hashval_t)); + +/* At some point, we could make these be NULL, and modify the + hash-table routines to handle NULL specially; that would avoid + function-call overhead for the common case of hashing pointers. */ +htab_hash htab_hash_pointer = hash_pointer; +htab_eq htab_eq_pointer = eq_pointer; + /* The following function returns the nearest prime number which is - greater than given source number. */ + greater than a given source number, N. */ static unsigned long higher_prime_number (n) @@ -68,24 +80,47 @@ higher_prime_number (n) { unsigned long i; - n |= 0x01; /* Force N to be odd. */ + /* Ensure we have a larger number and then force to odd. */ + n++; + n |= 0x01; + + /* All odd numbers < 9 are prime. */ if (n < 9) - return n; /* All odd numbers < 9 are prime. */ + return n; + + /* Otherwise find the next prime using a sieve. */ next: - n += 2; - i = 3; - do - { - if (n % i == 0) - goto next; - i += 2; - } - while ((i * i) <= n); + + for (i = 3; i * i <= n; i += 2) + if (n % i == 0) + { + n += 2; + goto next; + } return n; } +/* Returns a hash code for P. */ + +static hashval_t +hash_pointer (p) + const void *p; +{ + return (hashval_t) ((long)p >> 3); +} + +/* Returns non-zero if P1 and P2 are equal. */ + +static int +eq_pointer (p1, p2) + const void *p1; + const void *p2; +{ + return p1 == p2; +} + /* This function creates table with length slightly longer than given source length. Created hash table is initiated as empty (all the hash table entries are EMPTY_ENTRY). The function returns the @@ -118,13 +153,12 @@ htab_delete (htab) htab_t htab; { int i; + if (htab->del_f) for (i = htab->size - 1; i >= 0; i--) - { - if (htab->entries[i] != EMPTY_ENTRY - && htab->entries[i] != DELETED_ENTRY) - (*htab->del_f) (htab->entries[i]); - } + if (htab->entries[i] != EMPTY_ENTRY + && htab->entries[i] != DELETED_ENTRY) + (*htab->del_f) (htab->entries[i]); free (htab->entries); free (htab); @@ -137,13 +171,12 @@ htab_empty (htab) htab_t htab; { int i; + if (htab->del_f) for (i = htab->size - 1; i >= 0; i--) - { - if (htab->entries[i] != EMPTY_ENTRY - && htab->entries[i] != DELETED_ENTRY) - (*htab->del_f) (htab->entries[i]); - } + if (htab->entries[i] != EMPTY_ENTRY + && htab->entries[i] != DELETED_ENTRY) + (*htab->del_f) (htab->entries[i]); memset (htab->entries, 0, htab->size * sizeof (void *)); } @@ -154,22 +187,23 @@ htab_empty (htab) hash table. This function also assumes there are no deleted entries in the table. HASH is the hash value for the element to be inserted. */ + static void ** find_empty_slot_for_expand (htab, hash) htab_t htab; - unsigned int hash; + hashval_t hash; { size_t size = htab->size; - unsigned int hash2 = 1 + hash % (size - 2); + hashval_t hash2 = 1 + hash % (size - 2); unsigned int index = hash % size; for (;;) { void **slot = htab->entries + index; + if (*slot == EMPTY_ENTRY) return slot; - - if (*slot == DELETED_ENTRY) + else if (*slot == DELETED_ENTRY) abort (); index += hash2; @@ -196,7 +230,7 @@ htab_expand (htab) olimit = oentries + htab->size; htab->size = higher_prime_number (htab->size * 2); - htab->entries = xcalloc (htab->size, sizeof (void **)); + htab->entries = (void **) xcalloc (htab->size, sizeof (void **)); htab->n_elements -= htab->n_deleted; htab->n_deleted = 0; @@ -205,14 +239,18 @@ htab_expand (htab) do { void *x = *p; + if (x != EMPTY_ENTRY && x != DELETED_ENTRY) { void **q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x)); + *q = x; } + p++; } while (p < olimit); + free (oentries); } @@ -223,33 +261,41 @@ void * htab_find_with_hash (htab, element, hash) htab_t htab; const void *element; - unsigned int hash; + hashval_t hash; { - unsigned int index, hash2; + unsigned int index; + hashval_t hash2; size_t size; + void *entry; htab->searches++; size = htab->size; - hash2 = 1 + hash % (size - 2); index = hash % size; + entry = htab->entries[index]; + if (entry == EMPTY_ENTRY + || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element))) + return entry; + + hash2 = 1 + hash % (size - 2); + for (;;) { - void *entry = htab->entries[index]; - if (entry == EMPTY_ENTRY) - return NULL; - else if (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)) - return entry; - htab->collisions++; index += hash2; if (index >= size) index -= size; + + entry = htab->entries[index]; + if (entry == EMPTY_ENTRY + || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element))) + return entry; } } /* Like htab_find_slot_with_hash, but compute the hash value from the element. */ + void * htab_find (htab, element) htab_t htab; @@ -268,14 +314,15 @@ void ** htab_find_slot_with_hash (htab, element, hash, insert) htab_t htab; const void *element; - unsigned int hash; - int insert; + hashval_t hash; + enum insert_option insert; { void **first_deleted_slot; - unsigned int index, hash2; + unsigned int index; + hashval_t hash2; size_t size; - if (insert && htab->size * 3 <= htab->n_elements * 4) + if (insert == INSERT && htab->size * 3 <= htab->n_elements * 4) htab_expand (htab); size = htab->size; @@ -290,7 +337,7 @@ htab_find_slot_with_hash (htab, element, hash, insert) void *entry = htab->entries[index]; if (entry == EMPTY_ENTRY) { - if (!insert) + if (insert == NO_INSERT) return NULL; htab->n_elements++; @@ -309,11 +356,8 @@ htab_find_slot_with_hash (htab, element, hash, insert) if (!first_deleted_slot) first_deleted_slot = &htab->entries[index]; } - else - { - if ((*htab->eq_f) (entry, element)) - return &htab->entries[index]; - } + else if ((*htab->eq_f) (entry, element)) + return &htab->entries[index]; htab->collisions++; index += hash2; @@ -324,11 +368,12 @@ htab_find_slot_with_hash (htab, element, hash, insert) /* Like htab_find_slot_with_hash, but compute the hash value from the element. */ + void ** htab_find_slot (htab, element, insert) htab_t htab; const void *element; - int insert; + enum insert_option insert; { return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element), insert); @@ -345,7 +390,7 @@ htab_remove_elt (htab, element) { void **slot; - slot = htab_find_slot (htab, element, 0); + slot = htab_find_slot (htab, element, NO_INSERT); if (*slot == EMPTY_ENTRY) return; @@ -368,8 +413,10 @@ htab_clear_slot (htab, slot) if (slot < htab->entries || slot >= htab->entries + htab->size || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY) abort (); + if (htab->del_f) (*htab->del_f) (*slot); + *slot = DELETED_ENTRY; htab->n_deleted++; } @@ -385,12 +432,13 @@ htab_traverse (htab, callback, info) htab_trav callback; void *info; { - void **slot, **limit; - slot = htab->entries; - limit = slot + htab->size; + void **slot = htab->entries; + void **limit = slot + htab->size; + do { void *x = *slot; + if (x != EMPTY_ENTRY && x != DELETED_ENTRY) if (!(*callback) (slot, info)) break; @@ -398,7 +446,7 @@ htab_traverse (htab, callback, info) while (++slot < limit); } -/* The following function returns current size of given hash table. */ +/* Return the current size of given hash table. */ size_t htab_size (htab) @@ -407,8 +455,7 @@ htab_size (htab) return htab->size; } -/* The following function returns current number of elements in given - hash table. */ +/* Return the current number of elements in given hash table. */ size_t htab_elements (htab) @@ -417,17 +464,15 @@ htab_elements (htab) return htab->n_elements - htab->n_deleted; } -/* The following function returns number of percents of fixed - collisions during all work with given hash table. */ +/* Return the fraction of fixed collisions during all work with given + hash table. */ double htab_collisions (htab) htab_t htab; { - int searches; - - searches = htab->searches; - if (searches == 0) + if (htab->searches == 0) return 0.0; - return (double)htab->collisions / (double)searches; + + return (double) htab->collisions / (double) htab->searches; } diff --git a/libiberty/memcmp.c b/libiberty/memcmp.c index 127ae0c8019..0fd21cad11e 100644 --- a/libiberty/memcmp.c +++ b/libiberty/memcmp.c @@ -25,8 +25,8 @@ int DEFUN(memcmp, (str1, str2, count), const PTR str1 AND const PTR str2 AND size_t count) { - register unsigned char *s1 = (unsigned char*)str1; - register unsigned char *s2 = (unsigned char*)str2; + register const unsigned char *s1 = (const unsigned char*)str1; + register const unsigned char *s2 = (const unsigned char*)str2; while (count-- > 0) { diff --git a/libiberty/mkstemps.c b/libiberty/mkstemps.c index 16c16a23263..6ef526ece3d 100644 --- a/libiberty/mkstemps.c +++ b/libiberty/mkstemps.c @@ -39,7 +39,7 @@ /* We need to provide a type for gcc_uint64_t. */ #ifdef __GNUC__ -typedef unsigned long long gcc_uint64_t; +__extension__ typedef unsigned long long gcc_uint64_t; #else typedef unsigned long gcc_uint64_t; #endif diff --git a/libiberty/partition.c b/libiberty/partition.c index 52fb128d7bf..a5a734937ae 100644 --- a/libiberty/partition.c +++ b/libiberty/partition.c @@ -34,6 +34,8 @@ #include "libiberty.h" #include "partition.h" +static int elem_compare PARAMS ((const void *, const void *)); + /* Creates a partition of NUM_ELEMENTS elements. Initially each element is in a class by itself. */ @@ -128,8 +130,8 @@ elem_compare (elem1, elem2) const void *elem1; const void *elem2; { - int e1 = * (int *) elem1; - int e2 = * (int *) elem2; + int e1 = * (const int *) elem1; + int e2 = * (const int *) elem2; if (e1 < e2) return -1; else if (e1 > e2) @@ -175,7 +177,7 @@ partition_print (part, fp) c = elements[c].next - elements; } /* Sort them. */ - qsort ((void *) class_elements, count, sizeof (int), &elem_compare); + qsort ((void *) class_elements, count, sizeof (int), elem_compare); /* Print them. */ fputc ('(', fp); for (i = 0; i < count; ++i) diff --git a/libiberty/setenv.c b/libiberty/setenv.c index eec13006c22..a90c83ad78e 100644 --- a/libiberty/setenv.c +++ b/libiberty/setenv.c @@ -72,11 +72,13 @@ setenv (name, value, replace) size = 0; if (__environ != NULL) - for (ep = __environ; *ep != NULL; ++ep) - if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') - break; - else - ++size; + { + for (ep = __environ; *ep != NULL; ++ep) + if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') + break; + else + ++size; + } if (__environ == NULL || *ep == NULL) { diff --git a/libiberty/strncmp.c b/libiberty/strncmp.c new file mode 100644 index 00000000000..b3b9de16b10 --- /dev/null +++ b/libiberty/strncmp.c @@ -0,0 +1,28 @@ +/* strncmp -- compare two strings, stop after n bytes. + This function is in the public domain. */ + +#include <ansidecl.h> +#ifdef __STDC__ +#include <stddef.h> +#else +#define size_t unsigned long +#endif + +int +strncmp(s1, s2, n) + const char *s1, *s2; + register size_t n; +{ + register unsigned char u1, u2; + + while (n-- > 0) + { + u1 = (unsigned char) *s1++; + u2 = (unsigned char) *s2++; + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } + return 0; +} diff --git a/libiberty/xmalloc.c b/libiberty/xmalloc.c index 621c6d216c7..08c23f8126e 100644 --- a/libiberty/xmalloc.c +++ b/libiberty/xmalloc.c @@ -17,6 +17,9 @@ License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "ansidecl.h" #include "libiberty.h" |