Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source tools demangler osrc demangle.c
Document Actions

demangle.c

by Michael L Powell last modified 2007-01-26 03:24

Click here to get the file

Size 8.1 kB - File type text/plain

File contents

/*ident	"@(#)cls4:tools/demangler/osrc/demangle.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
 */

#include <ctype.h>
#include <setjmp.h>
#if __STDC__ == 1
#	include <stdlib.h>
#else
	extern long strtol();
#endif
#include "elf_dem.h"
#include "String.h"

#define eqop(str)		(*(str)=='o' && (*((str)+1)=='p'))
#define eq__(str)		(*(str)=='_' && (*((str)+1)=='_'))
#define eqt__(str)		(*(str)=='t' && (*((str)+1)=='_') && (*((str)+2)=='_'))


/* The variable "hold" contains the pointer to the array initially
 * handed to demangle.  It is returned if it is not possible to
 * demangle the string.  NULL is returned if a memory allocation
 * problem is encountered.  Thus one can do the following:
 *
 * char *mn = "Some mangled name";
 * char *dm = mangle(mn);
 * if (dm == NULL)
 *	printf("allocation error\n");
 * else if (dm == mn)
 * 	printf("name could not be demangled\n");
 * else
 *	printf("demangled name is: %s\n",dm);
 */
static char *hold;

/* this String is the working buffer for the demangle
 * routine.  A pointer into this String is returned
 * from demangle when it is possible to demangle the
 * String.  For this reason, the pointer should not
 * be saved between calls of demangle(), nor freed.
 */
static String *s = 0;

static int
getint(c)
char **c;
{
	return strtol(*c, c, 10);
}

/* If a mangled name has a __
 * that is not at the very beginning
 * of the string, then this routine
 * is called to demangle that part
 * of the name.  All overloaded functions,
 * and class members fall into this category.
 *
 * c should start with two underscores followed by a non-zero digit or an F.
 */
static char *
second(c)
char *c;
{
	int n;
	int ncl,nchar;
	int	const_flag = 0;

	if(!eq__(c))
		return hold;

	c += 2;

	if (!(isdigit(*c) || *c == 'F' || *c == 'Q'))
		return hold;

	if (isdigit(*c)) {
		int clen = -1;
		/* a member */
		n = getint(&c);
		if (n == 0 || (clen=strlen(c)) < n)
			return hold;
		s = prep_String("::",2,s);
		s = nprep_String(c,clen,s,n);
		c += n;
	}
	else if(*c == 'Q') {
		String *tmp;
		if (!isdigit(c[1]) || c[2] != '_') return hold;
		tmp = mk_String(0);
		ncl = c[1] - 48;
		c += 3;
		tmp = set_String(tmp,"",0);
		while (ncl--) {
			nchar = 0;
			while(isdigit(*c)) nchar = 10*nchar + (*c++ - 48);
			tmp = napp_String(tmp,c,strlen(c),nchar);
			tmp = app_String(tmp,"::",2);
			c += nchar;
		}
		s = prep_String(PTR(tmp),strlen(PTR(tmp)),s);
		free_String(&tmp);
	}
        while (*c == 'S' || *c == 'C') {
                if(*c == 'S') {
                c++;
                }
                if(*c == 'C') {
                const_flag = 1;
                c++;
                }
        }
	if(*c == 'F') {
		/* an overloaded function */
		switch (*++c) {
		case '\0':
			return hold;
		case 'v':
			s = app_String(s,"()",2);
			break;
		default:
			if(doargs(&s,c) < 0)
				return hold;
		}
	}
	if ( const_flag ) {
		s = app_String(s," const",6);
	}
	return PTR(s);
}

/* on entry: clen==strlen(c), or <0
 */
