132434Sbostic /*
232434Sbostic * Copyright (c) 1982 Regents of the University of California
332434Sbostic */
432434Sbostic #ifndef lint
532434Sbostic static char sccsid[] = "@(#)asmain.c 4.13 6/30/83";
632434Sbostic #endif not lint
732434Sbostic
832434Sbostic #include <stdio.h>
932434Sbostic #include <ctype.h>
1032434Sbostic #include <signal.h>
1132434Sbostic
1232434Sbostic #include "as.h"
1332434Sbostic #include "assyms.h"
1432434Sbostic #include "asscan.h"
1532434Sbostic #include "asexpr.h"
1637787Sbostic #include <paths.h>
1732434Sbostic
1832434Sbostic #define unix_lang_name "VAX/UNIX Assembler V6/30/83 4.13"
1932434Sbostic /*
2032434Sbostic * variables to manage reading the assembly source files
2132434Sbostic */
2232434Sbostic char *dotsname; /*the current file name; managed by the parser*/
2332434Sbostic int lineno; /*current line number; managed by the parser*/
2432434Sbostic char **innames; /*names of the files being assembled*/
2532434Sbostic int ninfiles; /*how many interesting files there are*/
2632434Sbostic FILE *source; /*current source file (for listing) */
2732434Sbostic char layout[400]; /*layout bytes */
2832434Sbostic char *layoutpos = layout; /*layout position in listfile */
2932434Sbostic int ind = 0; /*innames in-index: 0..minfiles */
3032434Sbostic int endofsource = 0;
3132434Sbostic long sourcepos;
3232434Sbostic /*
3332434Sbostic * Flags settable from the argv process argument list
3432434Sbostic */
3532434Sbostic int silent = 0; /*don't complain about any errors*/
3632434Sbostic int savelabels = 0; /*write the labels to the a.out file*/
3732434Sbostic int d124 = 4; /*default allocate 4 bytes for unknown pointers*/
3832434Sbostic int anyerrs = 0; /*no errors yet*/
3932434Sbostic int anywarnings=0; /*no warnings yet*/
4032434Sbostic int orgwarn = 0; /*Bad origins*/
4132434Sbostic int passno = 1; /* current pass*/
4232434Sbostic int jxxxJUMP = 0; /* in jxxxes that branch too far, use jmp instead of brw */
4332434Sbostic int readonlydata = 0; /* initialzed data -> text space */
4432434Sbostic int liston = 0; /* don't produce listing */
4532434Sbostic
4632434Sbostic
4732434Sbostic #ifdef DEBUG
4832434Sbostic int debug = 0;
4932434Sbostic int toktrace = 0;
5032434Sbostic #endif
5132434Sbostic
5232434Sbostic int useVM = 0;
5332434Sbostic
5432434Sbostic char *endcore; /*where to get more symbol space*/
5532434Sbostic
5632434Sbostic /*
5732434Sbostic * Managers of the a.out file.
5832434Sbostic */
5932434Sbostic struct exec hdr;
6032434Sbostic #define MAGIC 0407
6132434Sbostic u_long tsize; /* total text size */
6232434Sbostic u_long dsize; /* total data size */
6332434Sbostic u_long datbase; /* base of the data segment */
6432434Sbostic u_long trsize; /* total text relocation size */
6532434Sbostic u_long drsize; /* total data relocation size */
6632434Sbostic
6732434Sbostic /*
6832434Sbostic * Information about the current segment is accumulated in
6932434Sbostic * usedot; the most important information stored is the
7032434Sbostic * accumulated size of each of the text and data segments
7132434Sbostic *
7232434Sbostic * dotp points to the correct usedot expression for the current segment
7332434Sbostic */
7432434Sbostic struct exp usedot[NLOC+NLOC]; /* info about all segments */
7532434Sbostic struct exp *dotp; /* data/text location pointer */
7632434Sbostic /*
7732434Sbostic * The inter pass temporary token file is opened and closed by stdio, but
7832434Sbostic * is written to using direct read/write, as the temporary file
7932434Sbostic * is composed of buffers exactly BUFSIZ long.
8032434Sbostic */
8132434Sbostic FILE *tokfile; /* interpass communication file */
8232434Sbostic char tokfilename[TNAMESIZE];
8332434Sbostic /*
8432434Sbostic * The string file is the string table
8532434Sbostic * cat'ed to the end of the built up a.out file
8632434Sbostic */
8732434Sbostic FILE *strfile; /* interpass string file */
8832434Sbostic char strfilename[TNAMESIZE];
8932434Sbostic int strfilepos = 0; /* position within the string file */
9032434Sbostic /*
9132434Sbostic * a.out is created during the second pass.
9232434Sbostic * It is opened by stdio, but is filled with the parallel
9332434Sbostic * block I/O library
9432434Sbostic */
95*44770Sbostic char *outfile = "a.out";
9632434Sbostic FILE *a_out_file;
9732434Sbostic off_t a_out_off; /* cumulative offsets for segments */
9832434Sbostic /*
9932434Sbostic * The logical files containing the assembled data for each of
10032434Sbostic * the text and data segments are
10132434Sbostic * managed by the parallel block I/O library.
10232434Sbostic * a.out is logically opened in many places at once to
10332434Sbostic * receive the assembled data from the various segments as
10432434Sbostic * it all trickles in, but is physically opened only once
10532434Sbostic * to minimize file overhead.
10632434Sbostic */
10732434Sbostic BFILE *usefile[NLOC+NLOC]; /* text/data files */
10832434Sbostic BFILE *txtfil; /* current text/data file */
10932434Sbostic /*
11032434Sbostic * Relocation information is accumulated seperately for each
11132434Sbostic * segment. This is required by the old loader (from BTL),
11232434Sbostic * but not by the new loader (Bill Joy).
11332434Sbostic *
11432434Sbostic * However, the size of the relocation information can not be computed
11532434Sbostic * during or after the 1st pass because the ''absoluteness' of values
11632434Sbostic * is unknown until all locally declared symbols have been seen.
11732434Sbostic * Thus, the size of the relocation information is only
11832434Sbostic * known after the second pass is finished.
11932434Sbostic * This obviates the use of the block I/O
12032434Sbostic * library, which requires knowing the exact offsets in a.out.
12132434Sbostic *
12232434Sbostic * So, we save the relocation information internally (we don't
12332434Sbostic * go to internal files to minimize overhead).
12432434Sbostic *
12532434Sbostic * Empirically, we studied 259 files composing the system,
12632434Sbostic * two compilers and a compiler generator: (all of which have
12732434Sbostic * fairly large source files)
12832434Sbostic *
12932434Sbostic * Number of files = 259
13032434Sbostic * Number of non zero text reloc files: 233
13132434Sbostic * Number of non zero data reloc files: 53
13232434Sbostic * Average text relocation = 889
13332434Sbostic * Average data relocation = 346
13432434Sbostic * Number of files > BUFSIZ text relocation = 71
13532434Sbostic * Number of files > BUFSIZ data relocation = 6
13632434Sbostic *
13732434Sbostic * For compiled C code, there is usually one text segment and two
13832434Sbostic * data segments; we see that allocating our own buffers and
13932434Sbostic * doing our internal handling of relocation information will,
14032434Sbostic * on the average, not use more memory than taken up by the buffers
14132434Sbostic * allocated for doing file I/O in parallel to a number of file.
14232434Sbostic *
14332434Sbostic * If we are assembling with the -V option, we
14432434Sbostic * use the left over token buffers from the 2nd pass,
14532434Sbostic * otherwise, we create our own.
14632434Sbostic *
14732434Sbostic * When the 2nd pass is complete, closeoutrel flushes the token
14832434Sbostic * buffers out to a BFILE.
14932434Sbostic *
15032434Sbostic * The internals to relbufdesc are known only in assyms.c
15132434Sbostic *
15232434Sbostic * outrel constructs the relocation information.
15332434Sbostic * closeoutrel flushes the relocation information to relfil.
15432434Sbostic */
15532434Sbostic struct relbufdesc *rusefile[NLOC+NLOC];
15632434Sbostic struct relbufdesc *relfil; /* un concatnated relocation info */
15732434Sbostic BFILE *relocfile; /* concatnated relocation info */
15832434Sbostic /*
15932434Sbostic * Once the relocation information has been written,
16032434Sbostic * we can write out the symbol table using the Block I/O
16132434Sbostic * mechanisms, as we once again know the offsets into
16232434Sbostic * the a.out file.
16332434Sbostic *
16432434Sbostic * We use relfil to output the symbol table information.
16532434Sbostic */
16637787Sbostic char *tmpdirprefix = _PATH_TMP;
16732434Sbostic int delexit();
16832434Sbostic
main(argc,argv)16932434Sbostic main(argc, argv)
17032434Sbostic int argc;
17132434Sbostic char **argv;
17232434Sbostic {
17332434Sbostic char *sbrk();
17432434Sbostic
17532434Sbostic tokfilename[0] = 0;
17632434Sbostic strfilename[0] = 0;
17732434Sbostic endcore = sbrk(0);
17832434Sbostic
17932434Sbostic argprocess(argc, argv); /* process argument lists */
18032434Sbostic if (anyerrs) exit(1);
18132434Sbostic
18232434Sbostic initialize();
18332434Sbostic zeroorigins(); /* set origins to zero */
18432434Sbostic zerolocals(); /* fix local label counters */
18532434Sbostic
18632434Sbostic i_pass1(); /* open temp files, etc */
18732434Sbostic pass1(); /* first pass through .s files */
18832434Sbostic testlocals(); /* check for undefined locals */
18932434Sbostic if (anyerrs) delexit();
19032434Sbostic
19132434Sbostic pass1_5(); /* resolve jxxx */
19232434Sbostic if (anyerrs) delexit();
19332434Sbostic
19432434Sbostic open_a_out(); /* open a.out */
19532434Sbostic roundsegments(); /* round segments to FW */
19632434Sbostic build_hdr(); /* build initial header, and output */
19732434Sbostic
19832434Sbostic i_pass2(); /* reopen temporary file, etc */
19932434Sbostic pass2(); /* second pass through the virtual .s */
20032434Sbostic if (anyerrs) delexit();
20132434Sbostic
20232434Sbostic fillsegments(); /* fill segments with 0 to FW */
20332434Sbostic reloc_syms(); /* dump relocation and symbol table */
20432434Sbostic
20532434Sbostic delete(); /* remove tmp file */
20632434Sbostic bflush(); /* close off block I/O view of a.out */
20732434Sbostic fix_a_out(); /* add in text and data reloc counts */
20832434Sbostic
20932434Sbostic if (anyerrs == 0 && orgwarn)
21032434Sbostic yyerror("Caution: absolute origins.\n");
21132434Sbostic
21232434Sbostic exit(anyerrs != 0);
21332434Sbostic }
21432434Sbostic
argprocess(argc,argv)21532434Sbostic argprocess(argc, argv)
21632434Sbostic int argc;
21732434Sbostic char *argv[];
21832434Sbostic {
21932434Sbostic register char *cp;
22032434Sbostic
22132434Sbostic ninfiles = 0;
22232434Sbostic silent = 0;
22332434Sbostic #ifdef DEBUG
22432434Sbostic debug = 0;
22532434Sbostic #endif
22632434Sbostic innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
22732434Sbostic dotsname = "<argv error>";
22832434Sbostic while (argc > 1) {
22932434Sbostic if (argv[1][0] != '-')
23032434Sbostic innames[ninfiles++] = argv[1];
23132434Sbostic else {
23232434Sbostic cp = argv[1] + 1;
23332434Sbostic /*
23432434Sbostic * We can throw away single minus signs, so
23532434Sbostic * that make scripts for the PDP 11 assembler work
23632434Sbostic * on this assembler too
23732434Sbostic */
23832434Sbostic while (*cp){
23932434Sbostic switch(*cp++){
24032434Sbostic default:
24132434Sbostic yyerror("Unknown flag: %c", *--cp);
24232434Sbostic cp++;
24332434Sbostic break;
24432434Sbostic case 'v':
24532434Sbostic selfwhat(stdout);
24632434Sbostic exit(1);
24732434Sbostic case 'd':
24832434Sbostic d124 = *cp++ - '0';
24932434Sbostic if ( (d124 != 1) && (d124 != 2) &&
25032434Sbostic (d124 != 4)){
25132434Sbostic yyerror("-d[124] only");
25232434Sbostic exit(1);
25332434Sbostic }
25432434Sbostic break;
25532434Sbostic case 'P':
25632434Sbostic liston = 1;
25732434Sbostic listfile = stdout;
25832434Sbostic break;
25932434Sbostic case 'o':
26032434Sbostic if (argc < 3){
26132434Sbostic yyerror("-o what???");
26232434Sbostic exit(1);
26332434Sbostic }
264*44770Sbostic outfile = argv[2];
26532434Sbostic bumpone:
26632434Sbostic argc -= 2;
26732434Sbostic argv += 2;
26832434Sbostic goto nextarg;
26932434Sbostic
27032434Sbostic case 't':
27132434Sbostic if (argc < 3){
27232434Sbostic yyerror("-t what???");
27332434Sbostic exit(1);
27432434Sbostic }
27532434Sbostic tmpdirprefix = argv[2];
27632434Sbostic goto bumpone;
27732434Sbostic
27832434Sbostic case 'V':
27932434Sbostic useVM = 1;
28032434Sbostic break;
28132434Sbostic case 'W':
28232434Sbostic silent = 1;
28332434Sbostic break;
28432434Sbostic case 'L':
28532434Sbostic savelabels = 1;
28632434Sbostic break;
28732434Sbostic case 'J':
28832434Sbostic jxxxJUMP = 1;
28932434Sbostic break;
29032434Sbostic #ifdef DEBUG
29132434Sbostic case 'D':
29232434Sbostic debug = 1;
29332434Sbostic break;
29432434Sbostic case 'T':
29532434Sbostic toktrace = 1;
29632434Sbostic break;
29732434Sbostic #endif
29832434Sbostic case 'R':
29932434Sbostic readonlydata = 1;
30032434Sbostic break;
30132434Sbostic } /*end of the switch*/
30232434Sbostic } /*end of pulling out all arguments*/
30332434Sbostic } /*end of a flag argument*/
30432434Sbostic --argc; ++argv;
30532434Sbostic nextarg:;
30632434Sbostic }
30732434Sbostic /* innames[ninfiles] = 0; */
30832434Sbostic }
30932434Sbostic /*
31032434Sbostic * poke through the data space and find all sccs identifiers.
31132434Sbostic * We assume:
31232434Sbostic * a) that extern char **environ; is the first thing in the bss
31332434Sbostic * segment (true, if one is using the new version of cmgt.crt0.c)
31432434Sbostic * b) that the sccsid's have not been put into text space.
31532434Sbostic */
selfwhat(place)31632434Sbostic selfwhat(place)
31732434Sbostic FILE *place;
31832434Sbostic {
31932434Sbostic extern char **environ;
32032434Sbostic register char *ub;
32132434Sbostic register char *cp;
32232434Sbostic char *sbrk();
32332434Sbostic
32432434Sbostic for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){
32532434Sbostic if (cp[0] != '@') continue;
32632434Sbostic if (cp[1] != '(') continue;
32732434Sbostic if (cp[2] != '#') continue;
32832434Sbostic if (cp[3] != ')') continue;
32932434Sbostic fputc('\t', place);
33032434Sbostic for (cp += 4; cp < ub; cp++){
33132434Sbostic if (*cp == 0) break;
33232434Sbostic if (*cp == '>') break;
33332434Sbostic if (*cp == '\n') break;
33432434Sbostic fputc(*cp, place);
33532434Sbostic }
33632434Sbostic fputc('\n', place);
33732434Sbostic }
33832434Sbostic }
33932434Sbostic
initialize()34032434Sbostic initialize()
34132434Sbostic {
34232434Sbostic if (signal(SIGINT, SIG_IGN) != SIG_IGN)
34332434Sbostic signal(SIGINT, delexit);
34432434Sbostic /*
34532434Sbostic * Install symbols in the table
34632434Sbostic */
34732434Sbostic symtabinit();
34832434Sbostic syminstall();
34932434Sbostic /*
35032434Sbostic * Build the expression parser accelerator token sets
35132434Sbostic */
35232434Sbostic buildtokensets();
35332434Sbostic }
35432434Sbostic
zeroorigins()35532434Sbostic zeroorigins()
35632434Sbostic {
35732434Sbostic register int locindex;
35832434Sbostic /*
35932434Sbostic * Mark usedot: the first NLOC slots are for named text segments,
36032434Sbostic * the next for named data segments.
36132434Sbostic */
36232434Sbostic for (locindex = 0; locindex < NLOC; locindex++){
36332434Sbostic usedot[locindex].e_xtype = XTEXT;
36432434Sbostic usedot[NLOC + locindex].e_xtype = XDATA;
36532434Sbostic usedot[locindex].e_xvalue = 0;
36632434Sbostic usedot[NLOC + locindex].e_xvalue = 0;
36732434Sbostic }
36832434Sbostic }
36932434Sbostic
zerolocals()37032434Sbostic zerolocals()
37132434Sbostic {
37232434Sbostic register int i;
37332434Sbostic
37432434Sbostic for (i = 0; i <= 9; i++) {
37532434Sbostic lgensym[i] = 1;
37632434Sbostic genref[i] = 0;
37732434Sbostic }
37832434Sbostic }
37932434Sbostic
i_pass1()38032434Sbostic i_pass1()
38132434Sbostic {
38232434Sbostic FILE *tempopen();
38332434Sbostic if (useVM == 0)
38432434Sbostic tokfile = tempopen(tokfilename, "T");
38532434Sbostic strfile = tempopen(strfilename, "S");
38632434Sbostic /*
38732434Sbostic * write out the string length.
38832434Sbostic * This will be overwritten when the
38932434Sbostic * strings are tacked onto the growing a.out file
39032434Sbostic */
39132434Sbostic strfilepos = sizeof(int);
39232434Sbostic fwrite(&strfilepos, sizeof(int), 1, strfile);
39332434Sbostic
39432434Sbostic inittokfile();
39532434Sbostic initijxxx();
39632434Sbostic }
39732434Sbostic
tempopen(tname,part)39832434Sbostic FILE *tempopen(tname, part)
39932434Sbostic char *tname;
40032434Sbostic char *part;
40132434Sbostic {
40232434Sbostic FILE *file;
40332435Sbostic (void)sprintf(tname, "%s%sas%s%05d",
40432434Sbostic tmpdirprefix,
40532434Sbostic (tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : 0,
40632434Sbostic part,
40732434Sbostic getpid());
40832434Sbostic file = fopen(tname, "w");
40932434Sbostic if (file == NULL) {
41032434Sbostic yyerror("Bad pass 1 temporary file for writing %s", tname);
41132434Sbostic delexit();
41232434Sbostic }
41332434Sbostic return(file);
41432434Sbostic }
41532434Sbostic
pass1()41632434Sbostic pass1()
41732434Sbostic {
41832434Sbostic register int i;
41932434Sbostic
42032434Sbostic passno = 1;
42132434Sbostic dotp = &usedot[0];
42232434Sbostic txtfil = (BFILE *)0;
42332434Sbostic relfil = (struct relbufdesc *)0;
42432434Sbostic
42532434Sbostic if (ninfiles == 0){ /*take the input from stdin directly*/
42632434Sbostic lineno = 1;
42732434Sbostic dotsname = "<stdin>";
42832434Sbostic
42932434Sbostic yyparse();
43032434Sbostic } else { /*we have the names tanked*/
43132434Sbostic for (i = 0; i < ninfiles; i++){
43232434Sbostic new_dot_s(innames[i]);
43332434Sbostic if (freopen(innames[i], "r", stdin) == NULL) {
43432434Sbostic yyerror( "Can't open source file %s\n",
43532434Sbostic innames[i]);
43632434Sbostic exit(2);
43732434Sbostic }
43832434Sbostic /* stdio is NOT used to read the input characters */
43932434Sbostic /* we use read directly, into our own buffers */
44032434Sbostic yyparse();
44132434Sbostic }
44232434Sbostic }
44332434Sbostic
44432434Sbostic closetokfile(); /*kick out the last buffered intermediate text*/
44532434Sbostic }
44632434Sbostic
testlocals()44732434Sbostic testlocals()
44832434Sbostic {
44932434Sbostic register int i;
45032434Sbostic for (i = 0; i <= 9; i++) {
45132434Sbostic if (genref[i])
45232434Sbostic yyerror("Reference to undefined local label %df", i);
45332434Sbostic lgensym[i] = 1;
45432434Sbostic genref[i] = 0;
45532434Sbostic }
45632434Sbostic }
45732434Sbostic
pass1_5()45832434Sbostic pass1_5()
45932434Sbostic {
46032434Sbostic sortsymtab();
46132434Sbostic #ifdef DEBUG
46232434Sbostic if (debug) dumpsymtab();
46332434Sbostic #endif
46432434Sbostic jxxxfix();
46532434Sbostic #ifdef DEBUG
46632434Sbostic if (debug) dumpsymtab();
46732434Sbostic #endif
46832434Sbostic }
46932434Sbostic
open_a_out()47032434Sbostic open_a_out()
47132434Sbostic {
47232434Sbostic /*
47332434Sbostic * Open up the a.out file now, and get set to build
47432434Sbostic * up offsets into it for all of the various text,data
47532434Sbostic * text relocation and data relocation segments.
47632434Sbostic */
47732434Sbostic a_out_file = fopen(outfile, "w");
47832434Sbostic if (a_out_file == NULL) {
47932434Sbostic yyerror("Cannot create %s", outfile);
48032434Sbostic delexit();
48132434Sbostic }
48232434Sbostic biofd = a_out_file->_file;
48332434Sbostic a_out_off = 0;
48432434Sbostic }
48532434Sbostic
roundsegments()48632434Sbostic roundsegments()
48732434Sbostic {
48832434Sbostic register int locindex;
48932434Sbostic register long v;
49032434Sbostic /*
49132434Sbostic * round and assign text segment origins
49232434Sbostic * the exec header always goes in usefile[0]
49332434Sbostic */
49432434Sbostic tsize = 0;
49532434Sbostic for (locindex=0; locindex<NLOC; locindex++) {
49632434Sbostic v = round(usedot[locindex].e_xvalue, FW);
49732434Sbostic usedot[locindex].e_xvalue = tsize;
49832434Sbostic if ((locindex == 0) || (v != 0) ){
49932434Sbostic usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
50032434Sbostic bopen(usefile[locindex], a_out_off);
50132434Sbostic if (locindex == 0)
50232434Sbostic a_out_off = sizeof (struct exec);
50332434Sbostic } else {
50432434Sbostic usefile[locindex] = (BFILE *)-1;
50532434Sbostic }
50632434Sbostic tsize += v;
50732434Sbostic a_out_off += v;
50832434Sbostic }
50932434Sbostic /*
51032434Sbostic * Round and assign data segment origins.
51132434Sbostic */
51232434Sbostic datbase = round(tsize, FW);
51332434Sbostic for (locindex=0; locindex<NLOC; locindex++) {
51432434Sbostic v = round(usedot[NLOC+locindex].e_xvalue, FW);
51532434Sbostic usedot[NLOC+locindex].e_xvalue = datbase + dsize;
51632434Sbostic if (v != 0){
51732434Sbostic usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
51832434Sbostic bopen(usefile[NLOC + locindex], a_out_off);
51932434Sbostic } else {
52032434Sbostic usefile[NLOC + locindex] = (BFILE *)-1;
52132434Sbostic }
52232434Sbostic dsize += v;
52332434Sbostic a_out_off += v;
52432434Sbostic }
52532434Sbostic /*
52632434Sbostic * Assign final values to symbols
52732434Sbostic */
52832434Sbostic hdr.a_bss = dsize;
52932434Sbostic freezesymtab(); /* this touches hdr.a_bss */
53032434Sbostic stabfix();
53132434Sbostic /*
53232434Sbostic * Set up the relocation information "files" to
53332434Sbostic * be zero; outrel takes care of the rest
53432434Sbostic */
53532434Sbostic for (locindex = 0; locindex < NLOC + NLOC; locindex++){
53632434Sbostic rusefile[locindex] = (struct relbufdesc *)0;
53732434Sbostic }
53832434Sbostic }
53932434Sbostic
build_hdr()54032434Sbostic build_hdr()
54132434Sbostic {
54232434Sbostic /*
54332434Sbostic * Except for the text and data relocation sizes,
54432434Sbostic * calculate the final values for the header
54532434Sbostic *
54632434Sbostic * Write out the initial copy; we to come
54732434Sbostic * back later and patch up a_trsize and a_drsize,
54832434Sbostic * and overwrite this first version of the header.
54932434Sbostic */
55032434Sbostic hdr.a_magic = MAGIC;
55132434Sbostic hdr.a_text = tsize;
55232434Sbostic hdr.a_data = dsize;
55332434Sbostic hdr.a_bss -= dsize;
55432434Sbostic hdr.a_syms = sizesymtab(); /* Does not include string pool length */
55532434Sbostic hdr.a_entry = 0;
55632434Sbostic hdr.a_trsize = 0;
55732434Sbostic hdr.a_drsize = 0;
55832434Sbostic
55932434Sbostic bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
56032434Sbostic }
56132434Sbostic
i_pass2()56232434Sbostic i_pass2()
56332434Sbostic {
56432434Sbostic if (useVM == 0) {
56532434Sbostic fclose(tokfile);
56632434Sbostic tokfile = fopen(tokfilename, "r");
56732434Sbostic if (tokfile==NULL) {
56832434Sbostic yyerror("Bad pass 2 temporary file for reading %s", tokfilename);
56932434Sbostic delexit();
57032434Sbostic }
57132434Sbostic }
57232434Sbostic fclose(strfile);
57332434Sbostic strfile = fopen(strfilename, "r");
57432434Sbostic }
57532434Sbostic
pass2()57632434Sbostic pass2()
57732434Sbostic {
57832434Sbostic #ifdef DEBUG
57932434Sbostic if (debug)
58032434Sbostic printf("\n\n\n\t\tPASS 2\n\n\n\n");
58132434Sbostic #endif DEBUG
58232434Sbostic passno = 2;
58332434Sbostic lineno = 1;
58432434Sbostic if (liston && ninfiles != 0)
58532434Sbostic {
58632434Sbostic char ch;
58732434Sbostic source = fopen (innames[ind++], "r");
58832435Sbostic (void)sprintf (layoutpos, "%4ld 00000000 ", lineno);
58932434Sbostic layoutpos += LHEAD;
59032434Sbostic ch = getc (source);
59132434Sbostic if (ch == EOF)
59232434Sbostic {
59332434Sbostic if (ind == ninfiles)
59432434Sbostic endofsource = 1;
59532434Sbostic else
59632434Sbostic source = fopen (innames[ind++], "r");
59732434Sbostic }
59832434Sbostic else
59932434Sbostic ungetc (ch, source);
60032434Sbostic }
60132434Sbostic else
60232434Sbostic endofsource = 1;
60332434Sbostic dotp = &usedot[0];
60432434Sbostic txtfil = usefile[0]; /* already opened (always!) */
60532434Sbostic relfil = 0; /* outrel takes care of the rest */
60632434Sbostic initoutrel();
60732434Sbostic
60832434Sbostic inittokfile();
60932434Sbostic
61032434Sbostic yyparse();
61132434Sbostic
61232434Sbostic closetokfile();
61332434Sbostic }
61432434Sbostic
fillsegments()61532434Sbostic fillsegments()
61632434Sbostic {
61732434Sbostic int locindex;
61832434Sbostic /*
61932434Sbostic * Round text and data segments to FW by appending zeros
62032434Sbostic */
62132434Sbostic for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
62232434Sbostic if (usefile[locindex]) {
62332434Sbostic txtfil = usefile[locindex];
62432434Sbostic dotp = &usedot[locindex];
62532434Sbostic while (usedot[locindex].e_xvalue & FW)
62632434Sbostic outb(0);
62732434Sbostic }
62832434Sbostic }
62932434Sbostic }
63032434Sbostic
reloc_syms()63132434Sbostic reloc_syms()
63232434Sbostic {
63332434Sbostic u_long closerelfil();
63432434Sbostic /*
63532434Sbostic * Move the relocation information to a.out
63632434Sbostic * a_out_off is the offset so far:
63732434Sbostic * exec + text segments + data segments
63832434Sbostic */
63932434Sbostic relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
64032434Sbostic bopen(relocfile, a_out_off);
64132434Sbostic a_out_off += closeoutrel(relocfile);
64232434Sbostic
64332434Sbostic hdr.a_trsize = trsize;
64432434Sbostic hdr.a_drsize = drsize;
64532434Sbostic if (readonlydata) {
64632434Sbostic hdr.a_text += hdr.a_data;
64732434Sbostic hdr.a_data = 0;
64832434Sbostic hdr.a_trsize += hdr.a_drsize;
64932434Sbostic hdr.a_drsize = 0;
65032434Sbostic }
65132434Sbostic /*
65232434Sbostic * Output the symbol table and the string pool
65332434Sbostic *
65432434Sbostic * We must first rewind the string pool file to its beginning,
65532434Sbostic * in case it was seek'ed into for fetching ascii and asciz
65632434Sbostic * strings.
65732434Sbostic */
65832434Sbostic fseek(strfile, 0, 0);
65932434Sbostic symwrite(relocfile);
66032434Sbostic }
66132434Sbostic
fix_a_out()66232434Sbostic fix_a_out()
66332434Sbostic {
66432434Sbostic if (lseek(a_out_file->_file, 0L, 0) < 0L)
66532434Sbostic yyerror("Reposition for header rewrite fails");
66632434Sbostic if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
66732434Sbostic yyerror("Rewrite of header fails");
66832434Sbostic }
66932434Sbostic
delexit()67032434Sbostic delexit()
67132434Sbostic {
67232434Sbostic delete();
67332434Sbostic if (passno == 2){
67432434Sbostic unlink(outfile);
67532434Sbostic }
67632434Sbostic exit(1);
67732434Sbostic }
67832434Sbostic
delete()67932434Sbostic delete()
68032434Sbostic {
68132434Sbostic if (useVM == 0 || tokfilename[0])
68232434Sbostic unlink(tokfilename);
68332434Sbostic if (strfilename[0])
68432434Sbostic unlink(strfilename);
68532434Sbostic }
68632434Sbostic
sawabort()68732434Sbostic sawabort()
68832434Sbostic {
68932434Sbostic char *fillinbuffer();
69032434Sbostic while (fillinbuffer() != (char *)0)
69132434Sbostic continue;
69232434Sbostic delete();
69332434Sbostic exit(1); /*although the previous pass will also exit non zero*/
69432434Sbostic }
69532434Sbostic
panic(fmt,a1,a2,a3,a4)69632434Sbostic panic(fmt, a1, a2, a3, a4)
69732434Sbostic char *fmt;
69832434Sbostic /*VARARGS 1*/
69932434Sbostic {
70032434Sbostic yyerror("Assembler panic: bad internal data structure.");
70132434Sbostic yyerror(fmt, a1, a2, a3, a4);
70232434Sbostic delete();
70332434Sbostic abort();
70432434Sbostic }
705