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

args.c

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

Click here to get the file

Size 7.9 kB - File type text/plain

File contents

/*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 <ctype.h>
#if __STDC__ == 1
#	include <stdlib.h>
#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;
}
« April 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
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: