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