dem.c revision dc0093f44ee4fac928e006850f8ed53f68277af5
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*******************************************************************************
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) 1991 AT&T and UNIX System Laboratories, Inc.
Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "cafe_dem.h"
/************************* CUSTOMIZATION SECTION *************************/
#ifndef ELF_OBJ
#else
static int clip_under = 0;
#endif
/*#define DEM_MAIN*/ /* set if want standalone program */
/************************************************************************/
static char* spbase;
static char cc;
static char* base;
static int baselen;
static int waserror = 0;
#define MAXSTACK 200
static int sp = -1;
/************************* UTILITIES *************************/
/* fatal errors */
{
exit(1);
}
/* get space */
{
char* p;
if (s < 1)
fatal("bad argument to gs()", (char*)0, (char*)0);
/* align space on SP_ALIGN boundary */
spbase++;
p = spbase;
spbase += s;
return p;
}
/* copy a string */
static char* copy(char* s)
{
char* p;
if (s == NULL || !*s)
fatal("bad argument to copy()", (char*)0, (char*)0);
(void) strcpy(p, s);
return p;
}
/************************* DEMANGLE UTILITIES *************************/
/* push a string to scan */
static void push(char* s, int n)
{
if (s == NULL || !*s || n < 1)
fatal("bad argument to push()", (char*)0, (char*)0);
fatal("overflow of stack in push()", (char*)0, (char*)0);
sp++;
base = s;
baselen = n;
gc();
}
static void pop()
{
if (sp < 0)
fatal("bad argument to pop()", (char*)0, (char*)0);
sp--;
}
/************************* DEMANGLER *************************/
/* get a class name */
static DEMARG* getarglist();
{
int n;
int i;
int j;
int iter;
DEMCL* p;
iter = 1;
/* fix for ambiguity in encoding */
i = 0;
i = 1;
i = 2;
}
gc();
if (i)
gc();
if (i == 2)
gc();
}
/* might be nested class */
if (cc == 'Q') {
gc();
ERROR();
if (iter < 1)
ERROR();
gc();
if (cc != '_')
ERROR();
gc();
}
/* grab number of classes expected */
while (iter-- > 0) {
/* get a class */
ERROR();
n = cc - '0';
gc();
gc();
}
gc();
}
if (n < 1)
ERROR();
for (i = 0; i < n; i++) {
ERROR();
gc();
}
nbuf[i] = 0;
/* might be a template class */
for (j = 0; j < i; j++) {
break;
}
if (j == 0)
ERROR();
if (j == i) {
}
else {
ERROR();
nbuf[j] = 0;
j += 6;
ERROR();
n = nbuf[j] - '0';
j++;
j++;
}
j++;
}
if (n < 2)
ERROR();
if (nbuf[j] != '_')
ERROR();
j++;
n--;
if (!nbuf[j])
ERROR();
/* get arguments for template class */
ERROR();
pop();
}
/* link in to list */
curr = p;
}
else {
clhead = p;
}
}
return clhead;
}
/* copy an argument */
{
if (p == NULL)
fatal("bad argument to arg_copy()", (char*)0, (char*)0);
return p2;
}
/* get an argument */
{
char mods[100];
int mc;
int type;
static DEMARG* p;
long n;
DEMARG* getarglist();
int foundx;
long arrdim[100];
int arrp;
int i;
int wasm;
int waslm;
void dem_printcl();
int clc;
int ic;
/* might be stuff remaining from Nnn */
(*ncount)--;
return arg_copy(p);
}
mc = 0;
type = 0;
lp = 0;
foundx = 0;
arrp = 0;
wasm = 0;
clc = 0;
/* get type */
while (!type) {
switch (cc) {
/* modifiers and declarators */
case 'X':
gc();
foundx = 1;
break;
case 'U':
case 'C':
case 'V':
case 'S':
case 'P':
case 'R':
gc();
break;
/* fundamental types */
case 'v':
case 'c':
case 's':
case 'i':
case 'l':
case 'f':
case 'd':
case 'r':
case 'e':
case 'G':
gc();
break;
/* arrays */
case 'A':
gc();
ERROR();
n = cc - '0';
gc();
gc();
}
if (cc != '_')
ERROR();
gc();
break;
/* functions */
case 'F':
gc();
ERROR();
if (cc != '_')
ERROR();
gc();
ERROR();
break;
/* pointers to member */
case 'M':
wasm = 1;
gc();
ERROR();
break;
/* repeat previous argument */
case 'T':
gc();
ERROR();
n = cc - '0';
gc();
if (n < 1)
ERROR();
ERROR();
return p;
/* repeat previous argument N times */
case 'N':
gc();
ERROR();
ERROR();
if (*ncount < 0)
ERROR();
gc();
goto tcase;
/* class, struct, union, enum */
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': case 'Q':
ERROR();
type = 'C';
break;
default:
return NULL;
}
}
/* template literals */
n = 0;
waslm = 0;
gc();
gc();
gc();
if (!cc)
ERROR();
gc();
gc();
if (!cc)
ERROR();
gc();
n = cc - '0';
gc();
gc();
}
gc();
}
waslm = 1;
}
else if (cc == 'L') {
gc();
ERROR();
n = cc - '0';
gc();
gc();
gc();
}
if (cc == 'n') {
gc();
n--;
}
}
else if (cc == '0') {
n = 1;
}
n = cc - '0';
gc();
gc();
}
}
else {
ERROR();
}
if (!n && waslm) {
lp = 1;
}
else {
ic = -1;
while (n-- > 0) {
ERROR();
gc();
if (n > 0 && lp >= 2 &&
ERROR();
lp -= 2;
break;
}
}
}
}
}
if (arrp > 0) {
for (i = 0; i < arrp; i++)
}
else {
}
/* LINTED */
if (clc > 0) {
for (i = 0; i < clc; i++)
}
else {
}
return p;
}
/* get list of arguments */
static DEMARG* getarglist()
{
DEMARG* p;
int acmax;
int ncount;
acmax = -1;
ncount = 0;
for (;;) {
/* get the argument */
if (p == NULL) {
if (waserror)
return NULL;
return head;
}
/* cache it for Tn and Nnn */
head = p;
}
else {
curr = p;
}
}
}
/* entry point for demangling */
{
int nc;
long n;
char* t;
char* t2;
char* t3;
char* ob;
int flag;
int cuflag;
return -1;
cuflag = 0;
if (clip_under && *s == '_')
s++, cuflag = 1;
if (!*s)
return -1;
/* set up space and input buffer management */
sp = -1;
waserror = 0;
p->sc = 0;
p->f = NULL;
p->slev = -1;
/* special case local variables */
if (cuflag)
s--;
t = s + 2;
n = 0;
while (isdigit(*t)) {
n = n * 10 + *t - '0';
t++;
}
if (*t) {
p->f = copy(t);
/* LINTED */
p->slev = (short)n;
goto done2;
}
}
if (cuflag)
s++;
if (s[0] == '_' && s[1] == '_' &&
p->sc = s[4];
t = (s[2] == 's' ? s + 7 : s + 12);
while (*t == '_')
t++;
p->f = copy(t);
nc = 3;
nc = 2;
nc = 2;
nc = 4;
nc = 2;
if (t2)
cc = 0;
goto done2;
}
/* special case type names */
if (cuflag)
s--;
t = s;
flag = 0;
while (t[0] && (t[0] != '_' || t == s || t[-1] != '_'))
t++;
if (t[0] == '_' && t[1] == 'p' && t[2] == 't' &&
t[3] == '_' && t[4] == '_')
flag = 1;
if (t[0] == '_' && t[1] == '_' && t[2] == 'p' && t[3] == 't' &&
t[4] == '_' && t[5] == '_')
flag = 1;
if (!flag) {
t = s;
if ((t[0] == '_' && t[1] == '_' && t[2] == 'Q' &&
flag = 2;
}
if (flag) {
sp = -1;
waserror = 0;
if (flag == 1) {
}
else {
}
return -1;
cc = 0;
goto done2;
}
if (cuflag)
s++;
sp = -1;
push(s, 9999);
waserror = 0;
/* get function name */
nc = 0;
nbuf[0] = 0;
if (!base[0] ||
gc();
break;
}
gc();
/* conversion operators */
return -1;
break;
}
}
return -1;
/* pick off delimiter */
gc();
gc();
if (!cc)
return -1;
}
/* get class name */
return -1;
}
/* a function template */
gc();
gc();
gc();
gc();
gc();
return -1;
n = cc - '0';
gc();
gc();
}
gc();
}
if (n < 1)
return -1;
while (n-- > 0) {
return -1;
gc();
}
return -1;
gc();
gc();
}
goto done;
}
gc();
}
/* get arg list for function */
if (cc == 'F') {
gc();
return -1;
}
done:
return -1;
/* figure out type we got */
if (p->sc) {
switch (p->sc) {
case 'i':
break;
case 'd':
break;
case 'b':
break;
case 'C':
dt = DEM_CMFUNC;
break;
case 'S':
dt = DEM_SMFUNC;
break;
default:
fatal("bad type set for p->sc", (char*)0, (char*)0);
break;
}
}
else if (p->slev != -1) {
}
dt = DEM_OMFUNC;
}
t3 = p->f;
!t3[4])
else
}
else {
}
}
else {
}
}
else
}
else if (p->f != NULL) {
t3 = p->f;
!t3[6])
else
}
else {
}
}
fatal("cannot characterize type of input", (char*)0, (char*)0);
return 0;
}
/************************* PRINT AN UNMANGLED NAME *************************/
/* format a class name */
{
int i;
void dem_printarglist();
fatal("bad argument to dem_printcl()", (char*)0, (char*)0);
buf[0] = 0;
i = 0;
while (p != NULL) {
i++;
/* handle nested */
if (i > 1)
/* template class */
}
p = p->next;
}
}
/* format an argument list */
{
int i;
void dem_printarg();
fatal("bad argument to dem_printarglist()", (char*)0, (char*)0);
/* special case single "..." argument */
return;
}
/* special case single "void" argument */
return;
}
buf[0] = 0;
i = 0;
while (p != NULL) {
i++;
if (i > 1)
p = p->next;
}
}
/* format a single argument */
{
char* t;
char* m;
char* mm;
int arrindx;
long dim;
int i;
int sv;
char* s;
char* trail;
int clc;
fatal("bad argument to dem_printarg()", (char*)0, (char*)0);
/* format the underlying type */
sv = !f;
switch (p->base) {
/* fundamental types */
case 'v':
t = "void";
break;
case 'c':
t = "char";
break;
case 's':
t = "short";
break;
case 'i':
t = "int";
break;
case 'l':
t = "long";
break;
case 'f':
t = "float";
break;
case 'd':
t = "double";
break;
case 'r':
t = "long double";
break;
case 'G':
t = "T";
break;
case 'e':
t = "...";
sv = 1;
break;
/* functions */
case 'F':
break;
/* class, struct, union, enum */
case 'C':
t = bufc;
break;
default:
fatal("bad base type in dem_printarg()", (char*)0, (char*)0);
break;
}
/* handle modifiers and declarators */
pref[0] = 0;
m = p->mods;
if (m == NULL)
m = "";
/* const and unsigned */
mm = m;
while (*mm) {
break;
}
mm++;
}
mm = m;
while (*mm) {
if (*mm == 'U') {
break;
}
mm++;
}
/* go through modifier list */
mm = m;
ptrs[0] = 0;
arrindx = 0;
clc = 0;
while (*mm) {
if (mm[0] == 'P') {
}
else if (mm[0] == 'R') {
}
else if (mm[0] == 'M') {
}
mm++;
}
mm++;
}
mm++;
}
else if (mm[0] == 'A') {
if (!ptrs[0]) {
sv = 1;
}
}
else {
sv = 1;
}
}
/* ignore */
}
else {
fatal("bad value in modifier list", (char*)0, (char*)0);
}
mm++;
}
/* put it together */
if (p->base == 'F') {
i = 0;
if (ptrs[0] == ' ')
i = 1;
trail = "";
trail = " const";
if (ptrs[i])
else
}
else {
(void) sprintf(buf, "%s%s%s%s%s", pref, t, ptrs[0] == '(' || isalnum(ptrs[0]) || ptrs[0] == '_' ? " " : "", ptrs, s);
}
else
}
}
struct Ops {
char* encode;
char* name;
};
"__pp", "operator++",
"__as", "operator=",
"__vc", "operator[]",
"__nw", "operator new",
"__dl", "operator delete",
"__rf", "operator->",
"__ml", "operator*",
"__mm", "operator--",
"__oo", "operator||",
"__md", "operator%",
"__mi", "operator-",
"__rs", "operator>>",
"__ne", "operator!=",
"__gt", "operator>",
"__ge", "operator>=",
"__or", "operator|",
"__aa", "operator&&",
"__nt", "operator!",
"__apl", "operator+=",
"__amu", "operator*=",
"__amd", "operator%=",
"__ars", "operator>>=",
"__aor", "operator|=",
"__cm", "operator,",
"__dv", "operator/",
"__pl", "operator+",
"__ls", "operator<<",
"__eq", "operator==",
"__lt", "operator<",
"__le", "operator<=",
"__ad", "operator&",
"__er", "operator^",
"__co", "operator~",
"__ami", "operator-=",
"__adv", "operator/=",
"__als", "operator<<=",
"__aad", "operator&=",
"__aer", "operator^=",
"__rm", "operator->*",
"__cl", "operator()",
};
/* format a function name */
{
int i;
fatal("bad argument to dem_printfunc()", (char*)0, (char*)0);
/* conversion operators */
}
/* might be overloaded operator */
else {
i = 0;
i++;
else
}
}
else {
}
}
/* entry point to formatting functions */
{
char* s;
int t;
return -1;
buf[0] = 0;
/* type names */
return 0;
}
return 0;
}
if (p->sc == 'b') {
return 0;
}
/* format class name */
buf2[0] = 0;
}
/* special case constructors and destructors */
t = 0;
while (s >= buf2) {
if (*s == '>')
t++;
else if (*s == '<')
t--;
else if (*s == ':' && !t)
break;
s--;
}
if (!STRCMP(p->f, "__ct")) {
}
else if (!STRCMP(p->f, "__dt")) {
}
else {
dem_printfunc(p, buf2);
}
/* format argument list */
}
/* const member functions */
if (p->sc == 'C')
return 0;
}
/* explain a type */
char* dem_explain(enum DEM_TYPE t)
{
switch (t) {
case DEM_STI:
return "static construction function";
case DEM_STD:
return "static destruction function";
case DEM_VTBL:
return "virtual table";
case DEM_PTBL:
return "ptbl vector pointing to vtbls";
case DEM_FUNC:
return "function";
case DEM_MFUNC:
return "member function";
case DEM_SMFUNC:
return "static member function";
case DEM_CMFUNC:
return "constant member function";
case DEM_OMFUNC:
return "conversion operator member function";
case DEM_CTOR:
return "constructor";
case DEM_DTOR:
return "destructor";
case DEM_DATA:
return "data";
case DEM_MDATA:
return "member data";
case DEM_LOCAL:
return "local variable";
case DEM_CTYPE:
return "class type";
case DEM_TTYPE:
return "template type";
default:
fatal("bad type passed to dem_explain()", (char*)0, (char*)0);
return "";
}
}
/* ------------------------------------------------------------------------ */
/* demangle in --> out */
{
DEM d;
return -1;
return -1;
}
return 0;
}
/*
The routines below are provided to enable the tools nm,
prof, and gprof to use the demangling function provided
in this file.
Entry point is DemangleAndFormat() --MK
*/
#include <string.h>
static int CheckSpecialCase( char *, DEM *);
static void ProcessVtname( DEM *);
static char *FormatName( char *, char *, char *);
static char d_buf[512];
static char *ctor_str = "static constructor function for %s";
static char *dtor_str = "static destructor function for %s";
static char *ptbl_str = "pointer to the virtual table vector for %s";
static char *vtbl_str = "virtual table for class %s";
extern char *cafe_demangle(char *, char *);
{
int dem_ret_val;
{
/* a cafe symbol...
*/
}
{ /* name not demangled */
d_buf[0] = '\0';
}
else /* name demangled by dem() */
{
{
}
else /* not a special case */
{
}
}
return (name);
} /* DemangleAndFormat */
/* alloc memory and create name in necessary format.
Return name string
*/
{
return (OldName);
}
/*
Check for special cases: __sti__, _std__, __ptbl_vec__, __vtbl__
use demP for the procesing
Return 1 if it is a special case, otherwise return 0.
*/
{
int retVal = 1;
{
}
{
}
{
}
{
}
{
else
retVal = 0; /* not a special case */
}
else
{
retVal = 0; /* not a special case */
d_buf[0] = '\0';
}
return (retVal);
}
/* process demP->vtname */
/* called by CheckSpecialCase() */
{
char *nameString;
char *tail;
int marker;
char saveChar;
/* check if mangled name of derived class (a heuristic) */
/* different possibilities for string demP->vtname: */
/* (1) 'filename_ext' class name in file */
/* (2) '%dname' class derived from class */
/* (3) '%dname__filename_ext' class derived from class in file */
/* note: the filename itself could start with a digit */
marker = 2;
marker = 3;
else
marker = 0;
{
if (marker > 0)
if (marker > 0)
}
{ /* could be case (1) or case (2) */
/* case (1) if filename starts with a digit */
if (marker == 0) /* case (2) */
{
while (isdigit( *nameString))
nameString++;
}
else /* case (1) */
{
if (marker > 0)
if (marker > 0)
}
}
else /* case (3) */
{
while (isdigit( *nameString))
nameString++;
if (marker > 0)
if (marker > 0)
}
} /* ProcessVtname */