diff options
Diffstat (limited to 'gnu/usr.bin/gdb/libiberty')
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/COPYING.LIB | 481 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/Makefile | 13 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/README.FreeBSD | 7 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/alloca-conf.h | 11 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/argv.c | 332 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/basename.c | 56 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/concat.c | 118 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/config.h | 1 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/cplus-dem.c | 2669 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/fdmatch.c | 71 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/getopt.c | 750 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/getopt1.c | 180 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/ieee-float.c | 150 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/ieee-float.h | 65 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/obstack.c | 460 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/sigsetmask.c | 44 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/spaces.c | 67 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/strerror.c | 811 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/strsignal.c | 634 | ||||
| -rw-r--r-- | gnu/usr.bin/gdb/libiberty/xmalloc.c | 58 |
20 files changed, 6978 insertions, 0 deletions
diff --git a/gnu/usr.bin/gdb/libiberty/COPYING.LIB b/gnu/usr.bin/gdb/libiberty/COPYING.LIB new file mode 100644 index 000000000000..eb685a5ec981 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gnu/usr.bin/gdb/libiberty/Makefile b/gnu/usr.bin/gdb/libiberty/Makefile new file mode 100644 index 000000000000..838781295e82 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/Makefile @@ -0,0 +1,13 @@ +LIB= iberty +SRCS= argv.c basename.c concat.c cplus-dem.c fdmatch.c getopt.c \ + getopt1.c ieee-float.c obstack.c spaces.c strerror.c strsignal.c \ + xmalloc.c + +CFLAGS+= -I$(.CURDIR)/../gdb/. +NOPROFILE=no +NOPIC=no + +install: + @echo -n + +.include <bsd.lib.mk> diff --git a/gnu/usr.bin/gdb/libiberty/README.FreeBSD b/gnu/usr.bin/gdb/libiberty/README.FreeBSD new file mode 100644 index 000000000000..573fa0a9a809 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/README.FreeBSD @@ -0,0 +1,7 @@ +This is a greatly pared down libiberty directory. Only what's required to build +gdb-4.12 on FreeBSD was kept. + +This is temporary. In FreeBSD 2.0 a fully ported libiberty will likely appear +as a system library for use by all the build tools. + +paul@freefall.cdrom.com diff --git a/gnu/usr.bin/gdb/libiberty/alloca-conf.h b/gnu/usr.bin/gdb/libiberty/alloca-conf.h new file mode 100644 index 000000000000..e1d9177893a1 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/alloca-conf.h @@ -0,0 +1,11 @@ +/* "Normal" configuration for alloca. */ + +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#ifdef sparc +#include <alloca.h> +#else +char *alloca (); +#endif /* sparc */ +#endif /* not __GNUC__ */ diff --git a/gnu/usr.bin/gdb/libiberty/argv.c b/gnu/usr.bin/gdb/libiberty/argv.c new file mode 100644 index 000000000000..fed46e7d797b --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/argv.c @@ -0,0 +1,332 @@ +/* Create and destroy argument vectors (argv's) + Copyright (C) 1992 Free Software Foundation, Inc. + Written by Fred Fish @ Cygnus Support + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +/* Create and destroy argument vectors. An argument vector is simply an + array of string pointers, terminated by a NULL pointer. */ + +/* AIX requires this to be the first thing in the file. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#ifdef sparc +#include <alloca.h> +extern char *__builtin_alloca(); /* Stupid include file doesn't declare it */ +#else +#ifdef _AIX + #pragma alloca +#else +char *alloca (); +#endif +#endif /* sparc */ +#endif /* not __GNUC__ */ + +#define isspace(ch) ((ch) == ' ' || (ch) == '\t') + +#include "alloca-conf.h" + +/* Routines imported from standard C runtime libraries. */ + +#ifdef __STDC__ + +#include <stddef.h> +extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */ +extern size_t strlen (const char *s); /* 4.11.6.3 */ +extern void *malloc (size_t size); /* 4.10.3.3 */ +extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */ +extern void free (void *ptr); /* 4.10.3.2 */ +extern char *strdup (const char *s); /* Non-ANSI */ + +#else /* !__STDC__ */ + +extern char *memcpy (); /* Copy memory region */ +extern int strlen (); /* Count length of string */ +extern char *malloc (); /* Standard memory allocater */ +extern char *realloc (); /* Standard memory reallocator */ +extern void free (); /* Free malloc'd memory */ +extern char *strdup (); /* Duplicate a string */ + +#endif /* __STDC__ */ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef EOS +#define EOS '\0' +#endif + +#define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */ + + +/* + +NAME + + freeargv -- free an argument vector + +SYNOPSIS + + void freeargv (vector) + char **vector; + +DESCRIPTION + + Free an argument vector that was built using buildargv. Simply scans + through the vector, freeing the memory for each argument until the + terminating NULL is found, and then frees the vector itself. + +RETURNS + + No value. + +*/ + +void freeargv (vector) +char **vector; +{ + register char **scan; + + if (vector != NULL) + { + for (scan = vector; *scan != NULL; scan++) + { + free (*scan); + } + free (vector); + } +} + +/* + +NAME + + buildargv -- build an argument vector from a string + +SYNOPSIS + + char **buildargv (sp) + char *sp; + +DESCRIPTION + + Given a pointer to a string, parse the string extracting fields + separated by whitespace and optionally enclosed within either single + or double quotes (which are stripped off), and build a vector of + pointers to copies of the string for each field. The input string + remains unchanged. + + All of the memory for the pointer array and copies of the string + is obtained from malloc. All of the memory can be returned to the + system with the single function call freeargv, which takes the + returned result of buildargv, as it's argument. + + The memory for the argv array is dynamically expanded as necessary. + +RETURNS + + Returns a pointer to the argument vector if successful. Returns NULL + if the input string pointer is NULL or if there is insufficient + memory to complete building the argument vector. + +NOTES + + In order to provide a working buffer for extracting arguments into, + with appropriate stripping of quotes and translation of backslash + sequences, we allocate a working buffer at least as long as the input + string. This ensures that we always have enough space in which to + work, since the extracted arg is never larger than the input string. + + If the input is a null string (as opposed to a NULL pointer), then + buildarg returns an argv that has one arg, a null string. + + Argv is always kept terminated with a NULL arg pointer, so it can + be passed to freeargv at any time, or returned, as appropriate. +*/ + +char **buildargv (input) +char *input; +{ + char *arg; + char *copybuf; + int squote = 0; + int dquote = 0; + int bsquote = 0; + int argc = 0; + int maxargc = 0; + char **argv = NULL; + char **nargv; + + if (input != NULL) + { + copybuf = alloca (strlen (input) + 1); + /* Is a do{}while to always execute the loop once. Always return an + argv, even for null strings. See NOTES above, test case below. */ + do + { + /* Pick off argv[argc] */ + while (isspace (*input)) + { + input++; + } + if ((maxargc == 0) || (argc >= (maxargc - 1))) + { + /* argv needs initialization, or expansion */ + if (argv == NULL) + { + maxargc = INITIAL_MAXARGC; + nargv = (char **) malloc (maxargc * sizeof (char *)); + } + else + { + maxargc *= 2; + nargv = (char **) realloc (argv, maxargc * sizeof (char *)); + } + if (nargv == NULL) + { + if (argv != NULL) + { + freeargv (argv); + argv = NULL; + } + break; + } + argv = nargv; + argv[argc] = NULL; + } + /* Begin scanning arg */ + arg = copybuf; + while (*input != EOS) + { + if (isspace (*input) && !squote && !dquote && !bsquote) + { + break; + } + else + { + if (bsquote) + { + bsquote = 0; + *arg++ = *input; + } + else if (*input == '\\') + { + bsquote = 1; + } + else if (squote) + { + if (*input == '\'') + { + squote = 0; + } + else + { + *arg++ = *input; + } + } + else if (dquote) + { + if (*input == '"') + { + dquote = 0; + } + else + { + *arg++ = *input; + } + } + else + { + if (*input == '\'') + { + squote = 1; + } + else if (*input == '"') + { + dquote = 1; + } + else + { + *arg++ = *input; + } + } + input++; + } + } + *arg = EOS; + argv[argc] = strdup (copybuf); + if (argv[argc] == NULL) + { + freeargv (argv); + argv = NULL; + break; + } + argc++; + argv[argc] = NULL; + } + while (*input != EOS); + } + return (argv); +} + +#ifdef MAIN + +/* Simple little test driver. */ + +static char *tests[] = +{ + "a simple command line", + "arg 'foo' is single quoted", + "arg \"bar\" is double quoted", + "arg \"foo bar\" has embedded whitespace", + "arg 'Jack said \\'hi\\'' has single quotes", + "arg 'Jack said \\\"hi\\\"' has double quotes", + "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9", + "", + NULL +}; + +main () +{ + char **argv; + char **test; + char **targs; + + for (test = tests; *test != NULL; test++) + { + printf ("buildargv(\"%s\")\n", *test); + if ((argv = buildargv (*test)) == NULL) + { + printf ("failed!\n\n"); + } + else + { + for (targs = argv; *targs != NULL; targs++) + { + printf ("\t\"%s\"\n", *targs); + } + printf ("\n"); + } + freeargv (argv); + } + +} + +#endif /* MAIN */ diff --git a/gnu/usr.bin/gdb/libiberty/basename.c b/gnu/usr.bin/gdb/libiberty/basename.c new file mode 100644 index 000000000000..f61a308e9b53 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/basename.c @@ -0,0 +1,56 @@ +/* Return the basename of a pathname. + Copyright (C) 1991 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + +NAME + + basename -- return pointer to last component of a pathname + +SYNOPSIS + + char *basename (char *name) + +DESCRIPTION + + Given a pointer to a string containing a typical pathname + (/usr/src/cmd/ls/ls.c for example), returns a pointer to the + last component of the pathname ("ls.c" in this case). + +BUGS + + Presumes a UNIX style path with UNIX style separators. +*/ + + +char * +basename (name) + char *name; +{ + char *base = name; + + while (*name) + { + if (*name++ == '/') + { + base = name; + } + } + return (base); +} diff --git a/gnu/usr.bin/gdb/libiberty/concat.c b/gnu/usr.bin/gdb/libiberty/concat.c new file mode 100644 index 000000000000..61f7d97481ce --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/concat.c @@ -0,0 +1,118 @@ +/* Concatenate variable number of strings. + Copyright (C) 1991 Free Software Foundation, Inc. + Written by Fred Fish @ Cygnus Support + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +/* + +NAME + + concat -- concatenate a variable number of strings + +SYNOPSIS + + #include <varargs.h> + + char *concat (s1, s2, s3, ..., NULL) + +DESCRIPTION + + Concatenate a variable number of strings and return the result + in freshly malloc'd memory. + + Returns NULL if insufficient memory is available. The argument + list is terminated by the first NULL pointer encountered. Pointers + to empty strings are ignored. + +NOTES + + This function uses xmalloc() which is expected to be a front end + function to malloc() that deals with low memory situations. In + typical use, if malloc() returns NULL then xmalloc() diverts to an + error handler routine which never returns, and thus xmalloc will + never return a NULL pointer. If the client application wishes to + deal with low memory situations itself, it should supply an xmalloc + that just directly invokes malloc and blindly returns whatever + malloc returns. +*/ + + +#include <varargs.h> + +#define NULLP (char *)0 + +extern char *xmalloc (); + +/* VARARGS */ +char * +concat (va_alist) + va_dcl +{ + register int length = 0; + register char *newstr; + register char *end; + register char *arg; + va_list args; + + /* First compute the size of the result and get sufficient memory. */ + + va_start (args); + while ((arg = va_arg (args, char *)) != NULLP) + { + length += strlen (arg); + } + newstr = (char *) xmalloc (length + 1); + va_end (args); + + /* Now copy the individual pieces to the result string. */ + + if (newstr != NULLP) + { + va_start (args); + end = newstr; + while ((arg = va_arg (args, char *)) != NULLP) + { + while (*arg) + { + *end++ = *arg++; + } + } + *end = '\000'; + va_end (args); + } + + return (newstr); +} + +#ifdef MAIN + +/* Simple little test driver. */ + +main () +{ + printf ("\"\" = \"%s\"\n", concat (NULLP)); + printf ("\"a\" = \"%s\"\n", concat ("a", NULLP)); + printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP)); + printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP)); + printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP)); + printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP)); + printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP)); +} + +#endif diff --git a/gnu/usr.bin/gdb/libiberty/config.h b/gnu/usr.bin/gdb/libiberty/config.h new file mode 100644 index 000000000000..b37ee84a78ab --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/config.h @@ -0,0 +1 @@ +/* !Automatically generated from ./functions.def - DO NOT EDIT! */ diff --git a/gnu/usr.bin/gdb/libiberty/cplus-dem.c b/gnu/usr.bin/gdb/libiberty/cplus-dem.c new file mode 100644 index 000000000000..2ad0e971487b --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/cplus-dem.c @@ -0,0 +1,2669 @@ +/* Demangler for GNU C++ + Copyright 1989, 1991 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.uucp) + Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This file exports two functions; cplus_mangle_opname and cplus_demangle. + + This file imports xmalloc and xrealloc, which are like malloc and + realloc except that they generate a fatal error if there is no + available memory. */ + +#include <demangle.h> +#undef CURRENT_DEMANGLING_STYLE +#define CURRENT_DEMANGLING_STYLE work->options +#include <ctype.h> +#include <string.h> +#include <stdio.h> + +extern char *xmalloc PARAMS((long)); +extern char *xrealloc PARAMS((PTR, long)); +extern char *strstr PARAMS ((const char *, const char *)); +extern void free PARAMS((PTR)); + +/* In order to allow a single demangler executable to demangle strings + using various common values of CPLUS_MARKER, as well as any specific + one set at compile time, we maintain a string containing all the + commonly used ones, and check to see if the marker we are looking for + is in that string. CPLUS_MARKER is usually '$' on systems where the + assembler can deal with that. Where the assembler can't, it's usually + '.' (but on many systems '.' is used for other things). We put the + current defined CPLUS_MARKER first (which defaults to '$'), followed + by the next most common value, followed by an explicit '$' in case + the value of CPLUS_MARKER is not '$'. + + We could avoid this if we could just get g++ to tell us what the actual + cplus marker character is as part of the debug information, perhaps by + ensuring that it is the character that terminates the gcc<n>_compiled + marker symbol (FIXME). */ + +#if !defined (CPLUS_MARKER) +#define CPLUS_MARKER '$' +#endif + +enum demangling_styles current_demangling_style = gnu_demangling; + +static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; + +void +set_cplus_marker_for_demangling (ch) + int ch; +{ + cplus_markers[0] = ch; +} + +/* Stuff that is shared between sub-routines. + * Using a shared structure allows cplus_demangle to be reentrant. */ + +struct work_stuff +{ + int options; + char **typevec; + int ntypes; + int typevec_size; + int constructor; + int destructor; + int static_type; /* A static member function */ + int const_type; /* A const member function */ +}; + +#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) +#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) + +static CONST struct optable +{ + CONST char *in; + CONST char *out; + int flags; +} optable[] = { + {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ + {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ + {"new", " new", 0}, /* old (1.91, and 1.x) */ + {"delete", " delete", 0}, /* old (1.91, and 1.x) */ + {"as", "=", DMGL_ANSI}, /* ansi */ + {"ne", "!=", DMGL_ANSI}, /* old, ansi */ + {"eq", "==", DMGL_ANSI}, /* old, ansi */ + {"ge", ">=", DMGL_ANSI}, /* old, ansi */ + {"gt", ">", DMGL_ANSI}, /* old, ansi */ + {"le", "<=", DMGL_ANSI}, /* old, ansi */ + {"lt", "<", DMGL_ANSI}, /* old, ansi */ + {"plus", "+", 0}, /* old */ + {"pl", "+", DMGL_ANSI}, /* ansi */ + {"apl", "+=", DMGL_ANSI}, /* ansi */ + {"minus", "-", 0}, /* old */ + {"mi", "-", DMGL_ANSI}, /* ansi */ + {"ami", "-=", DMGL_ANSI}, /* ansi */ + {"mult", "*", 0}, /* old */ + {"ml", "*", DMGL_ANSI}, /* ansi */ + {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ + {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ + {"convert", "+", 0}, /* old (unary +) */ + {"negate", "-", 0}, /* old (unary -) */ + {"trunc_mod", "%", 0}, /* old */ + {"md", "%", DMGL_ANSI}, /* ansi */ + {"amd", "%=", DMGL_ANSI}, /* ansi */ + {"trunc_div", "/", 0}, /* old */ + {"dv", "/", DMGL_ANSI}, /* ansi */ + {"adv", "/=", DMGL_ANSI}, /* ansi */ + {"truth_andif", "&&", 0}, /* old */ + {"aa", "&&", DMGL_ANSI}, /* ansi */ + {"truth_orif", "||", 0}, /* old */ + {"oo", "||", DMGL_ANSI}, /* ansi */ + {"truth_not", "!", 0}, /* old */ + {"nt", "!", DMGL_ANSI}, /* ansi */ + {"postincrement","++", 0}, /* old */ + {"pp", "++", DMGL_ANSI}, /* ansi */ + {"postdecrement","--", 0}, /* old */ + {"mm", "--", DMGL_ANSI}, /* ansi */ + {"bit_ior", "|", 0}, /* old */ + {"or", "|", DMGL_ANSI}, /* ansi */ + {"aor", "|=", DMGL_ANSI}, /* ansi */ + {"bit_xor", "^", 0}, /* old */ + {"er", "^", DMGL_ANSI}, /* ansi */ + {"aer", "^=", DMGL_ANSI}, /* ansi */ + {"bit_and", "&", 0}, /* old */ + {"ad", "&", DMGL_ANSI}, /* ansi */ + {"aad", "&=", DMGL_ANSI}, /* ansi */ + {"bit_not", "~", 0}, /* old */ + {"co", "~", DMGL_ANSI}, /* ansi */ + {"call", "()", 0}, /* old */ + {"cl", "()", DMGL_ANSI}, /* ansi */ + {"alshift", "<<", 0}, /* old */ + {"ls", "<<", DMGL_ANSI}, /* ansi */ + {"als", "<<=", DMGL_ANSI}, /* ansi */ + {"arshift", ">>", 0}, /* old */ + {"rs", ">>", DMGL_ANSI}, /* ansi */ + {"ars", ">>=", DMGL_ANSI}, /* ansi */ + {"component", "->", 0}, /* old */ + {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ + {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ + {"indirect", "*", 0}, /* old */ + {"method_call", "->()", 0}, /* old */ + {"addr", "&", 0}, /* old (unary &) */ + {"array", "[]", 0}, /* old */ + {"vc", "[]", DMGL_ANSI}, /* ansi */ + {"compound", ", ", 0}, /* old */ + {"cm", ", ", DMGL_ANSI}, /* ansi */ + {"cond", "?:", 0}, /* old */ + {"cn", "?:", DMGL_ANSI}, /* psuedo-ansi */ + {"max", ">?", 0}, /* old */ + {"mx", ">?", DMGL_ANSI}, /* psuedo-ansi */ + {"min", "<?", 0}, /* old */ + {"mn", "<?", DMGL_ANSI}, /* psuedo-ansi */ + {"nop", "", 0}, /* old (for operator=) */ + {"rm", "->*", DMGL_ANSI} /* ansi */ +}; + + +typedef struct string /* Beware: these aren't required to be */ +{ /* '\0' terminated. */ + char *b; /* pointer to start of string */ + char *p; /* pointer after last character */ + char *e; /* pointer after end of allocated space */ +} string; + +#define STRING_EMPTY(str) ((str) -> b == (str) -> p) +#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ + string_prepend(str, " ");} +#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ + string_append(str, " ");} + +#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ +#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ + +/* Prototypes for local functions */ + +static char * +mop_up PARAMS ((struct work_stuff *, string *, int)); + +#if 0 +static int +demangle_method_args PARAMS ((struct work_stuff *work, CONST char **, string *)); +#endif + +static int +demangle_template PARAMS ((struct work_stuff *work, CONST char **, string *, + string *)); + +static int +demangle_qualified PARAMS ((struct work_stuff *, CONST char **, string *, + int, int)); + +static int +demangle_class PARAMS ((struct work_stuff *, CONST char **, string *)); + +static int +demangle_fund_type PARAMS ((struct work_stuff *, CONST char **, string *)); + +static int +demangle_signature PARAMS ((struct work_stuff *, CONST char **, string *)); + +static int +demangle_prefix PARAMS ((struct work_stuff *, CONST char **, string *)); + +static int +gnu_special PARAMS ((struct work_stuff *, CONST char **, string *)); + +static int +arm_special PARAMS ((struct work_stuff *, CONST char **, string *)); + +static void +string_need PARAMS ((string *, int)); + +static void +string_delete PARAMS ((string *)); + +static void +string_init PARAMS ((string *)); + +static void +string_clear PARAMS ((string *)); + +#if 0 +static int +string_empty PARAMS ((string *)); +#endif + +static void +string_append PARAMS ((string *, CONST char *)); + +static void +string_appends PARAMS ((string *, string *)); + +static void +string_appendn PARAMS ((string *, CONST char *, int)); + +static void +string_prepend PARAMS ((string *, CONST char *)); + +static void +string_prependn PARAMS ((string *, CONST char *, int)); + +static int +get_count PARAMS ((CONST char **, int *)); + +static int +consume_count PARAMS ((CONST char **)); + +static int +demangle_args PARAMS ((struct work_stuff *, CONST char **, string *)); + +static int +do_type PARAMS ((struct work_stuff *, CONST char **, string *)); + +static int +do_arg PARAMS ((struct work_stuff *, CONST char **, string *)); + +static void +demangle_function_name PARAMS ((struct work_stuff *, CONST char **, string *, + CONST char *)); + +static void +remember_type PARAMS ((struct work_stuff *, CONST char *, int)); + +static void +forget_types PARAMS ((struct work_stuff *)); + +static void +string_prepends PARAMS ((string *, string *)); + +/* Translate count to integer, consuming tokens in the process. + Conversion terminates on the first non-digit character. + Trying to consume something that isn't a count results in + no consumption of input and a return of 0. */ + +static int +consume_count (type) + CONST char **type; +{ + int count = 0; + + while (isdigit (**type)) + { + count *= 10; + count += **type - '0'; + (*type)++; + } + return (count); +} + +/* Takes operator name as e.g. "++" and returns mangled + operator name (e.g. "postincrement_expr"), or NULL if not found. + + If OPTIONS & DMGL_ANSI == 1, return the ANSI name; + if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ + +char * +cplus_mangle_opname (opname, options) + char *opname; + int options; +{ + int i; + int len; + + len = strlen (opname); + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + if (strlen (optable[i].out) == len + && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) + && memcmp (optable[i].out, opname, len) == 0) + return ((char *)optable[i].in); + } + return (0); +} + +/* check to see whether MANGLED can match TEXT in the first TEXT_LEN + characters. */ + +int cplus_match (mangled, text, text_len) + CONST char *mangled; + char *text; + int text_len; +{ + if (strncmp (mangled, text, text_len) != 0) { + return(0); /* cannot match either */ + } else { + return(1); /* matches mangled, may match demangled */ + } +} + +/* char *cplus_demangle (const char *name, int options) + + If NAME is a mangled function name produced by GNU C++, then + a pointer to a malloced string giving a C++ representation + of the name will be returned; otherwise NULL will be returned. + It is the caller's responsibility to free the string which + is returned. + + The OPTIONS arg may contain one or more of the following bits: + + DMGL_ANSI ANSI qualifiers such as `const' and `void' are + included. + DMGL_PARAMS Function parameters are included. + + For example, + + cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" + cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" + cplus_demangle ("foo__1Ai", 0) => "A::foo" + + cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" + cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" + cplus_demangle ("foo__1Afe", 0) => "A::foo" + + Note that any leading underscores, or other such characters prepended by + the compilation system, are presumed to have already been stripped from + TYPE. */ + +char * +cplus_demangle (mangled, options) + CONST char *mangled; + int options; +{ + string decl; + int success = 0; + struct work_stuff work[1]; + char *demangled = NULL; + + if ((mangled != NULL) && (*mangled != '\0')) + { + memset ((char *) work, 0, sizeof (work)); + work -> options = options; + if ((work->options & DMGL_STYLE_MASK) == 0) + work->options |= (int)current_demangling_style & DMGL_STYLE_MASK; + + string_init (&decl); + + /* First check to see if gnu style demangling is active and if the + string to be demangled contains a CPLUS_MARKER. If so, attempt to + recognize one of the gnu special forms rather than looking for a + standard prefix. In particular, don't worry about whether there + is a "__" string in the mangled string. Consider "_$_5__foo" for + example. */ + + if ((AUTO_DEMANGLING || GNU_DEMANGLING)) + { + success = gnu_special (work, &mangled, &decl); + } + if (!success) + { + success = demangle_prefix (work, &mangled, &decl); + } + if (success && (*mangled != '\0')) + { + success = demangle_signature (work, &mangled, &decl); + } + if (work->constructor == 2) + { + string_prepend(&decl, "global constructors keyed to "); + work->constructor = 0; + } + else if (work->destructor == 2) + { + string_prepend(&decl, "global destructors keyed to "); + work->destructor = 0; + } + demangled = mop_up (work, &decl, success); + } + return (demangled); +} + +static char * +mop_up (work, declp, success) + struct work_stuff *work; + string *declp; + int success; +{ + char *demangled = NULL; + + /* Discard the remembered types, if any. */ + + forget_types (work); + if (work -> typevec != NULL) + { + free ((char *) work -> typevec); + } + + /* If demangling was successful, ensure that the demangled string is null + terminated and return it. Otherwise, free the demangling decl. */ + + if (!success) + { + string_delete (declp); + } + else + { + string_appendn (declp, "", 1); + demangled = declp -> b; + } + return (demangled); +} + +/* + +LOCAL FUNCTION + + demangle_signature -- demangle the signature part of a mangled name + +SYNOPSIS + + static int + demangle_signature (struct work_stuff *work, const char **mangled, + string *declp); + +DESCRIPTION + + Consume and demangle the signature portion of the mangled name. + + DECLP is the string where demangled output is being built. At + entry it contains the demangled root name from the mangled name + prefix. I.E. either a demangled operator name or the root function + name. In some special cases, it may contain nothing. + + *MANGLED points to the current unconsumed location in the mangled + name. As tokens are consumed and demangling is performed, the + pointer is updated to continuously point at the next token to + be consumed. + + Demangling GNU style mangled names is nasty because there is no + explicit token that marks the start of the outermost function + argument list. +*/ + +static int +demangle_signature (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + int success = 1; + int func_done = 0; + int expect_func = 0; + CONST char *oldmangled = NULL; + string trawname; + string tname; + + while (success && (**mangled != '\0')) + { + switch (**mangled) + { + case 'Q': + oldmangled = *mangled; + success = demangle_qualified (work, mangled, declp, 1, 0); + if (success) + { + remember_type (work, oldmangled, *mangled - oldmangled); + } + if (AUTO_DEMANGLING || GNU_DEMANGLING) + { + expect_func = 1; + } + oldmangled = NULL; + break; + + case 'S': + /* Static member function */ + if (oldmangled == NULL) + { + oldmangled = *mangled; + } + (*mangled)++; + work -> static_type = 1; + break; + + case 'C': + /* a const member function */ + if (oldmangled == NULL) + { + oldmangled = *mangled; + } + (*mangled)++; + work -> const_type = 1; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (oldmangled == NULL) + { + oldmangled = *mangled; + } + success = demangle_class (work, mangled, declp); + if (success) + { + remember_type (work, oldmangled, *mangled - oldmangled); + } + if (AUTO_DEMANGLING || GNU_DEMANGLING) + { + expect_func = 1; + } + oldmangled = NULL; + break; + + case 'F': + /* Function */ + /* ARM style demangling includes a specific 'F' character after + the class name. For GNU style, it is just implied. So we can + safely just consume any 'F' at this point and be compatible + with either style. */ + + oldmangled = NULL; + func_done = 1; + (*mangled)++; + + /* For lucid/ARM style we have to forget any types we might + have remembered up to this point, since they were not argument + types. GNU style considers all types seen as available for + back references. See comment in demangle_args() */ + + if (LUCID_DEMANGLING || ARM_DEMANGLING) + { + forget_types (work); + } + success = demangle_args (work, mangled, declp); + break; + + case 't': + /* G++ Template */ + string_init(&trawname); + string_init(&tname); + success = demangle_template (work, mangled, &tname, &trawname); + string_append(&tname, "::"); + string_prepends(declp, &tname); + if (work -> destructor & 1) + { + string_prepend (&trawname, "~"); + string_appends (declp, &trawname); + work->destructor -= 1; + } + if ((work->constructor & 1) || (work->destructor & 1)) + { + string_appends (declp, &trawname); + work->constructor -= 1; + } + string_delete(&trawname); + string_delete(&tname); + expect_func = 1; + break; + + case '_': + /* At the outermost level, we cannot have a return type specified, + so if we run into another '_' at this point we are dealing with + a mangled name that is either bogus, or has been mangled by + some algorithm we don't know how to deal with. So just + reject the entire demangling. */ + success = 0; + break; + + default: + if (AUTO_DEMANGLING || GNU_DEMANGLING) + { + /* Assume we have stumbled onto the first outermost function + argument token, and start processing args. */ + func_done = 1; + success = demangle_args (work, mangled, declp); + } + else + { + /* Non-GNU demanglers use a specific token to mark the start + of the outermost function argument tokens. Typically 'F', + for ARM-demangling, for example. So if we find something + we are not prepared for, it must be an error. */ + success = 0; + } + break; + } + if (AUTO_DEMANGLING || GNU_DEMANGLING) + { + if (success && expect_func) + { + func_done = 1; + success = demangle_args (work, mangled, declp); + } + } + } + if (success && !func_done) + { + if (AUTO_DEMANGLING || GNU_DEMANGLING) + { + /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and + bar__3fooi is 'foo::bar(int)'. We get here when we find the + first case, and need to ensure that the '(void)' gets added to + the current declp. Note that with ARM, the first case + represents the name of a static data member 'foo::bar', + which is in the current declp, so we leave it alone. */ + success = demangle_args (work, mangled, declp); + } + } + if (success && work -> static_type && PRINT_ARG_TYPES) + { + string_append (declp, " static"); + } + if (success && work -> const_type && PRINT_ARG_TYPES) + { + string_append (declp, " const"); + } + return (success); +} + +#if 0 + +static int +demangle_method_args (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + int success = 0; + + if (work -> static_type) + { + string_append (declp, *mangled + 1); + *mangled += strlen (*mangled); + success = 1; + } + else + { + success = demangle_args (work, mangled, declp); + } + return (success); +} + +#endif + +static int +demangle_template (work, mangled, tname, trawname) + struct work_stuff *work; + CONST char **mangled; + string *tname; + string *trawname; +{ + int i; + int is_pointer; + int is_real; + int is_integral; + int r; + int need_comma = 0; + int success = 0; + int done; + CONST char *old_p; + CONST char *start; + int symbol_len; + string temp; + + (*mangled)++; + start = *mangled; + /* get template name */ + if ((r = consume_count (mangled)) == 0) + { + return (0); + } + if (trawname) + string_appendn (trawname, *mangled, r); + string_appendn (tname, *mangled, r); + *mangled += r; + string_append (tname, "<"); + /* get size of template parameter list */ + if (!get_count (mangled, &r)) + { + return (0); + } + for (i = 0; i < r; i++) + { + if (need_comma) + { + string_append (tname, ", "); + } + /* Z for type parameters */ + if (**mangled == 'Z') + { + (*mangled)++; + /* temp is initialized in do_type */ + success = do_type (work, mangled, &temp); + if (success) + { + string_appends (tname, &temp); + } + string_delete(&temp); + if (!success) + { + break; + } + } + else + { + /* otherwise, value parameter */ + old_p = *mangled; + is_pointer = 0; + is_real = 0; + is_integral = 0; + done = 0; + /* temp is initialized in do_type */ + success = do_type (work, mangled, &temp); + if (success) + { + string_appends (tname, &temp); + } + string_delete(&temp); + if (!success) + { + break; + } + string_append (tname, "="); + while (*old_p && !done) + { + switch (*old_p) + { + case 'P': + case 'R': + done = is_pointer = 1; + break; + case 'C': /* const */ + case 'S': /* explicitly signed [char] */ + case 'U': /* unsigned */ + case 'V': /* volatile */ + case 'F': /* function */ + case 'M': /* member function */ + case 'O': /* ??? */ + old_p++; + continue; + case 'Q': /* repetition of following */ + case 'T': /* remembered type */ + abort (); + break; + case 'v': /* void */ + abort (); + break; + case 'x': /* long long */ + case 'l': /* long */ + case 'i': /* int */ + case 's': /* short */ + case 'c': /* char */ + case 'w': /* wchar_t */ + done = is_integral = 1; + break; + case 'r': /* long double */ + case 'd': /* double */ + case 'f': /* float */ + done = is_real = 1; + break; + default: + abort (); + } + } + if (is_integral) + { + if (**mangled == 'm') + { + string_appendn (tname, "-", 1); + (*mangled)++; + } + while (isdigit (**mangled)) + { + string_appendn (tname, *mangled, 1); + (*mangled)++; + } + } + else if (is_real) + { + if (**mangled == 'm') + { + string_appendn (tname, "-", 1); + (*mangled)++; + } + while (isdigit (**mangled)) + { + string_appendn (tname, *mangled, 1); + (*mangled)++; + } + if (**mangled == '.') /* fraction */ + { + string_appendn (tname, ".", 1); + (*mangled)++; + while (isdigit (**mangled)) + { + string_appendn (tname, *mangled, 1); + (*mangled)++; + } + } + if (**mangled == 'e') /* exponent */ + { + string_appendn (tname, "e", 1); + (*mangled)++; + while (isdigit (**mangled)) + { + string_appendn (tname, *mangled, 1); + (*mangled)++; + } + } + } + else if (is_pointer) + { + if (!get_count (mangled, &symbol_len)) + { + success = 0; + break; + } + string_appendn (tname, *mangled, symbol_len); + *mangled += symbol_len; + } + } + need_comma = 1; + } + string_append (tname, ">"); + +/* + if (work -> static_type) + { + string_append (declp, *mangled + 1); + *mangled += strlen (*mangled); + success = 1; + } + else + { + success = demangle_args (work, mangled, declp); + } + } +*/ + return (success); +} + +static int +arm_pt (work, mangled, n, anchor, args) + struct work_stuff *work; + CONST char *mangled; + int n; + CONST char **anchor, **args; +{ + /* ARM template? */ + if (ARM_DEMANGLING && (*anchor = strstr(mangled, "__pt__"))) + { + int len; + *args = *anchor + 6; + len = consume_count (args); + if (*args + len == mangled + n && **args == '_') + { + ++*args; + return 1; + } + } + return 0; +} + +static int +demangle_class_name (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + int n; + int success = 0; + + n = consume_count (mangled); + if (strlen (*mangled) >= n) + { + CONST char *p; + CONST char *args; + CONST char *e = *mangled + n; + /* ARM template? */ + if (arm_pt (work, *mangled, n, &p, &args)) + { + string arg; + string_init (&arg); + string_appendn (declp, *mangled, p - *mangled); + string_append (declp, "<"); + /* should do error checking here */ + while (args < e) { + string_clear (&arg); + do_type (work, &args, &arg); + string_appends (declp, &arg); + string_append (declp, ","); + } + string_delete (&arg); + --declp->p; + string_append (declp, ">"); + } + else + { + string_appendn (declp, *mangled, n); + } + *mangled += n; + success = 1; + } + return (success); +} + +/* + +LOCAL FUNCTION + + demangle_class -- demangle a mangled class sequence + +SYNOPSIS + + static int + demangle_class (struct work_stuff *work, const char **mangled, + strint *declp) + +DESCRIPTION + + DECLP points to the buffer into which demangling is being done. + + *MANGLED points to the current token to be demangled. On input, + it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) + On exit, it points to the next token after the mangled class on + success, or the first unconsumed token on failure. + + If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then + we are demangling a constructor or destructor. In this case + we prepend "class::class" or "class::~class" to DECLP. + + Otherwise, we prepend "class::" to the current DECLP. + + Reset the constructor/destructor flags once they have been + "consumed". This allows demangle_class to be called later during + the same demangling, to do normal class demangling. + + Returns 1 if demangling is successful, 0 otherwise. + +*/ + +static int +demangle_class (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + int success = 0; + string class_name; + + string_init (&class_name); + if (demangle_class_name (work, mangled, &class_name)) + { + if ((work->constructor & 1) || (work->destructor & 1)) + { + string_prepends (declp, &class_name); + if (work -> destructor & 1) + { + string_prepend (declp, "~"); + work -> destructor -= 1; + } + else + { + work -> constructor -= 1; + } + } + string_prepend (declp, "::"); + string_prepends (declp, &class_name); + success = 1; + } + string_delete (&class_name); + return (success); +} + +/* + +LOCAL FUNCTION + + demangle_prefix -- consume the mangled name prefix and find signature + +SYNOPSIS + + static int + demangle_prefix (struct work_stuff *work, const char **mangled, + string *declp); + +DESCRIPTION + + Consume and demangle the prefix of the mangled name. + + DECLP points to the string buffer into which demangled output is + placed. On entry, the buffer is empty. On exit it contains + the root function name, the demangled operator name, or in some + special cases either nothing or the completely demangled result. + + MANGLED points to the current pointer into the mangled name. As each + token of the mangled name is consumed, it is updated. Upon entry + the current mangled name pointer points to the first character of + the mangled name. Upon exit, it should point to the first character + of the signature if demangling was successful, or to the first + unconsumed character if demangling of the prefix was unsuccessful. + + Returns 1 on success, 0 otherwise. + */ + +static int +demangle_prefix (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + int success = 1; + CONST char *scan; + int i; + + if (strncmp(*mangled, "_GLOBAL_$D$", 11) == 0) + { + /* it's a GNU global destructor to be executed at program exit */ + (*mangled) += 11; + work->destructor = 2; + } + else if (strncmp(*mangled, "_GLOBAL_$I$", 11) == 0) + { + /* it's a GNU global constructor to be executed at program initial */ + (*mangled) += 11; + work->constructor = 2; + } + else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0) + { + /* it's a ARM global destructor to be executed at program exit */ + (*mangled) += 7; + work->destructor = 2; + } + else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0) + { + /* it's a ARM global constructor to be executed at program initial */ + (*mangled) += 7; + work->constructor = 2; + } + +/* This block of code is a reduction in strength time optimization + of: + scan = strstr (*mangled, "__"); */ + + { + scan = *mangled; + + do { + scan = strchr (scan, '_'); + } while (scan != NULL && *++scan != '_'); + + if (scan != NULL) --scan; + } + + if (scan != NULL) + { + /* We found a sequence of two or more '_', ensure that we start at + the last pair in the sequence. */ + i = strspn (scan, "_"); + if (i > 2) + { + scan += (i - 2); + } + } + + if (scan == NULL) + { + success = 0; + } + else if (work -> static_type) + { + if (!isdigit (scan[0]) && (scan[0] != 't')) + { + success = 0; + } + } + else if ((scan == *mangled) && + (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't'))) + { + /* The ARM says nothing about the mangling of local variables. + But cfront mangles local variables by prepending __<nesting_level> + to them. As an extension to ARM demangling we handle this case. */ + if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2])) + { + *mangled = scan + 2; + consume_count (mangled); + string_append (declp, *mangled); + *mangled += strlen (*mangled); + success = 1; + } + else + { + /* A GNU style constructor starts with "__[0-9Qt]. */ + work -> constructor += 1; + *mangled = scan + 2; + } + } + else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't')) + { + /* Mangled name starts with "__". Skip over any leading '_' characters, + then find the next "__" that separates the prefix from the signature. + */ + if (!(ARM_DEMANGLING || LUCID_DEMANGLING) + || (arm_special (work, mangled, declp) == 0)) + { + while (*scan == '_') + { + scan++; + } + if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) + { + /* No separator (I.E. "__not_mangled"), or empty signature + (I.E. "__not_mangled_either__") */ + success = 0; + } + else + { + demangle_function_name (work, mangled, declp, scan); + } + } + } + else if (*(scan + 2) != '\0') + { + /* Mangled name does not start with "__" but does have one somewhere + in there with non empty stuff after it. Looks like a global + function name. */ + demangle_function_name (work, mangled, declp, scan); + } + else + { + /* Doesn't look like a mangled name */ + success = 0; + } + + if (!success && (work->constructor == 2 || work->destructor == 2)) + { + string_append (declp, *mangled); + *mangled += strlen (*mangled); + success = 1; + } + return (success); +} + +/* + +LOCAL FUNCTION + + gnu_special -- special handling of gnu mangled strings + +SYNOPSIS + + static int + gnu_special (struct work_stuff *work, const char **mangled, + string *declp); + + +DESCRIPTION + + Process some special GNU style mangling forms that don't fit + the normal pattern. For example: + + _$_3foo (destructor for class foo) + _vt$foo (foo virtual table) + _vt$foo$bar (foo::bar virtual table) + _3foo$varname (static data member) + _Q22rs2tu$vw (static data member) + __t6vector1Zii (constructor with template) + */ + +static int +gnu_special (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + int n; + int success = 1; + CONST char *p; + + if ((*mangled)[0] == '_' + && strchr (cplus_markers, (*mangled)[1]) != NULL + && (*mangled)[2] == '_') + { + /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */ + (*mangled) += 3; + work -> destructor += 1; + } + else if ((*mangled)[0] == '_' + && (*mangled)[1] == 'v' + && (*mangled)[2] == 't' + && strchr (cplus_markers, (*mangled)[3]) != NULL) + { + /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" + and create the decl. Note that we consume the entire mangled + input string, which means that demangle_signature has no work + to do. */ + (*mangled) += 4; + while (**mangled != '\0') + { + if (isdigit(*mangled[0])) + { + n = consume_count(mangled); + } + else + { + n = strcspn (*mangled, cplus_markers); + } + string_appendn (declp, *mangled, n); + (*mangled) += n; + + if (**mangled != '\0') + { + string_append (declp, "::"); + (*mangled)++; + } + } + string_append (declp, " virtual table"); + } + else if ((*mangled)[0] == '_' + && (strchr("0123456789Qt", (*mangled)[1]) != NULL) + && (p = strpbrk (*mangled, cplus_markers)) != NULL) + { + /* static data member, "_3foo$varname" for example */ + (*mangled)++; + switch (**mangled) + { + case 'Q': + success = demangle_qualified (work, mangled, declp, 0, 1); + break; + case 't': + success = demangle_template (work, mangled, declp, 0); + break; + default: + n = consume_count (mangled); + string_appendn (declp, *mangled, n); + (*mangled) += n; + } + if (success && (p == *mangled)) + { + /* Consumed everything up to the cplus_marker, append the + variable name. */ + (*mangled)++; + string_append (declp, "::"); + n = strlen (*mangled); + string_appendn (declp, *mangled, n); + (*mangled) += n; + } + else + { + success = 0; + } + } + else + { + success = 0; + } + return (success); +} + +/* + +LOCAL FUNCTION + + arm_special -- special handling of ARM/lucid mangled strings + +SYNOPSIS + + static int + arm_special (struct work_stuff *work, const char **mangled, + string *declp); + + +DESCRIPTION + + Process some special ARM style mangling forms that don't fit + the normal pattern. For example: + + __vtbl__3foo (foo virtual table) + __vtbl__3foo__3bar (bar::foo virtual table) + + */ + +static int +arm_special (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + int n; + int success = 1; + CONST char *scan; + + if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) + { + /* Found a ARM style virtual table, get past ARM_VTABLE_STRING + and create the decl. Note that we consume the entire mangled + input string, which means that demangle_signature has no work + to do. */ + scan = *mangled + ARM_VTABLE_STRLEN; + while (*scan != '\0') /* first check it can be demangled */ + { + n = consume_count (&scan); + if (n==0) + { + return (0); /* no good */ + } + scan += n; + if (scan[0] == '_' && scan[1] == '_') + { + scan += 2; + } + } + (*mangled) += ARM_VTABLE_STRLEN; + while (**mangled != '\0') + { + n = consume_count (mangled); + string_prependn (declp, *mangled, n); + (*mangled) += n; + if ((*mangled)[0] == '_' && (*mangled)[1] == '_') + { + string_prepend (declp, "::"); + (*mangled) += 2; + } + } + string_append (declp, " virtual table"); + } + else + { + success = 0; + } + return (success); +} + +/* + +LOCAL FUNCTION + + demangle_qualified -- demangle 'Q' qualified name strings + +SYNOPSIS + + static int + demangle_qualified (struct work_stuff *, const char *mangled, + string *result, int isfuncname, int append); + +DESCRIPTION + + Demangle a qualified name, such as "Q25Outer5Inner" which is + the mangled form of "Outer::Inner". The demangled output is + prepended or appended to the result string according to the + state of the append flag. + + If isfuncname is nonzero, then the qualified name we are building + is going to be used as a member function name, so if it is a + constructor or destructor function, append an appropriate + constructor or destructor name. I.E. for the above example, + the result for use as a constructor is "Outer::Inner::Inner" + and the result for use as a destructor is "Outer::Inner::~Inner". + +BUGS + + Numeric conversion is ASCII dependent (FIXME). + + */ + +static int +demangle_qualified (work, mangled, result, isfuncname, append) + struct work_stuff *work; + CONST char **mangled; + string *result; + int isfuncname; + int append; +{ + int qualifiers; + int namelength; + int success = 1; + CONST char *p; + char num[2]; + string temp; + + string_init (&temp); + switch ((*mangled)[1]) + { + case '_': + /* GNU mangled name with more than 9 classes. The count is preceded + by an underscore (to distinguish it from the <= 9 case) and followed + by an underscore. */ + p = *mangled + 2; + qualifiers = atoi (p); + if (!isdigit (*p) || *p == '0') + success = 0; + + /* Skip the digits. */ + while (isdigit (*p)) + ++p; + + if (*p != '_') + success = 0; + + *mangled = p + 1; + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + /* The count is in a single digit. */ + num[0] = (*mangled)[1]; + num[1] = '\0'; + qualifiers = atoi (num); + + /* If there is an underscore after the digit, skip it. This is + said to be for ARM-qualified names, but the ARM makes no + mention of such an underscore. Perhaps cfront uses one. */ + if ((*mangled)[2] == '_') + { + (*mangled)++; + } + (*mangled) += 2; + break; + + case '0': + default: + success = 0; + } + + if (!success) + return success; + + /* Pick off the names and collect them in the temp buffer in the order + in which they are found, separated by '::'. */ + + while (qualifiers-- > 0) + { + if (*mangled[0] == 't') + { + success = demangle_template(work, mangled, &temp, 0); + if (!success) break; + } + else + { + namelength = consume_count (mangled); + if (strlen (*mangled) < namelength) + { + /* Simple sanity check failed */ + success = 0; + break; + } + string_appendn (&temp, *mangled, namelength); + *mangled += namelength; + } + if (qualifiers > 0) + { + string_appendn (&temp, "::", 2); + } + } + + /* If we are using the result as a function name, we need to append + the appropriate '::' separated constructor or destructor name. + We do this here because this is the most convenient place, where + we already have a pointer to the name and the length of the name. */ + + if (isfuncname && (work->constructor & 1 || work->destructor & 1)) + { + string_appendn (&temp, "::", 2); + if (work -> destructor & 1) + { + string_append (&temp, "~"); + } + string_appendn (&temp, (*mangled) - namelength, namelength); + } + + /* Now either prepend the temp buffer to the result, or append it, + depending upon the state of the append flag. */ + + if (append) + { + string_appends (result, &temp); + } + else + { + if (!STRING_EMPTY (result)) + { + string_appendn (&temp, "::", 2); + } + string_prepends (result, &temp); + } + + string_delete (&temp); + return (success); +} + +/* + +LOCAL FUNCTION + + get_count -- convert an ascii count to integer, consuming tokens + +SYNOPSIS + + static int + get_count (const char **type, int *count) + +DESCRIPTION + + Return 0 if no conversion is performed, 1 if a string is converted. +*/ + +static int +get_count (type, count) + CONST char **type; + int *count; +{ + CONST char *p; + int n; + + if (!isdigit (**type)) + { + return (0); + } + else + { + *count = **type - '0'; + (*type)++; + if (isdigit (**type)) + { + p = *type; + n = *count; + do + { + n *= 10; + n += *p - '0'; + p++; + } + while (isdigit (*p)); + if (*p == '_') + { + *type = p + 1; + *count = n; + } + } + } + return (1); +} + +/* result will be initialised here; it will be freed on failure */ + +static int +do_type (work, mangled, result) + struct work_stuff *work; + CONST char **mangled; + string *result; +{ + int n; + int done; + int success; + string decl; + CONST char *remembered_type; + int constp; + int volatilep; + + string_init (&decl); + string_init (result); + + done = 0; + success = 1; + while (success && !done) + { + int member; + switch (**mangled) + { + + /* A pointer type */ + case 'P': + (*mangled)++; + string_prepend (&decl, "*"); + break; + + /* A reference type */ + case 'R': + (*mangled)++; + string_prepend (&decl, "&"); + break; + + /* An array */ + case 'A': + { + CONST char *p = ++(*mangled); + + string_prepend (&decl, "("); + string_append (&decl, ")["); + /* Copy anything up until the next underscore (the size of the + array). */ + while (**mangled && **mangled != '_') + ++(*mangled); + if (**mangled == '_') + { + string_appendn (&decl, p, *mangled - p); + string_append (&decl, "]"); + *mangled += 1; + } + else + success = 0; + break; + } + + /* A back reference to a previously seen type */ + case 'T': + (*mangled)++; + if (!get_count (mangled, &n) || n >= work -> ntypes) + { + success = 0; + } + else + { + remembered_type = work -> typevec[n]; + mangled = &remembered_type; + } + break; + + /* A function */ + case 'F': + (*mangled)++; + if (!STRING_EMPTY (&decl) && decl.b[0] == '*') + { + string_prepend (&decl, "("); + string_append (&decl, ")"); + } + /* After picking off the function args, we expect to either find the + function return type (preceded by an '_') or the end of the + string. */ + if (!demangle_args (work, mangled, &decl) + || (**mangled != '_' && **mangled != '\0')) + { + success = 0; + } + if (success && (**mangled == '_')) + { + (*mangled)++; + } + break; + + case 'M': + case 'O': + { + constp = 0; + volatilep = 0; + + member = **mangled == 'M'; + (*mangled)++; + if (!isdigit (**mangled)) + { + success = 0; + break; + } + n = consume_count (mangled); + if (strlen (*mangled) < n) + { + success = 0; + break; + } + string_append (&decl, ")"); + string_prepend (&decl, "::"); + string_prependn (&decl, *mangled, n); + string_prepend (&decl, "("); + *mangled += n; + if (member) + { + if (**mangled == 'C') + { + (*mangled)++; + constp = 1; + } + if (**mangled == 'V') + { + (*mangled)++; + volatilep = 1; + } + if (*(*mangled)++ != 'F') + { + success = 0; + break; + } + } + if ((member && !demangle_args (work, mangled, &decl)) + || **mangled != '_') + { + success = 0; + break; + } + (*mangled)++; + if (! PRINT_ANSI_QUALIFIERS) + { + break; + } + if (constp) + { + APPEND_BLANK (&decl); + string_append (&decl, "const"); + } + if (volatilep) + { + APPEND_BLANK (&decl); + string_append (&decl, "volatile"); + } + break; + } + case 'G': + (*mangled)++; + break; + + case 'C': + (*mangled)++; +/* + if ((*mangled)[1] == 'P') + { +*/ + if (PRINT_ANSI_QUALIFIERS) + { + if (!STRING_EMPTY (&decl)) + { + string_prepend (&decl, " "); + } + string_prepend (&decl, "const"); + } + break; +/* + } +*/ + + /* fall through */ + default: + done = 1; + break; + } + } + + switch (**mangled) + { + /* A qualified name, such as "Outer::Inner". */ + case 'Q': + success = demangle_qualified (work, mangled, result, 0, 1); + break; + + default: + success = demangle_fund_type (work, mangled, result); + break; + } + + if (success) + { + if (!STRING_EMPTY (&decl)) + { + string_append (result, " "); + string_appends (result, &decl); + } + } + else + { + string_delete (result); + } + string_delete (&decl); + return (success); +} + +/* Given a pointer to a type string that represents a fundamental type + argument (int, long, unsigned int, etc) in TYPE, a pointer to the + string in which the demangled output is being built in RESULT, and + the WORK structure, decode the types and add them to the result. + + For example: + + "Ci" => "const int" + "Sl" => "signed long" + "CUs" => "const unsigned short" + + */ + +static int +demangle_fund_type (work, mangled, result) + struct work_stuff *work; + CONST char **mangled; + string *result; +{ + int done = 0; + int success = 1; + + /* First pick off any type qualifiers. There can be more than one. */ + + while (!done) + { + switch (**mangled) + { + case 'C': + (*mangled)++; + if (PRINT_ANSI_QUALIFIERS) + { + APPEND_BLANK (result); + string_append (result, "const"); + } + break; + case 'U': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "unsigned"); + break; + case 'S': /* signed char only */ + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "signed"); + break; + case 'V': + (*mangled)++; + if (PRINT_ANSI_QUALIFIERS) + { + APPEND_BLANK (result); + string_append (result, "volatile"); + } + break; + default: + done = 1; + break; + } + } + + /* Now pick off the fundamental type. There can be only one. */ + + switch (**mangled) + { + case '\0': + case '_': + break; + case 'v': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "void"); + break; + case 'x': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "long long"); + break; + case 'l': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "long"); + break; + case 'i': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "int"); + break; + case 's': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "short"); + break; + case 'c': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "char"); + break; + case 'w': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "wchar_t"); + break; + case 'r': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "long double"); + break; + case 'd': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "double"); + break; + case 'f': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "float"); + break; + case 'G': + (*mangled)++; + if (!isdigit (**mangled)) + { + success = 0; + break; + } + /* fall through */ + /* An explicit type, such as "6mytype" or "7integer" */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + APPEND_BLANK (result); + if (!demangle_class_name (work, mangled, result)) { + --result->p; + success = 0; + } + break; + case 't': + success = demangle_template(work,mangled, result, 0); + break; + default: + success = 0; + break; + } + + return (success); +} + +/* `result' will be initialized in do_type; it will be freed on failure */ + +static int +do_arg (work, mangled, result) + struct work_stuff *work; + CONST char **mangled; + string *result; +{ + CONST char *start = *mangled; + + if (!do_type (work, mangled, result)) + { + return (0); + } + else + { + remember_type (work, start, *mangled - start); + return (1); + } +} + +static void +remember_type (work, start, len) + struct work_stuff *work; + CONST char *start; + int len; +{ + char *tem; + + if (work -> ntypes >= work -> typevec_size) + { + if (work -> typevec_size == 0) + { + work -> typevec_size = 3; + work -> typevec = + (char **) xmalloc (sizeof (char *) * work -> typevec_size); + } + else + { + work -> typevec_size *= 2; + work -> typevec = + (char **) xrealloc ((char *)work -> typevec, + sizeof (char *) * work -> typevec_size); + } + } + tem = xmalloc (len + 1); + memcpy (tem, start, len); + tem[len] = '\0'; + work -> typevec[work -> ntypes++] = tem; +} + +/* Forget the remembered types, but not the type vector itself. */ + +static void +forget_types (work) + struct work_stuff *work; +{ + int i; + + while (work -> ntypes > 0) + { + i = --(work -> ntypes); + if (work -> typevec[i] != NULL) + { + free (work -> typevec[i]); + work -> typevec[i] = NULL; + } + } +} + +/* Process the argument list part of the signature, after any class spec + has been consumed, as well as the first 'F' character (if any). For + example: + + "__als__3fooRT0" => process "RT0" + "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" + + DECLP must be already initialised, usually non-empty. It won't be freed + on failure. + + Note that g++ differs significantly from ARM and lucid style mangling + with regards to references to previously seen types. For example, given + the source fragment: + + class foo { + public: + foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); + }; + + foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } + void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } + + g++ produces the names: + + __3fooiRT0iT2iT2 + foo__FiR3fooiT1iT1 + + while lcc (and presumably other ARM style compilers as well) produces: + + foo__FiR3fooT1T2T1T2 + __ct__3fooFiR3fooT1T2T1T2 + + Note that g++ bases it's type numbers starting at zero and counts all + previously seen types, while lucid/ARM bases it's type numbers starting + at one and only considers types after it has seen the 'F' character + indicating the start of the function args. For lucid/ARM style, we + account for this difference by discarding any previously seen types when + we see the 'F' character, and subtracting one from the type number + reference. + + */ + +static int +demangle_args (work, mangled, declp) + struct work_stuff *work; + CONST char **mangled; + string *declp; +{ + string arg; + int need_comma = 0; + int r; + int t; + CONST char *tem; + char temptype; + + if (PRINT_ARG_TYPES) + { + string_append (declp, "("); + if (**mangled == '\0') + { + string_append (declp, "void"); + } + } + + while (**mangled != '_' && **mangled != '\0' && **mangled != 'e') + { + if ((**mangled == 'N') || (**mangled == 'T')) + { + temptype = *(*mangled)++; + + if (temptype == 'N') + { + if (!get_count (mangled, &r)) + { + return (0); + } + } + else + { + r = 1; + } + if (!get_count (mangled, &t)) + { + return (0); + } + if (LUCID_DEMANGLING || ARM_DEMANGLING) + { + t--; + } + /* Validate the type index. Protect against illegal indices from + malformed type strings. */ + if ((t < 0) || (t >= work -> ntypes)) + { + return (0); + } + while (--r >= 0) + { + tem = work -> typevec[t]; + if (need_comma && PRINT_ARG_TYPES) + { + string_append (declp, ", "); + } + if (!do_arg (work, &tem, &arg)) + { + return (0); + } + if (PRINT_ARG_TYPES) + { + string_appends (declp, &arg); + } + string_delete (&arg); + need_comma = 1; + } + } + else + { + if (need_comma & PRINT_ARG_TYPES) + { + string_append (declp, ", "); + } + if (!do_arg (work, mangled, &arg)) + { + return (0); + } + if (PRINT_ARG_TYPES) + { + string_appends (declp, &arg); + } + string_delete (&arg); + need_comma = 1; + } + } + + if (**mangled == 'e') + { + (*mangled)++; + if (PRINT_ARG_TYPES) + { + if (need_comma) + { + string_append (declp, ","); + } + string_append (declp, "..."); + } + } + + if (PRINT_ARG_TYPES) + { + string_append (declp, ")"); + } + return (1); +} + +static void +demangle_function_name (work, mangled, declp, scan) + struct work_stuff *work; + CONST char **mangled; + string *declp; + CONST char *scan; +{ + int i; + int len; + string type; + CONST char *tem; + + string_appendn (declp, (*mangled), scan - (*mangled)); + string_need (declp, 1); + *(declp -> p) = '\0'; + + /* Consume the function name, including the "__" separating the name + from the signature. We are guaranteed that SCAN points to the + separator. */ + + (*mangled) = scan + 2; + + if (LUCID_DEMANGLING || ARM_DEMANGLING) + { + + /* See if we have an ARM style constructor or destructor operator. + If so, then just record it, clear the decl, and return. + We can't build the actual constructor/destructor decl until later, + when we recover the class name from the signature. */ + + if (strcmp (declp -> b, "__ct") == 0) + { + work -> constructor += 1; + string_clear (declp); + return; + } + else if (strcmp (declp -> b, "__dt") == 0) + { + work -> destructor += 1; + string_clear (declp); + return; + } + } + + if (declp->p - declp->b >= 3 + && declp->b[0] == 'o' + && declp->b[1] == 'p' + && strchr (cplus_markers, declp->b[2]) != NULL) + { + /* see if it's an assignment expression */ + if (declp->p - declp->b >= 10 /* op$assign_ */ + && memcmp (declp->b + 3, "assign_", 7) == 0) + { + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + len = declp->p - declp->b - 10; + if (strlen (optable[i].in) == len + && memcmp (optable[i].in, declp->b + 10, len) == 0) + { + string_clear (declp); + string_append (declp, "operator"); + string_append (declp, optable[i].out); + string_append (declp, "="); + break; + } + } + } + else + { + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + int len = declp->p - declp->b - 3; + if (strlen (optable[i].in) == len + && memcmp (optable[i].in, declp->b + 3, len) == 0) + { + string_clear (declp); + string_append (declp, "operator"); + string_append (declp, optable[i].out); + break; + } + } + } + } + else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type$", 5) == 0) + { + /* type conversion operator */ + tem = declp->b + 5; + if (do_type (work, &tem, &type)) + { + string_clear (declp); + string_append (declp, "operator "); + string_appends (declp, &type); + string_delete (&type); + } + } + else if (declp->b[0] == '_' && declp->b[1] == '_' + && declp->b[2] == 'o' && declp->b[3] == 'p') + { + /* ANSI. */ + /* type conversion operator. */ + tem = declp->b + 4; + if (do_type (work, &tem, &type)) + { + string_clear (declp); + string_append (declp, "operator "); + string_appends (declp, &type); + string_delete (&type); + } + } + else if (declp->b[0] == '_' && declp->b[1] == '_' + && declp->b[2] >= 'a' && declp->b[2] <= 'z' + && declp->b[3] >= 'a' && declp->b[3] <= 'z') + { + if (declp->b[4] == '\0') + { + /* Operator. */ + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + if (strlen (optable[i].in) == 2 + && memcmp (optable[i].in, declp->b + 2, 2) == 0) + { + string_clear (declp); + string_append (declp, "operator"); + string_append (declp, optable[i].out); + break; + } + } + } + else + { + if (declp->b[2] == 'a' && declp->b[5] == '\0') + { + /* Assignment. */ + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + if (strlen (optable[i].in) == 3 + && memcmp (optable[i].in, declp->b + 2, 3) == 0) + { + string_clear (declp); + string_append (declp, "operator"); + string_append (declp, optable[i].out); + break; + } + } + } + } + } +} + +/* a mini string-handling package */ + +static void +string_need (s, n) + string *s; + int n; +{ + int tem; + + if (s->b == NULL) + { + if (n < 32) + { + n = 32; + } + s->p = s->b = xmalloc (n); + s->e = s->b + n; + } + else if (s->e - s->p < n) + { + tem = s->p - s->b; + n += tem; + n *= 2; + s->b = xrealloc (s->b, n); + s->p = s->b + tem; + s->e = s->b + n; + } +} + +static void +string_delete (s) + string *s; +{ + if (s->b != NULL) + { + free (s->b); + s->b = s->e = s->p = NULL; + } +} + +static void +string_init (s) + string *s; +{ + s->b = s->p = s->e = NULL; +} + +static void +string_clear (s) + string *s; +{ + s->p = s->b; +} + +#if 0 + +static int +string_empty (s) + string *s; +{ + return (s->b == s->p); +} + +#endif + +static void +string_append (p, s) + string *p; + CONST char *s; +{ + int n; + if (s == NULL || *s == '\0') + return; + n = strlen (s); + string_need (p, n); + memcpy (p->p, s, n); + p->p += n; +} + +static void +string_appends (p, s) + string *p, *s; +{ + int n; + + if (s->b != s->p) + { + n = s->p - s->b; + string_need (p, n); + memcpy (p->p, s->b, n); + p->p += n; + } +} + +static void +string_appendn (p, s, n) + string *p; + CONST char *s; + int n; +{ + if (n != 0) + { + string_need (p, n); + memcpy (p->p, s, n); + p->p += n; + } +} + +static void +string_prepend (p, s) + string *p; + CONST char *s; +{ + if (s != NULL && *s != '\0') + { + string_prependn (p, s, strlen (s)); + } +} + +static void +string_prepends (p, s) + string *p, *s; +{ + if (s->b != s->p) + { + string_prependn (p, s->b, s->p - s->b); + } +} + +static void +string_prependn (p, s, n) + string *p; + CONST char *s; + int n; +{ + char *q; + + if (n != 0) + { + string_need (p, n); + for (q = p->p - 1; q >= p->b; q--) + { + q[n] = q[0]; + } + memcpy (p->b, s, n); + p->p += n; + } +} + +/* To generate a standalone demangler program for testing purposes, just + compile and link this file with -DMAIN. When run, it demangles each + command line arg, or each stdin string, and prints the result on stdout. */ + +#ifdef MAIN + +static void +demangle_it (mangled_name) + char *mangled_name; +{ + char *result; + + result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI); + if (result == NULL) + { + printf ("%s\n", mangled_name); + } + else + { + printf ("%s\n", result); + free (result); + } +} + +char * +xmalloc (size) + long size; +{ + char * newmem; + + if ((newmem = (char *) malloc ((int) size)) == NULL) + { + fprintf (stderr, "\nCan't allocate %u bytes\n", size); + exit (1); + } + return (newmem); +} + +char * +xrealloc (oldmem, size) + PTR oldmem; + long size; +{ + char * newmem; + + if ((newmem = (char *) realloc ((char *) oldmem, (int) size)) == NULL) + { + fprintf (stderr, "\nCan't reallocate %u bytes\n", size); + exit (1); + } + return (newmem); +} + +#include "getopt.h" + +static char *program_name; +extern char *program_version; + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, "\ +Usage: %s [-_] [-s {gnu,lucid,arm}] [--strip-underscores]\n\ + [--format={gnu,lucid,arm}] [--help] [--version] [arg...]\n", + program_name); + exit (status); +} + +#define MBUF_SIZE 512 +char mbuffer[MBUF_SIZE]; + +/* Defined in the automatically-generated ../binutils/underscore.c. */ +extern int prepends_underscore; + +int strip_underscore = 0; + +static struct option long_options[] = { + {"strip-underscores", no_argument, 0, '_'}, + {"format", required_argument, 0, 's'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, + {0, no_argument, 0, 0} +}; + +int +main (argc, argv) + int argc; + char **argv; +{ + char *result; + int c; + + program_name = argv[0]; + strip_underscore = prepends_underscore; + + while ((c = getopt_long (argc, argv, "_s:", long_options, (int *) 0)) != EOF) + { + switch (c) + { + case '?': + usage (stderr, 1); + break; + case 'h': + usage (stdout, 0); + case 'v': + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + case '_': + strip_underscore = 1; + 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 + { + fprintf (stderr, "%s: unknown demangling style `%s'\n", + program_name, optarg); + exit (1); + } + break; + } + } + + if (optind < argc) + { + for ( ; optind < argc; optind++) + { + demangle_it (argv[optind]); + } + } + else + { + for (;;) + { + int i = 0; + c = getchar (); + /* Try to read a label. */ + while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.')) + { + if (i >= MBUF_SIZE-1) + break; + mbuffer[i++] = c; + c = getchar (); + } + if (i > 0) + { + int skip_first = strip_underscore && i > 1 && mbuffer[0] == '_'; + mbuffer[i] = 0; + + result = cplus_demangle (mbuffer+skip_first, + DMGL_PARAMS | DMGL_ANSI); + if (result) + { + fputs (result, stdout); + free (result); + } + else + fputs (mbuffer + skip_first, stdout); + } + if (c == EOF) + break; + putchar (c); + } + } + + exit (0); +} + +#endif /* main */ diff --git a/gnu/usr.bin/gdb/libiberty/fdmatch.c b/gnu/usr.bin/gdb/libiberty/fdmatch.c new file mode 100644 index 000000000000..0a6de2af0fd0 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/fdmatch.c @@ -0,0 +1,71 @@ +/* Compare two open file descriptors to see if they refer to the same file. + Copyright (C) 1991 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +/* + +NAME + + fdmatch -- see if two file descriptors refer to same file + +SYNOPSIS + + int fdmatch (int fd1, int fd2) + +DESCRIPTION + + Check to see if two open file descriptors refer to the same file. + This is useful, for example, when we have an open file descriptor + for an unnamed file, and the name of a file that we believe to + correspond to that fd. This can happen when we are exec'd with + an already open file (stdout for example) or from the SVR4 /proc + calls that return open file descriptors for mapped address spaces. + All we have to do is open the file by name and check the two file + descriptors for a match, which is done by comparing major&minor + device numbers and inode numbers. + +BUGS + + (FIXME: does this work for networks?) + It works for NFS, which assigns a device number to each mount. + +*/ + +#include <sys/types.h> +#include <sys/stat.h> + +int fdmatch (fd1, fd2) + int fd1; + int fd2; +{ + struct stat sbuf1; + struct stat sbuf2; + + if ((fstat (fd1, &sbuf1) == 0) && + (fstat (fd2, &sbuf2) == 0) && + (sbuf1.st_dev == sbuf2.st_dev) && + (sbuf1.st_ino == sbuf2.st_ino)) + { + return (1); + } + else + { + return (0); + } +} diff --git a/gnu/usr.bin/gdb/libiberty/getopt.c b/gnu/usr.bin/gdb/libiberty/getopt.c new file mode 100644 index 000000000000..c7a8b0326418 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/getopt.c @@ -0,0 +1,750 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License + as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#endif /* GNU C library. */ + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. + (Supposedly there are some machines where it might get a warning, + but changing this conditional to __STDC__ is too risky.) */ +#ifdef __GNUC__ +#ifdef IN_GCC +#include "gstddef.h" +#else +#include <stddef.h> +#endif +extern size_t strlen (const char *); +#endif + +#endif /* GNU C library. */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct option *pfound = NULL; + int indfound; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if (s - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = s + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gnu/usr.bin/gdb/libiberty/getopt1.c b/gnu/usr.bin/gdb/libiberty/getopt1.c new file mode 100644 index 000000000000..6806da5f983f --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/getopt1.c @@ -0,0 +1,180 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License + as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "getopt.h" + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#else +char *getenv (); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gnu/usr.bin/gdb/libiberty/ieee-float.c b/gnu/usr.bin/gdb/libiberty/ieee-float.c new file mode 100644 index 000000000000..b50eb859a1c1 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/ieee-float.c @@ -0,0 +1,150 @@ +/* IEEE floating point support routines, for GDB, the GNU Debugger. + Copyright (C) 1991 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "ieee-float.h" +#include <math.h> /* ldexp */ + +/* Convert an IEEE extended float to a double. + FROM is the address of the extended float. + Store the double in *TO. */ + +void +ieee_extended_to_double (ext_format, from, to) + CONST struct ext_format *ext_format; + char *from; + double *to; +{ + unsigned char *ufrom = (unsigned char *)from; + double dto; + unsigned long mant0, mant1, exponent; + + memcpy (&mant0, &from[MANBYTE_H], 4); + memcpy (&mant1, &from[MANBYTE_L], 4); + exponent = ((ufrom[EXPBYTE_H] & (unsigned char)~SIGNMASK) << 8) | ufrom[EXPBYTE_L]; + +#if 0 + /* We can't do anything useful with a NaN anyway, so ignore its + difference. It will end up as Infinity or something close. */ + if (exponent == EXT_EXP_NAN) { + /* We have a NaN source. */ + dto = 0.123456789; /* Not much else useful to do -- we don't know if + the host system even *has* NaNs, nor how to + generate an innocuous one if it does. */ + } else +#endif + if (exponent == 0 && mant0 == 0 && mant1 == 0) { + dto = 0; + } else { + /* Build the result algebraically. Might go infinite, underflow, etc; + who cares. */ + mant0 |= 0x80000000; + dto = ldexp ((double)mant0, exponent - EXT_EXP_BIAS - 31); + dto += ldexp ((double)mant1, exponent - EXT_EXP_BIAS - 31 - 32); + if (ufrom[EXPBYTE_H] & SIGNMASK) /* If negative... */ + dto = -dto; /* ...negate. */ + } + memcpy (to, &dto, sizeof (dto)); +} + +/* The converse: convert the double *FROM to an extended float + and store where TO points. Neither FROM nor TO have any alignment + restrictions. */ + +void +double_to_ieee_extended (ext_format, from, to) + CONST struct ext_format *ext_format; + double *from; + char *to; +{ + double dfrom; + unsigned long twolongs[2]; + unsigned long mant0, mant1, exponent; + unsigned char tobytes[8]; + + memcpy (&dfrom, from, sizeof (dfrom)); + memset (to, 0, TOTALSIZE); + if (dfrom == 0) + return; /* Result is zero */ + if (dfrom != dfrom) { + /* From is NaN */ + to[EXPBYTE_H] = (unsigned char)(EXT_EXP_NAN >> 8); + to[EXPBYTE_L] = (unsigned char)EXT_EXP_NAN; + to[MANBYTE_H] = 1; /* Be sure it's not infinity, but NaN value is irrel */ + return; /* Result is NaN */ + } + if (dfrom < 0) + to[SIGNBYTE] |= SIGNMASK; /* Set negative sign */ + /* How to tell an infinity from an ordinary number? FIXME-someday */ + + /* The following code assumes that the host has IEEE doubles. FIXME-someday. + It also assumes longs are 32 bits! FIXME-someday. */ + memcpy (twolongs, from, 8); + memcpy (tobytes, from, 8); +#if HOST_BYTE_ORDER == BIG_ENDIAN + exponent = ((tobytes[1] & 0xF0) >> 4) | (tobytes[0] & 0x7F) << 4; + mant0 = (twolongs[0] << 11) | twolongs[1] >> 21; + mant1 = (twolongs[1] << 11); +#else + exponent = ((tobytes[6] & 0xF0) >> 4) | (tobytes[7] & 0x7F) << 4; + mant0 = (twolongs[1] << 11) | twolongs[0] >> 21; + mant1 = (twolongs[0] << 11); +#endif + + /* Fiddle with leading 1-bit, implied in double, explicit in extended. */ + if (exponent == 0) + mant0 &= 0x7FFFFFFF; + else + mant0 |= 0x80000000; + + exponent -= DBL_EXP_BIAS; /* Get integer exp */ + exponent += EXT_EXP_BIAS; /* Offset for extended */ + + /* OK, now store it in extended format. */ + to[EXPBYTE_H] |= (unsigned char)(exponent >> 8); /* Retain sign */ + to[EXPBYTE_L] = (unsigned char) exponent; + + memcpy (&to[MANBYTE_H], &mant0, 4); + memcpy (&to[MANBYTE_L], &mant1, 4); +} + + +#ifdef IEEE_DEBUG + +/* Test some numbers to see that extended/double conversion works for them. */ + +ieee_test (n) + int n; +{ + union { double d; int i[2]; } di; + double result; + int i; + char exten[16]; + extern struct ext_format ext_format_68881; + + for (i = 0; i < n; i++) { + di.i[0] = (random() << 16) | (random() & 0xffff); + di.i[1] = (random() << 16) | (random() & 0xffff); + double_to_ieee_extended (&ext_format_68881, &di.d, exten); + ieee_extended_to_double (&ext_format_68881, exten, &result); + if (di.d != result) + printf ("Differ: %x %x %g => %x %x %g\n", di.d, di.d, result, result); + } +} + +#endif diff --git a/gnu/usr.bin/gdb/libiberty/ieee-float.h b/gnu/usr.bin/gdb/libiberty/ieee-float.h new file mode 100644 index 000000000000..68ef23b40fd9 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/ieee-float.h @@ -0,0 +1,65 @@ +/* IEEE floating point support declarations, for GDB, the GNU Debugger. + Copyright (C) 1991 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (IEEE_FLOAT_H) +#define IEEE_FLOAT_H 1 + +#include "ansidecl.h" + +/* Parameters for extended float format: */ + +struct ext_format { + unsigned totalsize; /* Total size of extended number */ + unsigned signbyte; /* Byte number of sign bit */ + unsigned char signmask; /* Mask for sign bit */ + unsigned expbyte_h; /* High byte of exponent */ + unsigned expbyte_l; /* Low byte of exponent */ + unsigned manbyte_h; /* High byte of mantissa */ + unsigned manbyte_l; /* Low byte of mantissa */ +}; + +#define TOTALSIZE ext_format->totalsize +#define SIGNBYTE ext_format->signbyte +#define SIGNMASK ext_format->signmask +#define EXPBYTE_H ext_format->expbyte_h +#define EXPBYTE_L ext_format->expbyte_l +#define MANBYTE_H ext_format->manbyte_h +#define MANBYTE_L ext_format->manbyte_l + +/* Actual ext_format structs for various machines are in the *-tdep.c file + for each machine. */ + +#define EXT_EXP_NAN 0x7FFF /* Exponent value that indicates NaN */ +#define EXT_EXP_BIAS 0x3FFF /* Amount added to "true" exponent for ext */ +#define DBL_EXP_BIAS 0x3FF /* Ditto, for doubles */ + +/* Convert an IEEE extended float to a double. + FROM is the address of the extended float. + Store the double in *TO. */ + +extern void +ieee_extended_to_double PARAMS ((const struct ext_format *, char *, double *)); + +/* The converse: convert the double *FROM to an extended float + and store where TO points. */ + +extern void +double_to_ieee_extended PARAMS ((const struct ext_format *, double *, char *)); + +#endif /* defined (IEEE_FLOAT_H) */ diff --git a/gnu/usr.bin/gdb/libiberty/obstack.c b/gnu/usr.bin/gdb/libiberty/obstack.c new file mode 100644 index 000000000000..4297bbbd51f1 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/obstack.c @@ -0,0 +1,460 @@ +/* obstack.c - subroutines used implicitly by object stack macros + Copyright (C) 1988, 1993 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU Library General Public License as published by the +Free Software Foundation; either version 2, 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 Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this program; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "obstack.h" + +/* This is just to get __GNU_LIBRARY__ defined. */ +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +#ifdef __STDC__ +#define POINTER void * +#else +#define POINTER char * +#endif + +/* Determine default alignment. */ +struct fooalign {char x; double d;}; +#define DEFAULT_ALIGNMENT \ + ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0)) +/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. + But in fact it might be less smart and round addresses to as much as + DEFAULT_ROUNDING. So we prepare for it to do that. */ +union fooround {long x; double d;}; +#define DEFAULT_ROUNDING (sizeof (union fooround)) + +/* When we copy a long block of data, this is the unit to do it with. + On some machines, copying successive ints does not work; + in such a case, redefine COPYING_UNIT to `long' (if that works) + or `char' as a last resort. */ +#ifndef COPYING_UNIT +#define COPYING_UNIT int +#endif + +/* The non-GNU-C macros copy the obstack into this global variable + to avoid multiple evaluation. */ + +struct obstack *_obstack; + +/* Define a macro that either calls functions with the traditional malloc/free + calling interface, or calls functions with the mmalloc/mfree interface + (that adds an extra first argument), based on the state of use_extra_arg. + For free, do not use ?:, since some compilers, like the MIPS compilers, + do not allow (expr) ? void : void. */ + +#define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(h)->chunkfun) ((size))) + +#define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(h)->freefun) ((old_chunk)); \ + } while (0) + + +/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). + Objects start on multiples of ALIGNMENT (0 means use default). + CHUNKFUN is the function to use to allocate chunks, + and FREEFUN the function to free them. */ + +void +_obstack_begin (h, size, alignment, chunkfun, freefun) + struct obstack *h; + int size; + int alignment; + POINTER (*chunkfun) (); + void (*freefun) (); +{ + register struct _obstack_chunk* chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; + h->freefun = freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->use_extra_arg = 0; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + h->next_free = h->object_base = chunk->contents; + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; +} + +void +_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) + struct obstack *h; + int size; + int alignment; + POINTER (*chunkfun) (); + void (*freefun) (); + POINTER arg; +{ + register struct _obstack_chunk* chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; + h->freefun = freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->extra_arg = arg; + h->use_extra_arg = 1; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + h->next_free = h->object_base = chunk->contents; + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; +} + +/* Allocate a new current chunk for the obstack *H + on the assumption that LENGTH bytes need to be added + to the current object, or a new object of length LENGTH allocated. + Copies any partial object from the end of the old chunk + to the beginning of the new one. */ + +void +_obstack_newchunk (h, length) + struct obstack *h; + int length; +{ + register struct _obstack_chunk* old_chunk = h->chunk; + register struct _obstack_chunk* new_chunk; + register long new_size; + register int obj_size = h->next_free - h->object_base; + register int i; + int already; + + /* Compute size for new chunk. */ + new_size = (obj_size + length) + (obj_size >> 3) + 100; + if (new_size < h->chunk_size) + new_size = h->chunk_size; + + /* Allocate and initialize the new chunk. */ + new_chunk = h->chunk = CALL_CHUNKFUN (h, new_size); + new_chunk->prev = old_chunk; + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; + + /* Move the existing object to the new chunk. + Word at a time is fast and is safe if the object + is sufficiently aligned. */ + if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) + { + for (i = obj_size / sizeof (COPYING_UNIT) - 1; + i >= 0; i--) + ((COPYING_UNIT *)new_chunk->contents)[i] + = ((COPYING_UNIT *)h->object_base)[i]; + /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, + but that can cross a page boundary on a machine + which does not do strict alignment for COPYING_UNITS. */ + already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); + } + else + already = 0; + /* Copy remaining bytes one by one. */ + for (i = already; i < obj_size; i++) + new_chunk->contents[i] = h->object_base[i]; + + /* If the object just copied was the only data in OLD_CHUNK, + free that chunk and remove it from the chain. + But not if that chunk might contain an empty object. */ + if (h->object_base == old_chunk->contents && ! h->maybe_empty_object) + { + new_chunk->prev = old_chunk->prev; + CALL_FREEFUN (h, old_chunk); + } + + h->object_base = new_chunk->contents; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} + +/* Return nonzero if object OBJ has been allocated from obstack H. + This is here for debugging. + If you use it in a program, you are probably losing. */ + +#ifdef __STDC__ +/* Suppress -Wmissing-prototypes warning. We don't want to declare this in + obstack.h because it is just for debugging. */ +int _obstack_allocated_p (struct obstack *h, POINTER obj); +#endif + +int +_obstack_allocated_p (h, obj) + struct obstack *h; + POINTER obj; +{ + register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk* plp; /* point to previous chunk if any */ + + lp = (h)->chunk; + /* We use >= rather than > since the object cannot be exactly at + the beginning of the chunk but might be an empty object exactly + at the end of an adjacent chunk. */ + while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) + { + plp = lp->prev; + lp = plp; + } + return lp != 0; +} + +/* Free objects in obstack H, including OBJ and everything allocate + more recently than OBJ. If OBJ is zero, free everything in H. */ + +#undef obstack_free + +/* This function has two names with identical definitions. + This is the first one, called from non-ANSI code. */ + +void +_obstack_free (h, obj) + struct obstack *h; + POINTER obj; +{ + register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk* plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) + { + plp = lp->prev; + CALL_FREEFUN (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *)(obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +/* This function is used from ANSI code. */ + +void +obstack_free (h, obj) + struct obstack *h; + POINTER obj; +{ + register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk* plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) + { + plp = lp->prev; + CALL_FREEFUN (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *)(obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +#if 0 +/* These are now turned off because the applications do not use it + and it uses bcopy via obstack_grow, which causes trouble on sysV. */ + +/* Now define the functional versions of the obstack macros. + Define them to simply use the corresponding macros to do the job. */ + +#ifdef __STDC__ +/* These function definitions do not work with non-ANSI preprocessors; + they won't pass through the macro names in parentheses. */ + +/* The function names appear in parentheses in order to prevent + the macro-definitions of the names from being expanded there. */ + +POINTER (obstack_base) (obstack) + struct obstack *obstack; +{ + return obstack_base (obstack); +} + +POINTER (obstack_next_free) (obstack) + struct obstack *obstack; +{ + return obstack_next_free (obstack); +} + +int (obstack_object_size) (obstack) + struct obstack *obstack; +{ + return obstack_object_size (obstack); +} + +int (obstack_room) (obstack) + struct obstack *obstack; +{ + return obstack_room (obstack); +} + +void (obstack_grow) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow (obstack, pointer, length); +} + +void (obstack_grow0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow0 (obstack, pointer, length); +} + +void (obstack_1grow) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow (obstack, character); +} + +void (obstack_blank) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank (obstack, length); +} + +void (obstack_1grow_fast) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow_fast (obstack, character); +} + +void (obstack_blank_fast) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank_fast (obstack, length); +} + +POINTER (obstack_finish) (obstack) + struct obstack *obstack; +{ + return obstack_finish (obstack); +} + +POINTER (obstack_alloc) (obstack, length) + struct obstack *obstack; + int length; +{ + return obstack_alloc (obstack, length); +} + +POINTER (obstack_copy) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy (obstack, pointer, length); +} + +POINTER (obstack_copy0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy0 (obstack, pointer, length); +} + +#endif /* __STDC__ */ + +#endif /* 0 */ + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/gnu/usr.bin/gdb/libiberty/sigsetmask.c b/gnu/usr.bin/gdb/libiberty/sigsetmask.c new file mode 100644 index 000000000000..545b12e57b3f --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/sigsetmask.c @@ -0,0 +1,44 @@ +/* Version of sigsetmask.c + Copyright 1991, 1992 Free Software Foundation, Inc. + Written by Steve Chamberlain (sac@cygnus.com). + Contributed by Cygnus Support. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Set the current signal mask to the set provided, and return the + previous value */ + +#define _POSIX_SOURCE +#include <ansidecl.h> +#include <signal.h> + +#ifdef SIG_SETMASK +int +DEFUN(sigsetmask,(set), + int set) +{ + sigset_t new; + sigset_t old; + + sigemptyset (&new); + if (set != 0) { + abort(); /* FIXME, we don't know how to translate old mask to new */ + } + sigprocmask(SIG_SETMASK, &new, &old); + return 1; /* FIXME, we always return 1 as old value. */ +} +#endif diff --git a/gnu/usr.bin/gdb/libiberty/spaces.c b/gnu/usr.bin/gdb/libiberty/spaces.c new file mode 100644 index 000000000000..28f07462d372 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/spaces.c @@ -0,0 +1,67 @@ +/* Allocate memory region filled with spaces. + Copyright (C) 1991 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + +NAME + + spaces -- return a pointer to a buffer full of spaces + +SYNOPSIS + + char *spaces (int count) + +DESCRIPTION + + Returns a pointer to a memory region filled with the specified + number of spaces and null terminated. The returned pointer is + valid until at least the next call. + +BUGS + +*/ + + +char * +spaces (count) + int count; +{ + register char *t; + static char *buf; + static int maxsize; + extern char *malloc (); + extern void free (); + + if (count > maxsize) + { + if (buf) + { + free (buf); + } + buf = malloc (count + 1); + for (t = buf + count ; t != buf ; ) + { + *--t = ' '; + } + maxsize = count; + buf[count] = '\0'; + } + return (buf + maxsize - count); +} + diff --git a/gnu/usr.bin/gdb/libiberty/strerror.c b/gnu/usr.bin/gdb/libiberty/strerror.c new file mode 100644 index 000000000000..f377311a4f56 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/strerror.c @@ -0,0 +1,811 @@ +/* Extended support for using errno values. + Copyright (C) 1992 Free Software Foundation, Inc. + Written by Fred Fish. fnf@cygnus.com + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "config.h" + +#ifndef NEED_sys_errlist +/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least) + might declare sys_errlist in a way that the compiler might consider + incompatible with our later declaration, perhaps by using const + attributes. So we hide the declaration in errno.h (if any) using a + macro. */ +#define sys_errlist sys_errlist__ +#endif + +#include <stdio.h> +#include <errno.h> + +#ifndef NEED_sys_errlist +#undef sys_errlist +#endif + +/* Routines imported from standard C runtime libraries. */ + +#ifdef __STDC__ +#include <stddef.h> +extern void *malloc (size_t size); /* 4.10.3.3 */ +extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */ +#else /* !__STDC__ */ +#ifndef const +#define const +#endif +extern char *malloc (); /* Standard memory allocater */ +extern char *memset (); +#endif /* __STDC__ */ + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* Translation table for errno values. See intro(2) in most UNIX systems + Programmers Reference Manuals. + + Note that this table is generally only accessed when it is used at runtime + to initialize errno name and message tables that are indexed by errno + value. + + Not all of these errnos will exist on all systems. This table is the only + thing that should have to be updated as new error numbers are introduced. + It's sort of ugly, but at least its portable. */ + +struct error_info +{ + int value; /* The numeric value from <errno.h> */ + char *name; /* The equivalent symbolic value */ + char *msg; /* Short message about this value */ +}; + +static const struct error_info error_table[] = +{ +#if defined (EPERM) + {EPERM, "EPERM", "Not owner"}, +#endif +#if defined (ENOENT) + {ENOENT, "ENOENT", "No such file or directory"}, +#endif +#if defined (ESRCH) + {ESRCH, "ESRCH", "No such process"}, +#endif +#if defined (EINTR) + {EINTR, "EINTR", "Interrupted system call"}, +#endif +#if defined (EIO) + {EIO, "EIO", "I/O error"}, +#endif +#if defined (ENXIO) + {ENXIO, "ENXIO", "No such device or address"}, +#endif +#if defined (E2BIG) + {E2BIG, "E2BIG", "Arg list too long"}, +#endif +#if defined (ENOEXEC) + {ENOEXEC, "ENOEXEC", "Exec format error"}, +#endif +#if defined (EBADF) + {EBADF, "EBADF", "Bad file number"}, +#endif +#if defined (ECHILD) + {ECHILD, "ECHILD", "No child processes"}, +#endif +#if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */ + {EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"}, +#endif +#if defined (EAGAIN) + {EAGAIN, "EAGAIN", "No more processes"}, +#endif +#if defined (ENOMEM) + {ENOMEM, "ENOMEM", "Not enough space"}, +#endif +#if defined (EACCES) + {EACCES, "EACCES", "Permission denied"}, +#endif +#if defined (EFAULT) + {EFAULT, "EFAULT", "Bad address"}, +#endif +#if defined (ENOTBLK) + {ENOTBLK, "ENOTBLK", "Block device required"}, +#endif +#if defined (EBUSY) + {EBUSY, "EBUSY", "Device busy"}, +#endif +#if defined (EEXIST) + {EEXIST, "EEXIST", "File exists"}, +#endif +#if defined (EXDEV) + {EXDEV, "EXDEV", "Cross-device link"}, +#endif +#if defined (ENODEV) + {ENODEV, "ENODEV", "No such device"}, +#endif +#if defined (ENOTDIR) + {ENOTDIR, "ENOTDIR", "Not a directory"}, +#endif +#if defined (EISDIR) + {EISDIR, "EISDIR", "Is a directory"}, +#endif +#if defined (EINVAL) + {EINVAL, "EINVAL", "Invalid argument"}, +#endif +#if defined (ENFILE) + {ENFILE, "ENFILE", "File table overflow"}, +#endif +#if defined (EMFILE) + {EMFILE, "EMFILE", "Too many open files"}, +#endif +#if defined (ENOTTY) + {ENOTTY, "ENOTTY", "Not a typewriter"}, +#endif +#if defined (ETXTBSY) + {ETXTBSY, "ETXTBSY", "Text file busy"}, +#endif +#if defined (EFBIG) + {EFBIG, "EFBIG", "File too large"}, +#endif +#if defined (ENOSPC) + {ENOSPC, "ENOSPC", "No space left on device"}, +#endif +#if defined (ESPIPE) + {ESPIPE, "ESPIPE", "Illegal seek"}, +#endif +#if defined (EROFS) + {EROFS, "EROFS", "Read-only file system"}, +#endif +#if defined (EMLINK) + {EMLINK, "EMLINK", "Too many links"}, +#endif +#if defined (EPIPE) + {EPIPE, "EPIPE", "Broken pipe"}, +#endif +#if defined (EDOM) + {EDOM, "EDOM", "Math argument out of domain of func"}, +#endif +#if defined (ERANGE) + {ERANGE, "ERANGE", "Math result not representable"}, +#endif +#if defined (ENOMSG) + {ENOMSG, "ENOMSG", "No message of desired type"}, +#endif +#if defined (EIDRM) + {EIDRM, "EIDRM", "Identifier removed"}, +#endif +#if defined (ECHRNG) + {ECHRNG, "ECHRNG", "Channel number out of range"}, +#endif +#if defined (EL2NSYNC) + {EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"}, +#endif +#if defined (EL3HLT) + {EL3HLT, "EL3HLT", "Level 3 halted"}, +#endif +#if defined (EL3RST) + {EL3RST, "EL3RST", "Level 3 reset"}, +#endif +#if defined (ELNRNG) + {ELNRNG, "ELNRNG", "Link number out of range"}, +#endif +#if defined (EUNATCH) + {EUNATCH, "EUNATCH", "Protocol driver not attached"}, +#endif +#if defined (ENOCSI) + {ENOCSI, "ENOCSI", "No CSI structure available"}, +#endif +#if defined (EL2HLT) + {EL2HLT, "EL2HLT", "Level 2 halted"}, +#endif +#if defined (EDEADLK) + {EDEADLK, "EDEADLK", "Deadlock condition"}, +#endif +#if defined (ENOLCK) + {ENOLCK, "ENOLCK", "No record locks available"}, +#endif +#if defined (EBADE) + {EBADE, "EBADE", "Invalid exchange"}, +#endif +#if defined (EBADR) + {EBADR, "EBADR", "Invalid request descriptor"}, +#endif +#if defined (EXFULL) + {EXFULL, "EXFULL", "Exchange full"}, +#endif +#if defined (ENOANO) + {ENOANO, "ENOANO", "No anode"}, +#endif +#if defined (EBADRQC) + {EBADRQC, "EBADRQC", "Invalid request code"}, +#endif +#if defined (EBADSLT) + {EBADSLT, "EBADSLT", "Invalid slot"}, +#endif +#if defined (EDEADLOCK) + {EDEADLOCK, "EDEADLOCK", "File locking deadlock error"}, +#endif +#if defined (EBFONT) + {EBFONT, "EBFONT", "Bad font file format"}, +#endif +#if defined (ENOSTR) + {ENOSTR, "ENOSTR", "Device not a stream"}, +#endif +#if defined (ENODATA) + {ENODATA, "ENODATA", "No data available"}, +#endif +#if defined (ETIME) + {ETIME, "ETIME", "Timer expired"}, +#endif +#if defined (ENOSR) + {ENOSR, "ENOSR", "Out of streams resources"}, +#endif +#if defined (ENONET) + {ENONET, "ENONET", "Machine is not on the network"}, +#endif +#if defined (ENOPKG) + {ENOPKG, "ENOPKG", "Package not installed"}, +#endif +#if defined (EREMOTE) + {EREMOTE, "EREMOTE", "Object is remote"}, +#endif +#if defined (ENOLINK) + {ENOLINK, "ENOLINK", "Link has been severed"}, +#endif +#if defined (EADV) + {EADV, "EADV", "Advertise error"}, +#endif +#if defined (ESRMNT) + {ESRMNT, "ESRMNT", "Srmount error"}, +#endif +#if defined (ECOMM) + {ECOMM, "ECOMM", "Communication error on send"}, +#endif +#if defined (EPROTO) + {EPROTO, "EPROTO", "Protocol error"}, +#endif +#if defined (EMULTIHOP) + {EMULTIHOP, "EMULTIHOP", "Multihop attempted"}, +#endif +#if defined (EDOTDOT) + {EDOTDOT, "EDOTDOT", "RFS specific error"}, +#endif +#if defined (EBADMSG) + {EBADMSG, "EBADMSG", "Not a data message"}, +#endif +#if defined (ENAMETOOLONG) + {ENAMETOOLONG, "ENAMETOOLONG", "File name too long"}, +#endif +#if defined (EOVERFLOW) + {EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"}, +#endif +#if defined (ENOTUNIQ) + {ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"}, +#endif +#if defined (EBADFD) + {EBADFD, "EBADFD", "File descriptor in bad state"}, +#endif +#if defined (EREMCHG) + {EREMCHG, "EREMCHG", "Remote address changed"}, +#endif +#if defined (ELIBACC) + {ELIBACC, "ELIBACC", "Can not access a needed shared library"}, +#endif +#if defined (ELIBBAD) + {ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"}, +#endif +#if defined (ELIBSCN) + {ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"}, +#endif +#if defined (ELIBMAX) + {ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"}, +#endif +#if defined (ELIBEXEC) + {ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"}, +#endif +#if defined (EILSEQ) + {EILSEQ, "EILSEQ", "Illegal byte sequence"}, +#endif +#if defined (ENOSYS) + {ENOSYS, "ENOSYS", "Operation not applicable"}, +#endif +#if defined (ELOOP) + {ELOOP, "ELOOP", "Too many symbolic links encountered"}, +#endif +#if defined (ERESTART) + {ERESTART, "ERESTART", "Interrupted system call should be restarted"}, +#endif +#if defined (ESTRPIPE) + {ESTRPIPE, "ESTRPIPE", "Streams pipe error"}, +#endif +#if defined (ENOTEMPTY) + {ENOTEMPTY, "ENOTEMPTY", "Directory not empty"}, +#endif +#if defined (EUSERS) + {EUSERS, "EUSERS", "Too many users"}, +#endif +#if defined (ENOTSOCK) + {ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"}, +#endif +#if defined (EDESTADDRREQ) + {EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"}, +#endif +#if defined (EMSGSIZE) + {EMSGSIZE, "EMSGSIZE", "Message too long"}, +#endif +#if defined (EPROTOTYPE) + {EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"}, +#endif +#if defined (ENOPROTOOPT) + {ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"}, +#endif +#if defined (EPROTONOSUPPORT) + {EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"}, +#endif +#if defined (ESOCKTNOSUPPORT) + {ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"}, +#endif +#if defined (EOPNOTSUPP) + {EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"}, +#endif +#if defined (EPFNOSUPPORT) + {EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"}, +#endif +#if defined (EAFNOSUPPORT) + {EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"}, +#endif +#if defined (EADDRINUSE) + {EADDRINUSE, "EADDRINUSE", "Address already in use"}, +#endif +#if defined (EADDRNOTAVAIL) + {EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"}, +#endif +#if defined (ENETDOWN) + {ENETDOWN, "ENETDOWN", "Network is down"}, +#endif +#if defined (ENETUNREACH) + {ENETUNREACH, "ENETUNREACH", "Network is unreachable"}, +#endif +#if defined (ENETRESET) + {ENETRESET, "ENETRESET", "Network dropped connection because of reset"}, +#endif +#if defined (ECONNABORTED) + {ECONNABORTED, "ECONNABORTED", "Software caused connection abort"}, +#endif +#if defined (ECONNRESET) + {ECONNRESET, "ECONNRESET", "Connection reset by peer"}, +#endif +#if defined (ENOBUFS) + {ENOBUFS, "ENOBUFS", "No buffer space available"}, +#endif +#if defined (EISCONN) + {EISCONN, "EISCONN", "Transport endpoint is already connected"}, +#endif +#if defined (ENOTCONN) + {ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"}, +#endif +#if defined (ESHUTDOWN) + {ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"}, +#endif +#if defined (ETOOMANYREFS) + {ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"}, +#endif +#if defined (ETIMEDOUT) + {ETIMEDOUT, "ETIMEDOUT", "Connection timed out"}, +#endif +#if defined (ECONNREFUSED) + {ECONNREFUSED, "ECONNREFUSED", "Connection refused"}, +#endif +#if defined (EHOSTDOWN) + {EHOSTDOWN, "EHOSTDOWN", "Host is down"}, +#endif +#if defined (EHOSTUNREACH) + {EHOSTUNREACH, "EHOSTUNREACH", "No route to host"}, +#endif +#if defined (EALREADY) + {EALREADY, "EALREADY", "Operation already in progress"}, +#endif +#if defined (EINPROGRESS) + {EINPROGRESS, "EINPROGRESS", "Operation now in progress"}, +#endif +#if defined (ESTALE) + {ESTALE, "ESTALE", "Stale NFS file handle"}, +#endif +#if defined (EUCLEAN) + {EUCLEAN, "EUCLEAN", "Structure needs cleaning"}, +#endif +#if defined (ENOTNAM) + {ENOTNAM, "ENOTNAM", "Not a XENIX named type file"}, +#endif +#if defined (ENAVAIL) + {ENAVAIL, "ENAVAIL", "No XENIX semaphores available"}, +#endif +#if defined (EISNAM) + {EISNAM, "EISNAM", "Is a named type file"}, +#endif +#if defined (EREMOTEIO) + {EREMOTEIO, "EREMOTEIO", "Remote I/O error"}, +#endif + {0, NULL, NULL} +}; + +/* Translation table allocated and initialized at runtime. Indexed by the + errno value to find the equivalent symbolic value. */ + +static char **error_names; +static int num_error_names = 0; + +/* Translation table allocated and initialized at runtime, if it does not + already exist in the host environment. Indexed by the errno value to find + the descriptive string. + + We don't export it for use in other modules because even though it has the + same name, it differs from other implementations in that it is dynamically + initialized rather than statically initialized. */ + +#ifdef NEED_sys_errlist + +static int sys_nerr; +static char **sys_errlist; + +#else + +extern int sys_nerr; +extern char *sys_errlist[]; + +#endif + + +/* + +NAME + + init_error_tables -- initialize the name and message tables + +SYNOPSIS + + static void init_error_tables (); + +DESCRIPTION + + Using the error_table, which is initialized at compile time, generate + the error_names and the sys_errlist (if needed) tables, which are + indexed at runtime by a specific errno value. + +BUGS + + The initialization of the tables may fail under low memory conditions, + in which case we don't do anything particularly useful, but we don't + bomb either. Who knows, it might succeed at a later point if we free + some memory in the meantime. In any case, the other routines know + how to deal with lack of a table after trying to initialize it. This + may or may not be considered to be a bug, that we don't specifically + warn about this particular failure mode. + +*/ + +static void +init_error_tables () +{ + const struct error_info *eip; + int nbytes; + + /* If we haven't already scanned the error_table once to find the maximum + errno value, then go find it now. */ + + if (num_error_names == 0) + { + for (eip = error_table; eip -> name != NULL; eip++) + { + if (eip -> value >= num_error_names) + { + num_error_names = eip -> value + 1; + } + } + } + + /* Now attempt to allocate the error_names table, zero it out, and then + initialize it from the statically initialized error_table. */ + + if (error_names == NULL) + { + nbytes = num_error_names * sizeof (char *); + if ((error_names = (char **) malloc (nbytes)) != NULL) + { + memset (error_names, 0, nbytes); + for (eip = error_table; eip -> name != NULL; eip++) + { + error_names[eip -> value] = eip -> name; + } + } + } + +#ifdef NEED_sys_errlist + + /* Now attempt to allocate the sys_errlist table, zero it out, and then + initialize it from the statically initialized error_table. */ + + if (sys_errlist == NULL) + { + nbytes = num_error_names * sizeof (char *); + if ((sys_errlist = (char **) malloc (nbytes)) != NULL) + { + memset (sys_errlist, 0, nbytes); + sys_nerr = num_error_names; + for (eip = error_table; eip -> name != NULL; eip++) + { + sys_errlist[eip -> value] = eip -> msg; + } + } + } + +#endif + +} + +/* + +NAME + + errno_max -- return the max errno value + +SYNOPSIS + + int errno_max (); + +DESCRIPTION + + Returns the maximum errno value for which a corresponding symbolic + name or message is available. Note that in the case where + we use the sys_errlist supplied by the system, it is possible for + there to be more symbolic names than messages, or vice versa. + In fact, the manual page for perror(3C) explicitly warns that one + should check the size of the table (sys_nerr) before indexing it, + since new error codes may be added to the system before they are + added to the table. Thus sys_nerr might be smaller than value + implied by the largest errno value defined in <errno.h>. + + We return the maximum value that can be used to obtain a meaningful + symbolic name or message. + +*/ + +int +errno_max () +{ + int maxsize; + + if (error_names == NULL) + { + init_error_tables (); + } + maxsize = MAX (sys_nerr, num_error_names); + return (maxsize - 1); +} + +#ifdef NEED_strerror + +/* + +NAME + + strerror -- map an error number to an error message string + +SYNOPSIS + + char *strerror (int errnoval) + +DESCRIPTION + + Maps an errno number to an error message string, the contents of + which are implementation defined. On systems which have the external + variables sys_nerr and sys_errlist, these strings will be the same + as the ones used by perror(). + + If the supplied error number is within the valid range of indices + for the sys_errlist, but no message is available for the particular + error number, then returns the string "Error NUM", where NUM is the + error number. + + If the supplied error number is not a valid index into sys_errlist, + returns NULL. + + The returned string is only guaranteed to be valid only until the + next call to strerror. + +*/ + +char * +strerror (errnoval) + int errnoval; +{ + char *msg; + static char buf[32]; + +#ifdef NEED_sys_errlist + + if (error_names == NULL) + { + init_error_tables (); + } + +#endif + + if ((errnoval < 0) || (errnoval >= sys_nerr)) + { + /* Out of range, just return NULL */ + msg = NULL; + } + else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL)) + { + /* In range, but no sys_errlist or no entry at this index. */ + sprintf (buf, "Error %d", errnoval); + msg = buf; + } + else + { + /* In range, and a valid message. Just return the message. */ + msg = sys_errlist[errnoval]; + } + + return (msg); +} + +#endif /* NEED_strerror */ + + +/* + +NAME + + strerrno -- map an error number to a symbolic name string + +SYNOPSIS + + char *strerrno (int errnoval) + +DESCRIPTION + + Given an error number returned from a system call (typically + returned in errno), returns a pointer to a string containing the + symbolic name of that error number, as found in <errno.h>. + + If the supplied error number is within the valid range of indices + for symbolic names, but no name is available for the particular + error number, then returns the string "Error NUM", where NUM is + the error number. + + If the supplied error number is not within the range of valid + indices, then returns NULL. + +BUGS + + The contents of the location pointed to are only guaranteed to be + valid until the next call to strerrno. + +*/ + +char * +strerrno (errnoval) + int errnoval; +{ + char *name; + static char buf[32]; + + if (error_names == NULL) + { + init_error_tables (); + } + + if ((errnoval < 0) || (errnoval >= num_error_names)) + { + /* Out of range, just return NULL */ + name = NULL; + } + else if ((error_names == NULL) || (error_names[errnoval] == NULL)) + { + /* In range, but no error_names or no entry at this index. */ + sprintf (buf, "Error %d", errnoval); + name = buf; + } + else + { + /* In range, and a valid name. Just return the name. */ + name = error_names[errnoval]; + } + + return (name); +} + +/* + +NAME + + strtoerrno -- map a symbolic errno name to a numeric value + +SYNOPSIS + + int strtoerrno (char *name) + +DESCRIPTION + + Given the symbolic name of a error number, map it to an errno value. + If no translation is found, returns 0. + +*/ + +int +strtoerrno (name) + char *name; +{ + int errnoval = 0; + + if (name != NULL) + { + if (error_names == NULL) + { + init_error_tables (); + } + for (errnoval = 0; errnoval < num_error_names; errnoval++) + { + if ((error_names[errnoval] != NULL) && + (strcmp (name, error_names[errnoval]) == 0)) + { + break; + } + } + if (errnoval == num_error_names) + { + errnoval = 0; + } + } + return (errnoval); +} + + +/* A simple little main that does nothing but print all the errno translations + if MAIN is defined and this file is compiled and linked. */ + +#ifdef MAIN + +main () +{ + int errn; + int errnmax; + char *name; + char *msg; + char *strerrno (); + char *strerror (); + + errnmax = errno_max (); + printf ("%d entries in names table.\n", num_error_names); + printf ("%d entries in messages table.\n", sys_nerr); + printf ("%d is max useful index.\n", errnmax); + + /* Keep printing values until we get to the end of *both* tables, not + *either* table. Note that knowing the maximum useful index does *not* + relieve us of the responsibility of testing the return pointer for + NULL. */ + + for (errn = 0; errn <= errnmax; errn++) + { + name = strerrno (errn); + name = (name == NULL) ? "<NULL>" : name; + msg = strerror (errn); + msg = (msg == NULL) ? "<NULL>" : msg; + printf ("%-4d%-18s%s\n", errn, name, msg); + } +} + +#endif diff --git a/gnu/usr.bin/gdb/libiberty/strsignal.c b/gnu/usr.bin/gdb/libiberty/strsignal.c new file mode 100644 index 000000000000..15411ff496c6 --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/strsignal.c @@ -0,0 +1,634 @@ +/* Extended support for using signal values. + Copyright (C) 1992 Free Software Foundation, Inc. + Written by Fred Fish. fnf@cygnus.com + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> + +#include "config.h" + +#ifdef LOSING_SYS_SIGLIST +#define sys_siglist no_such_symbol +#endif + +#include <stdio.h> +#include <signal.h> + +/* Routines imported from standard C runtime libraries. */ + +#ifdef __STDC__ +#include <stddef.h> +extern void *malloc (size_t size); /* 4.10.3.3 */ +extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */ +#else /* !__STDC__ */ +#ifndef const +#define const +#endif +extern char *malloc (); /* Standard memory allocater */ +extern char *memset (); +#endif /* __STDC__ */ + +#ifdef LOSING_SYS_SIGLIST +#undef sys_siglist +#endif + + +#ifndef NULL +# ifdef __STDC__ +# define NULL (void *) 0 +# else +# define NULL 0 +# endif +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* Translation table for signal values. + + Note that this table is generally only accessed when it is used at runtime + to initialize signal name and message tables that are indexed by signal + value. + + Not all of these signals will exist on all systems. This table is the only + thing that should have to be updated as new signal numbers are introduced. + It's sort of ugly, but at least its portable. */ + +struct signal_info +{ + int value; /* The numeric value from <signal.h> */ + char *name; /* The equivalent symbolic value */ + char *msg; /* Short message about this value */ +}; + +static const struct signal_info signal_table[] = +{ +#if defined (SIGHUP) + {SIGHUP, "SIGHUP", "Hangup"}, +#endif +#if defined (SIGINT) + {SIGINT, "SIGINT", "Interrupt"}, +#endif +#if defined (SIGQUIT) + {SIGQUIT, "SIGQUIT", "Quit"}, +#endif +#if defined (SIGILL) + {SIGILL, "SIGILL", "Illegal instruction"}, +#endif +#if defined (SIGTRAP) + {SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"}, +#endif +/* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT + overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */ +#if defined (SIGIOT) + {SIGIOT, "SIGIOT", "IOT trap"}, +#endif +#if defined (SIGABRT) + {SIGABRT, "SIGABRT", "Aborted"}, +#endif +#if defined (SIGEMT) + {SIGEMT, "SIGEMT", "Emulation trap"}, +#endif +#if defined (SIGFPE) + {SIGFPE, "SIGFPE", "Arithmetic exception"}, +#endif +#if defined (SIGKILL) + {SIGKILL, "SIGKILL", "Killed"}, +#endif +#if defined (SIGBUS) + {SIGBUS, "SIGBUS", "Bus error"}, +#endif +#if defined (SIGSEGV) + {SIGSEGV, "SIGSEGV", "Segmentation fault"}, +#endif +#if defined (SIGSYS) + {SIGSYS, "SIGSYS", "Bad system call"}, +#endif +#if defined (SIGPIPE) + {SIGPIPE, "SIGPIPE", "Broken pipe"}, +#endif +#if defined (SIGALRM) + {SIGALRM, "SIGALRM", "Alarm clock"}, +#endif +#if defined (SIGTERM) + {SIGTERM, "SIGTERM", "Terminated"}, +#endif +#if defined (SIGUSR1) + {SIGUSR1, "SIGUSR1", "User defined signal 1"}, +#endif +#if defined (SIGUSR2) + {SIGUSR2, "SIGUSR2", "User defined signal 2"}, +#endif +/* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD + overrides SIGCLD. SIGCHLD is in POXIX.1 */ +#if defined (SIGCLD) + {SIGCLD, "SIGCLD", "Child status changed"}, +#endif +#if defined (SIGCHLD) + {SIGCHLD, "SIGCHLD", "Child status changed"}, +#endif +#if defined (SIGPWR) + {SIGPWR, "SIGPWR", "Power fail/restart"}, +#endif +#if defined (SIGWINCH) + {SIGWINCH, "SIGWINCH", "Window size changed"}, +#endif +#if defined (SIGURG) + {SIGURG, "SIGURG", "Urgent I/O condition"}, +#endif +#if defined (SIGIO) + /* "I/O pending" has also been suggested, but is misleading since the + signal only happens when the process has asked for it, not everytime + I/O is pending. */ + {SIGIO, "SIGIO", "I/O possible"}, +#endif +#if defined (SIGPOLL) + {SIGPOLL, "SIGPOLL", "Pollable event occurred"}, +#endif +#if defined (SIGSTOP) + {SIGSTOP, "SIGSTOP", "Stopped (signal)"}, +#endif +#if defined (SIGTSTP) + {SIGTSTP, "SIGTSTP", "Stopped (user)"}, +#endif +#if defined (SIGCONT) + {SIGCONT, "SIGCONT", "Continued"}, +#endif +#if defined (SIGTTIN) + {SIGTTIN, "SIGTTIN", "Stopped (tty input)"}, +#endif +#if defined (SIGTTOU) + {SIGTTOU, "SIGTTOU", "Stopped (tty output)"}, +#endif +#if defined (SIGVTALRM) + {SIGVTALRM, "SIGVTALRM", "Virtual timer expired"}, +#endif +#if defined (SIGPROF) + {SIGPROF, "SIGPROF", "Profiling timer expired"}, +#endif +#if defined (SIGXCPU) + {SIGXCPU, "SIGXCPU", "CPU time limit exceeded"}, +#endif +#if defined (SIGXFSZ) + {SIGXFSZ, "SIGXFSZ", "File size limit exceeded"}, +#endif +#if defined (SIGWIND) + {SIGWIND, "SIGWIND", "SIGWIND"}, +#endif +#if defined (SIGPHONE) + {SIGPHONE, "SIGPHONE", "SIGPHONE"}, +#endif +#if defined (SIGLOST) + {SIGLOST, "SIGLOST", "Resource lost"}, +#endif +#if defined (SIGWAITING) + {SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"}, +#endif +#if defined (SIGLWP) + {SIGLWP, "SIGLWP", "Signal LWP"}, +#endif +#if defined (SIGDANGER) + {SIGDANGER, "SIGDANGER", "Swap space dangerously low"}, +#endif +#if defined (SIGGRANT) + {SIGGRANT, "SIGGRANT", "Monitor mode granted"}, +#endif +#if defined (SIGRETRACT) + {SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"}, +#endif +#if defined (SIGMSG) + {SIGMSG, "SIGMSG", "Monitor mode data available"}, +#endif +#if defined (SIGSOUND) + {SIGSOUND, "SIGSOUND", "Sound completed"}, +#endif +#if defined (SIGSAK) + {SIGSAK, "SIGSAK", "Secure attention"}, +#endif + {0, NULL, NULL} +}; + +/* Translation table allocated and initialized at runtime. Indexed by the + signal value to find the equivalent symbolic value. */ + +static char **signal_names; +static int num_signal_names = 0; + +/* Translation table allocated and initialized at runtime, if it does not + already exist in the host environment. Indexed by the signal value to find + the descriptive string. + + We don't export it for use in other modules because even though it has the + same name, it differs from other implementations in that it is dynamically + initialized rather than statically initialized. */ + +#ifdef NEED_sys_siglist + +static int sys_nsig; +static char **sys_siglist; + +#else + +static int sys_nsig = NSIG; +extern const char * const sys_siglist[]; + +#endif + + +/* + +NAME + + init_signal_tables -- initialize the name and message tables + +SYNOPSIS + + static void init_signal_tables (); + +DESCRIPTION + + Using the signal_table, which is initialized at compile time, generate + the signal_names and the sys_siglist (if needed) tables, which are + indexed at runtime by a specific signal value. + +BUGS + + The initialization of the tables may fail under low memory conditions, + in which case we don't do anything particularly useful, but we don't + bomb either. Who knows, it might succeed at a later point if we free + some memory in the meantime. In any case, the other routines know + how to deal with lack of a table after trying to initialize it. This + may or may not be considered to be a bug, that we don't specifically + warn about this particular failure mode. + +*/ + +static void +init_signal_tables () +{ + const struct signal_info *eip; + int nbytes; + + /* If we haven't already scanned the signal_table once to find the maximum + signal value, then go find it now. */ + + if (num_signal_names == 0) + { + for (eip = signal_table; eip -> name != NULL; eip++) + { + if (eip -> value >= num_signal_names) + { + num_signal_names = eip -> value + 1; + } + } + } + + /* Now attempt to allocate the signal_names table, zero it out, and then + initialize it from the statically initialized signal_table. */ + + if (signal_names == NULL) + { + nbytes = num_signal_names * sizeof (char *); + if ((signal_names = (char **) malloc (nbytes)) != NULL) + { + memset (signal_names, 0, nbytes); + for (eip = signal_table; eip -> name != NULL; eip++) + { + signal_names[eip -> value] = eip -> name; + } + } + } + +#ifdef NEED_sys_siglist + + /* Now attempt to allocate the sys_siglist table, zero it out, and then + initialize it from the statically initialized signal_table. */ + + if (sys_siglist == NULL) + { + nbytes = num_signal_names * sizeof (char *); + if ((sys_siglist = (char **) malloc (nbytes)) != NULL) + { + memset (sys_siglist, 0, nbytes); + sys_nsig = num_signal_names; + for (eip = signal_table; eip -> name != NULL; eip++) + { + sys_siglist[eip -> value] = eip -> msg; + } + } + } + +#endif + +} + + +/* + +NAME + + signo_max -- return the max signo value + +SYNOPSIS + + int signo_max (); + +DESCRIPTION + + Returns the maximum signo value for which a corresponding symbolic + name or message is available. Note that in the case where + we use the sys_siglist supplied by the system, it is possible for + there to be more symbolic names than messages, or vice versa. + In fact, the manual page for psignal(3b) explicitly warns that one + should check the size of the table (NSIG) before indexing it, + since new signal codes may be added to the system before they are + added to the table. Thus NSIG might be smaller than value + implied by the largest signo value defined in <signal.h>. + + We return the maximum value that can be used to obtain a meaningful + symbolic name or message. + +*/ + +int +signo_max () +{ + int maxsize; + + if (signal_names == NULL) + { + init_signal_tables (); + } + maxsize = MAX (sys_nsig, num_signal_names); + return (maxsize - 1); +} + + +/* + +NAME + + strsignal -- map a signal number to a signal message string + +SYNOPSIS + + char *strsignal (int signo) + +DESCRIPTION + + Maps an signal number to an signal message string, the contents of + which are implementation defined. On systems which have the external + variable sys_siglist, these strings will be the same as the ones used + by psignal(). + + If the supplied signal number is within the valid range of indices + for the sys_siglist, but no message is available for the particular + signal number, then returns the string "Signal NUM", where NUM is the + signal number. + + If the supplied signal number is not a valid index into sys_siglist, + returns NULL. + + The returned string is only guaranteed to be valid only until the + next call to strsignal. + +*/ + +char * +strsignal (signo) + int signo; +{ + char *msg; + static char buf[32]; + +#ifdef NEED_sys_siglist + + if (signal_names == NULL) + { + init_signal_tables (); + } + +#endif + + if ((signo < 0) || (signo >= sys_nsig)) + { + /* Out of range, just return NULL */ + msg = NULL; + } + else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL)) + { + /* In range, but no sys_siglist or no entry at this index. */ + sprintf (buf, "Signal %d", signo); + msg = buf; + } + else + { + /* In range, and a valid message. Just return the message. */ + msg = (char*)sys_siglist[signo]; + } + + return (msg); +} + + +/* + +NAME + + strsigno -- map an signal number to a symbolic name string + +SYNOPSIS + + char *strsigno (int signo) + +DESCRIPTION + + Given an signal number, returns a pointer to a string containing + the symbolic name of that signal number, as found in <signal.h>. + + If the supplied signal number is within the valid range of indices + for symbolic names, but no name is available for the particular + signal number, then returns the string "Signal NUM", where NUM is + the signal number. + + If the supplied signal number is not within the range of valid + indices, then returns NULL. + +BUGS + + The contents of the location pointed to are only guaranteed to be + valid until the next call to strsigno. + +*/ + +char * +strsigno (signo) + int signo; +{ + char *name; + static char buf[32]; + + if (signal_names == NULL) + { + init_signal_tables (); + } + + if ((signo < 0) || (signo >= num_signal_names)) + { + /* Out of range, just return NULL */ + name = NULL; + } + else if ((signal_names == NULL) || (signal_names[signo] == NULL)) + { + /* In range, but no signal_names or no entry at this index. */ + sprintf (buf, "Signal %d", signo); + name = buf; + } + else + { + /* In range, and a valid name. Just return the name. */ + name = signal_names[signo]; + } + + return (name); +} + + +/* + +NAME + + strtosigno -- map a symbolic signal name to a numeric value + +SYNOPSIS + + int strtosigno (char *name) + +DESCRIPTION + + Given the symbolic name of a signal, map it to a signal number. + If no translation is found, returns 0. + +*/ + +int +strtosigno (name) + char *name; +{ + int signo = 0; + + if (name != NULL) + { + if (signal_names == NULL) + { + init_signal_tables (); + } + for (signo = 0; signo < num_signal_names; signo++) + { + if ((signal_names[signo] != NULL) && + (strcmp (name, signal_names[signo]) == 0)) + { + break; + } + } + if (signo == num_signal_names) + { + signo = 0; + } + } + return (signo); +} + + +/* + +NAME + + psignal -- print message about signal to stderr + +SYNOPSIS + + void psignal (unsigned signo, char *message); + +DESCRIPTION + + Print to the standard error the message, followed by a colon, + followed by the description of the signal specified by signo, + followed by a newline. +*/ + +#ifdef NEED_psignal + +void +psignal (signo, message) + unsigned signo; + char *message; +{ + if (signal_names == NULL) + { + init_signal_tables (); + } + if ((signo <= 0) || (signo >= sys_nsig)) + { + fprintf (stderr, "%s: unknown signal\n", message); + } + else + { + fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]); + } +} + +#endif /* NEED_psignal */ + + +/* A simple little main that does nothing but print all the signal translations + if MAIN is defined and this file is compiled and linked. */ + +#ifdef MAIN + +main () +{ + int signo; + int maxsigno; + char *name; + char *msg; + char *strsigno (); + char *strsignal (); + + maxsigno = signo_max (); + printf ("%d entries in names table.\n", num_signal_names); + printf ("%d entries in messages table.\n", sys_nsig); + printf ("%d is max useful index.\n", maxsigno); + + /* Keep printing values until we get to the end of *both* tables, not + *either* table. Note that knowing the maximum useful index does *not* + relieve us of the responsibility of testing the return pointer for + NULL. */ + + for (signo = 0; signo <= maxsigno; signo++) + { + name = strsigno (signo); + name = (name == NULL) ? "<NULL>" : name; + msg = strsignal (signo); + msg = (msg == NULL) ? "<NULL>" : msg; + printf ("%-4d%-18s%s\n", signo, name, msg); + } +} + +#endif diff --git a/gnu/usr.bin/gdb/libiberty/xmalloc.c b/gnu/usr.bin/gdb/libiberty/xmalloc.c new file mode 100644 index 000000000000..be0c7aa9319c --- /dev/null +++ b/gnu/usr.bin/gdb/libiberty/xmalloc.c @@ -0,0 +1,58 @@ +/* memory allocation routines with error checking. + Copyright 1989, 1991, 1993 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> + +#include <stdio.h> + +#ifdef __STDC__ +#include <stddef.h> +#else +#define size_t unsigned long +#endif + + +PTR +xmalloc (size) + size_t size; +{ + char * newmem; + + if ((newmem = (char *) malloc ((int) size)) == NULL) + { + fprintf (stderr, "\nCan't allocate %u bytes\n", size); + exit (1); + } + return (newmem); +} + +PTR +xrealloc (oldmem, size) + PTR oldmem; + size_t size; +{ + char * newmem; + + if ((newmem = (char *) realloc ((char *) oldmem, (int) size)) == NULL) + { + fprintf (stderr, "\nCan't reallocate %u bytes\n", size); + exit (1); + } + return (newmem); +} |
