Charles.Forsyth20060303644188019 years agoHistory
251 lines · 3.8 KB · C
RawDownload
#include	"auxi.h" Prog *firstp, *textp, *curtext, *lastp, *etextp;Symx *hash[NHASH];Auto *lasta;long autosize;int version = 0; static intprivate(char *s){	return strcmp(s, "safe") == 0 || strcmp(s, "ret") == 0 || strcmp(s, "string") == 0;} static intzlen(char *s){	int i; 	for(i=1; s[i] != 0 || s[i+1] != 0; i += 2)		;	i++;	return i+1;} static Symx*allocsym(char *symb, int l, int v){	Symx *s; 	s = malloc(sizeof(Symx));	s->name = malloc(l);	memmove(s->name, symb, l);	s->name[l-1] = '\0';	s->type = 0;	s->version = v;	s->value = 0;	s->link = nil;	return s;} Symx*lookupsym(char *symb, int v){	Symx *s, **as;	char *p;	long h;	int c, l; 	h = v;	for(p=symb; c = *p; p++)		h = h+h+h + c;	l = (p - symb) + 1;	if(h < 0)		h = ~h;	h %= NHASH;	for(s = hash[h]; s != nil; s = s->link)		if(s->version == v)		if(memcmp(s->name, symb, l) == 0)			return s;	s = allocsym(symb, l, v);	for(as = &hash[h]; *as != nil; as = &((*as)->link))		;	*as = s;	// s->link = hash[h];	// hash[h] = s;	return s;} static voidaddauto(Auto **aut, Symx *s, int t, long v){	Auto *a, **aa; 	a = (Auto*)malloc(sizeof(Auto));	a->asym = s;	a->link = nil;	a->aoffset = v;	a->type = t;	for(aa = aut; *aa != nil; aa = &((*aa)->link))		;	*aa = a;} static Prog*newprog(int as, long pc, long ln){	Prog *p; 	p = (Prog *)malloc(sizeof(Prog));	p->as = as;	p->pc = pc;	p->line = ln;	p->link = p->cond = P;	if(firstp == P)		firstp = p;	else		lastp->link = p;	lastp = p;	if(as == ATEXT){		if(textp == P)			textp = p;		else			etextp->cond = p;		etextp = p;		}	return p;} static intline(long pc){	char buf[1024], *s; 	// return pc2line(pc);	if(fileline(buf, sizeof(buf), pc)){		for(s = buf; *s != ':' && *s != '\0'; s++)			;		if(*s != ':')			return -1;		return atoi(s+1);	}	return -1;} static voidlines(long v){	long ll, nl, pc;	if(etextp != P){		ll = 0;		for(pc = etextp->pc; pc < v; pc += 4){			nl = line(pc);			if(nl != -1 && nl != ll){				newprog(ATEXT-1, pc, nl);				ll = nl;			}		}		pc -= 4;		if(lastp->pc != pc){			nl = line(pc);			if(nl != -1)				newprog(ATEXT-1, pc, nl);		}	}} voidbeginsym(void){} /* create the same structures as in 5l so we can use same coff.c source file */voidnewsym(int i, char *nm, long v, int t){	long l, ver;	char *os;	Symx *s;	Prog *p; 	if(i == 0 && (t == 't' || t == 'T') && strcmp(nm, "etext") == 0)		return;	if(nm[0] == '.' && private(nm+1))		return;// print("%s %ld %c\n", nm, v, t);	ver = 0;	if(t == 't' || t == 'l' || t == 'd' || t == 'b'){		ver = ++version;		if(ver == 0)			diag("0 version for static");	}	if(t == 'a' || t == 'p')		s = allocsym(nm, strlen(nm)+1, 0);	else if(t == 'z' || t == 'Z')		s = allocsym(nm, zlen(nm), 0);	else if(t != 'm'){		s = lookupsym(nm, ver);		if(s->type != 0)			diag("seen sym before in newsym");		s->value = v;	}	else		s = nil;	switch(t){	case 'T':	case 'L':	case 't':	case 'l':		lines(v);		if(t == 'l' || t == 'L')			s->type = SLEAF;		else			s->type = STEXT;		p = newprog(ATEXT, v, line(v));		p->from.sym = s;		p->to.autom = lasta;		lasta = nil;		break;	case 'D':	case 'd':		s->type = SDATA;		s->value -= INITDAT;		break;	case 'B':	case 'b':		s->type = SBSS;		s->value -= INITDAT;		break;	case 'f':		// version++;		s->type = SFILE;		os = s->name;		l = strlen(os)+1;		s->name = malloc(l+1);		s->name[0] = '>';		memmove(s->name+1, os, l);		free(os);		break;/*	case 'f'+'a'-'A':		s->type = SFILE;		break;*/	case 'z':		addauto(&lasta, s, D_FILE, v);		break;	case 'Z':		addauto(&lasta, s, D_FILE1, v);		break;	case 'a':		addauto(&(etextp->to.autom), s, D_AUTO, -v);		break;	case 'p':		addauto(&(etextp->to.autom), s, D_PARAM, v);		break;	case 'm':		etextp->to.offset = v-4;		autosize = v;		break;	default:		diag("bad case in newsym");		break;	}} voidendsym(void){	lines(INITTEXT+textsize);}