xref: /csrg-svn/old/as.vax/as.h (revision 5829)
1*5829Srrh /*
2*5829Srrh  *	Copyright (c) 1982 Regents of the University of California
3*5829Srrh  *	@(#)as.h 4.9 02/14/82
4*5829Srrh  */
5601Sbill #ifdef VMS
6601Sbill # define	vax	1
7601Sbill # define	VAX	1
8601Sbill #endif VMS
9601Sbill 
10*5829Srrh #define	reg	register
11*5829Srrh 
12635Shenry #include <sys/types.h>
13635Shenry #ifdef UNIX
14635Shenry 
15635Shenry #ifdef FLEXNAMES
16635Shenry #  include <a.out.h>
17635Shenry #  include <stab.h>
18635Shenry #else not FLEXNAMES
191745Shenry #  define ONLIST
201745Shenry #  include "a.out.h"
21635Shenry #  include <stab.h>
22635Shenry #endif FLEXNAMES
23635Shenry 
24635Shenry #endif UNIX
25635Shenry #ifdef VMS
26635Shenry 
27635Shenry #ifdef UNIXDEVEL
28635Shenry #  include <a.out.h>
29635Shenry #else not UNIXDEVEL
30635Shenry #  include <aout.h>
31635Shenry #endif not UNIXDEVEL
32635Shenry 
33635Shenry #endif VMS
34635Shenry 
35601Sbill #define readonly
36601Sbill #define	NINST		300
37601Sbill 
38601Sbill #define	NEXP		20	/* max number of expr. terms per instruction */
39601Sbill #define	NARG		6	/* max number of args per instruction */
40601Sbill #define	NHASH		1103	/* hash table is dynamically extended */
41626Shenry #define	TNAMESIZE	32	/* maximum length of temporary file names */
42601Sbill #define	NLOC		4	/* number of location ctrs */
43601Sbill 
44601Sbill #ifdef UNIX
45601Sbill # ifndef	FLEXNAMES
46601Sbill #	ifndef	NCPS
47601Sbill #		define	NCPS	8	/* number of characters per symbol*/
48601Sbill #	endif
49601Sbill # else
50601Sbill #	ifdef NCPS
51601Sbill #		undef	NCPS
52601Sbill #	endif
53601Sbill #	define	NCPS	BUFSIZ	/* needed to allocate yytext */
54601Sbill # endif
55601Sbill # endif UNIX
56601Sbill 
57601Sbill # ifdef VMS
58601Sbill # ifdef NCPS
59601Sbill #	undef	NCPS
60601Sbill # endif NCPS
61601Sbill #	define	NCPS	15
62601Sbill # endif VMS
63601Sbill 
64601Sbill /*
65601Sbill  * Symbol types
66601Sbill  */
67601Sbill #define	XUNDEF	0x0
68601Sbill #define	XABS	0x2
69601Sbill #define	XTEXT	0x4
70601Sbill #define	XDATA	0x6
71601Sbill #define	XBSS	0x8
72601Sbill 
73601Sbill #define	XXTRN	0x1
74601Sbill #define	XTYPE	0x1E
75601Sbill 
76601Sbill #define	XFORW	0x20	/* Was forward-referenced when undefined */
77601Sbill 
78601Sbill #define	ERR	(-1)
79601Sbill #define	NBPW	32	/* Bits per word */
80601Sbill 
81601Sbill #define	AMASK	017
82601Sbill 
83601Sbill /*
84601Sbill  * Actual argument syntax types
85601Sbill  */
86626Shenry #define	AREG	1	/* %r */
87626Shenry #define	ABASE	2	/* (%r) */
88626Shenry #define	ADECR	3	/* -(%r) */
89626Shenry #define	AINCR	4	/* (%r)+ */
90626Shenry #define	ADISP	5	/* expr(%r) */
91626Shenry #define	AEXP	6	/* expr */
92626Shenry #define	AIMM	7	/* $ expr */
93626Shenry #define	ASTAR	8	/* * */
94626Shenry #define	AINDX	16	/* [%r] */
95601Sbill /*
96*5829Srrh  *	Definitions for the things found in ``instrs''
97601Sbill  */
98*5829Srrh #define	INSTTAB 1
99*5829Srrh #include "instrs.h"
100601Sbill 
101601Sbill /*
102*5829Srrh  *	Tells outrel what it is relocating
103*5829Srrh  *	RELOC_PCREL is an implicit argument to outrel; it is or'ed in
104*5829Srrh  *	with a TYPX
105601Sbill  */
106*5829Srrh #define	RELOC_PCREL	(1<<TYPLG)
107672Shenry /*
108672Shenry  *	reference types for loader
109672Shenry  */
110626Shenry #define	PCREL	1
111626Shenry #define	LEN1	2
112626Shenry #define	LEN2	4
113626Shenry #define	LEN4	6
114626Shenry #define	LEN8	8
115*5829Srrh #define	LEN16	10
116601Sbill 
117672Shenry extern	int	reflen[];	/* {LEN*+PCREL} ==> number of bytes */
118672Shenry extern	int	lgreflen[];	/* {LEN*+PCREL} ==> lg number of bytes */
119*5829Srrh extern	int	len124[];	/* {1,2,4,8,16} ==> {LEN1, LEN2, LEN4, LEN8} */
120*5829Srrh extern	char	mod124[];	/* {1,2,4,8,16} ==> {bits to construct operands */
121*5829Srrh extern	int	type_124[];	/* {1,2,4,8,16} ==> {TYPB,TYPW,TYPL,TYPQ,TYPO} */
122*5829Srrh extern	int	ty_NORELOC[];	/* {TYPB..TYPH} ==> {1 if relocation not OK */
123*5829Srrh extern	int	ty_float[];	/* {TYPB..TYPH} ==> {1 if floating number */
124*5829Srrh extern	int	ty_LEN[];	/* {TYPB..TYPH} ==> {LEN1..LEN16} */
125*5829Srrh extern	int	ty_nbyte[];	/* {TYPB..TYPH} ==> {1,2,4,8,16} */
126*5829Srrh extern	int	ty_nlg[];	/* {TYPB..TYPH} ==> lg{1,2,4,8,16} */
127*5829Srrh extern	char	*ty_string[];	/* {TYPB..TYPH} ==> printable */
128672Shenry 
129601Sbill #define	TMPC	7
130*5829Srrh #define	HW	0x1
131*5829Srrh #define	FW	0x3
132*5829Srrh #define	DW	0x7
133*5829Srrh #define	OW	0xF
134601Sbill 
135601Sbill #ifdef UNIX
136601Sbill #  include <pagsiz.h>
137601Sbill #endif UNIX
138601Sbill 
139601Sbill #ifdef VMS
140601Sbill #  define PAGRND	0x1FFL
141601Sbill #endif VMS
142601Sbill 
143601Sbill #define	round(x,y)	(((x)+(y)) & ~(y))
144601Sbill 
145601Sbill #define	STABTYPS	0340
146626Shenry #define	STABFLAG	0200
147601Sbill 
148601Sbill /*
149601Sbill  *	Follows are the definitions for the symbol table tags, which are
150601Sbill  *	all unsigned characters..
151601Sbill  *	High value tags are generated by the asembler for internal
152601Sbill  *	use.
153601Sbill  *	Low valued tags are the parser coded tokens the scanner returns.
154601Sbill  *	There are several pertinant bounds in this ordering:
155601Sbill  *		a)	Symbols greater than JXQUESTIONABLE
156601Sbill  *			are used by the jxxx bumper, indicating that
157601Sbill  *			the symbol table entry is a jxxx entry
158601Sbill  *			that has yet to be bumped.
159601Sbill  *		b)	Symbols greater than IGNOREBOUND are not
160601Sbill  *			bequeathed to the loader; they are truly
161601Sbill  *			for assembler internal use only.
162601Sbill  *		c)	Symbols greater than OKTOBUMP represent
163601Sbill  *			indices into the program text that should
164601Sbill  *			be changed in preceeding jumps or aligns
165601Sbill  *			must get turned into their long form.
166601Sbill  */
167601Sbill 
168626Shenry #define	TAGMASK		0xFF
169601Sbill 
170601Sbill #	define	JXACTIVE	0xFF	/*jxxx size unknown*/
171601Sbill #	define	JXNOTYET	0xFE	/*jxxx size known, but not yet expanded*/
172601Sbill #	define	JXALIGN		0xFD	/*align jxxx entry*/
173601Sbill #	define	JXINACTIVE	0xFC	/*jxxx size known and expanded*/
174601Sbill 
175626Shenry #define	JXQUESTIONABLE		0xFB
176601Sbill 
177601Sbill #	define	JXTUNNEL	0xFA	/*jxxx that jumps to another*/
178601Sbill #	define	OBSOLETE	0xF9	/*erroneously entered symbol*/
179601Sbill 
180601Sbill #define	IGNOREBOUND	0xF8		/*symbols greater than this are ignored*/
181601Sbill #	define	STABFLOATING	0xF7
182601Sbill #	define	LABELID		0xF6
183601Sbill 
184601Sbill #define	OKTOBUMP	0xF5
185601Sbill #	define	STABFIXED	0xF4
186601Sbill 
187601Sbill /*
188601Sbill  *	astoks.h contains reserved word codings the parser should
189601Sbill  *	know about
190601Sbill  */
191601Sbill #include "astoks.h"
192601Sbill 
193601Sbill /*
194601Sbill  *	The structure for one symbol table entry.
195601Sbill  *	Symbol table entries are used for both user defined symbols,
196601Sbill  *	and symbol slots generated to create the jxxx jump from
197601Sbill  *	slots.
198635Shenry  *	Caution: the instructions are stored in a shorter version
199635Shenry  *	of the struct symtab, using all fields in sym_nm and
200635Shenry  *	tag.  The fields used in sym_nm are carefully redeclared
201635Shenry  *	in struct Instab and struct instab (see below).
202635Shenry  *	If struct nlist gets changed, then Instab and instab may
203635Shenry  *	have to be changed.
204601Sbill  */
205601Sbill 
206601Sbill struct symtab{
207635Shenry 		struct	nlist	s_nm;
208635Shenry 		u_char	s_tag;		/* assembler tag */
209635Shenry 		u_char	s_ptype;	/* if tag == NAME */
210635Shenry 		u_char	s_jxoveralign;	/* if a JXXX, jumped over align */
211635Shenry 		short	s_index;	/* which segment */
212635Shenry 		struct	symtab *s_dest;	/* if JXXX, where going to */
213601Sbill #ifdef DJXXX
214635Shenry 		short	s_jxline;	/* source line of the jump from */
215601Sbill #endif
216601Sbill };
217635Shenry /*
218635Shenry  *	Redefinitions of the fields in symtab for
219635Shenry  *	use when the symbol table entry marks a jxxx instruction.
220635Shenry  */
221635Shenry #define	s_jxbump	s_ptype		/* tag == JX..., how far to expand */
222635Shenry #define	s_jxfear	s_desc		/* how far needs to be bumped */
223635Shenry /*
224635Shenry  *	Redefinitions of fields in the struct nlist for symbols so that
225635Shenry  *	one saves typing, and so that they conform
226635Shenry  *	with the old naming conventions.
227635Shenry  */
228635Shenry #ifdef	FLEXNAMES
229635Shenry #define	s_name	s_nm.n_un.n_name	/* name pointer */
230635Shenry #define	s_nmx	s_nm.n_un.n_strx	/* string table index */
231635Shenry #else 	not FLEXNAMES
232635Shenry #define	s_name	s_nm.n_name
233635Shenry #endif
234635Shenry #define	s_type	s_nm.n_type		/* type of the symbol */
235635Shenry #define	s_other	s_nm.n_other		/* other information for sdb */
236635Shenry #define	s_desc	s_nm.n_desc		/* type descriptor */
237635Shenry #define	s_value	s_nm.n_value		/* value of the symbol, or sdb delta */
238601Sbill 
239635Shenry struct	instab{
240635Shenry 	struct	nlist	s_nm;		/* instruction name, type (opcode) */
241635Shenry 	u_char	s_tag;
242*5829Srrh 	u_char	s_eopcode;
243*5829Srrh 	char	s_pad[2];		/* round to 20 bytes */
244601Sbill };
245*5829Srrh typedef	struct	instab	*Iptr;
246635Shenry /*
247635Shenry  *	The fields nm.n_desc and nm.n_value total 6 bytes; this is
248635Shenry  *	just enough for the 6 bytes describing the argument types.
249635Shenry  *	We use a macro to define access to these 6 bytes, assuming that
250635Shenry  *	they are allocated adjacently.
251635Shenry  *	IF THE FORMAT OF STRUCT nlist CHANGES, THESE MAY HAVE TO BE CHANGED.
252635Shenry  *
2531745Shenry  *	Instab is cleverly declared to look very much like the combination of
254635Shenry  *	a struct symtab and a struct nlist.
255635Shenry  */
256*5829Srrh /*
257*5829Srrh  *	With the 1981 VAX architecture reference manual,
258*5829Srrh  *	DEC defined and named two byte opcodes.
259*5829Srrh  *	In addition, DEC defined four new one byte instructions for
260*5829Srrh  *	queue manipulation.
261*5829Srrh  *	The assembler was patched in 1982 to reflect this change.
262*5829Srrh  *
263*5829Srrh  *	The two byte opcodes are preceded with an escape byte
264*5829Srrh  *	(usually an ESCD) and an opcode byte.
265*5829Srrh  *	For one byte opcodes, the opcode is called the primary opcode.
266*5829Srrh  *	For two byte opcodes, the second opcode is called the primary opcode.
267*5829Srrh  *
268*5829Srrh  *	We store the primary opcode in I_popcode,
269*5829Srrh  *	and the escape opcode in I_eopcode.
270*5829Srrh  *
271*5829Srrh  *	For one byte opcodes in the basic arhitecture,
272*5829Srrh  *		I_eopcode is CORE
273*5829Srrh  *	For one byte opcodes in the new architecture definition,
274*5829Srrh  *		I_eopcode is NEW
275*5829Srrh  *	For the two byte opcodes, I_eopcode is the escape byte.
276*5829Srrh  *
277*5829Srrh  *	The assembler checks if a NEW or two byte opcode is used,
278*5829Srrh  *	and issues a warning diagnostic.
279*5829Srrh  */
280*5829Srrh /*
281*5829Srrh  *	For upward compatability reasons, we can't have the two opcodes
282*5829Srrh  *	forming an operator specifier byte(s) be physically adjacent
283*5829Srrh  *	in the instruction table.
284*5829Srrh  *	We define a structure and a constructor that is used in
285*5829Srrh  *	the instruction generator.
286*5829Srrh  */
287*5829Srrh struct Opcode{
288*5829Srrh 	u_char	Op_eopcode;
289*5829Srrh 	u_char	Op_popcode;
290*5829Srrh };
291*5829Srrh 
292*5829Srrh #define	BADPOINT	0xAAAAAAAA
293*5829Srrh /*
294*5829Srrh  *	See if a structured opcode is bad
295*5829Srrh  */
296*5829Srrh #define	ITABCHECK(o)	((itab[o.Op_eopcode] != (Iptr*)BADPOINT) && (itab[o.Op_eopcode][o.Op_popcode] != (Iptr)BADPOINT))
297*5829Srrh /*
298*5829Srrh  *	Index the itab by a structured opcode
299*5829Srrh  */
300*5829Srrh #define	ITABFETCH(o)	itab[o.Op_eopcode][o.Op_popcode]
301*5829Srrh 
302635Shenry struct	Instab{
303635Shenry #ifdef FLEXNAMES
304635Shenry 	char	*I_name;
305635Shenry #else not FLEXNAMES
306635Shenry 	char	I_name[NCPS];
307635Shenry #endif
308*5829Srrh 	u_char	I_popcode;		/* basic op code */
309635Shenry 	char	I_nargs;
310635Shenry 	char	I_args[6];
311635Shenry 	u_char	I_s_tag;
312*5829Srrh 	u_char	I_eopcode;
313*5829Srrh 	char	I_pad[2];		/* round to 20 bytes */
314635Shenry };
315635Shenry /*
316635Shenry  *	Redefinitions of fields in the struct nlist for instructions so that
317635Shenry  *	one saves typing, and conforms to the old naming conventions
318635Shenry  */
319*5829Srrh #define	i_popcode	s_nm.n_type	/* use the same field as symtab.type */
320*5829Srrh #define	i_eopcode	s_eopcode
321635Shenry #define	i_nargs		s_nm.n_other	/* number of arguments */
322635Shenry #define	fetcharg(ptr, n) ((struct Instab *)ptr)->I_args[n]
323601Sbill 
324601Sbill struct	arg {				/*one argument to an instruction*/
325635Shenry 	char	a_atype;
326635Shenry 	char	a_areg1;
327635Shenry 	char	a_areg2;
328635Shenry 	char	a_dispsize;		/*usually d124, unless have B^, etc*/
329635Shenry 	struct	exp *a_xp;
330601Sbill };
331*5829Srrh /*
332*5829Srrh  *	Definitions for numbers and expressions.
333*5829Srrh  */
334*5829Srrh #include "asnumber.h"
335601Sbill struct	exp {
336*5829Srrh 	Bignum	e_number;	/* 128 bits of #, plus tag */
337635Shenry 	char	e_xtype;
338635Shenry 	char	e_xloc;
339*5829Srrh 	struct	symtab		*e_xname;
340601Sbill };
341*5829Srrh #define	e_xvalue	e_number.num_num.numIl_int.Il_long
342601Sbill 
343*5829Srrh #define		MINLIT		0
344*5829Srrh #define		MAXLIT		63
345601Sbill 
346*5829Srrh #define		MINBYTE		-128
347*5829Srrh #define		MAXBYTE		127
348*5829Srrh #define		MINUBYTE	0
349*5829Srrh #define		MAXUBYTE	255
350601Sbill 
351*5829Srrh #define		MINWORD		-32768
352*5829Srrh #define		MAXWORD		32767
353*5829Srrh #define		MINUWORD	0
354*5829Srrh #define		MAXUWORD	65535
355601Sbill 
356*5829Srrh #define		ISLIT(x)	(((x) >= MINLIT) && ((x) <= MAXLIT))
357*5829Srrh #define		ISBYTE(x)	(((x) >= MINBYTE) && ((x) <= MAXBYTE))
358*5829Srrh #define		ISUBYTE(x)	(((x) >= MINUBYTE) && ((x) <= MAXUBYTE))
359*5829Srrh #define		ISWORD(x)	(((x) >= MINWORD) && ((x) <= MAXWORD))
360*5829Srrh #define		ISUWORD(x)	(((x) >= MINUWORD) && ((x) <= MAXUWORD))
361601Sbill 
362601Sbill 	extern	struct	arg	arglist[NARG];	/*building operands in instructions*/
363601Sbill 	extern	struct	exp	explist[NEXP];	/*building up a list of expressions*/
364601Sbill 	extern	struct	exp	*xp;		/*current free expression*/
365601Sbill 	/*
366601Sbill 	 *	Communication between the scanner and the jxxx handlers.
367601Sbill 	 *	lastnam:	the last name seen on the input
368601Sbill 	 *	lastjxxx:	pointer to the last symbol table entry for
369601Sbill 	 *			a jump from
370601Sbill 	 */
371601Sbill 	extern	struct	symtab	*lastnam;
372601Sbill 	extern	struct	symtab	*lastjxxx;
373601Sbill 
374601Sbill #ifdef VMS
375635Shenry 	extern	char	*vms_obj_ptr;		/* object buffer pointer */
376635Shenry 	extern	char	sobuf[];		/* object buffer         */
377601Sbill 	extern	int	objfil;			/* VMS object file descriptor */
378601Sbill #endif VMS
379601Sbill 
380601Sbill 	/*
381601Sbill 	 *	Lgensym is used to make up funny names for local labels.
382601Sbill 	 *	lgensym[i] is the current funny number to put after
383601Sbill 	 *	references to if, lgensym[i]-1 is for ib.
384601Sbill 	 *	genref[i] is set when the label is referenced before
385601Sbill 	 *	it is defined (i.e. 2f) so that we can be sure these
386601Sbill 	 *	labels are always defined to avoid weird diagnostics
387601Sbill 	 *	from the loader later.
388601Sbill 	 */
389601Sbill 	extern	int	lgensym[10];
390601Sbill 	extern	char	genref[10];
391601Sbill 
392601Sbill 	extern	char	tmpn1[TNAMESIZE];	/* Interpass temporary */
393601Sbill 	extern	struct	exp	*dotp;		/* the current dot location */
394601Sbill 	extern	int	loctr;
395601Sbill 
396601Sbill 	extern	struct	exec	hdr;		/* a.out header */
397601Sbill 	extern	u_long	tsize;			/* total text size */
398601Sbill 	extern	u_long	dsize;			/* total data size */
399601Sbill 	extern	u_long	trsize;			/* total text relocation size */
400601Sbill 	extern	u_long	drsize;			/* total data relocation size */
401601Sbill 	extern	u_long	datbase;		/* base of the data segment */
402601Sbill 	/*
403601Sbill 	 *	Bitoff and bitfield keep track of the packing into
404601Sbill 	 *	bytes mandated by the expression syntax <expr> ':' <expr>
405601Sbill 	 */
406601Sbill 	extern	int	bitoff;
407601Sbill 	extern	long	bitfield;
408601Sbill 
409601Sbill 	/*
410601Sbill 	 *	The lexical analyzer builds up symbols in yytext.  Lookup
411601Sbill 	 *	expects its argument in this buffer
412601Sbill 	 */
413601Sbill 	extern	char	yytext[NCPS+2];		/* text buffer for lexical */
414601Sbill 	/*
415601Sbill 	 *	Variables to manage the input assembler source file
416601Sbill 	 */
417601Sbill 	extern	int	lineno;			/*the line number*/
418601Sbill 	extern	char	*dotsname;		/*the name of the as source*/
419601Sbill 
420601Sbill 	extern	FILE	*tmpfil;		/* interpass communication*/
421601Sbill 
422601Sbill 	extern	int	passno;			/* 1 or 2 */
423601Sbill 
424*5829Srrh 	extern	int	anyerrs;		/*errors as'ing arguments*/
425*5829Srrh 	extern	int	anywarnings;		/*warnings as'ing arguments*/
426601Sbill 	extern	int	silent;			/*don't mention the errors*/
427601Sbill 	extern	int	savelabels;		/*save labels in a.out*/
428601Sbill 	extern	int	orgwarn;		/* questionable origin ? */
429601Sbill 	extern	int	useVM;			/*use virtual memory temp file*/
430637Shenry 	extern	int	jxxxJUMP;		/*use jmp instead of brw for jxxx */
431639Sbill 	extern	int	readonlydata;		/*initialized data into text space*/
432*5829Srrh 	extern	int	nGHnumbers;		/* GH numbers used */
433*5829Srrh 	extern	int	nGHopcodes;		/* GH opcodes used */
434*5829Srrh 	extern	int	nnewopcodes;		/* new opcodes used */
435601Sbill #ifdef DEBUG
436601Sbill 	extern	int	debug;
437601Sbill 	extern	int	toktrace;
438601Sbill #endif
439601Sbill 	/*
440601Sbill 	 *	Information about the instructions
441601Sbill 	 */
442*5829Srrh 	extern	struct	instab	**itab[NINST];	/*maps opcodes to instructions*/
443635Shenry 	extern  readonly struct Instab instab[];
444601Sbill 
445601Sbill 	extern	int	curlen;			/*current literal storage size*/
446601Sbill 	extern	int	d124;			/*current pointer storage size*/
447601Sbill 
448601Sbill 	struct	symtab	**lookup();		/*argument in yytext*/
449601Sbill 	struct 	symtab	*symalloc();
450601Sbill 
451*5829Srrh 	char	*Calloc();
452*5829Srrh 	char	*ClearCalloc();
453*5829Srrh 
454635Shenry #define outb(val) {dotp->e_xvalue++; if (passno==2) bputc((val), (txtfil));}
455601Sbill 
456635Shenry #define outs(cp, lg) dotp->e_xvalue += (lg); if (passno == 2) bwrite((cp), (lg), (txtfil))
457601Sbill 
458*5829Srrh #ifdef UNIX
459*5829Srrh #define	Outb(o)	outb(o)
460*5829Srrh #endif UNIX
461*5829Srrh 
462*5829Srrh #ifdef VMS
463*5829Srrh #define	Outb(o)	{*vms_obj_ptr++=-1;*vms_obj_ptr++=(char)o;dotp->e_xvalue+=1;}
464*5829Srrh #endif VMS
465*5829Srrh 
466601Sbill /*
467601Sbill  *	Most of the time, the argument to flushfield is a power of two constant,
468601Sbill  *	the calculations involving it can be optimized to shifts.
469601Sbill  */
470601Sbill #define flushfield(n) if (bitoff != 0)  Flushfield( ( (bitoff+n-1) /n ) * n)
471601Sbill 
472601Sbill /*
473601Sbill  * The biobuf structure and associated routines are used to write
474601Sbill  * into one file at several places concurrently.  Calling bopen
475601Sbill  * with a biobuf structure sets it up to write ``biofd'' starting
476601Sbill  * at the specified offset.  You can then use ``bwrite'' and/or ``bputc''
477601Sbill  * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
478601Sbill  * Calling bflush drains all the buffers and MUST be done before exit.
479601Sbill  */
480601Sbill struct	biobuf {
481601Sbill 	short	b_nleft;		/* Number free spaces left in b_buf */
482601Sbill /* Initialize to be less than BUFSIZ initially, to boundary align in file */
483601Sbill 	char	*b_ptr;			/* Next place to stuff characters */
484601Sbill 	char	b_buf[BUFSIZ];		/* The buffer itself */
485601Sbill 	off_t	b_off;			/* Current file offset */
486601Sbill 	struct	biobuf *b_link;		/* Link in chain for bflush() */
487601Sbill };
488601Sbill #define	bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
489601Sbill 		       : bflushc(b, c))
490601Sbill #define BFILE	struct biobuf
491601Sbill 
492601Sbill 	extern	BFILE	*biobufs;	/* head of the block I/O buffer chain */
493601Sbill 	extern	int	biofd;		/* file descriptor for block I/O file */
494601Sbill 	extern	off_t	boffset;	/* physical position in logical file */
495601Sbill 
496601Sbill 	/*
497601Sbill 	 *	For each of the named .text .data segments
498601Sbill 	 *	(introduced by .text <expr>), we maintain
499601Sbill 	 *	the current value of the dot, and the BFILE where
500601Sbill 	 *	the information for each of the segments is placed
501601Sbill 	 *	during the second pass.
502601Sbill 	 */
503601Sbill 	extern	struct	exp	usedot[NLOC + NLOC];
504601Sbill 	extern		BFILE	*usefile[NLOC + NLOC];
505601Sbill 	extern		BFILE	*txtfil;/* file for text and data: into usefile */
506601Sbill 	/*
507601Sbill 	 *	Relocation information for each segment is accumulated
508601Sbill 	 *	seperately from the others.  Writing the relocation
509601Sbill 	 *	information is logically viewed as writing to one
510601Sbill 	 *	relocation saving file for  each segment; physically
511601Sbill 	 *	we have a bunch of buffers allocated internally that
512601Sbill 	 *	contain the relocation information.
513601Sbill 	 */
514601Sbill 	struct	relbufdesc	*rusefile[NLOC + NLOC];
515601Sbill 	struct	relbufdesc	*relfil;
516