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

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

unix.superglobalmegacorp.com

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