/*ident "@(#)cls4:tools/demangler/osrc/args.c 1.3" */ /******************************************************************************* C++ source for the C++ Language System, Release 3.0. This product is a new release of the original cfront developed in the computer science research center of AT&T Bell Laboratories. Copyright (c) 1993 UNIX System Laboratories, Inc. Copyright (c) 1991, 1992 AT&T and UNIX System Laboratories, Inc. Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System Laboratories, Inc. The copyright notice above does not evidence any actual or intended publication of such source code. *******************************************************************************/ /* * C++ Demangler Source Code * @(#)master 1.5 * 7/27/88 13:54:37 */ #include #if __STDC__ == 1 # include #else extern long strtol(); #endif #include "elf_dem.h" #include "String.h" /* This structure is used to keep * track of pointers to argument * descriptions in the mangled string. * This is needed for N and T encodings * to work. */ typedef struct { char *list[10]; int pos; } Place; static Place here; /* Strings and flags needed by the argument demangles. The declarator * is built up in ptr. Type modifiers are held in the flag fields. * The type itself is passed in separately. */ typedef struct { String *ptr; int Sign,Uns,Cons,Vol,Ptr,Ref; } Arg_Remem; /* initialize Arg_Remem */ static void mkar(r) Arg_Remem *r; { r->ptr = mk_String((String *)0); r->Sign = r->Uns = r->Cons = r->Vol = r->Ptr = r->Ref = 0; } /* free data for Arg_Remem */ static void delar(r) Arg_Remem *r; { free_String(&r->ptr); } /* This routine formats a single argument * on the buffer sptr. * c is the type or class name, n is its length. */ static void nsetarg(sptr,r,c,n) String **sptr; Arg_Remem *r; char *c; { r->ptr = nprep_String(c, -1, r->ptr, n); if(r->Cons) r->ptr = prep_String("const ",6,r->ptr); if(r->Vol) r->ptr = prep_String("volatile ",9,r->ptr); if(r->Uns) r->ptr = prep_String("unsigned ",9,r->ptr); else if(r->Sign) r->ptr = prep_String("signed ",7,r->ptr); *sptr = app_String(*sptr,PTR(r->ptr),-1); delar(r); } /* This routine formats a single argument * on the buffer sptr. * c is the null terminated type or class name. */ static void setarg(sptr,r,c) String **sptr; Arg_Remem *r; char *c; { nsetarg(sptr,r,c,NAME_MAX); } /* Demangle a single function argument. * Returns the number of characters processed from c. */ int doarg(sptr,c) String **sptr; char *c; { register int i; Arg_Remem ar; mkar(&ar); if(here.pos < 10 && here.pos >= 0) here.list[here.pos++] = c; for(i=0;c[i];i++) { /* Loop until you find a type. Then call setarg and return. */ switch(c[i]) { case 'T': { Place tmp; tmp = here; here.pos = c[1] - '1'; if(here.pos < 0 || here.pos >= tmp.pos-1) { delar(&ar); return -1; } doarg(sptr,here.list[here.pos]); here = tmp; delar(&ar); return 2; } case 'N': { Place tmp; int cycles,pos; cycles = c[1] - '0'; pos = c[2] - '1'; here.pos += cycles - 1; tmp = here; if(cycles <= 1 || cycles > 9 || pos < 0 || pos >= tmp.pos-1) { delar(&ar); return -1; } while(cycles--) { here = tmp; here.pos = pos; doarg(sptr,here.list[here.pos]); (*sptr) = app_String(*sptr,",",1); } *sptr = trunc_String(*sptr, 1); here = tmp; delar(&ar); return 3; } /* Qualifiers to type names */ case 'S': ar.Sign = 1; break; case 'U': ar.Uns = 1; break; case 'C': ar.Cons = 1; break; case 'V': ar.Vol = 1; break; /* Pointers, references, and Member Pointers */ case 'P': case 'R': case 'M': if(ar.Cons) { ar.ptr = prep_String(" const",6,ar.ptr); ar.Cons = 0; } if(ar.Vol) { ar.ptr = prep_String(" volatile",9,ar.ptr); ar.Vol = 0; } if(c[i] == 'P') { ar.ptr = prep_String("*",1,ar.ptr); ar.Ptr = 1; /* hmm, should i set this to zero somewhere, like Cons above? */ } else if(c[i] == 'R') { ar.ptr = prep_String("&",1,ar.ptr); ar.Ref = 1; /* same hmm */ } else { int cnt = 0; char *s; ar.ptr = prep_String("::*",3,ar.ptr); /* Skip over the 'M' */ i++; cnt = strtol(c+i, &s, 10); i = s - c; ar.ptr = nprep_String(c+i, -1, ar.ptr, cnt); ar.ptr = prep_String(" ",1,ar.ptr); i += cnt; /* The loop increments i */ i--; } break; /* Demangle for basic built-in types */ case 'i': setarg(sptr,&ar,"int"); return i + 1; case 'c': setarg(sptr,&ar,"char"); return i + 1; case 's': setarg(sptr,&ar,"short"); return i + 1; case 'l': setarg(sptr,&ar,"long"); return i + 1; case 'f': setarg(sptr,&ar,"float"); return i + 1; case 'd': setarg(sptr,&ar,"double"); return i + 1; case 'r': setarg(sptr,&ar,"long double"); return i + 1; /* Class encodings */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int cnt = 0; char *s; cnt = strtol(c+i, &s, 10); i = s - c; if(strlen(c+i) < cnt) { delar(&ar); return -1; } nsetarg(sptr,&ar,c+i,cnt); return i+cnt; } /* Ellipsis and void */ case 'e': if(ar.Cons || ar.Vol || ar.Uns || ar.Sign || *PTR(ar.ptr) != '\0') return -1; /* remove previous comma */ (*sptr) = trunc_String(*sptr,1); (*sptr) = app_String(*sptr," ...",4); delar(&ar); return ++i; case 'v': if(ar.Vol || ar.Uns || ar.Sign || *PTR(ar.ptr) == '\0') return -1; if(ar.Cons) { if (ar.Ptr) (*sptr) = app_String(*sptr,"const ",6); else return -1; } (*sptr) = app_String(*sptr,"void",4); (*sptr) = app_String(*sptr,PTR(ar.ptr),-1); delar(&ar); return ++i; /* Arrays */ case 'A': if(*PTR(ar.ptr)) { ar.ptr = prep_String("(",1,ar.ptr); ar.ptr = app_String(ar.ptr,")",1); } ar.ptr = app_String(ar.ptr,"[",1); { int cnt = 0; i++; while(isdigit(c[i+cnt])) cnt++; ar.ptr = napp_String(ar.ptr,c+i,-1,cnt); i += cnt; if(c[i] != '_') { delar(&ar); return -1; } } ar.ptr = app_String(ar.ptr,"]",1); break; /* Functions * This will always be called as a pointer * to a function. */ case 'F': ar.ptr = prep_String("(",1,ar.ptr); ar.ptr = app_String(ar.ptr,")",1); { Place tmp; tmp = here; i++; i += doargs(&ar.ptr,c+i); if(c[i] != '_') { delar(&ar); return -1; } here = tmp; } break; /* Qualified type name */ case 'Q': { String *tmp; int numquals = 0; char *s; int j; tmp = mk_String((String *) 0); numquals = strtol(c+i+1, &s, 10); if (*s != '_') { delar(&ar); return -1; } s++; for (j = 0; j < numquals; j++) { int cnt = strtol(s, &s, 10); if (cnt <= 0 || strlen(s) < cnt) { delar(&ar); return -1; } if (j > 0) { tmp = app_String(tmp,"::",2); } tmp = app_String(tmp,s,cnt); s += cnt; } i = s - c; setarg(sptr,&ar,PTR(tmp)); free_String(&tmp); return i; } break; /* Needed when this is called to demangle * an argument of a pointer to a function. */ case '_': delar(&ar); return 0; default: delar(&ar); return -1; } } /* Did the argument list terminate properly? */ { int rc = 0; if(*PTR(ar.ptr) || ar.Uns || ar.Sign || ar.Cons || ar.Vol) rc = -1; delar(&ar); return rc; } } /* This function is called to demangle * an argument list. * Returns the number of characters processed from c. */ int doargs(sptr,c) String **sptr; char *c; { int i,n = 0; here.pos = 0; *sptr = app_String(*sptr,"(",1); while(*c && (i = doarg(sptr,c)) > 0) { c += i; n += i; (*sptr) = app_String(*sptr,",",1); } if(i < 0) return -1; *sptr = app_String(trunc_String(*sptr, 1),")",1); return n; }