The string pool is maintained both in core, and in a second tmp file.
[unix-history] / usr / src / old / as.vax / asmain.c
CommitLineData
f70ab843
RH
1/*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4#ifndef lint
ec43bca4 5static char sccsid[] = "@(#)asmain.c 4.11 %G%";
f70ab843
RH
6#endif not lint
7
59e14996
BJ
8#include <stdio.h>
9#include <ctype.h>
59e14996 10#include <signal.h>
59e14996
BJ
11
12#include "as.h"
13#include "assyms.h"
59e14996 14#include "asscan.h"
f70ab843 15#include "asexpr.h"
59e14996
BJ
16
17#ifdef UNIX
ec43bca4 18#define unix_lang_name "VAX/UNIX Assembler V%G% 4.11"
59e14996
BJ
19#endif
20
21#ifdef VMS
451260e7 22#define vms_lang_name "VAX/VMS C Assembler V1.00"
59e14996
BJ
23#endif VMS
24
25/*
26 * variables to manage reading the assembly source files
27 */
28char *dotsname; /*the current file name; managed by the parser*/
29int lineno; /*current line number; managed by the parser*/
100d3f3c 30char **innames; /*names of the files being assembled*/
59e14996
BJ
31int ninfiles; /*how many interesting files there are*/
32/*
33 * Flags settable from the argv process argument list
34 */
35int silent = 0; /*don't complain about any errors*/
36int savelabels = 0; /*write the labels to the a.out file*/
37int d124 = 4; /*default allocate 4 bytes for unknown pointers*/
38int anyerrs = 0; /*no errors yet*/
f70ab843 39int anywarnings=0; /*no warnings yet*/
59e14996
BJ
40int orgwarn = 0; /*Bad origins*/
41int passno = 1; /* current pass*/
e5b9ebfb 42int jxxxJUMP = 0; /* in jxxxes that branch too far, use jmp instead of brw */
ed84d47b 43int readonlydata = 0; /* initialzed data -> text space */
59e14996 44
f70ab843
RH
45int nGHnumbers = 0; /* GH numbers used */
46int nGHopcodes = 0; /* GH opcodes used */
47int nnewopcodes = 0; /* new opcodes used */
48
59e14996
BJ
49#ifdef DEBUG
50int debug = 0;
51int toktrace = 0;
52#endif
53
54int useVM = /*put the temp file in virtual memory*/
55#ifdef VMS
56 1; /*VMS has virtual memory (duh)*/
57#endif VMS
58#ifdef UNIX
59 0;
60#endif
61
62char *endcore; /*where to get more symbol space*/
63
64/*
65 * Managers of the a.out file.
66 */
67struct exec hdr;
ed84d47b 68#define MAGIC 0407
59e14996
BJ
69u_long tsize; /* total text size */
70u_long dsize; /* total data size */
71u_long datbase; /* base of the data segment */
72u_long trsize; /* total text relocation size */
73u_long drsize; /* total data relocation size */
74
75/*
76 * Information about the current segment is accumulated in
77 * usedot; the most important information stored is the
78 * accumulated size of each of the text and data segments
79 *
80 * dotp points to the correct usedot expression for the current segment
81 */
82struct exp usedot[NLOC+NLOC]; /* info about all segments */
83struct exp *dotp; /* data/text location pointer */
84/*
ec43bca4 85 * The inter pass temporary token file is opened and closed by stdio, but
59e14996
BJ
86 * is written to using direct read/write, as the temporary file
87 * is composed of buffers exactly BUFSIZ long.
88 */
ec43bca4
RH
89FILE *tokfile; /* interpass communication file */
90char tokfilename[TNAMESIZE];
91/*
92 * The string file is the string table
93 * cat'ed to the end of the built up a.out file
94 */
95FILE *strfile; /* interpass string file */
96char strfilename[TNAMESIZE];
97int strfilepos = 0; /* position within the string file */
59e14996
BJ
98/*
99 * a.out is created during the second pass.
100 * It is opened by stdio, but is filled with the parallel
101 * block I/O library
102 */
103char *outfile = "a.out";
104FILE *a_out_file;
105off_t a_out_off; /* cumulative offsets for segments */
106/*
107 * The logical files containing the assembled data for each of
108 * the text and data segments are
109 * managed by the parallel block I/O library.
110 * a.out is logically opened in many places at once to
111 * receive the assembled data from the various segments as
112 * it all trickles in, but is physically opened only once
113 * to minimize file overhead.
114 */
115BFILE *usefile[NLOC+NLOC]; /* text/data files */
116BFILE *txtfil; /* current text/data file */
117/*
118 * Relocation information is accumulated seperately for each
119 * segment. This is required by the old loader (from BTL),
120 * but not by the new loader (Bill Joy).
121 *
122 * However, the size of the relocation information can not be computed
123 * during or after the 1st pass because the ''absoluteness' of values
124 * is unknown until all locally declared symbols have been seen.
125 * Thus, the size of the relocation information is only
126 * known after the second pass is finished.
127 * This obviates the use of the block I/O
128 * library, which requires knowing the exact offsets in a.out.
129 *
130 * So, we save the relocation information internally (we don't
131 * go to internal files to minimize overhead).
132 *
133 * Empirically, we studied 259 files composing the system,
134 * two compilers and a compiler generator: (all of which have
135 * fairly large source files)
136 *
137 * Number of files = 259
138 * Number of non zero text reloc files: 233
139 * Number of non zero data reloc files: 53
140 * Average text relocation = 889
141 * Average data relocation = 346
142 * Number of files > BUFSIZ text relocation = 71
143 * Number of files > BUFSIZ data relocation = 6
144 *
145 * For compiled C code, there is usually one text segment and two
146 * data segments; we see that allocating our own buffers and
147 * doing our internal handling of relocation information will,
148 * on the average, not use more memory than taken up by the buffers
149 * allocated for doing file I/O in parallel to a number of file.
150 *
151 * If we are assembling with the -V option, we
152 * use the left over token buffers from the 2nd pass,
153 * otherwise, we create our own.
154 *
155 * When the 2nd pass is complete, closeoutrel flushes the token
156 * buffers out to a BFILE.
157 *
158 * The internals to relbufdesc are known only in assyms.c
159 *
160 * outrel constructs the relocation information.
161 * closeoutrel flushes the relocation information to relfil.
162 */
163struct relbufdesc *rusefile[NLOC+NLOC];
164struct relbufdesc *relfil; /* un concatnated relocation info */
165BFILE *relocfile; /* concatnated relocation info */
166/*
167 * Once the relocation information has been written,
168 * we can write out the symbol table using the Block I/O
169 * mechanisms, as we once again know the offsets into
170 * the a.out file.
171 *
172 * We use relfil to output the symbol table information.
173 */
174
175char *tmpdirprefix =
176#ifdef UNIX
177 "/tmp/";
178#else VMS
179 "/usr/tmp/";
180#endif
181
59e14996
BJ
182
183int delexit();
184
185main(argc, argv)
186 int argc;
187 char **argv;
188{
f70ab843 189 char *sbrk();
59e14996 190
ec43bca4
RH
191 tokfilename[0] = 0;
192 strfilename[0] = 0;
f70ab843 193 endcore = sbrk(0);
59e14996
BJ
194
195 argprocess(argc, argv); /* process argument lists */
196 if (anyerrs) exit(1);
197
198 initialize();
199 zeroorigins(); /* set origins to zero */
200 zerolocals(); /* fix local label counters */
201
202 i_pass1(); /* open temp files, etc */
203 pass1(); /* first pass through .s files */
204 testlocals(); /* check for undefined locals */
205 if (anyerrs) delexit();
206
207 pass1_5(); /* resolve jxxx */
208 if (anyerrs) delexit();
209
210 open_a_out(); /* open a.out */
7a5aec15 211 roundsegments(); /* round segments to FW */
59e14996
BJ
212 build_hdr(); /* build initial header, and output */
213
214 i_pass2(); /* reopen temporary file, etc */
215 pass2(); /* second pass through the virtual .s */
216 if (anyerrs) delexit();
217
7a5aec15 218 fillsegments(); /* fill segments with 0 to FW */
59e14996
BJ
219 reloc_syms(); /* dump relocation and symbol table */
220
221 delete(); /* remove tmp file */
222 bflush(); /* close off block I/O view of a.out */
223 fix_a_out(); /* add in text and data reloc counts */
224
225 if (anyerrs == 0 && orgwarn)
226 yyerror("Caution: absolute origins.\n");
f70ab843
RH
227
228 if (nGHnumbers)
229 yywarning("Caution: G or H format floating point numbers");
230 if (nGHopcodes)
231 yywarning("Caution: G or H format floating point operators");
232 if (nnewopcodes)
233 yywarning("Caution: New Opcodes");
234 if (nGHnumbers || nGHopcodes || nnewopcodes)
235 yywarning("These are not defined for all implementations of the VAX architecture.\n");
236
59e14996
BJ
237 exit(anyerrs != 0);
238} /*end of UNIX main*/
239
240argprocess(argc, argv)
241 int argc;
242 char *argv[];
243{
244 register char *cp;
245
246 ninfiles = 0;
247 silent = 0;
248#ifdef DEBUG
249 debug = 0;
250#endif
100d3f3c 251 innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
59e14996
BJ
252 dotsname = "<argv error>";
253 while (argc > 1) {
100d3f3c
BJ
254 if (argv[1][0] != '-')
255 innames[ninfiles++] = argv[1];
256 else {
59e14996
BJ
257 cp = argv[1] + 1;
258 /*
259 * We can throw away single minus signs, so
260 * that make scripts for the PDP 11 assembler work
261 * on this assembler too
262 */
263 while (*cp){
264 switch(*cp++){
265 default:
266 yyerror("Unknown flag: %c", *--cp);
267 cp++;
268 break;
26c6a2ae
RH
269 case 'v':
270 selfwhat(stdout);
271 exit(1);
59e14996
BJ
272 case 'd':
273 d124 = *cp++ - '0';
274 if ( (d124 != 1) && (d124 != 2) &&
275 (d124 != 4)){
276 yyerror("-d[124] only");
277 exit(1);
278 }
279 break;
280 case 'o':
281 if (argc < 3){
282 yyerror("-o what???");
283 exit(1);
284 }
285 outfile = argv[2];
286 bumpone:
287 argc -= 2;
288 argv += 2;
289 goto nextarg;
290
291 case 't':
292 if (argc < 3){
293 yyerror("-t what???");
294 exit(1);
295 }
296 tmpdirprefix = argv[2];
297 goto bumpone;
298
299 case 'V':
300 useVM = 1;
301 break;
302 case 'W':
303 silent = 1;
304 break;
305 case 'L':
306 savelabels = 1;
307 break;
e5b9ebfb
RH
308 case 'J':
309 jxxxJUMP = 1;
310 break;
59e14996
BJ
311#ifdef DEBUG
312 case 'D':
313 debug = 1;
314 break;
315 case 'T':
316 toktrace = 1;
317 break;
318#endif
ed84d47b
BJ
319 case 'R':
320 readonlydata = 1;
321 break;
59e14996
BJ
322 } /*end of the switch*/
323 } /*end of pulling out all arguments*/
324 } /*end of a flag argument*/
59e14996
BJ
325 --argc; ++argv;
326 nextarg:;
327 }
100d3f3c 328 /* innames[ninfiles] = 0; */
59e14996 329}
26c6a2ae
RH
330/*
331 * poke through the data space and find all sccs identifiers.
332 * We assume:
333 * a) that extern char **environ; is the first thing in the bss
334 * segment (true, if one is using the new version of cmgt.crt0.c)
335 * b) that the sccsid's have not been put into text space.
336 */
337selfwhat(place)
338 FILE *place;
339{
340 extern char **environ;
341 register char *ub;
342 register char *cp;
343 register char *pat;
344 char *sbrk();
345
346 for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){
347 if (cp[0] != '@') continue;
348 if (cp[1] != '(') continue;
349 if (cp[2] != '#') continue;
350 if (cp[3] != ')') continue;
351 fputc('\t', place);
352 for (cp += 4; cp < ub; cp++){
353 if (*cp == 0) break;
354 if (*cp == '>') break;
355 if (*cp == '\n') break;
356 fputc(*cp, place);
357 }
358 fputc('\n', place);
359 }
360}
59e14996
BJ
361
362initialize()
363{
364 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
365 signal(SIGINT, delexit);
366 /*
367 * Install symbols in the table
368 */
369 symtabinit();
370 syminstall();
371 /*
372 * Build the expression parser accelerator token sets
373 */
374 buildtokensets();
375}
376
377zeroorigins()
378{
379 register int locindex;
380 /*
381 * Mark usedot: the first NLOC slots are for named text segments,
382 * the next for named data segments.
383 */
384 for (locindex = 0; locindex < NLOC; locindex++){
451260e7
RH
385 usedot[locindex].e_xtype = XTEXT;
386 usedot[NLOC + locindex].e_xtype = XDATA;
387 usedot[locindex].e_xvalue = 0;
388 usedot[NLOC + locindex].e_xvalue = 0;
59e14996
BJ
389 }
390}
391
392zerolocals()
393{
394 register int i;
395
396 for (i = 0; i <= 9; i++) {
397 lgensym[i] = 1;
398 genref[i] = 0;
399 }
400}
401
402i_pass1()
403{
ec43bca4
RH
404 FILE *tempopen();
405 if (useVM == 0)
406 tokfile = tempopen(tokfilename, "T");
407 strfile = tempopen(strfilename, "S");
408 /*
409 * write out the string length.
410 * This will be overwritten when the
411 * strings are tacked onto the growing a.out file
412 */
413 strfilepos = sizeof(int);
414 fwrite(&strfilepos, sizeof(int), 1, strfile);
59e14996 415
ec43bca4 416 inittokfile();
e5b9ebfb 417 initijxxx();
59e14996
BJ
418}
419
ec43bca4
RH
420FILE *tempopen(tname, part)
421 char *tname;
422 char *part;
423{
424 FILE *file;
425 sprintf(tname, "%s%sas%s%05d",
426 tmpdirprefix,
427 (tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : 0,
428 part,
429 getpid());
430 file = fopen(tname, "w");
431 if (file == NULL) {
432 yyerror("Bad pass 1 temporary file for writing %s", tname);
433 delexit();
434 }
435 return(file);
436}
437
59e14996
BJ
438pass1()
439{
440 register int i;
441
442 passno = 1;
443 dotp = &usedot[0];
444 txtfil = (BFILE *)0;
445 relfil = (struct relbufdesc *)0;
446
447 if (ninfiles == 0){ /*take the input from stdin directly*/
448 lineno = 1;
449 dotsname = "<stdin>";
450
451 yyparse();
452 } else { /*we have the names tanked*/
453 for (i = 0; i < ninfiles; i++){
454 new_dot_s(innames[i]);
455 if (freopen(innames[i], "r", stdin) == NULL) {
456 yyerror( "Can't open source file %s\n",
457 innames[i]);
458 exit(2);
459 }
460 /* stdio is NOT used to read the input characters */
461 /* we use read directly, into our own buffers */
462 yyparse();
463 }
464 }
465
ec43bca4 466 closetokfile(); /*kick out the last buffered intermediate text*/
59e14996
BJ
467}
468
469testlocals()
470{
471 register int i;
472 for (i = 0; i <= 9; i++) {
473 if (genref[i])
474 yyerror("Reference to undefined local label %df", i);
475 lgensym[i] = 1;
476 genref[i] = 0;
477 }
478}
479
480pass1_5()
481{
482 sortsymtab();
483#ifdef DEBUG
484 if (debug) dumpsymtab();
485#endif
486 jxxxfix();
487#ifdef DEBUG
488 if (debug) dumpsymtab();
489#endif
490}
491
492open_a_out()
493{
494 /*
495 * Open up the a.out file now, and get set to build
496 * up offsets into it for all of the various text,data
497 * text relocation and data relocation segments.
498 */
499 a_out_file = fopen(outfile, "w");
500 if (a_out_file == NULL) {
501 yyerror("Cannot create %s", outfile);
502 delexit();
503 }
504 biofd = a_out_file->_file;
505 a_out_off = 0;
506}
507
508roundsegments()
509{
510 register int locindex;
511 register long v;
512 /*
513 * round and assign text segment origins
514 * the exec header always goes in usefile[0]
515 */
516 tsize = 0;
517 for (locindex=0; locindex<NLOC; locindex++) {
7a5aec15 518 v = round(usedot[locindex].e_xvalue, FW);
451260e7 519 usedot[locindex].e_xvalue = tsize;
59e14996
BJ
520 if ((locindex == 0) || (v != 0) ){
521 usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
522 bopen(usefile[locindex], a_out_off);
523 if (locindex == 0)
524 a_out_off = sizeof (struct exec);
525 } else {
526 usefile[locindex] = (BFILE *)-1;
527 }
528 tsize += v;
529 a_out_off += v;
530 }
531 /*
532 * Round and assign data segment origins.
533 */
7a5aec15 534 datbase = round(tsize, FW);
59e14996 535 for (locindex=0; locindex<NLOC; locindex++) {
7a5aec15 536 v = round(usedot[NLOC+locindex].e_xvalue, FW);
451260e7 537 usedot[NLOC+locindex].e_xvalue = datbase + dsize;
59e14996
BJ
538 if (v != 0){
539 usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
540 bopen(usefile[NLOC + locindex], a_out_off);
541 } else {
542 usefile[NLOC + locindex] = (BFILE *)-1;
543 }
544 dsize += v;
545 a_out_off += v;
546 }
547 /*
548 * Assign final values to symbols
549 */
550 hdr.a_bss = dsize;
551 freezesymtab(); /* this touches hdr.a_bss */
552 stabfix();
553 /*
554 * Set up the relocation information "files" to
555 * be zero; outrel takes care of the rest
556 */
557 for (locindex = 0; locindex < NLOC + NLOC; locindex++){
558 rusefile[locindex] = (struct relbufdesc *)0;
559 }
560}
561
562build_hdr()
563{
564 /*
565 * Except for the text and data relocation sizes,
566 * calculate the final values for the header
567 *
568 * Write out the initial copy; we to come
569 * back later and patch up a_trsize and a_drsize,
570 * and overwrite this first version of the header.
571 */
572 hdr.a_magic = MAGIC;
573 hdr.a_text = tsize;
574 hdr.a_data = dsize;
575 hdr.a_bss -= dsize;
576 hdr.a_syms = sizesymtab(); /* Does not include string pool length */
577 hdr.a_entry = 0;
578 hdr.a_trsize = 0;
579 hdr.a_drsize = 0;
580
581 bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
582}
583
584i_pass2()
585{
586 if (useVM == 0) {
ec43bca4
RH
587 fclose(tokfile);
588 tokfile = fopen(tokfilename, "r");
589 if (tokfile==NULL) {
590 yyerror("Bad pass 2 temporary file for reading %s", tokfilename);
59e14996
BJ
591 delexit();
592 }
593 }
ec43bca4
RH
594 fclose(strfile);
595 strfile = fopen(strfilename, "r");
59e14996
BJ
596}
597
598pass2()
599{
600#ifdef DEBUG
601 if (debug)
602 printf("\n\n\n\t\tPASS 2\n\n\n\n");
603#endif DEBUG
604 passno = 2;
605 lineno = 1;
606 dotp = &usedot[0];
607 txtfil = usefile[0]; /* already opened (always!) */
608 relfil = 0; /* outrel takes care of the rest */
609 initoutrel();
610
ec43bca4 611 inittokfile();
59e14996
BJ
612
613 yyparse();
614
ec43bca4 615 closetokfile();
59e14996
BJ
616}
617
618fillsegments()
619{
620 int locindex;
621 /*
7a5aec15 622 * Round text and data segments to FW by appending zeros
59e14996
BJ
623 */
624 for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
625 if (usefile[locindex]) {
626 txtfil = usefile[locindex];
627 dotp = &usedot[locindex];
7a5aec15 628 while (usedot[locindex].e_xvalue & FW)
59e14996
BJ
629 outb(0);
630 }
631 }
632}
633
634reloc_syms()
635{
636 u_long closerelfil();
637 /*
638 * Move the relocation information to a.out
639 * a_out_off is the offset so far:
640 * exec + text segments + data segments
641 */
642 relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
643 bopen(relocfile, a_out_off);
644 a_out_off += closeoutrel(relocfile);
645
646 hdr.a_trsize = trsize;
647 hdr.a_drsize = drsize;
ed84d47b
BJ
648 if (readonlydata) {
649 hdr.a_text += hdr.a_data;
650 hdr.a_data = 0;
651 hdr.a_trsize += hdr.a_drsize;
652 hdr.a_drsize = 0;
653 }
59e14996
BJ
654 /*
655 * Output the symbol table
656 * and if FLEXNAMES is set, the string pool
ec43bca4
RH
657 *
658 * We must first rewind the string pool file to its beginning,
659 * in case it was seek'ed into for fetching ascii and asciz
660 * strings.
59e14996 661 */
ec43bca4 662 fseek(strfile, 0, 0);
59e14996
BJ
663 symwrite(relocfile);
664}
665
666fix_a_out()
667{
f70ab843 668 if (lseek(a_out_file->_file, 0L, 0) < 0L)
59e14996
BJ
669 yyerror("Reposition for header rewrite fails");
670 if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
671 yyerror("Rewrite of header fails");
672}
673
674delexit()
675{
676 delete();
677 if (passno == 2){
678 unlink(outfile);
679 }
680 exit(1);
681}
682
683delete()
684{
ec43bca4
RH
685 if (useVM == 0 || tokfilename[0])
686 unlink(tokfilename);
687 if (strfilename[0])
688 unlink(strfilename);
59e14996
BJ
689}
690
691sawabort()
692{
693 char *fillinbuffer();
694 while (fillinbuffer() != (char *)0)
695 continue;
696 delete();
697 exit(1); /*although the previous pass will also exit non zero*/
698}
699
700panic(fmt, a1, a2, a3, a4)
701 char *fmt;
702 /*VARARGS 1*/
703{
704 yyerror("Assembler panic: bad internal data structure.");
705 yyerror(fmt, a1, a2, a3, a4);
706 delete();
707 abort();
708}