static char *no_pt_demangle_withlen(c, clen)
char *c;
int clen;
{
	register int i = 0;
	register int ncl,nchar;
	extern jmp_buf jbuf;

	if (setjmp(jbuf))
		return 0;

	hold = c;
	s = mk_String(s);
	s = set_String(s,"",0);

	if(c == 0 || *c == 0)
		return hold;

	if(!eq__(c)) {
		/* If a name does not begin with a __
		 * but it does contain one, it is either
		 * a member or an overloaded function.
		 */
		while (1) {
			while(c[i] && !eq__(c+i))
				i++;
			if (c[i]) {
				/* Advance to first non-underscore */
				while (c[i+2] == '_')
					i++;
			}
			if (strncmp(c+i, "__pt__", 6) != 0) break;
			i += 6;
		}
		
		if(eq__(c+i)) {
			/* Copy the simple name */
			s = napp_String(s,c,clen,i);
			/* Process the signature */
			return second(c+i);
		} else
			return hold;
	} else {
		char *x;
		int oplen;
		c += 2;
		clen -= 2;

		/* For automatic variables, or internal static
		 * variables, a __(number) is prepended to the
		 * name.  If this is encountered, strip this off
		 * and return.
		 */
		if(isdigit(*c)) {
			while(isdigit(*c))
				c++;
			return c;
		}

		if(*c == 'Q') {
			ncl = c[1] - 48;
			c += 3;
			while (ncl--) {
				nchar = 0;
				while(isdigit(*c)) 
					nchar = 10*nchar + (*c++ - 48);
				s = napp_String(s,c,strlen(c),nchar);
				if (ncl) s = app_String(s,"::",2);
				c += nchar;
			}
			return PTR(s);
		}
		/* Handle operator functions -- this
		 * automatically calls second, since
		 * all operator functions are overloaded.
		 */
		if(x = findop(c, &oplen)) {
			s = app_String(s,"operator",8);
			s = app_String(s,x,-1);
			c += oplen;
			return second(c);
		}

		/* Operator cast does not fit the mould
		 * of the other operators.  Its type name
		 * is encoded.  The cast function must
		 * take a void as an argument.
		 */
		if(eqop(c)) {
			int r;
			s = app_String(s,"operator ",9);
			c += 2;
			r = doarg(&s,c);
			if(r < 0)
				return hold;
			c += r;
			return second(c);
		}

		/* Constructors and Destructors are also
		 * a special case of operator name.  Note
		 * that the destructor, while overloaded,
		 * must always take the same arguments --
		 * none.
		 */
		if ((*c == 'c' || *c == 'd') && eqt__(c+1)) {
			int n;
			char *c2 = c+2;
			char cx = c[0];
			c += 4;
			clen -= 4;
			n = getint(&c);
			if(n == 0)
				return hold;
			s = napp_String(s,c,clen,n);
			if(cx == 'd')
				s = prep_String("~",1,s);
			return second(c2);
		}
		return hold;
	}
}

/*
 *	this function finds the first occurrence of __pt__ in
 *	the string.  It returns 0 if __pt__ is not found.
 */
static char *find_pt(p)
char *p;
{
	while (*p) {
		while (*p && *p != '_') p++;
		if (*p != '_') return (0);
		if (strncmp(p, "__pt__", 6) == 0) {
			return (p);
		}
		p++;
	}
	return (0);
}

static String *val1, *val2;
static String *arglist;

static char *demangle_ptstuff(c)
char *c;
{
	char *retval;
	char *p, *q;
	char *argsptr;
	int count;
	int arglen;
	int savec;
	
	p = find_pt(c);
	if (p == 0) {
		return (c);
	}
	
	val1 = mk_String(val1);
	val1 = set_String(val1,"",0);
	val1 = app_String(val1,c,p-c);
	arglist = mk_String(arglist);
	
	while (1) {
		q = find_pt(p);
		if (q == 0) break;
		val1 = app_String(val1,p,q-p); /* append all of the chars
						  up to the __pt__ */
		p = q + 6;		/* advance past the __pt__ */
		
		/* see if this is a parameterized function */
		
		if (*p == 'F') {
			p++;
			arglen = strtol(p, &p, 10);
			p += arglen;
			continue;
		}
		
		/* now demangle the PT argument list */
		
		/* first get the number of characters in the arglist */
		arglen = strtol(p, &p, 10);
		
		/* next get ready to call doargs */
		savec = p[arglen];
		p[arglen] = '\0';
		arglist = set_String(arglist,"",0);
		
		count = doargs(&arglist,p+1);
		
		/* replace the parentheses with angle brackets */
		argsptr = PTR(arglist);
		
		argsptr[0] = '<';
		argsptr[strlen(argsptr)-1] = '>';
		
		val1 = app_String(val1,argsptr,strlen(argsptr));
		
		/* cleanup */
		p[arglen] = savec;
		p += arglen;
	}
	if (p != 0 && strlen(p) > 0) {
		val1 = app_String(val1,p,strlen(p));
	}
	
	retval = PTR(val1);
	p = find_pt(retval);
	if (p == 0) {
		return (retval);
	}
	else {
		/* we need to pt-demangle again */
		val2 = mk_String(val2);
		val2 = set_String(val2,retval,strlen(retval));
		retval = PTR(val2);
		return (demangle_ptstuff(retval));
	}
}

char *demangle_withlen(c, clen)
char *c;
int clen;
{
	char *retval, *p;
	
	retval = no_pt_demangle_withlen(c, clen);
	p = find_pt(retval);
	if (p == 0) {
		return (retval);
	}
	else {
		return (demangle_ptstuff(retval));
	}
}

char *demangle(c)
char *c;
{
	return demangle_withlen(c, strlen(c));
}
« December 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: