BSD 3 development
[unix-history] / usr / src / cmd / as / asmain.c
CommitLineData
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
10int curlen;
11/*
12 * variables to manage the assembly input
13 */
14char *dotsname; /*the current file name; managed by the parser*/
15int lineno; /*current line number; managed by the parser*/
16int silent; /*don't complain about any errors*/
17int savelabels; /*write the labels to the a.out file*/
18
19#ifdef DEBUG
20int debug;
21int toktrace;
22#endif
23
24long datbase;
25
26char *endcore; /*where to get more symbol space*/
27
28struct hdr hdr = {
29 0410, 0, 0, 0, 0, 0, 0, 0,
30};
31
32#ifndef vax
33struct {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
38char *tmpn1;
39char *tmpn2;
40char *tmpn3;
41
42struct exp usedot[NLOC+NLOC];
43
44FILE *usefile[NLOC+NLOC];
45FILE *rusefile[NLOC+NLOC];
46char sibuf[TOKBUFLG]; /*buffer used for all input*/
47char sobuf[TOKBUFLG]; /*buffer used for all output*/
48 /*except stdout and relfil*/
49char stdoutbuf[BUFSIZ]; /*stdout buffer*/
50
51extern int njxxx; /*number of jumpxxx instructs*/
52extern int d124; /*allocate 1,2 or 4 bytes for unknowns*/
53
54int delexit();
55
56char *innames[32]; /*names of the files being assembled*/
57int ninfiles; /*how many interesting files there are*/
58
59main(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
401delexit()
402{
403 delete();
404#ifdef METRIC
405 pcounters();
406#endif
407 exit(1);
408}
409
410sawabort()
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
422delete()
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
440pcounters()
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