xref: /inferno-os/utils/5coff/auxi.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include	"auxi.h"
2 
3 Prog *firstp, *textp, *curtext, *lastp, *etextp;
4 Symx *hash[NHASH];
5 Auto *lasta;
6 long autosize;
7 int version = 0;
8 
9 static int
private(char * s)10 private(char *s)
11 {
12 	return strcmp(s, "safe") == 0 || strcmp(s, "ret") == 0 || strcmp(s, "string") == 0;
13 }
14 
15 static int
zlen(char * s)16 zlen(char *s)
17 {
18 	int i;
19 
20 	for(i=1; s[i] != 0 || s[i+1] != 0; i += 2)
21 		;
22 	i++;
23 	return i+1;
24 }
25 
26 static Symx*
allocsym(char * symb,int l,int v)27 allocsym(char *symb, int l, int v)
28 {
29 	Symx *s;
30 
31 	s = malloc(sizeof(Symx));
32 	s->name = malloc(l);
33 	memmove(s->name, symb, l);
34 	s->name[l-1] = '\0';
35 	s->type = 0;
36 	s->version = v;
37 	s->value = 0;
38 	s->link = nil;
39 	return s;
40 }
41 
42 Symx*
lookupsym(char * symb,int v)43 lookupsym(char *symb, int v)
44 {
45 	Symx *s, **as;
46 	char *p;
47 	long h;
48 	int c, l;
49 
50 	h = v;
51 	for(p=symb; c = *p; p++)
52 		h = h+h+h + c;
53 	l = (p - symb) + 1;
54 	if(h < 0)
55 		h = ~h;
56 	h %= NHASH;
57 	for(s = hash[h]; s != nil; s = s->link)
58 		if(s->version == v)
59 		if(memcmp(s->name, symb, l) == 0)
60 			return s;
61 	s = allocsym(symb, l, v);
62 	for(as = &hash[h]; *as != nil; as = &((*as)->link))
63 		;
64 	*as = s;
65 	// s->link = hash[h];
66 	// hash[h] = s;
67 	return s;
68 }
69 
70 static void
addauto(Auto ** aut,Symx * s,int t,long v)71 addauto(Auto **aut, Symx *s, int t, long v)
72 {
73 	Auto *a, **aa;
74 
75 	a = (Auto*)malloc(sizeof(Auto));
76 	a->asym = s;
77 	a->link = nil;
78 	a->aoffset = v;
79 	a->type = t;
80 	for(aa = aut; *aa != nil; aa = &((*aa)->link))
81 		;
82 	*aa = a;
83 }
84 
85 static Prog*
newprog(int as,long pc,long ln)86 newprog(int as, long pc, long ln)
87 {
88 	Prog *p;
89 
90 	p = (Prog *)malloc(sizeof(Prog));
91 	p->as = as;
92 	p->pc = pc;
93 	p->line = ln;
94 	p->link = p->cond = P;
95 	if(firstp == P)
96 		firstp = p;
97 	else
98 		lastp->link = p;
99 	lastp = p;
100 	if(as == ATEXT){
101 		if(textp == P)
102 			textp = p;
103 		else
104 			etextp->cond = p;
105 		etextp = p;
106 	}
107 	return p;
108 }
109 
110 static int
line(long pc)111 line(long pc)
112 {
113 	char buf[1024], *s;
114 
115 	// return pc2line(pc);
116 	if(fileline(buf, sizeof(buf), pc)){
117 		for(s = buf; *s != ':' && *s != '\0'; s++)
118 			;
119 		if(*s != ':')
120 			return -1;
121 		return atoi(s+1);
122 	}
123 	return -1;
124 }
125 
126 static void
lines(long v)127 lines(long v)
128 {
129 	long ll, nl, pc;
130 	if(etextp != P){
131 		ll = 0;
132 		for(pc = etextp->pc; pc < v; pc += 4){
133 			nl = line(pc);
134 			if(nl != -1 && nl != ll){
135 				newprog(ATEXT-1, pc, nl);
136 				ll = nl;
137 			}
138 		}
139 		pc -= 4;
140 		if(lastp->pc != pc){
141 			nl = line(pc);
142 			if(nl != -1)
143 				newprog(ATEXT-1, pc, nl);
144 		}
145 	}
146 }
147 
148 void
beginsym(void)149 beginsym(void)
150 {
151 }
152 
153 /* create the same structures as in 5l so we can use same coff.c source file */
154 void
newsym(int i,char * nm,long v,int t)155 newsym(int i, char *nm, long v, int t)
156 {
157 	long l, ver;
158 	char *os;
159 	Symx *s;
160 	Prog *p;
161 
162 	if(i == 0 && (t == 't' || t == 'T') && strcmp(nm, "etext") == 0)
163 		return;
164 	if(nm[0] == '.' && private(nm+1))
165 		return;
166 // print("%s %ld %c\n", nm, v, t);
167 	ver = 0;
168 	if(t == 't' || t == 'l' || t == 'd' || t == 'b'){
169 		ver = ++version;
170 		if(ver == 0)
171 			diag("0 version for static");
172 	}
173 	if(t == 'a' || t == 'p')
174 		s = allocsym(nm, strlen(nm)+1, 0);
175 	else if(t == 'z' || t == 'Z')
176 		s = allocsym(nm, zlen(nm), 0);
177 	else if(t != 'm'){
178 		s = lookupsym(nm, ver);
179 		if(s->type != 0)
180 			diag("seen sym before in newsym");
181 		s->value = v;
182 	}
183 	else
184 		s = nil;
185 	switch(t){
186 	case 'T':
187 	case 'L':
188 	case 't':
189 	case 'l':
190 		lines(v);
191 		if(t == 'l' || t == 'L')
192 			s->type = SLEAF;
193 		else
194 			s->type = STEXT;
195 		p = newprog(ATEXT, v, line(v));
196 		p->from.sym = s;
197 		p->to.autom = lasta;
198 		lasta = nil;
199 		break;
200 	case 'D':
201 	case 'd':
202 		s->type = SDATA;
203 		s->value -= INITDAT;
204 		break;
205 	case 'B':
206 	case 'b':
207 		s->type = SBSS;
208 		s->value -= INITDAT;
209 		break;
210 	case 'f':
211 		// version++;
212 		s->type = SFILE;
213 		os = s->name;
214 		l = strlen(os)+1;
215 		s->name = malloc(l+1);
216 		s->name[0] = '>';
217 		memmove(s->name+1, os, l);
218 		free(os);
219 		break;
220 /*
221 	case 'f'+'a'-'A':
222 		s->type = SFILE;
223 		break;
224 */
225 	case 'z':
226 		addauto(&lasta, s, D_FILE, v);
227 		break;
228 	case 'Z':
229 		addauto(&lasta, s, D_FILE1, v);
230 		break;
231 	case 'a':
232 		addauto(&(etextp->to.autom), s, D_AUTO, -v);
233 		break;
234 	case 'p':
235 		addauto(&(etextp->to.autom), s, D_PARAM, v);
236 		break;
237 	case 'm':
238 		etextp->to.offset = v-4;
239 		autosize = v;
240 		break;
241 	default:
242 		diag("bad case in newsym");
243 		break;
244 	}
245 }
246 
247 void
endsym(void)248 endsym(void)
249 {
250 	lines(INITTEXT+textsize);
251 }
252