xref: /csrg-svn/old/as.tahoe/asmain.c (revision 44770)
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