Annotation of gcc/cp-dem.c, revision 1.1.1.4

1.1       root        1: /* Demangler for GNU C++ 
1.1.1.4 ! root        2:    Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
        !             3:    Written by James Clark ([email protected]).
1.1       root        4:    
                      5:    This program is free software; you can redistribute it and/or modify
                      6:    it under the terms of the GNU General Public License as published by
                      7:    the Free Software Foundation; either version 2, or (at your option)
                      8:    any later version.
                      9: 
                     10:    This program is distributed in the hope that it will be useful,
                     11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:    GNU General Public License for more details.
                     14: 
                     15:    You should have received a copy of the GNU General Public License
                     16:    along with this program; if not, write to the Free Software
                     17:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     18: 
                     19: /* This is for g++ 1.36.1 (November 6 version). It will probably
                     20:    require changes for any other version.
                     21: 
                     22:    Modified for g++ 1.36.2 (November 18 version).
                     23: 
                     24:    Modified for g++ 1.90.06 (December 31 version).
                     25: 
1.1.1.2   root       26:    Modified for g++ 1.95.03 (November 13 version).  */
1.1       root       27: 
                     28: /* This file exports one function
                     29: 
                     30:    char *cplus_demangle (const char *name)
                     31: 
                     32:    If NAME is a mangled function name produced by GNU C++, then
                     33:    a pointer to a malloced string giving a C++ representation
                     34:    of the name will be returned; otherwise NULL will be returned.
                     35:    It is the caller's responsibility to free the string which
                     36:    is returned.
                     37: 
                     38:    For example,
                     39:    
                     40:    cplus_demangle ("_foo__1Ai")
                     41:    
                     42:    returns
                     43: 
                     44:    "A::foo(int)"
                     45: 
                     46:    This file imports xmalloc and xrealloc, which are like malloc and
                     47:    realloc except that they generate a fatal error if there is no
                     48:    available memory. */
                     49: 
                     50: /* #define nounderscore 1 /* define this is names don't start with _ */
                     51: 
                     52: #include <stdio.h>
                     53: #include <ctype.h>
                     54: 
                     55: #ifdef USG
                     56: #include <memory.h>
                     57: #else
                     58: #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
                     59: #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
                     60: #endif
                     61: 
                     62: /* This is '$' on systems where the assembler can deal with that.
                     63:    Where the assembler can't, it's '.' (but on many systems '.' is
                     64:    used for other things).  */
                     65: #if !defined (CPLUS_MARKER)
                     66: #define CPLUS_MARKER '$'
                     67: #endif
                     68: 
                     69: #ifndef __STDC__
                     70: #define const
                     71: #endif
                     72: 
                     73: #ifdef __STDC__
                     74: extern char *cplus_demangle (const char *type);
                     75: #else
                     76: extern char *cplus_demangle ();
                     77: #endif
                     78: 
                     79: #ifdef __STDC__
                     80: extern char *xmalloc (int);
                     81: extern char *xrealloc (char *, int);
                     82: extern void free (char *);
                     83: #else
                     84: extern char *xmalloc ();
                     85: extern char *xrealloc ();
                     86: extern void free ();
                     87: #endif
                     88: 
                     89: static char **typevec = 0;
                     90: static int ntypes = 0;
                     91: static int typevec_size = 0;
                     92: 
                     93: static struct {
                     94:   const char *in;
                     95:   const char *out;
                     96: } optable[] = {
                     97:   "nw", " new",                        /* new (1.92, ansi) */
                     98:   "dl", " delete",             /* new (1.92, ansi) */
                     99:   "new", " new",               /* old (1.91) */
                    100:   "delete", " delete",         /* old (1.91) */
                    101:   "ne", "!=",                  /* old, ansi */
                    102:   "eq", "==",                  /* old, ansi */
                    103:   "ge", ">=",                  /* old, ansi */
                    104:   "gt", ">",                   /* old, ansi */
                    105:   "le", "<=",                  /* old, ansi */
                    106:   "lt", "<",                   /* old, ansi */
                    107:   "plus", "+",                 /* old */
                    108:   "pl", "+",                   /* ansi */
                    109:   "apl", "+=",                 /* ansi */
                    110:   "minus", "-",                        /* old */
                    111:   "mi", "-",                   /* ansi */
                    112:   "ami", "-=",                 /* ansi */
                    113:   "mult", "*",                 /* old */
                    114:   "ml", "*",                   /* ansi */
                    115:   "aml", "*=",                 /* ansi */
                    116:   "convert", "+",              /* old (unary +) */
                    117:   "negate", "-",               /* old (unary -) */
                    118:   "trunc_mod", "%",            /* old */
                    119:   "md", "%",                   /* ansi */
                    120:   "amd", "%=",                 /* ansi */
                    121:   "trunc_div", "/",            /* old */
                    122:   "dv", "/",                   /* ansi */
                    123:   "adv", "/=",                 /* ansi */
                    124:   "truth_andif", "&&",         /* old */
                    125:   "aa", "&&",                  /* ansi */
                    126:   "truth_orif", "||",          /* old */
                    127:   "oo", "||",                  /* ansi */
                    128:   "truth_not", "!",            /* old */
                    129:   "nt", "!",                   /* ansi */
                    130:   "postincrement", "++",       /* old */
                    131:   "pp", "++",                  /* ansi */
                    132:   "postdecrement", "--",       /* old */
                    133:   "mm", "--",                  /* ansi */
                    134:   "bit_ior", "|",              /* old */
                    135:   "or", "|",                   /* ansi */
                    136:   "aor", "|=",                 /* ansi */
                    137:   "bit_xor", "^",              /* old */
                    138:   "er", "^",                   /* ansi */
                    139:   "aer", "^=",                 /* ansi */
                    140:   "bit_and", "&",              /* old */
                    141:   "ad", "&",                   /* ansi */
                    142:   "aad", "&=",                 /* ansi */
                    143:   "bit_not", "~",              /* old */
                    144:   "co", "~",                   /* ansi */
                    145:   "call", "()",                        /* old */
                    146:   "cl", "()",                  /* ansi */
                    147:   "cond", "?:",                        /* old */
                    148:   "alshift", "<<",             /* old */
                    149:   "ls", "<<",                  /* ansi */
                    150:   "als", "<<=",                        /* ansi */
                    151:   "arshift", ">>",             /* old */
                    152:   "rs", ">>",                  /* ansi */
                    153:   "ars", ">>=",                        /* ansi */
                    154:   "component", "->",           /* old */
                    155:   "rf", "->",                  /* ansi */
                    156:   "indirect", "*",             /* old */
                    157:   "method_call", "->()",       /* old */
                    158:   "addr", "&",                 /* old (unary &) */
                    159:   "array", "[]",               /* old */
                    160:   "vc", "[]",                  /* ansi */
                    161:   "compound", ",",             /* old */
                    162:   "cm", ",",                   /* ansi */
                    163:   "nop", "",                   /* old (for operator=) */
1.1.1.2   root      164:   "as", "=",                   /* ansi */
1.1       root      165: };
                    166: 
                    167: /* Beware: these aren't '\0' terminated. */
                    168: 
                    169: typedef struct {
                    170:   char *b;                     /* pointer to start of string */
                    171:   char *p;                     /* pointer after last character */
                    172:   char *e;                     /* pointer after end of allocated space */
                    173: } string;
                    174: 
                    175: #ifdef __STDC__
                    176: static void string_need (string *s, int n);
                    177: static void string_delete (string *s);
                    178: static void string_init (string *s);
                    179: static void string_clear (string *s);
                    180: static int string_empty (string *s);
                    181: static void string_append (string *p, const char *s);
                    182: static void string_appends (string *p, string *s);
                    183: static void string_appendn (string *p, const char *s, int n);
                    184: static void string_prepend (string *p, const char *s);
                    185: #if 0
                    186: static void string_prepends (string *p, string *s);
                    187: #endif
                    188: static void string_prependn (string *p, const char *s, int n);
                    189: static int get_count (const char **type, int *count);
                    190: static int do_args (const char **type, string *decl);
                    191: static int do_type (const char **type, string *result);
                    192: static int do_arg (const char **type, string *result);
                    193: static int do_args (const char **type, string *decl);
                    194: static void munge_function_name (string *name);
                    195: static void remember_type (const char *type, int len);
                    196: #else
                    197: static void string_need ();
                    198: static void string_delete ();
                    199: static void string_init ();
                    200: static void string_clear ();
                    201: static int string_empty ();
                    202: static void string_append ();
                    203: static void string_appends ();
                    204: static void string_appendn ();
                    205: static void string_prepend ();
                    206: static void string_prepends ();
                    207: static void string_prependn ();
                    208: static int get_count ();
                    209: static int do_args ();
                    210: static int do_type ();
                    211: static int do_arg ();
                    212: static int do_args ();
                    213: static void munge_function_name ();
                    214: static void remember_type ();
                    215: #endif
                    216: 
                    217: int
                    218: get_simple_count (type, res)
                    219:      char **type;
                    220:      int *res;
                    221: {
                    222:   int n = 0, success = 1;;
                    223:   
                    224:   do
                    225:     {
                    226:       n *= 10;
                    227:       n += **type - '0';
                    228:       *type += 1;
                    229:     } 
                    230:   while (isdigit (**type));
                    231:   if (strlen (*type) < n)
                    232:     {
                    233:       success = 0;
                    234:     }
                    235: 
                    236:   *res = n;
                    237:   return success;
                    238: }
                    239: 
                    240: char *
                    241: cplus_demangle (type)
                    242:      const char *type;
                    243: {
                    244:   string decl;
                    245:   int n;
                    246:   int success = 0;
                    247:   int constructor = 0;
                    248:   int destructor = 0;
                    249:   int static_type = 0;
                    250:   int const_flag = 0;
                    251:   int i;
                    252:   const char *p;
                    253: #ifndef LONGERNAMES
                    254:   const char *premangle;
                    255: #endif
                    256: 
                    257:   if (type == NULL || *type == '\0')
                    258:     return NULL;
                    259: #ifndef nounderscore
                    260:   if (*type++ != '_')
                    261:     return NULL;
                    262: #endif
                    263:   p = type;
                    264:   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
                    265:     p++;
                    266:   if (*p == '\0')
                    267:     {
                    268:       /* destructor */
                    269:       if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_')
                    270:        {
                    271:          destructor = 1;
                    272:          p = type;
                    273:        }
                    274:       /* static data member */
1.1.1.3   root      275:       else if (*type != '_' && (index (type, CPLUS_MARKER) != NULL))
1.1       root      276:        {
                    277:          static_type = 1;
                    278:          p = type;
                    279:        }
                    280:       /* virtual table "_vt$"  */
                    281:       else if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER)
                    282:        {
                    283:          int n = strlen (type + 4) + 14 + 1;
                    284:          char *tem = (char *) xmalloc (n);
                    285:          strcpy (tem, type + 4);
                    286:          strcat (tem, " virtual table");
                    287:          return tem;
                    288:        }
                    289:       else return NULL;
                    290:     }
                    291: 
                    292:   string_init (&decl);
                    293: 
                    294:   if (static_type)
                    295:     {
                    296:       if (!isdigit (p[0]) && ('t' != p[0]))
                    297:        {
                    298:          string_delete (&decl);
                    299:          return NULL;
                    300:        }
                    301:     }
                    302:   else if (destructor)
                    303:     {
                    304:       if (!isdigit (p[3])&& ('t' != p[3]))
                    305:        {
                    306:          string_delete (&decl);
                    307:          return NULL;
                    308:        }
                    309:       p += 3;
                    310:     }
                    311:   else if (p == type)
                    312:     {
                    313:       if (!isdigit (p[2]) && ('t' != p[2]))
                    314:        {
                    315:          p += 1;
                    316:          while (*p != '\0' && !(*p == '_' && p[1] == '_'))
                    317:            p++;
                    318:          string_appendn (&decl, type, p - type);         
                    319:          string_appendn (&decl, "", 1);
                    320:          munge_function_name (&decl);
                    321:          if (decl.b[0] == '_')
                    322:            {
                    323:              string_delete (&decl);
                    324:              return NULL;
                    325:            }
                    326:          else
                    327:            p += 2;
                    328:        }
                    329:       else
                    330:        {
                    331:          constructor = 1;
                    332:          p += 2;
                    333:        }
                    334:     }
                    335:   else
                    336:     {
                    337:       string_appendn (&decl, type, p - type);
                    338:       decl.p[0] = '0';
                    339:       munge_function_name (&decl);
                    340:       p += 2;
                    341:     }
                    342: 
                    343: #ifndef LONGERNAMES
                    344:   premangle = p;
                    345: #endif
                    346:   switch (*p)
                    347:     {
                    348:     case 'C':
                    349:       /* a const member function */
                    350:       if (!isdigit (p[1]))
                    351:        {
                    352:          string_delete (&decl);
                    353:          return NULL;
                    354:        }
                    355:       p += 1;
                    356:       const_flag = 1;
                    357:       /* fall through */
                    358:     case '0':
                    359:     case '1':
                    360:     case '2':
                    361:     case '3':
                    362:     case '4':
                    363:     case '5':
                    364:     case '6':
                    365:     case '7':
                    366:     case '8':
                    367:     case '9':
                    368:       n = 0;
                    369:       do
                    370:        {
                    371:          n *= 10;
                    372:          n += *p - '0';
                    373:          p += 1;
                    374:        }
                    375:       while (isdigit (*p));
                    376:       if (strlen (p) < n)
                    377:        {
                    378:          string_delete (&decl);
                    379:          return NULL;
                    380:        }
                    381:       if (constructor || destructor)
                    382:        {
                    383:          string_appendn (&decl, p, n);
                    384:          string_append (&decl, "::");
                    385:          if (destructor)
                    386:            string_append(&decl, "~");
                    387:          string_appendn (&decl, p, n);
                    388:        }
                    389:       else
                    390:        {
                    391:          string_prepend (&decl, "::");
                    392:          string_prependn (&decl, p, n);
                    393:        }
                    394:       p += n;
                    395: #ifndef LONGERNAMES
                    396:       remember_type (premangle, p - premangle);
                    397: #endif
                    398:       if (static_type)
                    399:        {
                    400:          string_append(&decl, p+1);
                    401:          p += strlen(p);
                    402:          success = 1;
                    403:        }
                    404:       else
                    405:        success = do_args (&p, &decl);
                    406:       if (const_flag)
                    407:        string_append (&decl, " const");
                    408:       break;
                    409:     case 'F':
                    410:       p += 1;
                    411:       success = do_args (&p, &decl);
                    412:       break;
                    413:     /* template additions */
                    414:     case 't':
                    415:       p += 1;
                    416:       {
                    417:        int r, i;
                    418:        string tname;
                    419:        string trawname;
                    420:        
                    421:        string temp;
                    422:        int need_comma = 0;
                    423:        
                    424:        string_init(&tname);
                    425:        string_init(&trawname);
                    426:        
                    427:        /* get template name */
                    428:        if (!get_simple_count (&p, &r))
                    429:          {
                    430:            string_delete (&decl);
                    431:            return 0;
                    432:          }
                    433:        string_appendn (&tname, p, r);
                    434:        string_appendn (&trawname, p, r);
                    435:        string_appendn (&trawname, "", 1);
                    436:        p += r;
                    437:        string_append (&tname, "<");
                    438:        /* get size of template parameter list */
                    439:        if (!get_count (&p, &r))
                    440:          return 0;
                    441:        for (i = 0; i < r; i++)
                    442:          {
                    443:            if (need_comma)
                    444:              string_append (&tname, ", ");
                    445:            /* Z for type parameters */
                    446:            if (*p == 'Z')
                    447:              {
                    448:                p += 1;
                    449:                
                    450:                success = do_type (&p, &temp);
                    451:                string_appendn (&temp, "", 1);
                    452:                if (success)
                    453:                  string_append (&tname, temp.b);
                    454:                string_delete(&temp);
                    455:                if (!success)
                    456:                  break;
                    457:              }
                    458:            /* otherwise, value parameter */
                    459:            else
                    460:              {
                    461:                const char *old_p  = p;
                    462:                int is_pointer = 0;
                    463:                int is_real = 0;
                    464:                int is_integral = 0;
                    465:                int done = 0;
                    466: 
                    467:                success = do_type (&p, &temp);
                    468:                string_appendn (&temp, "", 1);
                    469:                if (success)
                    470:                  string_append (&tname, temp.b);
                    471:                string_delete(&temp);
                    472:                if (!success)
                    473:                  break;
                    474:                string_append (&tname, "=");
                    475:                while (*old_p && !done)
                    476:                  {     
                    477:                    switch (*old_p)
                    478:                      {
                    479:                      case 'P':
                    480:                      case 'R':
                    481:                        done = is_pointer = 1;
                    482:                        break;
                    483:                      case 'C': /* const */
1.1.1.4 ! root      484:                      case 'S': /* explicitly signed [char] */
1.1       root      485:                      case 'U': /* unsigned */
                    486:                      case 'V': /* volatile */
                    487:                      case 'F': /* function */
                    488:                      case 'M': /* member function */
                    489:                      case 'O': /* ??? */
                    490:                        old_p++;
                    491:                        continue;
                    492:                      case 'Q': /* repetition of following */
                    493:                      case 'T': /* remembered type */
                    494:                        abort();
                    495:                        break;
                    496:                      case 'v': /* void */
                    497:                        abort();
                    498:                        break;
                    499:                      case 'x': /* long long */
                    500:                      case 'l': /* long */
                    501:                      case 'i': /* int */
                    502:                      case 's': /* short */
                    503:                      case 'c': /* char */
1.1.1.3   root      504:                      case 'w': /* wchar_t */
1.1       root      505:                        done = is_integral = 1;
                    506:                        break;
                    507:                      case 'r': /* long double */
                    508:                      case 'd': /* double */
                    509:                      case 'f': /* float */
                    510:                        done = is_real = 1;
                    511:                        break;
                    512:                      default:
                    513:                        abort();
                    514:                      }
                    515:                  }
                    516:                if (is_integral)
                    517:                  {
                    518:                    if (*p == 'm')
                    519:                      {
                    520:                        string_appendn (&tname, "-", 1);
                    521:                        p++;
                    522:                      }
                    523:                    while (isdigit (*p))        
                    524:                      {
                    525:                        string_appendn (&tname, p, 1);
                    526:                        p++;
                    527:                      }
                    528:                  }
                    529:                else if (is_real)
                    530:                  {
                    531:                    if (*p == 'm')
                    532:                      {
                    533:                        string_appendn (&tname, "-", 1);
                    534:                        p++;
                    535:                      }
                    536:                    while (isdigit (*p))        
                    537:                      {
                    538:                        string_appendn (&tname, p, 1);
                    539:                        p++;
                    540:                      }
                    541:                    if (*p == '.') /* fraction */
                    542:                      {
                    543:                        string_appendn (&tname, ".", 1);
                    544:                        p++;
                    545:                        while (isdigit (*p))    
                    546:                          {
                    547:                            string_appendn (&tname, p, 1);
                    548:                            p++;
                    549:                          }
                    550:                      }
                    551:                    if (*p == 'e') /* exponent */
                    552:                      {
                    553:                        string_appendn (&tname, "e", 1);
                    554:                        p++;
                    555:                        while (isdigit (*p))    
                    556:                          {
                    557:                            string_appendn (&tname, p, 1);
                    558:                            p++;
                    559:                          }
                    560:                      }
                    561:                  }
                    562:                else if (is_pointer)
                    563:                  {
                    564:                    int symbol_len;
                    565:                    
                    566:                    if (!get_count (&p, &symbol_len))
                    567:                      {
                    568:                        success = 0;
                    569:                        break;
                    570:                      }
                    571:                    string_appendn (&tname, p, symbol_len);
                    572:                    p += symbol_len;
                    573:                  }
                    574:              }
                    575:            need_comma = 1;
                    576:          }
                    577:        string_append (&tname, ">::");
                    578:        if (destructor)
                    579:          string_append(&tname, "~");
                    580:        if (constructor || destructor) {
                    581:          string_appendn (&trawname, "", 1);
                    582:          string_append (&tname, trawname.b);
                    583:        }
                    584:        string_delete(&trawname);
                    585:        
                    586:        if (!success) {
                    587:          string_delete(&tname);
                    588:          return 0;
                    589:        }
                    590:        string_appendn (&tname, "", 1);
                    591:        string_prepend (&decl, tname.b);
                    592:        string_delete (&tname);
                    593: 
                    594:        if (static_type)
                    595:          {
                    596:            string_append (&decl, p+1);
                    597:            p += strlen (p);
                    598:            success = 1;
                    599:          }
                    600:        else
                    601:          success = do_args (&p, &decl);
                    602:        break;
                    603:       }
                    604:     }
                    605: 
                    606:   for (i = 0; i < ntypes; i++)
                    607:     if (typevec[i] != NULL)
                    608:       free (typevec[i]);
                    609:   ntypes = 0;
                    610:   if (typevec != NULL)
                    611:     {
                    612:       free ((char *)typevec);
                    613:       typevec = NULL;
                    614:       typevec_size = 0;
                    615:     }
                    616: 
                    617:   if (success)
                    618:     {
                    619:       string_appendn (&decl, "", 1);
                    620:       return decl.b;
                    621:     }
                    622:   else
                    623:     {
                    624:       string_delete (&decl);
                    625:       return NULL;
                    626:     }
                    627: }
                    628: 
                    629: static int
                    630: get_count (type, count)
                    631:      const char **type;
                    632:      int *count;
                    633: {
                    634:   if (!isdigit (**type))
                    635:     return 0;
                    636:   *count = **type - '0';
                    637:   *type += 1;
                    638:   /* see flush_repeats in cp-method.c */
                    639:   if (isdigit (**type))
                    640:     {
                    641:       const char *p = *type;
                    642:       int n = *count;
                    643:       do 
                    644:        {
                    645:          n *= 10;
                    646:          n += *p - '0';
                    647:          p += 1;
                    648:        } 
                    649:       while (isdigit (*p));
                    650:       if (*p == '_')
                    651:        {
                    652:          *type = p + 1;
                    653:          *count = n;
                    654:        }
                    655:     }
                    656:   return 1;
                    657: }
                    658: 
                    659: /* result will be initialised here; it will be freed on failure */
                    660: 
                    661: static int
                    662: do_type (type, result)
                    663:      const char **type;
                    664:      string *result;
                    665: {
                    666:   int n;
                    667:   int done;
                    668:   int non_empty = 0;
                    669:   int success;
                    670:   string decl;
                    671:   const char *remembered_type;
                    672: 
                    673:   string_init (&decl);
                    674:   string_init (result);
                    675: 
                    676:   done = 0;
                    677:   success = 1;
                    678:   while (success && !done)
                    679:     {
                    680:       int member;
                    681:       switch (**type)
                    682:        {
                    683:        case 'Q':
                    684:          n = (*type)[1] - '0';
                    685:          if (n < 0 || n > 9)
                    686:            success = 0;
                    687:          *type += 2;
                    688:          while (n-- > 0)
                    689:            do_type (type, result);
                    690:          break;
                    691: 
                    692:        case 'P':
                    693:          *type += 1;
                    694:          string_prepend (&decl, "*");
                    695:          break;
                    696: 
                    697:        case 'R':
                    698:          *type += 1;
                    699:          string_prepend (&decl, "&");
                    700:          break;
                    701: 
                    702:        case 'T':
                    703:          *type += 1;
                    704:          if (!get_count (type, &n) || n >= ntypes)
                    705:            success = 0;
                    706:          else
                    707:            {
                    708:              remembered_type = typevec[n];
                    709:              type = &remembered_type;
                    710:            }
                    711:          break;
                    712: 
                    713:        case 'F':
                    714:          *type += 1;
                    715:          if (!string_empty (&decl) && decl.b[0] == '*')
                    716:            {
                    717:              string_prepend (&decl, "(");
                    718:              string_append (&decl, ")");
                    719:            }
                    720:          if (!do_args (type, &decl) || **type != '_')
                    721:            success = 0;
                    722:          else
                    723:            *type += 1;
                    724:          break;
                    725: 
                    726:        case 'M':
                    727:        case 'O':
                    728:          {
                    729:            int constp = 0;
                    730:            int volatilep = 0;
                    731: 
                    732:            member = **type == 'M';
                    733:            *type += 1;
                    734:            if (!isdigit (**type))
                    735:              {
                    736:                success = 0;
                    737:                break;
                    738:              }
                    739:            n = 0;
                    740:            do
                    741:              {
                    742:                n *= 10;
                    743:                n += **type - '0';
                    744:                *type += 1;
                    745:              } 
                    746:            while (isdigit (**type));
                    747:            if (strlen (*type) < n)
                    748:              {
                    749:                success = 0;
                    750:                break;
                    751:              }
                    752:            string_append (&decl, ")");
                    753:            string_prepend (&decl, "::");
                    754:            string_prependn (&decl, *type, n);
                    755:            string_prepend (&decl, "(");
                    756:            *type += n;
                    757:            if (member)
                    758:              {
                    759:                if (**type == 'C')
                    760:                  {
                    761:                    *type += 1;
                    762:                    constp = 1;
                    763:                  }
                    764:                if (**type == 'V')
                    765:                  {
                    766:                    *type += 1;
                    767:                    volatilep = 1;
                    768:                  }
                    769:                if (*(*type)++ != 'F')
                    770:                  {
                    771:                    success = 0;
                    772:                    break;
                    773:                  }
                    774:              }
                    775:            if ((member && !do_args (type, &decl)) || **type != '_')
                    776:              {
                    777:                success = 0;
                    778:                break;
                    779:              }
                    780:            *type += 1;
                    781:            if (constp)
                    782:              {
                    783:                if (non_empty)
                    784:                  string_append (&decl, " ");
                    785:                else
                    786:                  non_empty = 1;
                    787:                string_append (&decl, "const");
                    788:              }
                    789:            if (volatilep)
                    790:              {
                    791:                if (non_empty)
                    792:                  string_append (&decl, " ");
                    793:                else
                    794:                  non_empty = 1;
                    795:                string_append (&decl, "volatile");
                    796:              }
                    797:            break;
                    798:          }
                    799: 
                    800:        case 'C':
                    801:          if ((*type)[1] == 'P')
                    802:            {
                    803:              *type += 1;
                    804:              if (!string_empty (&decl))
                    805:                string_prepend (&decl, " ");
                    806:              string_prepend (&decl, "const");
                    807:              break;
                    808:            }
                    809: 
                    810:          /* fall through */
                    811:        default:
                    812:          done = 1;
                    813:          break;
                    814:        }
                    815:     }
                    816: 
                    817:   non_empty = 0;
                    818:   if (success)
                    819:     success = do_cuv_prefix (type, result, &non_empty);
                    820: 
                    821:   if (success)
                    822:     success = do_builtin_type(type, result, &non_empty);
                    823:   
                    824:   if (success)
                    825:     {
                    826:       if (!string_empty (&decl))
                    827:        {
                    828:          string_append (result, " ");
                    829:          string_appends (result, &decl);
                    830:        }
                    831:       string_delete (&decl);
                    832:       return 1;
                    833:     }
                    834:   else
                    835:     {
                    836:       string_delete (&decl);
                    837:       string_delete (result);
                    838:       return 0;
                    839:     }
                    840: }
                    841: 
                    842: int
                    843: do_cuv_prefix (type, result, non_empty)
                    844:      char **type;
                    845:      string* result;
                    846:      int* non_empty;
                    847: {
                    848:   int success = 1;
                    849:   int done = 0;
                    850:   
                    851:   while (success && !done)
                    852:     {
                    853:       switch (**type)
                    854:        {
                    855:        case 'C':
                    856:          *type += 1;
                    857:          if (*non_empty)
                    858:            string_append (result, " ");
                    859:          else
                    860:            *non_empty = 1;
                    861:          string_append (result, "const");
                    862:          break;
1.1.1.4 ! root      863:        case 'S': /* signed char only */
        !           864:          *type += 1;
        !           865:          if (*non_empty)
        !           866:            string_append (result, " ");
        !           867:          else
        !           868:            *non_empty = 1;
        !           869:          string_append (result, "signed");
        !           870:          break;
1.1       root      871:        case 'U':
                    872:          *type += 1;
                    873:          if (*non_empty)
                    874:            string_append (result, " ");
                    875:          else
                    876:            *non_empty = 1;
                    877:          string_append (result, "unsigned");
                    878:          break;
                    879:        case 'V':
                    880:          *type += 1;
                    881:          if (*non_empty)
                    882:            string_append (result, " ");
                    883:          else
                    884:            *non_empty = 1;
                    885:          string_append (result, "volatile");
                    886:          break;
                    887:        default:
                    888:          done = 1;
                    889:          break;
                    890:        }
                    891:     }
                    892:   return success;
                    893: }
                    894: 
                    895: int
                    896: do_builtin_type (type, result, non_empty)
                    897:      char **type;
                    898:      string* result;
                    899:      int *non_empty;
                    900: {
                    901:   int success = 1;
                    902:   int n;
                    903:   
                    904:   switch (**type)
                    905:     {
                    906:     case '\0':
                    907:     case '_':
                    908:       break;
                    909:     case 'v':
                    910:       *type += 1;
                    911:       if (*non_empty)
                    912:        string_append (result, " ");
                    913:       string_append (result, "void");
                    914:       break;
                    915:     case 'x':
                    916:       *type += 1;
                    917:       if (*non_empty)
                    918:        string_append (result, " ");
                    919:       string_append (result, "long long");
                    920:       break;
                    921:     case 'l':
                    922:       *type += 1;
                    923:       if (*non_empty)
                    924:        string_append (result, " ");
                    925:       string_append (result, "long");
                    926:       break;
                    927:     case 'i':
                    928:       *type += 1;
                    929:       if (*non_empty)
                    930:        string_append (result, " ");
                    931:       string_append (result, "int");
                    932:       break;
                    933:     case 's':
                    934:       *type += 1;
                    935:       if (*non_empty)
                    936:        string_append (result, " ");
                    937:       string_append (result, "short");
                    938:       break;
                    939:     case 'c':
                    940:       *type += 1;
                    941:       if (*non_empty)
                    942:        string_append (result, " ");
                    943:       string_append (result, "char");
                    944:       break;
1.1.1.3   root      945:     case 'w':
                    946:       *type += 1;
                    947:       if (*non_empty)
                    948:        string_append (result, " ");
                    949:       string_append (result, "wchar_t");
                    950:       break;
1.1       root      951:     case 'r':
                    952:       *type += 1;
                    953:       if (*non_empty)
                    954:        string_append (result, " ");
                    955:       string_append (result, "long double");
                    956:       break;
                    957:     case 'd':
                    958:       *type += 1;
                    959:       if (*non_empty)
                    960:        string_append (result, " ");
                    961:       string_append (result, "double");
                    962:       break;
                    963:     case 'f':
                    964:       *type += 1;
                    965:       if (*non_empty)
                    966:        string_append (result, " ");
                    967:       string_append (result, "float");
                    968:       break;
                    969:     case 'G':
                    970:       *type += 1;
                    971:       if (!isdigit (**type))
                    972:        {
                    973:          success = 0;
                    974:          break;
                    975:        }
                    976:       /* fall through */
                    977:     case '0':
                    978:     case '1':
                    979:     case '2':
                    980:     case '3':
                    981:     case '4':
                    982:     case '5':
                    983:     case '6':
                    984:     case '7':
                    985:     case '8':
                    986:     case '9':
                    987:       n = 0;
                    988:       do
                    989:        {
                    990:          n *= 10;
                    991:          n += **type - '0';
                    992:          *type += 1;
                    993:        }
                    994:       while (isdigit (**type));
                    995:       if (strlen (*type) < n)
                    996:        {
                    997:          success = 0;
                    998:          break;
                    999:        }
                   1000:       if (*non_empty)
                   1001:        string_append (result, " ");
                   1002:       string_appendn (result, *type, n);
                   1003:       *type += n;
                   1004:       break;
                   1005:     default:
                   1006:       success = 0;
                   1007:       break;
                   1008:     }
                   1009:   return success;
                   1010: }
                   1011: 
                   1012: /* `result' will be initialised in do_type; it will be freed on failure */
                   1013: 
                   1014: static int
                   1015: do_arg (type, result)
                   1016:      const char **type;
                   1017:      string *result;
                   1018: {
                   1019:   const char *start = *type;
                   1020: 
                   1021:   if (!do_type (type, result))
                   1022:     return 0;
                   1023:   remember_type (start, *type - start);
                   1024:   return 1;
                   1025: }
                   1026: 
                   1027: static void
                   1028: remember_type (start, len)
                   1029:      const char *start;
                   1030:      int len;
                   1031: {
                   1032:   char *tem;
                   1033: 
                   1034:   if (ntypes >= typevec_size)
                   1035:     {
                   1036:       if (typevec_size == 0)
                   1037:        {
                   1038:          typevec_size = 3;
                   1039:          typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
                   1040:        }
                   1041:       else
                   1042:        {
                   1043:          typevec_size *= 2;
                   1044:          typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
                   1045:        }
                   1046:     }
                   1047:   tem = (char *) xmalloc (len + 1);
                   1048:   memcpy (tem, start, len);
                   1049:   tem[len] = '\0';
                   1050:   typevec[ntypes++] = tem;
                   1051: }
                   1052: 
                   1053: /* `decl' must be already initialised, usually non-empty;
                   1054:    it won't be freed on failure */
                   1055: 
                   1056: static int
                   1057: do_args (type, decl)
                   1058:      const char **type;
                   1059:      string *decl;
                   1060: {
                   1061:   string arg;
                   1062:   int need_comma = 0;
                   1063: 
                   1064:   string_append (decl, "(");
                   1065: 
                   1066:   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
                   1067:     {
                   1068:       if (**type == 'N')
                   1069:        {
                   1070:          int r;
                   1071:          int t;
                   1072:          *type += 1;
                   1073:          if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
                   1074:            return 0;
                   1075:          while (--r >= 0)
                   1076:            {
                   1077:              const char *tem = typevec[t];
                   1078:              if (need_comma)
                   1079:                string_append (decl, ", ");
                   1080:              if (!do_arg (&tem, &arg))
                   1081:                return 0;
                   1082:              string_appends (decl, &arg);
                   1083:              string_delete (&arg);
                   1084:              need_comma = 1;
                   1085:            }
                   1086:        }
                   1087:       else
                   1088:        {
                   1089:          if (need_comma)
                   1090:            string_append (decl, ", ");
                   1091:          if (!do_arg (type, &arg))
                   1092:            return 0;
                   1093:          string_appends (decl, &arg);
                   1094:          string_delete (&arg);
                   1095:          need_comma = 1;
                   1096:        }
                   1097:     }
                   1098: 
                   1099:   if (**type == 'v')
                   1100:     *type += 1;
                   1101:   else if (**type == 'e')
                   1102:     {
                   1103:       *type += 1;
                   1104:       if (need_comma)
                   1105:        string_append (decl, ",");
                   1106:       string_append (decl, "...");
                   1107:     }
                   1108: 
                   1109:   string_append (decl, ")");
                   1110:   return 1;
                   1111: }
                   1112: 
                   1113: static void
                   1114: munge_function_name (name)
                   1115:      string *name;
                   1116: {
                   1117:   if (string_empty (name))
                   1118:     return;
                   1119: 
                   1120:   if (name->p - name->b >= 3 
                   1121:       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER)
                   1122:     {
                   1123:       int i;
                   1124:       /* see if it's an assignment expression */
                   1125:       if (name->p - name->b >= 10 /* op$assign_ */
                   1126:          && memcmp (name->b + 3, "assign_", 7) == 0)
                   1127:        {
                   1128:          for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
                   1129:            {
                   1130:              int len = name->p - name->b - 10;
                   1131:              if (strlen (optable[i].in) == len
                   1132:                  && memcmp (optable[i].in, name->b + 10, len) == 0)
                   1133:                {
                   1134:                  string_clear (name);
                   1135:                  string_append (name, "operator");
                   1136:                  string_append (name, optable[i].out);
                   1137:                  string_append (name, "=");
                   1138:                  return;
                   1139:                }
                   1140:            }
                   1141:        }
                   1142:       else
                   1143:        {
                   1144:          for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
                   1145:            {
                   1146:              int len = name->p - name->b - 3;
                   1147:              if (strlen (optable[i].in) == len 
                   1148:                  && memcmp (optable[i].in, name->b + 3, len) == 0)
                   1149:                {
                   1150:                  string_clear (name);
                   1151:                  string_append (name, "operator");
                   1152:                  string_append (name, optable[i].out);
                   1153:                  return;
                   1154:                }
                   1155:            }
                   1156:        }
                   1157:       return;
                   1158:     }
                   1159:   else if (name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0)
                   1160:     {
                   1161:       /* type conversion operator */
                   1162:       string type;
                   1163:       const char *tem = name->b + 5;
                   1164:       if (do_type (&tem, &type))
                   1165:        {
                   1166:          string_clear (name);
                   1167:          string_append (name, "operator ");
                   1168:          string_appends (name, &type);
                   1169:          string_delete (&type);
                   1170:          return;
                   1171:        }
                   1172:     }
                   1173:   /* ANSI.  */
                   1174:   else if (name->b[2] == 'o' && name->b[3] == 'p')
                   1175:     {
                   1176:       /* type conversion operator.  */
                   1177:       string type;
                   1178:       const char *tem = name->b + 4;
                   1179:       if (do_type (&tem, &type))
                   1180:        {
                   1181:          string_clear (name);
                   1182:          string_append (name, "operator ");
                   1183:          string_appends (name, &type);
                   1184:          string_delete (&type);
                   1185:          return;
                   1186:        }
                   1187:     }
                   1188:   else if (name->b[2] >= 'a' && name->b[2] <= 'z'
                   1189:           && name->b[3] >= 'a' && name->b[3] <= 'z')
                   1190:     {
                   1191:       int i;
                   1192: 
                   1193:       if (name->b[4] == '\0')
                   1194:        {
                   1195:          /* Operator.  */
                   1196:          for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
                   1197:            {
                   1198:              if (strlen (optable[i].in) == 2
                   1199:                  && memcmp (optable[i].in, name->b + 2, 2) == 0)
                   1200:                {
                   1201:                  string_clear (name);
                   1202:                  string_append (name, "operator");
                   1203:                  string_append (name, optable[i].out);
                   1204:                  return;
                   1205:                }
                   1206:            }
                   1207:        }
                   1208:       else
                   1209:        {
                   1210:          if (name->b[2] != 'a' || name->b[5] != '\0')
                   1211:            return;
                   1212:          /* Assignment.  */
                   1213:          for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
                   1214:            {
                   1215:              if (strlen (optable[i].in) == 3
                   1216:                  && memcmp (optable[i].in, name->b + 2, 3) == 0)
                   1217:                {
                   1218:                  string_clear (name);
                   1219:                  string_append (name, "operator");
                   1220:                  string_append (name, optable[i].out);
                   1221:                  return;
                   1222:                }
                   1223:            }
                   1224:        }
                   1225:     }
                   1226: }
                   1227: 
                   1228: /* a mini string-handling package */
                   1229: 
                   1230: static void
                   1231: string_need (s, n)
                   1232:      string *s;
                   1233:      int n;
                   1234: {
                   1235:   if (s->b == NULL)
                   1236:     {
                   1237:       if (n < 32)
                   1238:        n = 32;
                   1239:       s->p = s->b = (char *) xmalloc (n);
                   1240:       s->e = s->b + n;
                   1241:     }
                   1242:   else if (s->e - s->p < n)
                   1243:     {
                   1244:       int tem = s->p - s->b;
                   1245:       n += tem;
                   1246:       n *= 2;
                   1247:       s->b = (char *) xrealloc (s->b, n);
                   1248:       s->p = s->b + tem;
                   1249:       s->e = s->b + n;
                   1250:     }
                   1251: }
                   1252: 
                   1253: static void
                   1254: string_delete (s)
                   1255:      string *s;
                   1256: {
                   1257:   if (s->b != NULL)
                   1258:     {
                   1259:       free (s->b);
                   1260:       s->b = s->e = s->p = NULL;
                   1261:     }
                   1262: }
                   1263: 
                   1264: static void
                   1265: string_init (s)
                   1266:      string *s;
                   1267: {
                   1268:   s->b = s->p = s->e = NULL;
                   1269: }
                   1270: 
                   1271: static void 
                   1272: string_clear (s)
                   1273:      string *s;
                   1274: {
                   1275:   s->p = s->b;
                   1276: }
                   1277: 
                   1278: static int
                   1279: string_empty (s)
                   1280:      string *s;
                   1281: {
                   1282:   return s->b == s->p;
                   1283: }
                   1284: 
                   1285: static void
                   1286: string_append (p, s)
                   1287:      string *p;
                   1288:      const char *s;
                   1289: {
                   1290:   int n;
                   1291:   if (s == NULL || *s == '\0')
                   1292:     return;
                   1293:   n = strlen (s);
                   1294:   string_need (p, n);
                   1295:   memcpy (p->p, s, n);
                   1296:   p->p += n;
                   1297: }
                   1298: 
                   1299: static void
                   1300: string_appends (p, s)
                   1301:      string *p, *s;
                   1302: {
                   1303:   int n;
                   1304:   if (s->b == s->p)
                   1305:     return;
                   1306:   n = s->p - s->b;
                   1307:   string_need (p, n);
                   1308:   memcpy (p->p, s->b, n);
                   1309:   p->p += n;
                   1310: }
                   1311: 
                   1312: static void
                   1313: string_appendn (p, s, n)
                   1314:      string *p;
                   1315:      const char *s;
                   1316:      int n;
                   1317: {
                   1318:   if (n == 0)
                   1319:     return;
                   1320:   string_need (p, n);
                   1321:   memcpy (p->p, s, n);
                   1322:   p->p += n;
                   1323: }
                   1324: 
                   1325: static void
                   1326: string_prepend (p, s)
                   1327:      string *p;
                   1328:      const char *s;
                   1329: {
                   1330:   if (s == NULL || *s == '\0')
                   1331:     return;
                   1332:   string_prependn (p, s, strlen (s));
                   1333: }
                   1334: 
                   1335: #if 0
                   1336: static void
                   1337: string_prepends (p, s)
                   1338:      string *p, *s;
                   1339: {
                   1340:   if (s->b == s->p)
                   1341:     return;
                   1342:   string_prependn (p, s->b, s->p - s->b);
                   1343: }
                   1344: #endif
                   1345: 
                   1346: static void
                   1347: string_prependn (p, s, n)
                   1348:      string *p;
                   1349:      const char *s;
                   1350:      int n;
                   1351: {
                   1352:   char *q;
                   1353: 
                   1354:   if (n == 0)
                   1355:     return;
                   1356:   string_need (p, n);
                   1357:   for (q = p->p - 1; q >= p->b; q--)
                   1358:     q[n] = q[0];
                   1359:   memcpy (p->b, s, n);
                   1360:   p->p += n;
                   1361: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.