Commit | Line | Data |
---|---|---|
629188b5 JR |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | #include <stdio.h> | |
3 | #include <signal.h> | |
4 | ||
5 | #include "as.h" | |
6 | #include "assyms.h" | |
7 | #include "asexpr.h" | |
8 | #include "asscan.h" | |
9 | ||
10 | int curlen; | |
11 | /* | |
12 | * variables to manage the assembly input | |
13 | */ | |
14 | char *dotsname; /*the current file name; managed by the parser*/ | |
15 | int lineno; /*current line number; managed by the parser*/ | |
16 | int silent; /*don't complain about any errors*/ | |
17 | int savelabels; /*write the labels to the a.out file*/ | |
18 | ||
19 | #ifdef DEBUG | |
20 | int debug; | |
21 | int toktrace; | |
22 | #endif | |
23 | ||
24 | long datbase; | |
25 | ||
26 | char *endcore; /*where to get more symbol space*/ | |
27 | ||
28 | struct hdr hdr = { | |
29 | 0410, 0, 0, 0, 0, 0, 0, 0, | |
30 | }; | |
31 | ||
32 | #ifndef vax | |
33 | struct {short hiword; short loword;}; /* stupid fp-11 */ | |
34 | #else | |
35 | #define writel(p,n,f) fwrite( (long) p, sizeof (long), n, f) | |
36 | #endif | |
37 | ||
38 | char *tmpn1; | |
39 | char *tmpn2; | |
40 | char *tmpn3; | |
41 | ||
42 | struct exp usedot[NLOC+NLOC]; | |
43 | ||
44 | FILE *usefile[NLOC+NLOC]; | |
45 | FILE *rusefile[NLOC+NLOC]; | |
46 | char sibuf[TOKBUFLG]; /*buffer used for all input*/ | |
47 | char sobuf[TOKBUFLG]; /*buffer used for all output*/ | |
48 | /*except stdout and relfil*/ | |
49 | char stdoutbuf[BUFSIZ]; /*stdout buffer*/ | |
50 | ||
51 | extern int njxxx; /*number of jumpxxx instructs*/ | |
52 | extern int d124; /*allocate 1,2 or 4 bytes for unknowns*/ | |
53 | ||
54 | int delexit(); | |
55 | ||
56 | char *innames[32]; /*names of the files being assembled*/ | |
57 | int ninfiles; /*how many interesting files there are*/ | |
58 | ||
59 | main(argc, argv) | |
60 | int argc; | |
61 | char **argv; | |
62 | { | |
63 | int locindex; | |
64 | long v; | |
65 | char *outfile = "a.out"; | |
66 | int filestep; | |
67 | char *cp; | |
68 | ||
69 | setbuf(stdout, stdoutbuf); | |
70 | ninfiles = 0; | |
71 | silent = 0; | |
72 | useVM = 0; | |
73 | #ifdef DEBUG | |
74 | debug = 0; | |
75 | #endif | |
76 | /* | |
77 | * Give the error processor something to complain about | |
78 | * if there is an error processing an argument | |
79 | */ | |
80 | dotsname = "<argv error>"; | |
81 | while (argc > 1) { | |
82 | if (argv[1][0] == '-'){ | |
83 | cp = argv[1] + 1; | |
84 | /* | |
85 | * We can throw away single minus signs, so | |
86 | * that make scripts for the PDP 11 assembler work | |
87 | * on this assembler too | |
88 | */ | |
89 | while (*cp){ | |
90 | switch(*cp++){ | |
91 | default: | |
92 | yyerror("Unknown flag: %c", *--cp); | |
93 | cp++; | |
94 | break; | |
95 | case 'd': | |
96 | d124 = *cp++ - '0'; | |
97 | if ( (d124 != 1) && (d124 != 2) && | |
98 | (d124 != 4)){ | |
99 | yyerror("-d[124] only"); | |
100 | exit(1); | |
101 | } | |
102 | break; | |
103 | case 'o': | |
104 | if (argc < 3){ | |
105 | yyerror("-o what???"); | |
106 | exit(1); | |
107 | } | |
108 | outfile = argv[2]; | |
109 | argc -= 2; | |
110 | argv += 2; | |
111 | goto nextarg; | |
112 | ||
113 | case 'V': | |
114 | useVM = 1; | |
115 | break; | |
116 | #ifdef fooiearg | |
117 | case 'M': | |
118 | if (argc < 3){ | |
119 | yyerror("Mode what?"); | |
120 | exit(1); | |
121 | } | |
122 | hdr.magic = 0; | |
123 | cp = argv[2]; | |
124 | while (*cp && ('0' <= *cp) && (*cp <= '7')) | |
125 | hdr.magic = hdr.magic<<3 + *cp++ - '0'; | |
126 | argc -= 2; | |
127 | argv += 2; | |
128 | goto nextarg; | |
129 | case 'W': silent = 1; | |
130 | break; | |
131 | #endif | |
132 | ||
133 | #ifdef DEBUG | |
134 | case 'D': debug = 1; | |
135 | break; | |
136 | case 'T': toktrace = 1; | |
137 | break; | |
138 | #endif | |
139 | #ifdef METRIC | |
140 | case 'C': outcounters = 1; | |
141 | break; | |
142 | #endif | |
143 | case 'L': savelabels = 1; | |
144 | break; | |
145 | } /*end of the switch*/ | |
146 | } /*end of pulling out all arguments*/ | |
147 | } /*end of a flag argument*/ | |
148 | else { /*file name*/ | |
149 | if (ninfiles > 32){ | |
150 | yyerror("More than 32 file names"); | |
151 | exit(3); | |
152 | } | |
153 | innames[ninfiles++] = argv[1]; | |
154 | } | |
155 | --argc; ++argv; | |
156 | nextarg:; | |
157 | } /*end of looking at all of the arguments*/ | |
158 | ||
159 | if (anyerrs) | |
160 | exit(1); | |
161 | ||
162 | endcore = (char *)sbrk(0); | |
163 | ||
164 | /* | |
165 | * Install symbols in the table | |
166 | */ | |
167 | symtabinit(); | |
168 | syminstall(); | |
169 | /* | |
170 | * mark usedot: first NLOC slots for named text segments, | |
171 | * the next for named data segments. | |
172 | */ | |
173 | for (locindex=0; locindex<NLOC; locindex++) { | |
174 | usedot[locindex].xtype = XTEXT; | |
175 | usedot[locindex+NLOC].xtype = XDATA; | |
176 | } | |
177 | ||
178 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) | |
179 | signal(SIGINT, delexit); | |
180 | ||
181 | tmpn1 = (char *)mktemp("/tmp/asXXXXX"); | |
182 | tmpfil = fopen(tmpn1, "w"); | |
183 | if (tmpfil==NULL) { | |
184 | yyerror("Bad pass 1 temporary file for writing %s", tmpn1); | |
185 | delexit(); | |
186 | } | |
187 | setbuf(tmpfil,sobuf); | |
188 | ||
189 | inittmpfile(); | |
190 | buildtokensets(); /*sets to implement expression lookahead*/ | |
191 | ||
192 | if (ninfiles == 0){ /*take the input from stdin directly*/ | |
193 | setbuf(stdin, sibuf); | |
194 | lineno = 1; | |
195 | dotsname = "<stdin>"; | |
196 | ||
197 | yyparse(); | |
198 | } else { /*we have the names tanked*/ | |
199 | for (filestep = 0; filestep < ninfiles; filestep++){ | |
200 | new_dot_s(innames[filestep]); | |
201 | if (freopen(innames[filestep], "r", stdin) == NULL) { | |
202 | yyerror( "Can't open source file %s\n", | |
203 | innames[filestep]); | |
204 | exit(2); | |
205 | } | |
206 | setbuf(stdin,sibuf); | |
207 | ||
208 | yyparse(); | |
209 | } | |
210 | } | |
211 | ||
212 | closetmpfile(); /*kick out the last buffered intermediate text*/ | |
213 | ||
214 | if (anyerrs) | |
215 | delexit(); | |
216 | ||
217 | /* | |
218 | * Pass 1.5 | |
219 | */ | |
220 | sortsymtab(); | |
221 | ||
222 | #ifdef DEBUG | |
223 | if (debug) | |
224 | dumpsymtab(); | |
225 | #endif | |
226 | ||
227 | jxxxfix(); | |
228 | ||
229 | #ifdef DEBUG | |
230 | if (debug) | |
231 | dumpsymtab(); | |
232 | #endif | |
233 | ||
234 | #ifdef METRIC | |
235 | lgtmpfile = ftell(tmpfil); | |
236 | #endif | |
237 | ||
238 | fclose(tmpfil); | |
239 | tmpfil = fopen(tmpn1, "r"); | |
240 | if (tmpfil==NULL) { | |
241 | yyerror("Bad pass 2 temporary file for reading %s", tmpn1); | |
242 | delexit(); | |
243 | } | |
244 | setbuf(tmpfil,sibuf); | |
245 | ||
246 | /* | |
247 | * round and assign text segment origins | |
248 | */ | |
249 | tsize = 0; | |
250 | for (locindex=0; locindex<NLOC; locindex++) { | |
251 | v = round(usedot[locindex].xvalue, FW); | |
252 | usedot[locindex].xvalue = tsize; | |
253 | tsize += v; | |
254 | } | |
255 | /* | |
256 | * round and assign data segment origins | |
257 | */ | |
258 | datbase = round(tsize, PAGRND); | |
259 | for (locindex=0; locindex<NLOC; locindex++) { | |
260 | v = round(usedot[NLOC+locindex].xvalue, FW); | |
261 | usedot[NLOC+locindex].xvalue = datbase+dsize; | |
262 | dsize += v; | |
263 | } | |
264 | ||
265 | hdr.bsize = dsize; | |
266 | ||
267 | /* | |
268 | * Assign final values to symbols | |
269 | */ | |
270 | freezesymtab(); | |
271 | stabfix(); | |
272 | ||
273 | hdr.bsize -= dsize; | |
274 | ||
275 | txtfil = fopen(outfile, "w"); | |
276 | if (txtfil==NULL) { | |
277 | yyerror("Cannot create %s", outfile); | |
278 | delexit(); | |
279 | } | |
280 | setbuf(txtfil,sobuf); | |
281 | ||
282 | usefile[0] = txtfil; | |
283 | ||
284 | tmpn2 = (char *)mktemp("/tmp/aaatXXXXX"); | |
285 | tmpn3 = (char *)mktemp("/tmp/abatXXXXX"); | |
286 | ||
287 | relfil = fopen(tmpn3, "w"); | |
288 | if (relfil==NULL) { | |
289 | yyerror("Bad temp file for writing extra text segments %s", tmpn3); | |
290 | delexit(); | |
291 | } | |
292 | rusefile[0] = relfil; | |
293 | ||
294 | hdr.tsize = tsize; | |
295 | hdr.dsize = dsize; | |
296 | hdr.ssize = sizesymtab(); | |
297 | /* | |
298 | * hdr.trsize, hdr.drsize set by outrel | |
299 | */ | |
300 | ||
301 | /* *************** PASS 2 **************** */ | |
302 | ||
303 | writel(&hdr,8,txtfil); | |
304 | tsize = 0; | |
305 | dsize = 0; | |
306 | lineno = 1; | |
307 | dotp = &usedot[0]; | |
308 | #ifdef DEBUG | |
309 | if (debug) | |
310 | printf("\n\n\n\t\tPASS 2\n\n\n\n"); | |
311 | #endif | |
312 | passno = 2; | |
313 | inittmpfile(); | |
314 | ||
315 | yyparse(); | |
316 | ||
317 | closetmpfile(); | |
318 | ||
319 | /* | |
320 | * round csects to FW | |
321 | */ | |
322 | for (locindex=0; locindex<NLOC; locindex++) { | |
323 | if (usefile[locindex]) { | |
324 | txtfil=usefile[locindex]; | |
325 | dotp= &usedot[locindex]; | |
326 | while (usedot[locindex].xvalue & FW) | |
327 | outb(0); | |
328 | if (locindex>0) | |
329 | fclose(usefile[locindex]); | |
330 | fclose(rusefile[locindex]); | |
331 | } | |
332 | if (usefile[NLOC+locindex]) { | |
333 | txtfil = usefile[NLOC+locindex]; | |
334 | dotp= &usedot[locindex+NLOC]; | |
335 | relfil = rusefile[NLOC+locindex]; | |
336 | while (usedot[locindex+NLOC].xvalue & FW) | |
337 | outb(0); | |
338 | fclose(txtfil); | |
339 | fclose(relfil); | |
340 | } | |
341 | } | |
342 | ||
343 | txtfil = usefile[0]; | |
344 | /* | |
345 | * append csect text onto text for csect 0 | |
346 | */ | |
347 | for (locindex=1; locindex<NLOC+NLOC; locindex++) { | |
348 | char buffer[BUFSIZ]; | |
349 | if (usefile[locindex]) { | |
350 | tmpn2[TMPC] = locindex+'a'; | |
351 | relfil = fopen(tmpn2, "r"); | |
352 | if (relfil==NULL) { | |
353 | yyerror("cannot reopen temp"); | |
354 | continue; | |
355 | } | |
356 | while (!feof(relfil)) | |
357 | fwrite(buffer, 1, | |
358 | fread(buffer, 1, BUFSIZ, relfil), | |
359 | txtfil); | |
360 | fclose(relfil); | |
361 | } | |
362 | } | |
363 | /* | |
364 | * append relocation info onto text | |
365 | */ | |
366 | for (locindex=0; locindex<NLOC+NLOC; locindex++) { | |
367 | char buffer[BUFSIZ]; | |
368 | if (rusefile[locindex]) { | |
369 | tmpn3[TMPC] = locindex+'a'; | |
370 | relfil = fopen(tmpn3, "r"); | |
371 | if (relfil==NULL) { | |
372 | yyerror("cannot reopen temp"); | |
373 | continue; | |
374 | } | |
375 | while (!feof(relfil)) | |
376 | fwrite(buffer, 1, | |
377 | fread(buffer, 1, BUFSIZ, relfil), | |
378 | txtfil); | |
379 | fclose(relfil); | |
380 | } | |
381 | } | |
382 | ||
383 | symwrite(txtfil); | |
384 | /* | |
385 | * Go back and patch up rsize | |
386 | */ | |
387 | fseek(txtfil,0L,0); | |
388 | writel(&hdr,8,txtfil); | |
389 | ||
390 | delete(); | |
391 | ||
392 | if (anyerrs==0 && orgwarn) | |
393 | yyerror("Caution: absolute origins.\n"); | |
394 | #ifdef METRIC | |
395 | pcounters(); | |
396 | #endif | |
397 | exit(anyerrs!=0); | |
398 | } /*end of main*/ | |
399 | ||
400 | ||
401 | delexit() | |
402 | { | |
403 | delete(); | |
404 | #ifdef METRIC | |
405 | pcounters(); | |
406 | #endif | |
407 | exit(1); | |
408 | } | |
409 | ||
410 | sawabort() | |
411 | { | |
412 | char buffer[BUFSIZ]; | |
413 | #ifdef METRIC | |
414 | pcounters(); | |
415 | #endif | |
416 | while (!feof(stdin)) | |
417 | fread(buffer, 1, BUFSIZ, stdin); | |
418 | delete(); | |
419 | exit(1); /*although the previous pass will also exit non zero*/ | |
420 | } | |
421 | ||
422 | delete() | |
423 | { | |
424 | register locindex; | |
425 | ||
426 | if (tmpn1) | |
427 | unlink(tmpn1); | |
428 | for (locindex=0; locindex<NLOC+NLOC; locindex++) { | |
429 | if (tmpn2) { | |
430 | tmpn2[TMPC] = locindex+'a'; | |
431 | unlink(tmpn2); | |
432 | } | |
433 | if (tmpn3) { | |
434 | tmpn3[TMPC] = locindex+'a'; | |
435 | unlink(tmpn3); | |
436 | } | |
437 | } | |
438 | } | |
439 | #ifdef METRIC | |
440 | pcounters() | |
441 | { | |
442 | int i; | |
443 | struct { | |
444 | long p_user; | |
445 | long p_sys; | |
446 | long c_user; | |
447 | long c_sys; | |
448 | } tbuffer; | |
449 | ||
450 | if (!outcounters) return; | |
451 | printf("Assembly of files: "); | |
452 | if (innames[0] == 0) | |
453 | printf("<Standard Input.>\n"); | |
454 | else { | |
455 | for (i = 0; i<ninfiles; i++) | |
456 | printf("%s ", innames[i]); | |
457 | printf("\n"); | |
458 | } | |
459 | if (useVM) | |
460 | printf("Using "); | |
461 | else | |
462 | printf("NOT using "); | |
463 | printf("Virtual Memory for the interpass temporary file.\n"); | |
464 | printf("%d hashing collsions\n", nhcollisions); | |
465 | printf("%d hash table accesses\n", nhashed); | |
466 | printf("%d values entered in the hash table\n", nentered); | |
467 | printf("%d byte length of the temporary file\n", lgtmpfile); | |
468 | printf("%d symbols in the symbol table\n", nsyms); | |
469 | printf("%d labels in the symbol table\n", nlabels); | |
470 | printf("%d forgotten symbols\n", nforgotten); | |
471 | printf("%d iterations through all symbols to remove jxxxes\n", | |
472 | jxxxiterate); | |
473 | printf("%d jumps resolved via tunnelling\n", jxxxtunnel); | |
474 | if (jxdeadlock) | |
475 | printf("%d DEADLOCKED JXXXentries: Resolved by %s jumping\n", | |
476 | jxdeadlock, nbadjxsegs == 0 ? "short" : "long"); | |
477 | if (nbadjxsegs) | |
478 | printf("%d Segments with jxxx over aligns.\n", | |
479 | nbadjxsegs); | |
480 | times(&tbuffer); | |
481 | printf("%1.2fu 1.2fs\n", | |
482 | ((float)tbuffer.p_user)/60.0, | |
483 | ((float)tbuffer.p_sys)/60.0); | |
484 | } | |
485 | #endif |