OSDN Git Service

* alpha/alpha.h (TARGET_WINDOWS_NT, TARGET_OPEN_VMS): Just make them
[pf3gnuchains/gcc-fork.git] / gcc / cplus-dem.c
1 /* Demangler for GNU C++ 
2    Copyright 1989, 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
3    Written by James Clark (jjc@jclark.uucp)
4    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
5    
6 This file is part of the libiberty library.
7 Libiberty is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 Libiberty is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with libiberty; see the file COPYING.LIB.  If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
23
24    This file imports xmalloc and xrealloc, which are like malloc and
25    realloc except that they generate a fatal error if there is no
26    available memory.  */
27
28 /* This file lives in both GCC and libiberty.  When making changes, please
29    try not to break either.  */
30
31 #include <ctype.h>
32 #include <string.h>
33 #include <stdio.h>
34
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38
39 #include <demangle.h>
40 #undef CURRENT_DEMANGLING_STYLE
41 #define CURRENT_DEMANGLING_STYLE work->options
42
43 extern char *xmalloc PARAMS((unsigned));
44 extern char *xrealloc PARAMS((char *, unsigned));
45
46 static const char *mystrstr PARAMS ((const char *, const char *));
47
48 static const char *
49 mystrstr (s1, s2)
50      const char *s1, *s2;
51 {
52   register const char *p = s1;
53   register int len = strlen (s2);
54
55   for (; (p = strchr (p, *s2)) != 0; p++)
56     {
57       if (strncmp (p, s2, len) == 0)
58         {
59           return (p);
60         }
61     }
62   return (0);
63 }
64
65 /* In order to allow a single demangler executable to demangle strings
66    using various common values of CPLUS_MARKER, as well as any specific
67    one set at compile time, we maintain a string containing all the
68    commonly used ones, and check to see if the marker we are looking for
69    is in that string.  CPLUS_MARKER is usually '$' on systems where the
70    assembler can deal with that.  Where the assembler can't, it's usually
71    '.' (but on many systems '.' is used for other things).  We put the
72    current defined CPLUS_MARKER first (which defaults to '$'), followed
73    by the next most common value, followed by an explicit '$' in case
74    the value of CPLUS_MARKER is not '$'.
75
76    We could avoid this if we could just get g++ to tell us what the actual
77    cplus marker character is as part of the debug information, perhaps by
78    ensuring that it is the character that terminates the gcc<n>_compiled
79    marker symbol (FIXME).  */
80
81 #if !defined (CPLUS_MARKER)
82 #define CPLUS_MARKER '$'
83 #endif
84
85 enum demangling_styles current_demangling_style = gnu_demangling;
86
87 static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
88
89 void
90 set_cplus_marker_for_demangling (ch)
91      int ch;
92 {
93   cplus_markers[0] = ch;
94 }
95
96 /* Stuff that is shared between sub-routines.
97    Using a shared structure allows cplus_demangle to be reentrant.  */
98
99 struct work_stuff
100 {
101   int options;
102   char **typevec;
103   int ntypes;
104   int typevec_size;
105   int constructor;
106   int destructor;
107   int static_type;      /* A static member function */
108   int const_type;       /* A const member function */
109   char **tmpl_argvec;   /* Template function arguments. */
110   int ntmpl_args;       /* The number of template function arguments. */
111 };
112
113 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
114 #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
115
116 static const struct optable
117 {
118   const char *in;
119   const char *out;
120   int flags;
121 } optable[] = {
122   {"nw",          " new",       DMGL_ANSI},     /* new (1.92,    ansi) */
123   {"dl",          " delete",    DMGL_ANSI},     /* new (1.92,    ansi) */
124   {"new",         " new",       0},             /* old (1.91,    and 1.x) */
125   {"delete",      " delete",    0},             /* old (1.91,    and 1.x) */
126   {"vn",          " new []",    DMGL_ANSI},     /* GNU, pending ansi */
127   {"vd",          " delete []", DMGL_ANSI},     /* GNU, pending ansi */
128   {"as",          "=",          DMGL_ANSI},     /* ansi */
129   {"ne",          "!=",         DMGL_ANSI},     /* old, ansi */
130   {"eq",          "==",         DMGL_ANSI},     /* old, ansi */
131   {"ge",          ">=",         DMGL_ANSI},     /* old, ansi */
132   {"gt",          ">",          DMGL_ANSI},     /* old, ansi */
133   {"le",          "<=",         DMGL_ANSI},     /* old, ansi */
134   {"lt",          "<",          DMGL_ANSI},     /* old, ansi */
135   {"plus",        "+",          0},             /* old */
136   {"pl",          "+",          DMGL_ANSI},     /* ansi */
137   {"apl",         "+=",         DMGL_ANSI},     /* ansi */
138   {"minus",       "-",          0},             /* old */
139   {"mi",          "-",          DMGL_ANSI},     /* ansi */
140   {"ami",         "-=",         DMGL_ANSI},     /* ansi */
141   {"mult",        "*",          0},             /* old */
142   {"ml",          "*",          DMGL_ANSI},     /* ansi */
143   {"amu",         "*=",         DMGL_ANSI},     /* ansi (ARM/Lucid) */
144   {"aml",         "*=",         DMGL_ANSI},     /* ansi (GNU/g++) */
145   {"convert",     "+",          0},             /* old (unary +) */
146   {"negate",      "-",          0},             /* old (unary -) */
147   {"trunc_mod",   "%",          0},             /* old */
148   {"md",          "%",          DMGL_ANSI},     /* ansi */
149   {"amd",         "%=",         DMGL_ANSI},     /* ansi */
150   {"trunc_div",   "/",          0},             /* old */
151   {"dv",          "/",          DMGL_ANSI},     /* ansi */
152   {"adv",         "/=",         DMGL_ANSI},     /* ansi */
153   {"truth_andif", "&&",         0},             /* old */
154   {"aa",          "&&",         DMGL_ANSI},     /* ansi */
155   {"truth_orif",  "||",         0},             /* old */
156   {"oo",          "||",         DMGL_ANSI},     /* ansi */
157   {"truth_not",   "!",          0},             /* old */
158   {"nt",          "!",          DMGL_ANSI},     /* ansi */
159   {"postincrement","++",        0},             /* old */
160   {"pp",          "++",         DMGL_ANSI},     /* ansi */
161   {"postdecrement","--",        0},             /* old */
162   {"mm",          "--",         DMGL_ANSI},     /* ansi */
163   {"bit_ior",     "|",          0},             /* old */
164   {"or",          "|",          DMGL_ANSI},     /* ansi */
165   {"aor",         "|=",         DMGL_ANSI},     /* ansi */
166   {"bit_xor",     "^",          0},             /* old */
167   {"er",          "^",          DMGL_ANSI},     /* ansi */
168   {"aer",         "^=",         DMGL_ANSI},     /* ansi */
169   {"bit_and",     "&",          0},             /* old */
170   {"ad",          "&",          DMGL_ANSI},     /* ansi */
171   {"aad",         "&=",         DMGL_ANSI},     /* ansi */
172   {"bit_not",     "~",          0},             /* old */
173   {"co",          "~",          DMGL_ANSI},     /* ansi */
174   {"call",        "()",         0},             /* old */
175   {"cl",          "()",         DMGL_ANSI},     /* ansi */
176   {"alshift",     "<<",         0},             /* old */
177   {"ls",          "<<",         DMGL_ANSI},     /* ansi */
178   {"als",         "<<=",        DMGL_ANSI},     /* ansi */
179   {"arshift",     ">>",         0},             /* old */
180   {"rs",          ">>",         DMGL_ANSI},     /* ansi */
181   {"ars",         ">>=",        DMGL_ANSI},     /* ansi */
182   {"component",   "->",         0},             /* old */
183   {"pt",          "->",         DMGL_ANSI},     /* ansi; Lucid C++ form */
184   {"rf",          "->",         DMGL_ANSI},     /* ansi; ARM/GNU form */
185   {"indirect",    "*",          0},             /* old */
186   {"method_call",  "->()",      0},             /* old */
187   {"addr",        "&",          0},             /* old (unary &) */
188   {"array",       "[]",         0},             /* old */
189   {"vc",          "[]",         DMGL_ANSI},     /* ansi */
190   {"compound",    ", ",         0},             /* old */
191   {"cm",          ", ",         DMGL_ANSI},     /* ansi */
192   {"cond",        "?:",         0},             /* old */
193   {"cn",          "?:",         DMGL_ANSI},     /* pseudo-ansi */
194   {"max",         ">?",         0},             /* old */
195   {"mx",          ">?",         DMGL_ANSI},     /* pseudo-ansi */
196   {"min",         "<?",         0},             /* old */
197   {"mn",          "<?",         DMGL_ANSI},     /* pseudo-ansi */
198   {"nop",         "",           0},             /* old (for operator=) */
199   {"rm",          "->*",        DMGL_ANSI}      /* ansi */
200 };
201
202
203 typedef struct string           /* Beware: these aren't required to be */
204 {                               /*  '\0' terminated.  */
205   char *b;                      /* pointer to start of string */
206   char *p;                      /* pointer after last character */
207   char *e;                      /* pointer after end of allocated space */
208 } string;
209
210 #define STRING_EMPTY(str)       ((str) -> b == (str) -> p)
211 #define PREPEND_BLANK(str)      {if (!STRING_EMPTY(str)) \
212     string_prepend(str, " ");}
213 #define APPEND_BLANK(str)       {if (!STRING_EMPTY(str)) \
214     string_append(str, " ");}
215
216 #define ARM_VTABLE_STRING "__vtbl__"    /* Lucid/ARM virtual table prefix */
217 #define ARM_VTABLE_STRLEN 8             /* strlen (ARM_VTABLE_STRING) */
218
219 /* Prototypes for local functions */
220
221 static char *
222 mop_up PARAMS ((struct work_stuff *, string *, int));
223
224 #if 0
225 static int
226 demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *));
227 #endif
228
229 static int
230 demangle_template_template_parm PARAMS ((struct work_stuff *work, 
231                                          const char **, string *));
232
233 static int
234 demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
235                            string *, int));
236
237 static int
238 arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
239                 const char **));
240
241 static void
242 demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
243
244 static int
245 demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
246
247 static int
248 demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
249                             int, int));
250
251 static int
252 demangle_class PARAMS ((struct work_stuff *, const char **, string *));
253
254 static int
255 demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
256
257 static int
258 demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
259
260 static int
261 demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
262
263 static int
264 gnu_special PARAMS ((struct work_stuff *, const char **, string *));
265
266 static int
267 arm_special PARAMS ((struct work_stuff *, const char **, string *));
268
269 static void
270 string_need PARAMS ((string *, int));
271
272 static void
273 string_delete PARAMS ((string *));
274
275 static void
276 string_init PARAMS ((string *));
277
278 static void
279 string_clear PARAMS ((string *));
280
281 #if 0
282 static int
283 string_empty PARAMS ((string *));
284 #endif
285
286 static void
287 string_append PARAMS ((string *, const char *));
288
289 static void
290 string_appends PARAMS ((string *, string *));
291
292 static void
293 string_appendn PARAMS ((string *, const char *, int));
294
295 static void
296 string_prepend PARAMS ((string *, const char *));
297
298 static void
299 string_prependn PARAMS ((string *, const char *, int));
300
301 static int
302 get_count PARAMS ((const char **, int *));
303
304 static int
305 consume_count PARAMS ((const char **));
306
307 static int 
308 consume_count_with_underscores PARAMS ((const char**));
309
310 static int
311 demangle_args PARAMS ((struct work_stuff *, const char **, string *));
312
313 static int
314 do_type PARAMS ((struct work_stuff *, const char **, string *));
315
316 static int
317 do_arg PARAMS ((struct work_stuff *, const char **, string *));
318
319 static void
320 demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
321                                 const char *));
322
323 static void
324 remember_type PARAMS ((struct work_stuff *, const char *, int));
325
326 static void
327 forget_types PARAMS ((struct work_stuff *));
328
329 static void
330 string_prepends PARAMS ((string *, string *));
331
332 /*  Translate count to integer, consuming tokens in the process.
333     Conversion terminates on the first non-digit character.
334     Trying to consume something that isn't a count results in
335     no consumption of input and a return of 0.  */
336
337 static int
338 consume_count (type)
339      const char **type;
340 {
341   int count = 0;
342
343   while (isdigit (**type))
344     {
345       count *= 10;
346       count += **type - '0';
347       (*type)++;
348     }
349   return (count);
350 }
351
352
353 /* Like consume_count, but for counts that are preceded and followed
354    by '_' if they are greater than 10.  Also, -1 is returned for
355    failure, since 0 can be a valid value.  */
356
357 static int
358 consume_count_with_underscores (mangled)
359      const char **mangled;
360 {
361   int idx;
362
363   if (**mangled == '_')
364     {
365       (*mangled)++;
366       if (!isdigit (**mangled))
367         return -1;
368
369       idx = consume_count (mangled);
370       if (**mangled != '_')
371         /* The trailing underscore was missing. */
372         return -1;
373             
374       (*mangled)++;
375     }
376   else
377     {
378       if (**mangled < '0' || **mangled > '9')
379         return -1;
380             
381       idx = **mangled - '0';
382       (*mangled)++;
383     }
384
385   return idx;
386 }
387
388 int
389 cplus_demangle_opname (opname, result, options)
390      const char *opname;
391      char *result;
392      int options;
393 {
394   int len, i, len1, ret;
395   string type;
396   struct work_stuff work[1];
397   const char *tem;
398
399   len = strlen(opname);
400   result[0] = '\0';
401   ret = 0;
402   work->options = options;
403   
404   if (opname[0] == '_' && opname[1] == '_'
405       && opname[2] == 'o' && opname[3] == 'p')
406     {
407       /* ANSI.  */
408       /* type conversion operator.  */
409       tem = opname + 4;
410       if (do_type (work, &tem, &type))
411         {
412           strcat (result, "operator ");
413           strncat (result, type.b, type.p - type.b);
414           string_delete (&type);
415           ret = 1;
416         }
417     }
418   else if (opname[0] == '_' && opname[1] == '_'
419            && opname[2] >= 'a' && opname[2] <= 'z'
420            && opname[3] >= 'a' && opname[3] <= 'z')
421     {
422       if (opname[4] == '\0')
423         {
424           /* Operator.  */
425           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
426             {
427               if (strlen (optable[i].in) == 2
428                   && memcmp (optable[i].in, opname + 2, 2) == 0)
429                 {
430                   strcat (result, "operator");
431                   strcat (result, optable[i].out);
432                   ret = 1;
433                   break;
434                 }
435             }
436         }
437       else
438         {
439           if (opname[2] == 'a' && opname[5] == '\0')
440             {
441               /* Assignment.  */
442               for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
443                 {
444                   if (strlen (optable[i].in) == 3
445                       && memcmp (optable[i].in, opname + 2, 3) == 0)
446                     {
447                       strcat (result, "operator");
448                       strcat (result, optable[i].out);
449                       ret = 1;
450                       break;
451                     }                 
452                 }
453             }
454         }
455     }
456   else if (len >= 3 
457            && opname[0] == 'o'
458            && opname[1] == 'p'
459            && strchr (cplus_markers, opname[2]) != NULL)
460     {
461       /* see if it's an assignment expression */
462       if (len >= 10 /* op$assign_ */
463           && memcmp (opname + 3, "assign_", 7) == 0)
464         {
465           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
466             {
467               len1 = len - 10;
468               if (strlen (optable[i].in) == len1
469                   && memcmp (optable[i].in, opname + 10, len1) == 0)
470                 {
471                   strcat (result, "operator");
472                   strcat (result, optable[i].out);
473                   strcat (result, "=");
474                   ret = 1;
475                   break;
476                 }
477             }
478         }
479       else
480         {
481           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
482             {
483               len1 = len - 3;
484               if (strlen (optable[i].in) == len1 
485                   && memcmp (optable[i].in, opname + 3, len1) == 0)
486                 {
487                   strcat (result, "operator");
488                   strcat (result, optable[i].out);
489                   ret = 1;
490                   break;
491                 }
492             }
493         }
494     }
495   else if (len >= 5 && memcmp (opname, "type", 4) == 0
496            && strchr (cplus_markers, opname[4]) != NULL)
497     {
498       /* type conversion operator */
499       tem = opname + 5;
500       if (do_type (work, &tem, &type))
501         {
502           strcat (result, "operator ");
503           strncat (result, type.b, type.p - type.b);
504           string_delete (&type);
505           ret = 1;
506         }
507     }
508   return ret;
509
510 }
511 /* Takes operator name as e.g. "++" and returns mangled
512    operator name (e.g. "postincrement_expr"), or NULL if not found.
513
514    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
515    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
516
517 const char *
518 cplus_mangle_opname (opname, options)
519      const char *opname;
520      int options;
521 {
522   int i;
523   int len;
524
525   len = strlen (opname);
526   for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
527     {
528       if (strlen (optable[i].out) == len
529           && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
530           && memcmp (optable[i].out, opname, len) == 0)
531         return optable[i].in;
532     }
533   return (0);
534 }
535
536 /* char *cplus_demangle (const char *mangled, int options)
537
538    If MANGLED is a mangled function name produced by GNU C++, then
539    a pointer to a malloced string giving a C++ representation
540    of the name will be returned; otherwise NULL will be returned.
541    It is the caller's responsibility to free the string which
542    is returned.
543
544    The OPTIONS arg may contain one or more of the following bits:
545
546         DMGL_ANSI       ANSI qualifiers such as `const' and `void' are
547                         included.
548         DMGL_PARAMS     Function parameters are included.
549
550    For example,
551    
552    cplus_demangle ("foo__1Ai", DMGL_PARAMS)             => "A::foo(int)"
553    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
554    cplus_demangle ("foo__1Ai", 0)                       => "A::foo"
555
556    cplus_demangle ("foo__1Afe", DMGL_PARAMS)            => "A::foo(float,...)"
557    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
558    cplus_demangle ("foo__1Afe", 0)                      => "A::foo"
559
560    Note that any leading underscores, or other such characters prepended by
561    the compilation system, are presumed to have already been stripped from
562    MANGLED.  */
563
564 char *
565 cplus_demangle (mangled, options)
566      const char *mangled;
567      int options;
568 {
569   string decl;
570   int success = 0;
571   struct work_stuff work[1];
572   char *demangled = NULL;
573
574   if ((mangled != NULL) && (*mangled != '\0'))
575     {
576       memset ((char *) work, 0, sizeof (work));
577       work -> options = options;
578       if ((work->options & DMGL_STYLE_MASK) == 0)
579         work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
580       
581       string_init (&decl);
582
583       /* First check to see if gnu style demangling is active and if the
584          string to be demangled contains a CPLUS_MARKER.  If so, attempt to
585          recognize one of the gnu special forms rather than looking for a
586          standard prefix.  In particular, don't worry about whether there
587          is a "__" string in the mangled string.  Consider "_$_5__foo" for
588          example.  */
589
590       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
591         {
592           success = gnu_special (work, &mangled, &decl);
593         }
594       if (!success)
595         {
596           success = demangle_prefix (work, &mangled, &decl);
597         }
598       if (success && (*mangled != '\0'))
599         {
600           success = demangle_signature (work, &mangled, &decl);
601         }
602       if (work->constructor == 2)
603         {
604           string_prepend(&decl, "global constructors keyed to ");
605           work->constructor = 0;
606         }
607       else if (work->destructor == 2)
608         {
609           string_prepend(&decl, "global destructors keyed to ");
610           work->destructor = 0;
611         }
612       demangled = mop_up (work, &decl, success);
613     }
614   return (demangled);
615 }
616
617 static char *
618 mop_up (work, declp, success)
619      struct work_stuff *work;
620      string *declp;
621      int success;
622 {
623   char *demangled = NULL;
624
625   /* Discard the remembered types, if any.  */
626   
627   forget_types (work);
628   if (work -> typevec != NULL)
629     {
630       free ((char *) work -> typevec);
631     }
632   if (work->tmpl_argvec)
633     {
634       int i;
635
636       for (i = 0; i < work->ntmpl_args; i++)
637         if (work->tmpl_argvec[i])
638           free ((char*) work->tmpl_argvec[i]);
639       
640       free ((char*) work->tmpl_argvec);
641     }
642
643   /* If demangling was successful, ensure that the demangled string is null
644      terminated and return it.  Otherwise, free the demangling decl.  */
645   
646   if (!success)
647     {
648       string_delete (declp);
649     }
650   else
651     {
652       string_appendn (declp, "", 1);
653       demangled = declp -> b;
654     }
655   return (demangled);
656 }
657
658 /*
659
660 LOCAL FUNCTION
661
662         demangle_signature -- demangle the signature part of a mangled name
663
664 SYNOPSIS
665
666         static int
667         demangle_signature (struct work_stuff *work, const char **mangled,
668                             string *declp);
669
670 DESCRIPTION
671
672         Consume and demangle the signature portion of the mangled name.
673
674         DECLP is the string where demangled output is being built.  At
675         entry it contains the demangled root name from the mangled name
676         prefix.  I.E. either a demangled operator name or the root function
677         name.  In some special cases, it may contain nothing.
678
679         *MANGLED points to the current unconsumed location in the mangled
680         name.  As tokens are consumed and demangling is performed, the
681         pointer is updated to continuously point at the next token to
682         be consumed.
683
684         Demangling GNU style mangled names is nasty because there is no
685         explicit token that marks the start of the outermost function
686         argument list.  */
687
688 static int
689 demangle_signature (work, mangled, declp)
690      struct work_stuff *work;
691      const char **mangled;
692      string *declp;
693 {
694   int success = 1;
695   int func_done = 0;
696   int expect_func = 0;
697   int expect_return_type = 0;
698   const char *oldmangled = NULL;
699   string trawname;
700   string tname;
701
702   while (success && (**mangled != '\0'))
703     {
704       switch (**mangled)
705         {
706         case 'Q':
707           oldmangled = *mangled;
708           success = demangle_qualified (work, mangled, declp, 1, 0);
709           if (success)
710             {
711               remember_type (work, oldmangled, *mangled - oldmangled);
712             }
713           if (AUTO_DEMANGLING || GNU_DEMANGLING)
714             {
715               expect_func = 1;
716             }
717           oldmangled = NULL;
718           break;
719           
720         case 'S':
721           /* Static member function */
722           if (oldmangled == NULL)
723             {
724               oldmangled = *mangled;
725             }
726           (*mangled)++;
727           work -> static_type = 1;
728           break;
729
730         case 'C':
731           /* a const member function */
732           if (oldmangled == NULL)
733             {
734               oldmangled = *mangled;
735             }
736           (*mangled)++;
737           work -> const_type = 1;
738           break;
739           
740         case '0': case '1': case '2': case '3': case '4':
741         case '5': case '6': case '7': case '8': case '9':
742           if (oldmangled == NULL)
743             {
744               oldmangled = *mangled;
745             }
746           success = demangle_class (work, mangled, declp);
747           if (success)
748             {
749               remember_type (work, oldmangled, *mangled - oldmangled);
750             }
751           if (AUTO_DEMANGLING || GNU_DEMANGLING)
752             {
753               expect_func = 1;
754             }
755           oldmangled = NULL;
756           break;
757           
758         case 'F':
759           /* Function */
760           /* ARM style demangling includes a specific 'F' character after
761              the class name.  For GNU style, it is just implied.  So we can
762              safely just consume any 'F' at this point and be compatible
763              with either style.  */
764
765           oldmangled = NULL;
766           func_done = 1;
767           (*mangled)++;
768
769           /* For lucid/ARM style we have to forget any types we might
770              have remembered up to this point, since they were not argument
771              types.  GNU style considers all types seen as available for
772              back references.  See comment in demangle_args() */
773
774           if (LUCID_DEMANGLING || ARM_DEMANGLING)
775             {
776               forget_types (work);
777             }
778           success = demangle_args (work, mangled, declp);
779           break;
780           
781         case 't':
782           /* G++ Template */
783           string_init(&trawname); 
784           string_init(&tname);
785           if (oldmangled == NULL)
786             {
787               oldmangled = *mangled;
788             }
789           success = demangle_template (work, mangled, &tname, &trawname, 1);
790           if (success)
791             {
792               remember_type (work, oldmangled, *mangled - oldmangled);
793             }
794           string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::");
795           string_prepends(declp, &tname);
796           if (work -> destructor & 1)
797             {
798               string_prepend (&trawname, "~");
799               string_appends (declp, &trawname);
800               work->destructor -= 1;
801             }
802           if ((work->constructor & 1) || (work->destructor & 1))
803             {
804               string_appends (declp, &trawname);
805               work->constructor -= 1;
806             }
807           string_delete(&trawname);
808           string_delete(&tname);
809           oldmangled = NULL;
810           expect_func = 1;
811           break;
812
813         case '_':
814           if (GNU_DEMANGLING && expect_return_type) 
815             {
816               /* Read the return type. */
817               string return_type;
818               string_init (&return_type);
819
820               (*mangled)++;
821               success = do_type (work, mangled, &return_type);
822               APPEND_BLANK (&return_type);
823
824               string_prepends (declp, &return_type);
825               string_delete (&return_type);
826               break;
827             }
828           else
829             /* At the outermost level, we cannot have a return type specified,
830                so if we run into another '_' at this point we are dealing with
831                a mangled name that is either bogus, or has been mangled by
832                some algorithm we don't know how to deal with.  So just
833                reject the entire demangling.  */
834             success = 0;
835           break;
836
837         case 'H':
838           if (GNU_DEMANGLING) 
839             {
840               /* A G++ template function.  Read the template arguments. */
841               success = demangle_template (work, mangled, declp, 0, 0);
842               if (!(work->constructor & 1))
843                 expect_return_type = 1;
844               (*mangled)++;
845               break;
846             }
847           else
848             /* fall through */
849             {;}
850
851         default:
852           if (AUTO_DEMANGLING || GNU_DEMANGLING)
853             {
854               /* Assume we have stumbled onto the first outermost function
855                  argument token, and start processing args.  */
856               func_done = 1;
857               success = demangle_args (work, mangled, declp);
858             }
859           else
860             {
861               /* Non-GNU demanglers use a specific token to mark the start
862                  of the outermost function argument tokens.  Typically 'F',
863                  for ARM-demangling, for example.  So if we find something
864                  we are not prepared for, it must be an error.  */
865               success = 0;
866             }
867           break;
868         }
869       /*
870         if (AUTO_DEMANGLING || GNU_DEMANGLING)
871         */
872       {
873         if (success && expect_func)
874           {
875             func_done = 1;
876             success = demangle_args (work, mangled, declp);
877             /* Since template include the mangling of their return types,
878                we must set expect_func to 0 so that we don't try do
879                demangle more arguments the next time we get here.  */
880             expect_func = 0;
881           }
882       }
883     }
884   if (success && !func_done)
885     {
886       if (AUTO_DEMANGLING || GNU_DEMANGLING)
887         {
888           /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
889              bar__3fooi is 'foo::bar(int)'.  We get here when we find the
890              first case, and need to ensure that the '(void)' gets added to
891              the current declp.  Note that with ARM, the first case
892              represents the name of a static data member 'foo::bar',
893              which is in the current declp, so we leave it alone.  */
894           success = demangle_args (work, mangled, declp);
895         }
896     }
897   if (success && work -> static_type && PRINT_ARG_TYPES)
898     {
899       string_append (declp, " static");
900     }
901   if (success && work -> const_type && PRINT_ARG_TYPES)
902     {
903       string_append (declp, " const");
904     }
905   return (success);
906 }
907
908 #if 0
909
910 static int
911 demangle_method_args (work, mangled, declp)
912      struct work_stuff *work;
913      const char **mangled;
914      string *declp;
915 {
916   int success = 0;
917
918   if (work -> static_type)
919     {
920       string_append (declp, *mangled + 1);
921       *mangled += strlen (*mangled);
922       success = 1;
923     }
924   else
925     {
926       success = demangle_args (work, mangled, declp);
927     }
928   return (success);
929 }
930
931 #endif
932
933 static int
934 demangle_template_template_parm (work, mangled, tname)
935      struct work_stuff *work;
936      const char **mangled;
937      string *tname;
938 {
939   int i;
940   int r;
941   int need_comma = 0;
942   int success = 1;
943   string temp;
944
945   string_append (tname, "template <");
946   /* get size of template parameter list */
947   if (get_count (mangled, &r))
948     {
949       for (i = 0; i < r; i++)
950         {
951           if (need_comma)
952             {
953               string_append (tname, ", ");
954             }
955
956             /* Z for type parameters */
957             if (**mangled == 'Z')
958               {
959                 (*mangled)++;
960                 string_append (tname, "class");
961               }
962               /* z for template parameters */
963             else if (**mangled == 'z')
964               {
965                 (*mangled)++;
966                 success = 
967                   demangle_template_template_parm (work, mangled, tname);
968                 if (!success)
969                   {
970                     break;
971                   }
972               }
973             else
974               {
975                 /* temp is initialized in do_type */
976                 success = do_type (work, mangled, &temp);
977                 if (success)
978                   {
979                     string_appends (tname, &temp);
980                   }
981                 string_delete(&temp);
982                 if (!success)
983                   {
984                     break;
985                   }
986               }
987           need_comma = 1;
988         }
989
990     }
991   if (tname->p[-1] == '>')
992     string_append (tname, " ");
993   string_append (tname, "> class");
994   return (success);
995 }
996
997 static int
998 demangle_template (work, mangled, tname, trawname, is_type)
999      struct work_stuff *work;
1000      const char **mangled;
1001      string *tname;
1002      string *trawname;
1003      int is_type;
1004 {
1005   int i;
1006   int is_pointer;
1007   int is_real;
1008   int is_integral;
1009   int is_char;
1010   int is_bool;
1011   int r;
1012   int need_comma = 0;
1013   int success = 0;
1014   int done;
1015   const char *old_p;
1016   const char *start;
1017   int symbol_len;
1018   int is_java_array = 0;
1019   string temp;
1020
1021   (*mangled)++;
1022   if (is_type)
1023     {
1024       start = *mangled;
1025       /* get template name */
1026       if (**mangled == 'z')
1027         {
1028           int idx;
1029           (*mangled)++;
1030           (*mangled)++;
1031
1032           idx = consume_count_with_underscores (mangled);
1033           if (idx == -1 
1034               || (work->tmpl_argvec && idx >= work->ntmpl_args)
1035               || consume_count_with_underscores (mangled) == -1)
1036             {
1037               return (0);
1038             }
1039           if (work->tmpl_argvec)
1040             {
1041               string_append (tname, work->tmpl_argvec[idx]);
1042               if (trawname)
1043                 string_append (trawname, work->tmpl_argvec[idx]);
1044             }
1045           else
1046             {
1047               char buf[10];
1048               sprintf(buf, "T%d", idx);
1049               string_append (tname, buf);
1050               if (trawname)
1051                 string_append (trawname, work->tmpl_argvec[idx]);
1052             }
1053         }
1054       else
1055         {
1056           if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
1057             {
1058               return (0);
1059             }
1060           if (trawname)
1061             string_appendn (trawname, *mangled, r);
1062           is_java_array = (work -> options & DMGL_JAVA)
1063             && strncmp (*mangled, "JArray1Z", 8) == 0;
1064           if (! is_java_array)
1065             {
1066               string_appendn (tname, *mangled, r);
1067             }
1068           *mangled += r;
1069         }
1070     }
1071   if (!is_java_array)
1072     string_append (tname, "<");
1073   /* get size of template parameter list */
1074   if (!get_count (mangled, &r))
1075     {
1076       return (0);
1077     }
1078   if (!is_type)
1079     {
1080       /* Create an array for saving the template argument values. */
1081       work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
1082       work->ntmpl_args = r;
1083       for (i = 0; i < r; i++)
1084         work->tmpl_argvec[i] = 0;
1085     }
1086   for (i = 0; i < r; i++)
1087     {
1088       if (need_comma)
1089         {
1090           string_append (tname, ", ");
1091         }
1092       /* Z for type parameters */
1093       if (**mangled == 'Z')
1094         {
1095           (*mangled)++;
1096           /* temp is initialized in do_type */
1097           success = do_type (work, mangled, &temp);
1098           if (success)
1099             {
1100               string_appends (tname, &temp);
1101
1102               if (!is_type)
1103                 {
1104                   /* Save the template argument. */
1105                   int len = temp.p - temp.b;
1106                   work->tmpl_argvec[i] = xmalloc (len + 1);
1107                   memcpy (work->tmpl_argvec[i], temp.b, len);
1108                   work->tmpl_argvec[i][len] = '\0';
1109                 }
1110             }
1111           string_delete(&temp);
1112           if (!success)
1113             {
1114               break;
1115             }
1116         }
1117       /* z for template parameters */
1118       else if (**mangled == 'z')
1119         {
1120           int r2;
1121           (*mangled)++;
1122           success = demangle_template_template_parm (work, mangled, tname);
1123           
1124           if (success
1125               && (r2 = consume_count (mangled)) > 0 && strlen (*mangled) >= r2)
1126             {
1127               string_append (tname, " ");
1128               string_appendn (tname, *mangled, r2);
1129               if (!is_type)
1130                 {
1131                   /* Save the template argument. */
1132                   int len = r2;
1133                   work->tmpl_argvec[i] = xmalloc (len + 1);
1134                   memcpy (work->tmpl_argvec[i], *mangled, len);
1135                   work->tmpl_argvec[i][len] = '\0';
1136                 }
1137               *mangled += r2;
1138             }
1139           if (!success)
1140             {
1141               break;
1142             }
1143         }
1144       else
1145         {
1146           string  param;
1147           string* s;
1148
1149           /* otherwise, value parameter */
1150           old_p  = *mangled;
1151           is_pointer = 0;
1152           is_real = 0;
1153           is_integral = 0;
1154           is_char = 0;
1155           is_bool = 0;
1156           done = 0;
1157           /* temp is initialized in do_type */
1158           success = do_type (work, mangled, &temp);
1159           /*
1160             if (success)
1161             {
1162             string_appends (s, &temp);
1163             }
1164             */
1165           string_delete(&temp);
1166           if (!success)
1167             {
1168               break;
1169             }
1170           /*
1171             string_append (s, "=");
1172             */
1173
1174           if (!is_type)
1175             {
1176               s = &param;
1177               string_init (s);
1178             }
1179           else
1180             s = tname;
1181
1182           while (*old_p && !done)
1183             {   
1184               switch (*old_p)
1185                 {
1186                 case 'P':
1187                 case 'p':
1188                 case 'R':
1189                   done = is_pointer = 1;
1190                   break;
1191                 case 'C':       /* const */
1192                 case 'S':       /* explicitly signed [char] */
1193                 case 'U':       /* unsigned */
1194                 case 'V':       /* volatile */
1195                 case 'F':       /* function */
1196                 case 'M':       /* member function */
1197                 case 'O':       /* ??? */
1198                 case 'J':       /* complex */
1199                   old_p++;
1200                   continue;
1201                 case 'Q':       /* qualified name */
1202                   done = is_integral = 1;
1203                   break;
1204                 case 'T':       /* remembered type */
1205                   abort ();
1206                   break;
1207                 case 'v':       /* void */
1208                   abort ();
1209                   break;
1210                 case 'x':       /* long long */
1211                 case 'l':       /* long */
1212                 case 'i':       /* int */
1213                 case 's':       /* short */
1214                 case 'w':       /* wchar_t */
1215                   done = is_integral = 1;
1216                   break;
1217                 case 'b':       /* bool */
1218                   done = is_bool = 1;
1219                   break;
1220                 case 'c':       /* char */
1221                   done = is_char = 1;
1222                   break;
1223                 case 'r':       /* long double */
1224                 case 'd':       /* double */
1225                 case 'f':       /* float */
1226                   done = is_real = 1;
1227                   break;
1228                 default:
1229                   /* it's probably user defined type, let's assume
1230                      it's integral, it seems hard to figure out
1231                      what it really is */
1232                   done = is_integral = 1;
1233                 }
1234             }
1235           if (**mangled == 'Y')
1236             {
1237               /* The next argument is a template parameter. */
1238               int idx;
1239
1240               (*mangled)++;
1241               idx = consume_count_with_underscores (mangled);
1242               if (idx == -1 
1243                   || (work->tmpl_argvec && idx >= work->ntmpl_args)
1244                   || consume_count_with_underscores (mangled) == -1)
1245                 {
1246                   success = 0;
1247                   if (!is_type)
1248                     string_delete (s);
1249                   break;
1250                 }
1251               if (work->tmpl_argvec)
1252                 string_append (s, work->tmpl_argvec[idx]);
1253               else
1254                 {
1255                   char buf[10];
1256                   sprintf(buf, "T%d", idx);
1257                   string_append (s, buf);
1258                 }
1259             }
1260           else if (is_integral)
1261             {
1262               if (**mangled == 'm')
1263                 {
1264                   string_appendn (s, "-", 1);
1265                   (*mangled)++;
1266                 }
1267               while (isdigit (**mangled))       
1268                 {
1269                   string_appendn (s, *mangled, 1);
1270                   (*mangled)++;
1271                 }
1272             }
1273           else if (is_char)
1274             {
1275               char tmp[2];
1276               int val;
1277               if (**mangled == 'm')
1278                 {
1279                   string_appendn (s, "-", 1);
1280                   (*mangled)++;
1281                 }
1282               string_appendn (s, "'", 1);
1283               val = consume_count(mangled);
1284               if (val == 0)
1285                 {
1286                   success = 0;
1287                   if (!is_type)
1288                     string_delete (s);
1289                   break;
1290                 }
1291               tmp[0] = (char)val;
1292               tmp[1] = '\0';
1293               string_appendn (s, &tmp[0], 1);
1294               string_appendn (s, "'", 1);
1295             }
1296           else if (is_bool)
1297             {
1298               int val = consume_count (mangled);
1299               if (val == 0)
1300                 string_appendn (s, "false", 5);
1301               else if (val == 1)
1302                 string_appendn (s, "true", 4);
1303               else
1304                 success = 0;
1305             }
1306           else if (is_real)
1307             {
1308               if (**mangled == 'm')
1309                 {
1310                   string_appendn (s, "-", 1);
1311                   (*mangled)++;
1312                 }
1313               while (isdigit (**mangled))       
1314                 {
1315                   string_appendn (s, *mangled, 1);
1316                   (*mangled)++;
1317                 }
1318               if (**mangled == '.') /* fraction */
1319                 {
1320                   string_appendn (s, ".", 1);
1321                   (*mangled)++;
1322                   while (isdigit (**mangled))   
1323                     {
1324                       string_appendn (s, *mangled, 1);
1325                       (*mangled)++;
1326                     }
1327                 }
1328               if (**mangled == 'e') /* exponent */
1329                 {
1330                   string_appendn (s, "e", 1);
1331                   (*mangled)++;
1332                   while (isdigit (**mangled))   
1333                     {
1334                       string_appendn (s, *mangled, 1);
1335                       (*mangled)++;
1336                     }
1337                 }
1338             }
1339           else if (is_pointer)
1340             {
1341               symbol_len = consume_count (mangled);
1342               if (symbol_len == 0)
1343                 {
1344                   success = 0;
1345                   if (!is_type)
1346                     string_delete (s);
1347                   break;
1348                 }
1349               if (symbol_len == 0)
1350                 string_appendn (s, "0", 1);
1351               else
1352                 {
1353                   char *p = xmalloc (symbol_len + 1), *q;
1354                   strncpy (p, *mangled, symbol_len);
1355                   p [symbol_len] = '\0';
1356                   q = cplus_demangle (p, work->options);
1357                   string_appendn (s, "&", 1);
1358                   if (q)
1359                     {
1360                       string_append (s, q);
1361                       free (q);
1362                     }
1363                   else
1364                     string_append (s, p);
1365                   free (p);
1366                 }
1367               *mangled += symbol_len;
1368             }
1369           if (!is_type)
1370             {
1371               int len = s->p - s->b;
1372               work->tmpl_argvec[i] = xmalloc (len + 1);
1373               memcpy (work->tmpl_argvec[i], s->b, len);
1374               work->tmpl_argvec[i][len] = '\0';
1375               
1376               string_appends (tname, s);
1377               string_delete (s);
1378             }
1379         }
1380       need_comma = 1;
1381     }
1382   if (is_java_array)
1383     {
1384       string_append (tname, "[]");
1385     }
1386   else
1387     {
1388       if (tname->p[-1] == '>')
1389         string_append (tname, " ");
1390       string_append (tname, ">");
1391     }
1392   
1393   /*
1394     if (work -> static_type)
1395     {
1396     string_append (declp, *mangled + 1);
1397     *mangled += strlen (*mangled);
1398     success = 1;
1399     }
1400     else
1401     {
1402     success = demangle_args (work, mangled, declp);
1403     }
1404     }
1405     */
1406   return (success);
1407 }
1408
1409 static int
1410 arm_pt (work, mangled, n, anchor, args)
1411      struct work_stuff *work;
1412      const char *mangled;
1413      int n;
1414      const char **anchor, **args;
1415 {
1416   /* ARM template? */
1417   if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1418     {
1419       int len;
1420       *args = *anchor + 6;
1421       len = consume_count (args);
1422       if (*args + len == mangled + n && **args == '_')
1423         {
1424           ++*args;
1425           return 1;
1426         }
1427     }
1428   return 0;
1429 }
1430
1431 static void
1432 demangle_arm_pt (work, mangled, n, declp)
1433      struct work_stuff *work;
1434      const char **mangled;
1435      int n;
1436      string *declp;
1437 {
1438   const char *p;
1439   const char *args;
1440   const char *e = *mangled + n;
1441
1442   /* ARM template? */
1443   if (arm_pt (work, *mangled, n, &p, &args))
1444     {
1445       string arg;
1446       string_init (&arg);
1447       string_appendn (declp, *mangled, p - *mangled);
1448       string_append (declp, "<");
1449       /* should do error checking here */
1450       while (args < e) {
1451         string_clear (&arg);
1452         do_type (work, &args, &arg);
1453         string_appends (declp, &arg);
1454         string_append (declp, ",");
1455       }
1456       string_delete (&arg);
1457       --declp->p;
1458       string_append (declp, ">");
1459     }
1460   else
1461     {
1462       string_appendn (declp, *mangled, n);
1463     }
1464   *mangled += n;
1465 }
1466
1467 static int
1468 demangle_class_name (work, mangled, declp)
1469      struct work_stuff *work;
1470      const char **mangled;
1471      string *declp;
1472 {
1473   int n;
1474   int success = 0;
1475
1476   n = consume_count (mangled);
1477   if (strlen (*mangled) >= n)
1478     {
1479       demangle_arm_pt (work, mangled, n, declp);
1480       success = 1;
1481     }
1482
1483   return (success);
1484 }
1485
1486 /*
1487
1488 LOCAL FUNCTION
1489
1490         demangle_class -- demangle a mangled class sequence
1491
1492 SYNOPSIS
1493
1494         static int
1495         demangle_class (struct work_stuff *work, const char **mangled,
1496                         strint *declp)
1497
1498 DESCRIPTION
1499
1500         DECLP points to the buffer into which demangling is being done.
1501
1502         *MANGLED points to the current token to be demangled.  On input,
1503         it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1504         On exit, it points to the next token after the mangled class on
1505         success, or the first unconsumed token on failure.
1506
1507         If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1508         we are demangling a constructor or destructor.  In this case
1509         we prepend "class::class" or "class::~class" to DECLP.
1510
1511         Otherwise, we prepend "class::" to the current DECLP.
1512
1513         Reset the constructor/destructor flags once they have been
1514         "consumed".  This allows demangle_class to be called later during
1515         the same demangling, to do normal class demangling.
1516
1517         Returns 1 if demangling is successful, 0 otherwise.
1518
1519 */
1520
1521 static int
1522 demangle_class (work, mangled, declp)
1523      struct work_stuff *work;
1524      const char **mangled;
1525      string *declp;
1526 {
1527   int success = 0;
1528   string class_name;
1529
1530   string_init (&class_name);
1531   if (demangle_class_name (work, mangled, &class_name))
1532     {
1533       if ((work->constructor & 1) || (work->destructor & 1))
1534         {
1535           string_prepends (declp, &class_name);
1536           if (work -> destructor & 1)
1537             {
1538               string_prepend (declp, "~");
1539               work -> destructor -= 1;
1540             }
1541           else
1542             {
1543               work -> constructor -= 1; 
1544             }
1545         }
1546       string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::");
1547       string_prepends (declp, &class_name);
1548       success = 1;
1549     }
1550   string_delete (&class_name);
1551   return (success);
1552 }
1553
1554 /*
1555
1556 LOCAL FUNCTION
1557
1558         demangle_prefix -- consume the mangled name prefix and find signature
1559
1560 SYNOPSIS
1561
1562         static int
1563         demangle_prefix (struct work_stuff *work, const char **mangled,
1564                          string *declp);
1565
1566 DESCRIPTION
1567
1568         Consume and demangle the prefix of the mangled name.
1569
1570         DECLP points to the string buffer into which demangled output is
1571         placed.  On entry, the buffer is empty.  On exit it contains
1572         the root function name, the demangled operator name, or in some
1573         special cases either nothing or the completely demangled result.
1574
1575         MANGLED points to the current pointer into the mangled name.  As each
1576         token of the mangled name is consumed, it is updated.  Upon entry
1577         the current mangled name pointer points to the first character of
1578         the mangled name.  Upon exit, it should point to the first character
1579         of the signature if demangling was successful, or to the first
1580         unconsumed character if demangling of the prefix was unsuccessful.
1581         
1582         Returns 1 on success, 0 otherwise.
1583  */
1584
1585 static int
1586 demangle_prefix (work, mangled, declp)
1587      struct work_stuff *work;
1588      const char **mangled;
1589      string *declp;
1590 {
1591   int success = 1;
1592   const char *scan;
1593   int i;
1594
1595   if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1596     {
1597       char *marker = strchr (cplus_markers, (*mangled)[8]);
1598       if (marker != NULL && *marker == (*mangled)[10])
1599         {
1600           if ((*mangled)[9] == 'D')
1601             {
1602               /* it's a GNU global destructor to be executed at program exit */
1603               (*mangled) += 11;
1604               work->destructor = 2;
1605               if (gnu_special (work, mangled, declp))
1606                 return success;
1607             }
1608           else if ((*mangled)[9] == 'I')
1609             {
1610               /* it's a GNU global constructor to be executed at program init */
1611               (*mangled) += 11;
1612               work->constructor = 2;
1613               if (gnu_special (work, mangled, declp))
1614                 return success;
1615             }
1616         }
1617     }
1618   else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1619     {
1620       /* it's a ARM global destructor to be executed at program exit */
1621       (*mangled) += 7;
1622       work->destructor = 2;
1623     }
1624   else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1625     {
1626       /* it's a ARM global constructor to be executed at program initial */
1627       (*mangled) += 7;
1628       work->constructor = 2;
1629     }
1630
1631   /*  This block of code is a reduction in strength time optimization
1632       of:
1633       scan = mystrstr (*mangled, "__"); */
1634
1635   {
1636     scan = *mangled;
1637
1638     do {
1639       scan = strchr (scan, '_');
1640     } while (scan != NULL && *++scan != '_');
1641
1642     if (scan != NULL) --scan;
1643   }
1644
1645   if (scan != NULL)
1646     {
1647       /* We found a sequence of two or more '_', ensure that we start at
1648          the last pair in the sequence.  */
1649       i = strspn (scan, "_");
1650       if (i > 2)
1651         {
1652           scan += (i - 2); 
1653         }
1654     }
1655  
1656   if (scan == NULL)
1657     {
1658       success = 0;
1659     }
1660   else if (work -> static_type)
1661     {
1662       if (!isdigit (scan[0]) && (scan[0] != 't'))
1663         {
1664           success = 0;
1665         }
1666     }
1667   else if ((scan == *mangled)
1668            && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')
1669                || (scan[2] == 'H')))
1670     {
1671       /* The ARM says nothing about the mangling of local variables.
1672          But cfront mangles local variables by prepending __<nesting_level>
1673          to them. As an extension to ARM demangling we handle this case.  */
1674       if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
1675         {
1676           *mangled = scan + 2;
1677           consume_count (mangled);
1678           string_append (declp, *mangled);
1679           *mangled += strlen (*mangled);
1680           success = 1; 
1681         }
1682       else
1683         {
1684           /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
1685              names like __Q2_3foo3bar for nested type names.  So don't accept
1686              this style of constructor for cfront demangling.  A GNU
1687              style member-template constructor starts with 'H'. */
1688           if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
1689             work -> constructor += 1;
1690           *mangled = scan + 2;
1691         }
1692     }
1693   else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
1694     {
1695       /* Mangled name starts with "__".  Skip over any leading '_' characters,
1696          then find the next "__" that separates the prefix from the signature.
1697          */
1698       if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
1699           || (arm_special (work, mangled, declp) == 0))
1700         {
1701           while (*scan == '_')
1702             {
1703               scan++;
1704             }
1705           if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
1706             {
1707               /* No separator (I.E. "__not_mangled"), or empty signature
1708                  (I.E. "__not_mangled_either__") */
1709               success = 0;
1710             }
1711           else
1712             {
1713               demangle_function_name (work, mangled, declp, scan);
1714             }
1715         }
1716     }
1717   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
1718     {
1719       /* Cfront-style parameterized type.  Handled later as a signature.  */
1720       success = 1;
1721
1722       /* ARM template? */
1723       demangle_arm_pt (work, mangled, strlen (*mangled), declp);
1724     }
1725   else if (*(scan + 2) != '\0')
1726     {
1727       /* Mangled name does not start with "__" but does have one somewhere
1728          in there with non empty stuff after it.  Looks like a global
1729          function name.  */
1730       demangle_function_name (work, mangled, declp, scan);
1731     }
1732   else
1733     {
1734       /* Doesn't look like a mangled name */
1735       success = 0;
1736     }
1737
1738   if (!success && (work->constructor == 2 || work->destructor == 2))
1739     {
1740       string_append (declp, *mangled);
1741       *mangled += strlen (*mangled);
1742       success = 1;
1743     } 
1744   return (success);
1745 }
1746
1747 /*
1748
1749 LOCAL FUNCTION
1750
1751         gnu_special -- special handling of gnu mangled strings
1752
1753 SYNOPSIS
1754
1755         static int
1756         gnu_special (struct work_stuff *work, const char **mangled,
1757                      string *declp);
1758
1759
1760 DESCRIPTION
1761
1762         Process some special GNU style mangling forms that don't fit
1763         the normal pattern.  For example:
1764
1765                 _$_3foo         (destructor for class foo)
1766                 _vt$foo         (foo virtual table)
1767                 _vt$foo$bar     (foo::bar virtual table)
1768                 __vt_foo        (foo virtual table, new style with thunks)
1769                 _3foo$varname   (static data member)
1770                 _Q22rs2tu$vw    (static data member)
1771                 __t6vector1Zii  (constructor with template)
1772                 __thunk_4__$_7ostream (virtual function thunk)
1773  */
1774
1775 static int
1776 gnu_special (work, mangled, declp)
1777      struct work_stuff *work;
1778      const char **mangled;
1779      string *declp;
1780 {
1781   int n;
1782   int success = 1;
1783   const char *p;
1784
1785   if ((*mangled)[0] == '_'
1786       && strchr (cplus_markers, (*mangled)[1]) != NULL
1787       && (*mangled)[2] == '_')
1788     {
1789       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1790       (*mangled) += 3;
1791       work -> destructor += 1;
1792     }
1793   else if ((*mangled)[0] == '_'
1794            && (((*mangled)[1] == '_'
1795                 && (*mangled)[2] == 'v'
1796                 && (*mangled)[3] == 't'
1797                 && (*mangled)[4] == '_')
1798                || ((*mangled)[1] == 'v'
1799                    && (*mangled)[2] == 't'
1800                    && strchr (cplus_markers, (*mangled)[3]) != NULL)))
1801     {
1802       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1803          and create the decl.  Note that we consume the entire mangled
1804          input string, which means that demangle_signature has no work
1805          to do.  */
1806       if ((*mangled)[2] == 'v')
1807         (*mangled) += 5; /* New style, with thunks: "__vt_" */
1808       else
1809         (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1810       while (**mangled != '\0')
1811         {
1812           p = strpbrk (*mangled, cplus_markers);
1813           switch (**mangled)
1814             {
1815             case 'Q':
1816               success = demangle_qualified (work, mangled, declp, 0, 1);
1817               break;
1818             case 't':
1819               success = demangle_template (work, mangled, declp, 0, 1);
1820               break;
1821             default:
1822               if (isdigit(*mangled[0]))
1823                 {
1824                   n = consume_count(mangled);
1825                 }
1826               else
1827                 {
1828                   n = strcspn (*mangled, cplus_markers);
1829                 }
1830               string_appendn (declp, *mangled, n);
1831               (*mangled) += n;
1832             }
1833
1834           if (success && ((p == NULL) || (p == *mangled)))
1835             {
1836               if (p != NULL)
1837                 {
1838                   string_append (declp,
1839                                  (work -> options & DMGL_JAVA) ? "." : "::");
1840                   (*mangled)++;
1841                 }
1842             }
1843           else
1844             {
1845               success = 0;
1846               break;
1847             }
1848         }
1849       if (success)
1850         string_append (declp, " virtual table");
1851     }
1852   else if ((*mangled)[0] == '_'
1853            && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
1854            && (p = strpbrk (*mangled, cplus_markers)) != NULL)
1855     {
1856       /* static data member, "_3foo$varname" for example */
1857       (*mangled)++;
1858       switch (**mangled)
1859         {
1860         case 'Q':
1861           success = demangle_qualified (work, mangled, declp, 0, 1);
1862           break;
1863         case 't':
1864           success = demangle_template (work, mangled, declp, 0, 1);
1865           break;
1866         default:
1867           n = consume_count (mangled);
1868           string_appendn (declp, *mangled, n);
1869           (*mangled) += n;
1870         }
1871       if (success && (p == *mangled))
1872         {
1873           /* Consumed everything up to the cplus_marker, append the
1874              variable name.  */
1875           (*mangled)++;
1876           string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::");
1877           n = strlen (*mangled);
1878           string_appendn (declp, *mangled, n);
1879           (*mangled) += n;
1880         }
1881       else
1882         {
1883           success = 0;
1884         }
1885     }
1886   else if (strncmp (*mangled, "__thunk_", 8) == 0)
1887     {
1888       int delta = ((*mangled) += 8, consume_count (mangled));
1889       char *method = cplus_demangle (++*mangled, work->options);
1890       if (method)
1891         {
1892           char buf[50];
1893           sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
1894           string_append (declp, buf);
1895           string_append (declp, method);
1896           free (method);
1897           n = strlen (*mangled);
1898           (*mangled) += n;
1899         }
1900       else
1901         {
1902           success = 0;
1903         }
1904     }
1905   else if (strncmp (*mangled, "__t", 3) == 0
1906            && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
1907     {
1908       p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
1909       (*mangled) += 4;
1910       switch (**mangled)
1911         {
1912         case 'Q':
1913           success = demangle_qualified (work, mangled, declp, 0, 1);
1914           break;
1915         case 't':
1916           success = demangle_template (work, mangled, declp, 0, 1);
1917           break;
1918         default:
1919           success = demangle_fund_type (work, mangled, declp);
1920           break;
1921         }
1922       if (success && **mangled != '\0')
1923         success = 0;
1924       if (success)
1925         string_append (declp, p);
1926     }
1927   else
1928     {
1929       success = 0;
1930     }
1931   return (success);
1932 }
1933
1934 /*
1935
1936 LOCAL FUNCTION
1937
1938         arm_special -- special handling of ARM/lucid mangled strings
1939
1940 SYNOPSIS
1941
1942         static int
1943         arm_special (struct work_stuff *work, const char **mangled,
1944                         string *declp);
1945
1946
1947 DESCRIPTION
1948
1949         Process some special ARM style mangling forms that don't fit
1950         the normal pattern.  For example:
1951
1952                 __vtbl__3foo            (foo virtual table)
1953                 __vtbl__3foo__3bar      (bar::foo virtual table)
1954
1955  */
1956
1957 static int
1958 arm_special (work, mangled, declp)
1959      struct work_stuff *work;
1960      const char **mangled;
1961      string *declp;
1962 {
1963   int n;
1964   int success = 1;
1965   const char *scan;
1966
1967   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
1968     {
1969       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
1970          and create the decl.  Note that we consume the entire mangled
1971          input string, which means that demangle_signature has no work
1972          to do.  */
1973       scan = *mangled + ARM_VTABLE_STRLEN;
1974       while (*scan != '\0')        /* first check it can be demangled */
1975         {
1976           n = consume_count (&scan);
1977           if (n==0)
1978             {
1979               return (0);           /* no good */
1980             }
1981           scan += n;
1982           if (scan[0] == '_' && scan[1] == '_')
1983             {
1984               scan += 2;
1985             }
1986         }
1987       (*mangled) += ARM_VTABLE_STRLEN;
1988       while (**mangled != '\0')
1989         {
1990           n = consume_count (mangled);
1991           string_prependn (declp, *mangled, n);
1992           (*mangled) += n;
1993           if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
1994             {
1995               string_prepend (declp, "::");
1996               (*mangled) += 2;
1997             }
1998         }
1999       string_append (declp, " virtual table");
2000     }
2001   else
2002     {
2003       success = 0;
2004     }
2005   return (success);
2006 }
2007
2008 /*
2009
2010 LOCAL FUNCTION
2011
2012         demangle_qualified -- demangle 'Q' qualified name strings
2013
2014 SYNOPSIS
2015
2016         static int
2017         demangle_qualified (struct work_stuff *, const char *mangled,
2018                             string *result, int isfuncname, int append);
2019
2020 DESCRIPTION
2021
2022         Demangle a qualified name, such as "Q25Outer5Inner" which is
2023         the mangled form of "Outer::Inner".  The demangled output is
2024         prepended or appended to the result string according to the
2025         state of the append flag.
2026
2027         If isfuncname is nonzero, then the qualified name we are building
2028         is going to be used as a member function name, so if it is a
2029         constructor or destructor function, append an appropriate
2030         constructor or destructor name.  I.E. for the above example,
2031         the result for use as a constructor is "Outer::Inner::Inner"
2032         and the result for use as a destructor is "Outer::Inner::~Inner".
2033
2034 BUGS
2035
2036         Numeric conversion is ASCII dependent (FIXME).
2037
2038  */
2039
2040 static int
2041 demangle_qualified (work, mangled, result, isfuncname, append)
2042      struct work_stuff *work;
2043      const char **mangled;
2044      string *result;
2045      int isfuncname;
2046      int append;
2047 {
2048   int qualifiers;
2049   int namelength;
2050   int success = 1;
2051   const char *p;
2052   char num[2];
2053   string temp;
2054
2055   string_init (&temp);
2056   switch ((*mangled)[1])
2057     {
2058     case '_':
2059       /* GNU mangled name with more than 9 classes.  The count is preceded
2060          by an underscore (to distinguish it from the <= 9 case) and followed
2061          by an underscore.  */
2062       p = *mangled + 2;
2063       qualifiers = atoi (p);
2064       if (!isdigit (*p) || *p == '0')
2065         success = 0;
2066
2067       /* Skip the digits.  */
2068       while (isdigit (*p))
2069         ++p;
2070
2071       if (*p != '_')
2072         success = 0;
2073
2074       *mangled = p + 1;
2075       break;
2076
2077     case '1':
2078     case '2':
2079     case '3':
2080     case '4':
2081     case '5':
2082     case '6':
2083     case '7':
2084     case '8':
2085     case '9':
2086       /* The count is in a single digit.  */
2087       num[0] = (*mangled)[1];
2088       num[1] = '\0';
2089       qualifiers = atoi (num);
2090
2091       /* If there is an underscore after the digit, skip it.  This is
2092          said to be for ARM-qualified names, but the ARM makes no
2093          mention of such an underscore.  Perhaps cfront uses one.  */
2094       if ((*mangled)[2] == '_')
2095         {
2096           (*mangled)++;
2097         }
2098       (*mangled) += 2;
2099       break;
2100
2101     case '0':
2102     default:
2103       success = 0;
2104     }
2105
2106   if (!success)
2107     return success;
2108
2109   /* Pick off the names and collect them in the temp buffer in the order
2110      in which they are found, separated by '::'.  */
2111
2112   while (qualifiers-- > 0)
2113     {
2114       if (*mangled[0] == '_') 
2115         *mangled = *mangled + 1;
2116       if (*mangled[0] == 't')
2117         {
2118           success = demangle_template(work, mangled, &temp, 0, 1);
2119           if (!success) break;
2120         }
2121       else if (*mangled[0] == 'X')
2122         {
2123           success = do_type (work, mangled, &temp);
2124           if (!success) break;
2125         }
2126       else
2127         {       
2128           namelength = consume_count (mangled);
2129           if (strlen (*mangled) < namelength)
2130             {
2131               /* Simple sanity check failed */
2132               success = 0;
2133               break;
2134             }
2135           string_appendn (&temp, *mangled, namelength);
2136           *mangled += namelength;
2137         }
2138       if (qualifiers > 0)
2139         {
2140           string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2141         }
2142     }
2143
2144   /* If we are using the result as a function name, we need to append
2145      the appropriate '::' separated constructor or destructor name.
2146      We do this here because this is the most convenient place, where
2147      we already have a pointer to the name and the length of the name.  */
2148
2149   if (isfuncname && (work->constructor & 1 || work->destructor & 1))
2150     {
2151       string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2152       if (work -> destructor & 1)
2153         {
2154           string_append (&temp, "~");
2155         }
2156       string_appendn (&temp, (*mangled) - namelength, namelength);
2157     }
2158
2159   /* Now either prepend the temp buffer to the result, or append it, 
2160      depending upon the state of the append flag.  */
2161
2162   if (append)
2163     {
2164       string_appends (result, &temp);
2165     }
2166   else
2167     {
2168       if (!STRING_EMPTY (result))
2169         {
2170           string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
2171         }
2172       string_prepends (result, &temp);
2173     }
2174
2175   string_delete (&temp);
2176   return (success);
2177 }
2178
2179 /*
2180
2181 LOCAL FUNCTION
2182
2183         get_count -- convert an ascii count to integer, consuming tokens
2184
2185 SYNOPSIS
2186
2187         static int
2188         get_count (const char **type, int *count)
2189
2190 DESCRIPTION
2191
2192         Return 0 if no conversion is performed, 1 if a string is converted.
2193 */
2194
2195 static int
2196 get_count (type, count)
2197      const char **type;
2198      int *count;
2199 {
2200   const char *p;
2201   int n;
2202
2203   if (!isdigit (**type))
2204     {
2205       return (0);
2206     }
2207   else
2208     {
2209       *count = **type - '0';
2210       (*type)++;
2211       if (isdigit (**type))
2212         {
2213           p = *type;
2214           n = *count;
2215           do 
2216             {
2217               n *= 10;
2218               n += *p - '0';
2219               p++;
2220             } 
2221           while (isdigit (*p));
2222           if (*p == '_')
2223             {
2224               *type = p + 1;
2225               *count = n;
2226             }
2227         }
2228     }
2229   return (1);
2230 }
2231
2232 /* result will be initialised here; it will be freed on failure */
2233
2234 static int
2235 do_type (work, mangled, result)
2236      struct work_stuff *work;
2237      const char **mangled;
2238      string *result;
2239 {
2240   int n;
2241   int done;
2242   int success;
2243   string decl;
2244   const char *remembered_type;
2245   int constp;
2246   int volatilep;
2247
2248   string_init (&decl);
2249   string_init (result);
2250
2251   done = 0;
2252   success = 1;
2253   while (success && !done)
2254     {
2255       int member;
2256       switch (**mangled)
2257         {
2258
2259           /* A pointer type */
2260         case 'P':
2261         case 'p':
2262           (*mangled)++;
2263           if (! (work -> options & DMGL_JAVA))
2264             string_prepend (&decl, "*");
2265           break;
2266
2267           /* A reference type */
2268         case 'R':
2269           (*mangled)++;
2270           string_prepend (&decl, "&");
2271           break;
2272
2273           /* An array */
2274         case 'A':
2275           {
2276             const char *p = ++(*mangled);
2277
2278             string_prepend (&decl, "(");
2279             string_append (&decl, ")[");
2280             /* Copy anything up until the next underscore (the size of the
2281                array).  */
2282             while (**mangled && **mangled != '_')
2283               ++(*mangled);
2284             if (**mangled == '_')
2285               {
2286                 string_appendn (&decl, p, *mangled - p);
2287                 string_append (&decl, "]");             
2288                 *mangled += 1;
2289               }
2290             else
2291               success = 0;
2292             break;
2293           }
2294
2295         /* A back reference to a previously seen type */
2296         case 'T':
2297           (*mangled)++;
2298           if (!get_count (mangled, &n) || n >= work -> ntypes)
2299             {
2300               success = 0;
2301             }
2302           else
2303             {
2304               remembered_type = work -> typevec[n];
2305               mangled = &remembered_type;
2306             }
2307           break;
2308
2309           /* A function */
2310         case 'F':
2311           (*mangled)++;
2312           if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
2313             {
2314               string_prepend (&decl, "(");
2315               string_append (&decl, ")");
2316             }
2317           /* After picking off the function args, we expect to either find the
2318              function return type (preceded by an '_') or the end of the
2319              string.  */
2320           if (!demangle_args (work, mangled, &decl)
2321               || (**mangled != '_' && **mangled != '\0'))
2322             {
2323               success = 0;
2324             }
2325           if (success && (**mangled == '_'))
2326             {
2327               (*mangled)++;
2328             }
2329           break;
2330
2331         case 'M':
2332         case 'O':
2333           {
2334             constp = 0;
2335             volatilep = 0;
2336
2337             member = **mangled == 'M';
2338             (*mangled)++;
2339             if (!isdigit (**mangled) && **mangled != 't')
2340               {
2341                 success = 0;
2342                 break;
2343               }
2344
2345             string_append (&decl, ")");
2346             string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::");
2347             if (isdigit (**mangled)) 
2348               {
2349                 n = consume_count (mangled);
2350                 if (strlen (*mangled) < n)
2351                   {
2352                     success = 0;
2353                     break;
2354                   }
2355                 string_prependn (&decl, *mangled, n);
2356                 *mangled += n;
2357               }
2358             else
2359               {
2360                 string temp;
2361                 string_init (&temp);
2362                 success = demangle_template (work, mangled, &temp, NULL, 1);
2363                 if (success)
2364                   {
2365                     string_prependn (&decl, temp.b, temp.p - temp.b);
2366                     string_clear (&temp);
2367                   }
2368                 else
2369                   break;
2370               }
2371             string_prepend (&decl, "(");
2372             if (member)
2373               {
2374                 if (**mangled == 'C')
2375                   {
2376                     (*mangled)++;
2377                     constp = 1;
2378                   }
2379                 if (**mangled == 'V')
2380                   {
2381                     (*mangled)++;
2382                     volatilep = 1;
2383                   }
2384                 if (*(*mangled)++ != 'F')
2385                   {
2386                     success = 0;
2387                     break;
2388                   }
2389               }
2390             if ((member && !demangle_args (work, mangled, &decl))
2391                 || **mangled != '_')
2392               {
2393                 success = 0;
2394                 break;
2395               }
2396             (*mangled)++;
2397             if (! PRINT_ANSI_QUALIFIERS)
2398               {
2399                 break;
2400               }
2401             if (constp)
2402               {
2403                 APPEND_BLANK (&decl);
2404                 string_append (&decl, "const");
2405               }
2406             if (volatilep)
2407               {
2408                 APPEND_BLANK (&decl);
2409                 string_append (&decl, "volatile");
2410               }
2411             break;
2412           }
2413         case 'G':
2414           (*mangled)++;
2415           break;
2416
2417         case 'C':
2418           (*mangled)++;
2419           /*
2420             if ((*mangled)[1] == 'P')
2421             {
2422             */
2423           if (PRINT_ANSI_QUALIFIERS)
2424             {
2425               if (!STRING_EMPTY (&decl))
2426                 {
2427                   string_prepend (&decl, " ");
2428                 }
2429               string_prepend (&decl, "const");
2430             }
2431           break;
2432           /*
2433             }
2434             */
2435
2436           /* fall through */
2437         default:
2438           done = 1;
2439           break;
2440         }
2441     }
2442
2443   switch (**mangled)
2444     {
2445       /* A qualified name, such as "Outer::Inner".  */
2446     case 'Q':
2447       success = demangle_qualified (work, mangled, result, 0, 1);
2448       break;
2449
2450     case 'X':
2451     case 'Y':
2452       /* A template parm.  We substitute the corresponding argument. */
2453       {
2454         int idx;
2455
2456         (*mangled)++;
2457         idx = consume_count_with_underscores (mangled);
2458
2459         if (idx == -1 
2460             || (work->tmpl_argvec && idx >= work->ntmpl_args)
2461             || consume_count_with_underscores (mangled) == -1)
2462           {
2463             success = 0;
2464             break;
2465           }
2466
2467         if (work->tmpl_argvec)
2468           string_append (result, work->tmpl_argvec[idx]);
2469         else
2470           {
2471             char buf[10];
2472             sprintf(buf, "T%d", idx);
2473             string_append (result, buf);
2474           }
2475
2476         success = 1;
2477       }
2478     break;
2479
2480     default:
2481       success = demangle_fund_type (work, mangled, result);
2482       break;
2483     }
2484
2485   if (success)
2486     {
2487       if (!STRING_EMPTY (&decl))
2488         {
2489           string_append (result, " ");
2490           string_appends (result, &decl);
2491         }
2492     }
2493   else
2494     {
2495       string_delete (result);
2496     }
2497   string_delete (&decl);
2498   return (success);
2499 }
2500
2501 /* Given a pointer to a type string that represents a fundamental type
2502    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2503    string in which the demangled output is being built in RESULT, and
2504    the WORK structure, decode the types and add them to the result.
2505
2506    For example:
2507
2508         "Ci"    =>      "const int"
2509         "Sl"    =>      "signed long"
2510         "CUs"   =>      "const unsigned short"
2511
2512    */
2513
2514 static int
2515 demangle_fund_type (work, mangled, result)
2516      struct work_stuff *work;
2517      const char **mangled;
2518      string *result;
2519 {
2520   int done = 0;
2521   int success = 1;
2522
2523   /* First pick off any type qualifiers.  There can be more than one.  */
2524
2525   while (!done)
2526     {
2527       switch (**mangled)
2528         {
2529         case 'C':
2530           (*mangled)++;
2531           if (PRINT_ANSI_QUALIFIERS)
2532             {
2533               APPEND_BLANK (result);
2534               string_append (result, "const");
2535             }
2536           break;
2537         case 'U':
2538           (*mangled)++;
2539           APPEND_BLANK (result);
2540           string_append (result, "unsigned");
2541           break;
2542         case 'S': /* signed char only */
2543           (*mangled)++;
2544           APPEND_BLANK (result);
2545           string_append (result, "signed");
2546           break;
2547         case 'V':
2548           (*mangled)++;
2549           if (PRINT_ANSI_QUALIFIERS)
2550             {
2551               APPEND_BLANK (result);
2552               string_append (result, "volatile");
2553             }
2554           break;
2555         case 'J':
2556           (*mangled)++;
2557           APPEND_BLANK (result);
2558           string_append (result, "__complex");
2559           break;
2560         default:
2561           done = 1;
2562           break;
2563         }
2564     }
2565
2566   /* Now pick off the fundamental type.  There can be only one.  */
2567
2568   switch (**mangled)
2569     {
2570     case '\0':
2571     case '_':
2572       break;
2573     case 'v':
2574       (*mangled)++;
2575       APPEND_BLANK (result);
2576       string_append (result, "void");
2577       break;
2578     case 'x':
2579       (*mangled)++;
2580       APPEND_BLANK (result);
2581       string_append (result, "long long");
2582       break;
2583     case 'l':
2584       (*mangled)++;
2585       APPEND_BLANK (result);
2586       string_append (result, "long");
2587       break;
2588     case 'i':
2589       (*mangled)++;
2590       APPEND_BLANK (result);
2591       string_append (result, "int");
2592       break;
2593     case 's':
2594       (*mangled)++;
2595       APPEND_BLANK (result);
2596       string_append (result, "short");
2597       break;
2598     case 'b':
2599       (*mangled)++;
2600       APPEND_BLANK (result);
2601       string_append (result, "bool");
2602       break;
2603     case 'c':
2604       (*mangled)++;
2605       APPEND_BLANK (result);
2606       string_append (result, "char");
2607       break;
2608     case 'w':
2609       (*mangled)++;
2610       APPEND_BLANK (result);
2611       string_append (result, "wchar_t");
2612       break;
2613     case 'r':
2614       (*mangled)++;
2615       APPEND_BLANK (result);
2616       string_append (result, "long double");
2617       break;
2618     case 'd':
2619       (*mangled)++;
2620       APPEND_BLANK (result);
2621       string_append (result, "double");
2622       break;
2623     case 'f':
2624       (*mangled)++;
2625       APPEND_BLANK (result);
2626       string_append (result, "float");
2627       break;
2628     case 'G':
2629       (*mangled)++;
2630       if (!isdigit (**mangled))
2631         {
2632           success = 0;
2633           break;
2634         }
2635       /* fall through */
2636       /* An explicit type, such as "6mytype" or "7integer" */
2637     case '0':
2638     case '1':
2639     case '2':
2640     case '3':
2641     case '4':
2642     case '5':
2643     case '6':
2644     case '7':
2645     case '8':
2646     case '9':
2647       APPEND_BLANK (result);
2648       if (!demangle_class_name (work, mangled, result)) {
2649         --result->p;
2650         success = 0;
2651       }
2652       break;
2653     case 't':
2654       success = demangle_template(work,mangled, result, 0, 1);
2655       break;
2656     default:
2657       success = 0;
2658       break;
2659     }
2660
2661   return (success);
2662 }
2663
2664 /* `result' will be initialized in do_type; it will be freed on failure */
2665
2666 static int
2667 do_arg (work, mangled, result)
2668      struct work_stuff *work;
2669      const char **mangled;
2670      string *result;
2671 {
2672   const char *start = *mangled;
2673
2674   if (!do_type (work, mangled, result))
2675     {
2676       return (0);
2677     }
2678   else
2679     {
2680       remember_type (work, start, *mangled - start);
2681       return (1);
2682     }
2683 }
2684
2685 static void
2686 remember_type (work, start, len)
2687      struct work_stuff *work;
2688      const char *start;
2689      int len;
2690 {
2691   char *tem;
2692
2693   if (work -> ntypes >= work -> typevec_size)
2694     {
2695       if (work -> typevec_size == 0)
2696         {
2697           work -> typevec_size = 3;
2698           work -> typevec
2699             = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
2700         }
2701       else
2702         {
2703           work -> typevec_size *= 2;
2704           work -> typevec
2705             = (char **) xrealloc ((char *)work -> typevec,
2706                                   sizeof (char *) * work -> typevec_size);
2707         }
2708     }
2709   tem = xmalloc (len + 1);
2710   memcpy (tem, start, len);
2711   tem[len] = '\0';
2712   work -> typevec[work -> ntypes++] = tem;
2713 }
2714
2715 /* Forget the remembered types, but not the type vector itself.  */
2716
2717 static void
2718 forget_types (work)
2719      struct work_stuff *work;
2720 {
2721   int i;
2722
2723   while (work -> ntypes > 0)
2724     {
2725       i = --(work -> ntypes);
2726       if (work -> typevec[i] != NULL)
2727         {
2728           free (work -> typevec[i]);
2729           work -> typevec[i] = NULL;
2730         }
2731     }
2732 }
2733
2734 /* Process the argument list part of the signature, after any class spec
2735    has been consumed, as well as the first 'F' character (if any).  For
2736    example:
2737
2738    "__als__3fooRT0"             =>      process "RT0"
2739    "complexfunc5__FPFPc_PFl_i"  =>      process "PFPc_PFl_i"
2740
2741    DECLP must be already initialised, usually non-empty.  It won't be freed
2742    on failure.
2743
2744    Note that g++ differs significantly from ARM and lucid style mangling
2745    with regards to references to previously seen types.  For example, given
2746    the source fragment:
2747
2748      class foo {
2749        public:
2750        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
2751      };
2752
2753      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2754      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
2755
2756    g++ produces the names:
2757
2758      __3fooiRT0iT2iT2
2759      foo__FiR3fooiT1iT1
2760
2761    while lcc (and presumably other ARM style compilers as well) produces:
2762
2763      foo__FiR3fooT1T2T1T2
2764      __ct__3fooFiR3fooT1T2T1T2
2765
2766    Note that g++ bases it's type numbers starting at zero and counts all
2767    previously seen types, while lucid/ARM bases it's type numbers starting
2768    at one and only considers types after it has seen the 'F' character
2769    indicating the start of the function args.  For lucid/ARM style, we
2770    account for this difference by discarding any previously seen types when
2771    we see the 'F' character, and subtracting one from the type number
2772    reference.
2773
2774  */
2775
2776 static int
2777 demangle_args (work, mangled, declp)
2778      struct work_stuff *work;
2779      const char **mangled;
2780      string *declp;
2781 {
2782   string arg;
2783   int need_comma = 0;
2784   int r;
2785   int t;
2786   const char *tem;
2787   char temptype;
2788
2789   if (PRINT_ARG_TYPES)
2790     {
2791       string_append (declp, "(");
2792       if (**mangled == '\0')
2793         {
2794           string_append (declp, "void");
2795         }
2796     }
2797
2798   while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
2799     {
2800       if ((**mangled == 'N') || (**mangled == 'T'))
2801         {
2802           temptype = *(*mangled)++;
2803           
2804           if (temptype == 'N')
2805             {
2806               if (!get_count (mangled, &r))
2807                 {
2808                   return (0);
2809                 }
2810             }
2811           else
2812             {
2813               r = 1;
2814             }
2815           if (ARM_DEMANGLING && work -> ntypes >= 10)
2816             {
2817               /* If we have 10 or more types we might have more than a 1 digit
2818                  index so we'll have to consume the whole count here. This
2819                  will lose if the next thing is a type name preceded by a
2820                  count but it's impossible to demangle that case properly
2821                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
2822                  Pc, ...)"  or "(..., type12, char *, ...)" */
2823               if ((t = consume_count(mangled)) == 0)
2824                 {
2825                   return (0);
2826                 }
2827             }
2828           else
2829             {
2830               if (!get_count (mangled, &t))
2831                 {
2832                   return (0);
2833                 }
2834             }
2835           if (LUCID_DEMANGLING || ARM_DEMANGLING)
2836             {
2837               t--;
2838             }
2839           /* Validate the type index.  Protect against illegal indices from
2840              malformed type strings.  */
2841           if ((t < 0) || (t >= work -> ntypes))
2842             {
2843               return (0);
2844             }
2845           while (--r >= 0)
2846             {
2847               tem = work -> typevec[t];
2848               if (need_comma && PRINT_ARG_TYPES)
2849                 {
2850                   string_append (declp, ", ");
2851                 }
2852               if (!do_arg (work, &tem, &arg))
2853                 {
2854                   return (0);
2855                 }
2856               if (PRINT_ARG_TYPES)
2857                 {
2858                   string_appends (declp, &arg);
2859                 }
2860               string_delete (&arg);
2861               need_comma = 1;
2862             }
2863         }
2864       else
2865         {
2866           if (need_comma & PRINT_ARG_TYPES)
2867             {
2868               string_append (declp, ", ");
2869             }
2870           if (!do_arg (work, mangled, &arg))
2871             {
2872               return (0);
2873             }
2874           if (PRINT_ARG_TYPES)
2875             {
2876               string_appends (declp, &arg);
2877             }
2878           string_delete (&arg);
2879           need_comma = 1;
2880         }
2881     }
2882
2883   if (**mangled == 'e')
2884     {
2885       (*mangled)++;
2886       if (PRINT_ARG_TYPES)
2887         {
2888           if (need_comma)
2889             {
2890               string_append (declp, ",");
2891             }
2892           string_append (declp, "...");
2893         }
2894     }
2895
2896   if (PRINT_ARG_TYPES)
2897     {
2898       string_append (declp, ")");
2899     }
2900   return (1);
2901 }
2902
2903 static void
2904 demangle_function_name (work, mangled, declp, scan)
2905      struct work_stuff *work;
2906      const char **mangled;
2907      string *declp;
2908      const char *scan;
2909 {
2910   int i;
2911   int len;
2912   string type;
2913   const char *tem;
2914
2915   string_appendn (declp, (*mangled), scan - (*mangled));
2916   string_need (declp, 1);
2917   *(declp -> p) = '\0';
2918
2919   /* Consume the function name, including the "__" separating the name
2920      from the signature.  We are guaranteed that SCAN points to the
2921      separator.  */
2922
2923   (*mangled) = scan + 2;
2924
2925   if (LUCID_DEMANGLING || ARM_DEMANGLING)
2926     {
2927
2928       /* See if we have an ARM style constructor or destructor operator.
2929          If so, then just record it, clear the decl, and return.
2930          We can't build the actual constructor/destructor decl until later,
2931          when we recover the class name from the signature.  */
2932
2933       if (strcmp (declp -> b, "__ct") == 0)
2934         {
2935           work -> constructor += 1;
2936           string_clear (declp);
2937           return;
2938         }
2939       else if (strcmp (declp -> b, "__dt") == 0)
2940         {
2941           work -> destructor += 1;
2942           string_clear (declp);
2943           return;
2944         }
2945     }
2946
2947   if (declp->p - declp->b >= 3 
2948       && declp->b[0] == 'o'
2949       && declp->b[1] == 'p'
2950       && strchr (cplus_markers, declp->b[2]) != NULL)
2951     {
2952       /* see if it's an assignment expression */
2953       if (declp->p - declp->b >= 10 /* op$assign_ */
2954           && memcmp (declp->b + 3, "assign_", 7) == 0)
2955         {
2956           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2957             {
2958               len = declp->p - declp->b - 10;
2959               if (strlen (optable[i].in) == len
2960                   && memcmp (optable[i].in, declp->b + 10, len) == 0)
2961                 {
2962                   string_clear (declp);
2963                   string_append (declp, "operator");
2964                   string_append (declp, optable[i].out);
2965                   string_append (declp, "=");
2966                   break;
2967                 }
2968             }
2969         }
2970       else
2971         {
2972           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
2973             {
2974               int len = declp->p - declp->b - 3;
2975               if (strlen (optable[i].in) == len 
2976                   && memcmp (optable[i].in, declp->b + 3, len) == 0)
2977                 {
2978                   string_clear (declp);
2979                   string_append (declp, "operator");
2980                   string_append (declp, optable[i].out);
2981                   break;
2982                 }
2983             }
2984         }
2985     }
2986   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
2987            && strchr (cplus_markers, declp->b[4]) != NULL)
2988     {
2989       /* type conversion operator */
2990       tem = declp->b + 5;
2991       if (do_type (work, &tem, &type))
2992         {
2993           string_clear (declp);
2994           string_append (declp, "operator ");
2995           string_appends (declp, &type);
2996           string_delete (&type);
2997         }
2998     }
2999   else if (declp->b[0] == '_' && declp->b[1] == '_'
3000            && declp->b[2] == 'o' && declp->b[3] == 'p')
3001     {
3002       /* ANSI.  */
3003       /* type conversion operator.  */
3004       tem = declp->b + 4;
3005       if (do_type (work, &tem, &type))
3006         {
3007           string_clear (declp);
3008           string_append (declp, "operator ");
3009           string_appends (declp, &type);
3010           string_delete (&type);
3011         }
3012     }
3013   else if (declp->b[0] == '_' && declp->b[1] == '_'
3014            && declp->b[2] >= 'a' && declp->b[2] <= 'z'
3015            && declp->b[3] >= 'a' && declp->b[3] <= 'z')
3016     {
3017       if (declp->b[4] == '\0')
3018         {
3019           /* Operator.  */
3020           for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3021             {
3022               if (strlen (optable[i].in) == 2
3023                   && memcmp (optable[i].in, declp->b + 2, 2) == 0)
3024                 {
3025                   string_clear (declp);
3026                   string_append (declp, "operator");
3027                   string_append (declp, optable[i].out);
3028                   break;
3029                 }
3030             }
3031         }
3032       else
3033         {
3034           if (declp->b[2] == 'a' && declp->b[5] == '\0')
3035             {
3036               /* Assignment.  */
3037               for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3038                 {
3039                   if (strlen (optable[i].in) == 3
3040                       && memcmp (optable[i].in, declp->b + 2, 3) == 0)
3041                     {
3042                       string_clear (declp);
3043                       string_append (declp, "operator");
3044                       string_append (declp, optable[i].out);
3045                       break;
3046                     }                 
3047                 }
3048             }
3049         }
3050     }
3051 }
3052
3053 /* a mini string-handling package */
3054
3055 static void
3056 string_need (s, n)
3057      string *s;
3058      int n;
3059 {
3060   int tem;
3061
3062   if (s->b == NULL)
3063     {
3064       if (n < 32)
3065         {
3066           n = 32;
3067         }
3068       s->p = s->b = xmalloc (n);
3069       s->e = s->b + n;
3070     }
3071   else if (s->e - s->p < n)
3072     {
3073       tem = s->p - s->b;
3074       n += tem;
3075       n *= 2;
3076       s->b = xrealloc (s->b, n);
3077       s->p = s->b + tem;
3078       s->e = s->b + n;
3079     }
3080 }
3081
3082 static void
3083 string_delete (s)
3084      string *s;
3085 {
3086   if (s->b != NULL)
3087     {
3088       free (s->b);
3089       s->b = s->e = s->p = NULL;
3090     }
3091 }
3092
3093 static void
3094 string_init (s)
3095      string *s;
3096 {
3097   s->b = s->p = s->e = NULL;
3098 }
3099
3100 static void 
3101 string_clear (s)
3102      string *s;
3103 {
3104   s->p = s->b;
3105 }
3106
3107 #if 0
3108
3109 static int
3110 string_empty (s)
3111      string *s;
3112 {
3113   return (s->b == s->p);
3114 }
3115
3116 #endif
3117
3118 static void
3119 string_append (p, s)
3120      string *p;
3121      const char *s;
3122 {
3123   int n;
3124   if (s == NULL || *s == '\0')
3125     return;
3126   n = strlen (s);
3127   string_need (p, n);
3128   memcpy (p->p, s, n);
3129   p->p += n;
3130 }
3131
3132 static void
3133 string_appends (p, s)
3134      string *p, *s;
3135 {
3136   int n;
3137
3138   if (s->b != s->p)
3139     {
3140       n = s->p - s->b;
3141       string_need (p, n);
3142       memcpy (p->p, s->b, n);
3143       p->p += n;
3144     }
3145 }
3146
3147 static void
3148 string_appendn (p, s, n)
3149      string *p;
3150      const char *s;
3151      int n;
3152 {
3153   if (n != 0)
3154     {
3155       string_need (p, n);
3156       memcpy (p->p, s, n);
3157       p->p += n;
3158     }
3159 }
3160
3161 static void
3162 string_prepend (p, s)
3163      string *p;
3164      const char *s;
3165 {
3166   if (s != NULL && *s != '\0')
3167     {
3168       string_prependn (p, s, strlen (s));
3169     }
3170 }
3171
3172 static void
3173 string_prepends (p, s)
3174      string *p, *s;
3175 {
3176   if (s->b != s->p)
3177     {
3178       string_prependn (p, s->b, s->p - s->b);
3179     }
3180 }
3181
3182 static void
3183 string_prependn (p, s, n)
3184      string *p;
3185      const char *s;
3186      int n;
3187 {
3188   char *q;
3189
3190   if (n != 0)
3191     {
3192       string_need (p, n);
3193       for (q = p->p - 1; q >= p->b; q--)
3194         {
3195           q[n] = q[0];
3196         }
3197       memcpy (p->b, s, n);
3198       p->p += n;
3199     }
3200 }
3201
3202 /* To generate a standalone demangler program for testing purposes,
3203    just compile and link this file with -DMAIN and libiberty.a.  When
3204    run, it demangles each command line arg, or each stdin string, and
3205    prints the result on stdout.  */
3206
3207 #ifdef MAIN
3208
3209 #include "getopt.h"
3210
3211 static char *program_name;
3212 static char *program_version = VERSION;
3213 static int flags = DMGL_PARAMS | DMGL_ANSI;
3214
3215 static void demangle_it PARAMS ((char *));
3216 static void usage PARAMS ((FILE *, int));
3217 static void fatal PARAMS ((char *));
3218
3219 static void
3220 demangle_it (mangled_name)
3221      char *mangled_name;
3222 {
3223   char *result;
3224
3225   result = cplus_demangle (mangled_name, flags);
3226   if (result == NULL)
3227     {
3228       printf ("%s\n", mangled_name);
3229     }
3230   else
3231     {
3232       printf ("%s\n", result);
3233       free (result);
3234     }
3235 }
3236
3237 static void
3238 usage (stream, status)
3239      FILE *stream;
3240      int status;
3241 {    
3242   fprintf (stream, "\
3243 Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3244       [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3245       [--help] [--version] [arg...]\n",
3246            program_name);
3247   exit (status);
3248 }
3249
3250 #define MBUF_SIZE 512
3251 char mbuffer[MBUF_SIZE];
3252
3253 /* Defined in the automatically-generated underscore.c.  */
3254 extern int prepends_underscore;
3255
3256 int strip_underscore = 0;
3257
3258 static struct option long_options[] = {
3259   {"strip-underscores", no_argument, 0, '_'},
3260   {"format", required_argument, 0, 's'},
3261   {"help", no_argument, 0, 'h'},
3262   {"java", no_argument, 0, 'j'},
3263   {"no-strip-underscores", no_argument, 0, 'n'},
3264   {"version", no_argument, 0, 'v'},
3265   {0, no_argument, 0, 0}
3266 };
3267
3268 /* More 'friendly' abort that prints the line and file.
3269    config.h can #define abort fancy_abort if you like that sort of thing.  */
3270
3271 void
3272 fancy_abort ()
3273 {
3274   fatal ("Internal gcc abort.");
3275 }
3276
3277 int
3278 main (argc, argv)
3279      int argc;
3280      char **argv;
3281 {
3282   char *result;
3283   int c;
3284
3285   program_name = argv[0];
3286
3287   strip_underscore = prepends_underscore;
3288
3289   while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
3290     {
3291       switch (c)
3292         {
3293         case '?':
3294           usage (stderr, 1);
3295           break;
3296         case 'h':
3297           usage (stdout, 0);
3298         case 'n':
3299           strip_underscore = 0;
3300           break;
3301         case 'v':
3302           printf ("GNU %s version %s\n", program_name, program_version);
3303           exit (0);
3304         case '_':
3305           strip_underscore = 1;
3306           break;
3307         case 'j':
3308           flags |= DMGL_JAVA;
3309           break;
3310         case 's':
3311           if (strcmp (optarg, "gnu") == 0)
3312             {
3313               current_demangling_style = gnu_demangling;
3314             }
3315           else if (strcmp (optarg, "lucid") == 0)
3316             {
3317               current_demangling_style = lucid_demangling;
3318             }
3319           else if (strcmp (optarg, "arm") == 0)
3320             {
3321               current_demangling_style = arm_demangling;
3322             }
3323           else
3324             {
3325               fprintf (stderr, "%s: unknown demangling style `%s'\n",
3326                        program_name, optarg);
3327               exit (1);
3328             }
3329           break;
3330         }
3331     }
3332
3333   if (optind < argc)
3334     {
3335       for ( ; optind < argc; optind++)
3336         {
3337           demangle_it (argv[optind]);
3338         }
3339     }
3340   else
3341     {
3342       for (;;)
3343         {
3344           int i = 0;
3345           c = getchar ();
3346           /* Try to read a label.  */
3347           while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
3348             {
3349               if (i >= MBUF_SIZE-1)
3350                 break;
3351               mbuffer[i++] = c;
3352               c = getchar ();
3353             }
3354           if (i > 0)
3355             {
3356               int skip_first = 0;
3357
3358               if (mbuffer[0] == '.')
3359                 ++skip_first;
3360               if (strip_underscore && mbuffer[skip_first] == '_')
3361                 ++skip_first;
3362
3363               if (skip_first > i)
3364                 skip_first = i;
3365
3366               mbuffer[i] = 0;
3367               
3368               result = cplus_demangle (mbuffer + skip_first, flags);
3369               if (result)
3370                 {
3371                   if (mbuffer[0] == '.')
3372                     putc ('.', stdout);
3373                   fputs (result, stdout);
3374                   free (result);
3375                 }
3376               else
3377                 fputs (mbuffer, stdout);
3378
3379               fflush (stdout);
3380             }
3381           if (c == EOF)
3382             break;
3383           putchar (c);
3384         }
3385     }
3386
3387   exit (0);
3388 }
3389
3390 static void
3391 fatal (str)
3392      char *str;
3393 {
3394   fprintf (stderr, "%s: %s\n", program_name, str);
3395   exit (1);
3396 }
3397
3398 char * malloc ();
3399 char * realloc ();
3400
3401 char *
3402 xmalloc (size)
3403      unsigned size;
3404 {
3405   register char *value = (char *) malloc (size);
3406   if (value == 0)
3407     fatal ("virtual memory exhausted");
3408   return value;
3409 }
3410
3411 char *
3412 xrealloc (ptr, size)
3413      char *ptr;
3414      unsigned size;
3415 {
3416   register char *value = (char *) realloc (ptr, size);
3417   if (value == 0)
3418     fatal ("virtual memory exhausted");
3419   return value;
3420 }
3421 #endif  /* main */