xref: /csrg-svn/old/as.vax/as.h (revision 23849)
15829Srrh /*
218713Sdist  * Copyright (c) 1982 Regents of the University of California.
318713Sdist  * All rights reserved.  The Berkeley software License Agreement
418713Sdist  * specifies the terms and conditions for redistribution.
518713Sdist  *
6*23849Sbloom  *	@(#)as.h	5.3 (Berkeley) 07/06/85
75829Srrh  */
818713Sdist 
95829Srrh #define	reg	register
105829Srrh 
11635Shenry #include <sys/types.h>
1213523Srrh #include <a.out.h>
1313523Srrh #include <stab.h>
14635Shenry 
15601Sbill #define readonly
16601Sbill #define	NINST		300
17601Sbill 
18601Sbill #define	NEXP		20	/* max number of expr. terms per instruction */
19601Sbill #define	NARG		6	/* max number of args per instruction */
20601Sbill #define	NHASH		1103	/* hash table is dynamically extended */
21*23849Sbloom #define	TNAMESIZE	256	/* maximum length of temporary file names */
22601Sbill #define	NLOC		4	/* number of location ctrs */
2313461Srrh /*
2413461Srrh  *	Sizes for character buffers.
2513461Srrh  *	what			size #define name	comments
2613461Srrh  *
2713523Srrh  *	name assembly		NCPName
2813574Srrh  *	name save		STRPOOLDALLOP
2913461Srrh  *
3013574Srrh  *	-name saving is a simple first fit
3113461Srrh  */
3213461Srrh #ifndef STRPOOLDALLOP
3313461Srrh #	define STRPOOLDALLOP	8192
3413461Srrh #endif not STRPOOLDALLOP
35601Sbill 
3613461Srrh #define	NCPName	NCPS
3713523Srrh #ifndef NCPS
3813523Srrh #	undef	NCPName
3913523Srrh #	define	NCPName	4096
4013523Srrh #endif not NCPS
41601Sbill /*
4213461Srrh  *	Check sizes, and compiler error if sizes botch
4313461Srrh  */
4413574Srrh #if STRPOOLDALLOP < NCPName
4513461Srrh 	$$$botch with definition sizes
4613461Srrh #endif test botches
4713461Srrh /*
48601Sbill  * Symbol types
49601Sbill  */
50601Sbill #define	XUNDEF	0x0
51601Sbill #define	XABS	0x2
52601Sbill #define	XTEXT	0x4
53601Sbill #define	XDATA	0x6
54601Sbill #define	XBSS	0x8
55601Sbill 
56601Sbill #define	XXTRN	0x1
57601Sbill #define	XTYPE	0x1E
58601Sbill 
59601Sbill #define	XFORW	0x20	/* Was forward-referenced when undefined */
60601Sbill 
61601Sbill #define	ERR	(-1)
6223577Smckusick #define	NBWD	32	/* Bits per word */
63601Sbill 
64601Sbill #define	AMASK	017
65601Sbill 
66601Sbill /*
67601Sbill  * Actual argument syntax types
68601Sbill  */
69626Shenry #define	AREG	1	/* %r */
70626Shenry #define	ABASE	2	/* (%r) */
71626Shenry #define	ADECR	3	/* -(%r) */
72626Shenry #define	AINCR	4	/* (%r)+ */
73626Shenry #define	ADISP	5	/* expr(%r) */
74626Shenry #define	AEXP	6	/* expr */
75626Shenry #define	AIMM	7	/* $ expr */
76626Shenry #define	ASTAR	8	/* * */
77626Shenry #define	AINDX	16	/* [%r] */
78601Sbill /*
795829Srrh  *	Definitions for the things found in ``instrs''
80601Sbill  */
815829Srrh #define	INSTTAB 1
825829Srrh #include "instrs.h"
83601Sbill 
84601Sbill /*
855829Srrh  *	Tells outrel what it is relocating
865829Srrh  *	RELOC_PCREL is an implicit argument to outrel; it is or'ed in
875829Srrh  *	with a TYPX
88601Sbill  */
895829Srrh #define	RELOC_PCREL	(1<<TYPLG)
90672Shenry /*
91672Shenry  *	reference types for loader
92672Shenry  */
93626Shenry #define	PCREL	1
94626Shenry #define	LEN1	2
95626Shenry #define	LEN2	4
96626Shenry #define	LEN4	6
97626Shenry #define	LEN8	8
985829Srrh #define	LEN16	10
99601Sbill 
100672Shenry extern	int	reflen[];	/* {LEN*+PCREL} ==> number of bytes */
101672Shenry extern	int	lgreflen[];	/* {LEN*+PCREL} ==> lg number of bytes */
1025829Srrh extern	int	len124[];	/* {1,2,4,8,16} ==> {LEN1, LEN2, LEN4, LEN8} */
1035829Srrh extern	char	mod124[];	/* {1,2,4,8,16} ==> {bits to construct operands */
1045829Srrh extern	int	type_124[];	/* {1,2,4,8,16} ==> {TYPB,TYPW,TYPL,TYPQ,TYPO} */
1055829Srrh extern	int	ty_NORELOC[];	/* {TYPB..TYPH} ==> {1 if relocation not OK */
1065829Srrh extern	int	ty_float[];	/* {TYPB..TYPH} ==> {1 if floating number */
1075829Srrh extern	int	ty_LEN[];	/* {TYPB..TYPH} ==> {LEN1..LEN16} */
1085829Srrh extern	int	ty_nbyte[];	/* {TYPB..TYPH} ==> {1,2,4,8,16} */
1095829Srrh extern	int	ty_nlg[];	/* {TYPB..TYPH} ==> lg{1,2,4,8,16} */
1105829Srrh extern	char	*ty_string[];	/* {TYPB..TYPH} ==> printable */
111672Shenry 
112601Sbill #define	TMPC	7
1135829Srrh #define	HW	0x1
1145829Srrh #define	FW	0x3
1155829Srrh #define	DW	0x7
1165829Srrh #define	OW	0xF
117601Sbill 
118601Sbill #define	round(x,y)	(((x)+(y)) & ~(y))
119601Sbill 
120601Sbill #define	STABTYPS	0340
121626Shenry #define	STABFLAG	0200
122601Sbill 
123601Sbill /*
124601Sbill  *	Follows are the definitions for the symbol table tags, which are
125601Sbill  *	all unsigned characters..
126601Sbill  *	High value tags are generated by the asembler for internal
127601Sbill  *	use.
128601Sbill  *	Low valued tags are the parser coded tokens the scanner returns.
129601Sbill  *	There are several pertinant bounds in this ordering:
130601Sbill  *		a)	Symbols greater than JXQUESTIONABLE
131601Sbill  *			are used by the jxxx bumper, indicating that
132601Sbill  *			the symbol table entry is a jxxx entry
133601Sbill  *			that has yet to be bumped.
134601Sbill  *		b)	Symbols greater than IGNOREBOUND are not
135601Sbill  *			bequeathed to the loader; they are truly
136601Sbill  *			for assembler internal use only.
137601Sbill  *		c)	Symbols greater than OKTOBUMP represent
138601Sbill  *			indices into the program text that should
139601Sbill  *			be changed in preceeding jumps or aligns
140601Sbill  *			must get turned into their long form.
141601Sbill  */
142601Sbill 
143626Shenry #define	TAGMASK		0xFF
144601Sbill 
145601Sbill #	define	JXACTIVE	0xFF	/*jxxx size unknown*/
146601Sbill #	define	JXNOTYET	0xFE	/*jxxx size known, but not yet expanded*/
147601Sbill #	define	JXALIGN		0xFD	/*align jxxx entry*/
148601Sbill #	define	JXINACTIVE	0xFC	/*jxxx size known and expanded*/
149601Sbill 
150626Shenry #define	JXQUESTIONABLE		0xFB
151601Sbill 
152601Sbill #	define	JXTUNNEL	0xFA	/*jxxx that jumps to another*/
153601Sbill #	define	OBSOLETE	0xF9	/*erroneously entered symbol*/
154601Sbill 
155601Sbill #define	IGNOREBOUND	0xF8		/*symbols greater than this are ignored*/
156601Sbill #	define	STABFLOATING	0xF7
157601Sbill #	define	LABELID		0xF6
158601Sbill 
159601Sbill #define	OKTOBUMP	0xF5
160601Sbill #	define	STABFIXED	0xF4
161601Sbill 
162601Sbill /*
163601Sbill  *	astoks.h contains reserved word codings the parser should
164601Sbill  *	know about
165601Sbill  */
166601Sbill #include "astoks.h"
167601Sbill 
168601Sbill /*
169601Sbill  *	The structure for one symbol table entry.
170601Sbill  *	Symbol table entries are used for both user defined symbols,
171601Sbill  *	and symbol slots generated to create the jxxx jump from
172601Sbill  *	slots.
173635Shenry  *	Caution: the instructions are stored in a shorter version
174635Shenry  *	of the struct symtab, using all fields in sym_nm and
175635Shenry  *	tag.  The fields used in sym_nm are carefully redeclared
176635Shenry  *	in struct Instab and struct instab (see below).
177635Shenry  *	If struct nlist gets changed, then Instab and instab may
178635Shenry  *	have to be changed.
179601Sbill  */
180601Sbill 
181601Sbill struct symtab{
182635Shenry 		struct	nlist	s_nm;
183635Shenry 		u_char	s_tag;		/* assembler tag */
184635Shenry 		u_char	s_ptype;	/* if tag == NAME */
185635Shenry 		u_char	s_jxoveralign;	/* if a JXXX, jumped over align */
186635Shenry 		short	s_index;	/* which segment */
187635Shenry 		struct	symtab *s_dest;	/* if JXXX, where going to */
18815233Sralph #ifdef DEBUG
189635Shenry 		short	s_jxline;	/* source line of the jump from */
190601Sbill #endif
191601Sbill };
192635Shenry /*
193635Shenry  *	Redefinitions of the fields in symtab for
194635Shenry  *	use when the symbol table entry marks a jxxx instruction.
195635Shenry  */
196635Shenry #define	s_jxbump	s_ptype		/* tag == JX..., how far to expand */
197635Shenry #define	s_jxfear	s_desc		/* how far needs to be bumped */
198635Shenry /*
199635Shenry  *	Redefinitions of fields in the struct nlist for symbols so that
200635Shenry  *	one saves typing, and so that they conform
201635Shenry  *	with the old naming conventions.
202635Shenry  */
20313515Srrh #define	s_name	s_nm.n_un.n_name
20413515Srrh #define	i_name	s_name
20513515Srrh #define	FETCHNAME(sp)	(((struct strdesc *)(sp)->s_name)->sd_string)
20613515Srrh #define	STRLEN(sp)	(((struct strdesc *)(sp)->s_name)->sd_strlen)
20713515Srrh #define	STROFF(sp)	(((struct strdesc *)(sp)->s_name)->sd_stroff)
20814449Srrh #define	STRPLACE(sp)	(((struct strdesc *)(sp)->s_name)->sd_place)
209635Shenry #define	s_nmx	s_nm.n_un.n_strx	/* string table index */
210635Shenry #define	s_type	s_nm.n_type		/* type of the symbol */
211635Shenry #define	s_other	s_nm.n_other		/* other information for sdb */
212635Shenry #define	s_desc	s_nm.n_desc		/* type descriptor */
213635Shenry #define	s_value	s_nm.n_value		/* value of the symbol, or sdb delta */
214601Sbill 
215635Shenry struct	instab{
216635Shenry 	struct	nlist	s_nm;		/* instruction name, type (opcode) */
217635Shenry 	u_char	s_tag;
2185829Srrh 	u_char	s_eopcode;
2195829Srrh 	char	s_pad[2];		/* round to 20 bytes */
220601Sbill };
2215829Srrh typedef	struct	instab	*Iptr;
222635Shenry /*
223635Shenry  *	The fields nm.n_desc and nm.n_value total 6 bytes; this is
224635Shenry  *	just enough for the 6 bytes describing the argument types.
225635Shenry  *	We use a macro to define access to these 6 bytes, assuming that
226635Shenry  *	they are allocated adjacently.
227635Shenry  *	IF THE FORMAT OF STRUCT nlist CHANGES, THESE MAY HAVE TO BE CHANGED.
228635Shenry  *
2291745Shenry  *	Instab is cleverly declared to look very much like the combination of
230635Shenry  *	a struct symtab and a struct nlist.
231635Shenry  */
2325829Srrh /*
2335829Srrh  *	With the 1981 VAX architecture reference manual,
2345829Srrh  *	DEC defined and named two byte opcodes.
2355829Srrh  *	In addition, DEC defined four new one byte instructions for
2365829Srrh  *	queue manipulation.
2375829Srrh  *	The assembler was patched in 1982 to reflect this change.
2385829Srrh  *
2395829Srrh  *	The two byte opcodes are preceded with an escape byte
2405829Srrh  *	(usually an ESCD) and an opcode byte.
2415829Srrh  *	For one byte opcodes, the opcode is called the primary opcode.
2425829Srrh  *	For two byte opcodes, the second opcode is called the primary opcode.
2435829Srrh  *
2445829Srrh  *	We store the primary opcode in I_popcode,
2455829Srrh  *	and the escape opcode in I_eopcode.
2465829Srrh  *
2475829Srrh  *	For one byte opcodes in the basic arhitecture,
2485829Srrh  *		I_eopcode is CORE
2495829Srrh  *	For one byte opcodes in the new architecture definition,
2505829Srrh  *		I_eopcode is NEW
2515829Srrh  *	For the two byte opcodes, I_eopcode is the escape byte.
2525829Srrh  *
2535829Srrh  *	The assembler checks if a NEW or two byte opcode is used,
2545829Srrh  *	and issues a warning diagnostic.
2555829Srrh  */
2565829Srrh /*
2575829Srrh  *	For upward compatability reasons, we can't have the two opcodes
2585829Srrh  *	forming an operator specifier byte(s) be physically adjacent
2595829Srrh  *	in the instruction table.
2605829Srrh  *	We define a structure and a constructor that is used in
2615829Srrh  *	the instruction generator.
2625829Srrh  */
2635829Srrh struct Opcode{
2645829Srrh 	u_char	Op_eopcode;
2655829Srrh 	u_char	Op_popcode;
2665829Srrh };
2675829Srrh 
2685829Srrh #define	BADPOINT	0xAAAAAAAA
2695829Srrh /*
2705829Srrh  *	See if a structured opcode is bad
2715829Srrh  */
2725829Srrh #define	ITABCHECK(o)	((itab[o.Op_eopcode] != (Iptr*)BADPOINT) && (itab[o.Op_eopcode][o.Op_popcode] != (Iptr)BADPOINT))
2735829Srrh /*
2745829Srrh  *	Index the itab by a structured opcode
2755829Srrh  */
2765829Srrh #define	ITABFETCH(o)	itab[o.Op_eopcode][o.Op_popcode]
2775829Srrh 
278635Shenry struct	Instab{
279635Shenry 	char	*I_name;
2805829Srrh 	u_char	I_popcode;		/* basic op code */
281635Shenry 	char	I_nargs;
282635Shenry 	char	I_args[6];
283635Shenry 	u_char	I_s_tag;
2845829Srrh 	u_char	I_eopcode;
2855829Srrh 	char	I_pad[2];		/* round to 20 bytes */
286635Shenry };
287635Shenry /*
288635Shenry  *	Redefinitions of fields in the struct nlist for instructions so that
289635Shenry  *	one saves typing, and conforms to the old naming conventions
290635Shenry  */
2915829Srrh #define	i_popcode	s_nm.n_type	/* use the same field as symtab.type */
2925829Srrh #define	i_eopcode	s_eopcode
293635Shenry #define	i_nargs		s_nm.n_other	/* number of arguments */
294635Shenry #define	fetcharg(ptr, n) ((struct Instab *)ptr)->I_args[n]
295601Sbill 
296601Sbill struct	arg {				/*one argument to an instruction*/
297635Shenry 	char	a_atype;
298635Shenry 	char	a_areg1;
299635Shenry 	char	a_areg2;
300635Shenry 	char	a_dispsize;		/*usually d124, unless have B^, etc*/
301635Shenry 	struct	exp *a_xp;
302601Sbill };
3035829Srrh /*
3045829Srrh  *	Definitions for numbers and expressions.
3055829Srrh  */
3065829Srrh #include "asnumber.h"
307601Sbill struct	exp {
3085829Srrh 	Bignum	e_number;	/* 128 bits of #, plus tag */
309635Shenry 	char	e_xtype;
310635Shenry 	char	e_xloc;
3115829Srrh 	struct	symtab		*e_xname;
312601Sbill };
3135829Srrh #define	e_xvalue	e_number.num_num.numIl_int.Il_long
314601Sbill 
3155829Srrh #define		MINLIT		0
3165829Srrh #define		MAXLIT		63
317601Sbill 
3185829Srrh #define		MINBYTE		-128
3195829Srrh #define		MAXBYTE		127
3205829Srrh #define		MINUBYTE	0
3215829Srrh #define		MAXUBYTE	255
322601Sbill 
3235829Srrh #define		MINWORD		-32768
3245829Srrh #define		MAXWORD		32767
3255829Srrh #define		MINUWORD	0
3265829Srrh #define		MAXUWORD	65535
327601Sbill 
3285829Srrh #define		ISLIT(x)	(((x) >= MINLIT) && ((x) <= MAXLIT))
3295829Srrh #define		ISBYTE(x)	(((x) >= MINBYTE) && ((x) <= MAXBYTE))
3305829Srrh #define		ISUBYTE(x)	(((x) >= MINUBYTE) && ((x) <= MAXUBYTE))
3315829Srrh #define		ISWORD(x)	(((x) >= MINWORD) && ((x) <= MAXWORD))
3325829Srrh #define		ISUWORD(x)	(((x) >= MINUWORD) && ((x) <= MAXUWORD))
33313515Srrh /*
33413515Srrh  *	Definitions for strings.
33513515Srrh  *
33613515Srrh  *	Strings are stored in the string pool; see strsave(str, length)
33713515Srrh  *	Strings are known by their length and values.
33813515Srrh  *	A string pointer points to the beginning of the value bytes;
33913515Srrh  *
34013515Srrh  *	If this structure is changed, change insts also.
34113515Srrh  */
34213515Srrh struct	strdesc{
34313515Srrh 	int	sd_stroff;	/* offset into string file */
34413515Srrh 	short	sd_place;	/* where string is */
34513515Srrh 	u_short	sd_strlen;	/* string length */
34613515Srrh 	char	sd_string[1];	/* the string itself, flexible length */
34713515Srrh };
34813515Srrh /*
34913515Srrh  *	Where a string can be.  If these are changed, also change instrs.
35013515Srrh  */
35113515Srrh #define	STR_FILE	0x1
35213515Srrh #define	STR_CORE	0x2
35313515Srrh #define	STR_BOTH	0x3
354601Sbill 
35513515Srrh struct strdesc *savestr();
35613515Srrh 
35713515Srrh /*
35813515Srrh  *	Global variables
35913515Srrh  */
360601Sbill 	extern	struct	arg	arglist[NARG];	/*building operands in instructions*/
361601Sbill 	extern	struct	exp	explist[NEXP];	/*building up a list of expressions*/
362601Sbill 	extern	struct	exp	*xp;		/*current free expression*/
363601Sbill 	/*
364601Sbill 	 *	Communication between the scanner and the jxxx handlers.
365601Sbill 	 *	lastnam:	the last name seen on the input
366601Sbill 	 *	lastjxxx:	pointer to the last symbol table entry for
367601Sbill 	 *			a jump from
368601Sbill 	 */
369601Sbill 	extern	struct	symtab	*lastnam;
370601Sbill 	extern	struct	symtab	*lastjxxx;
371601Sbill 	/*
372601Sbill 	 *	Lgensym is used to make up funny names for local labels.
373601Sbill 	 *	lgensym[i] is the current funny number to put after
374601Sbill 	 *	references to if, lgensym[i]-1 is for ib.
375601Sbill 	 *	genref[i] is set when the label is referenced before
376601Sbill 	 *	it is defined (i.e. 2f) so that we can be sure these
377601Sbill 	 *	labels are always defined to avoid weird diagnostics
378601Sbill 	 *	from the loader later.
379601Sbill 	 */
380601Sbill 	extern	int	lgensym[10];
381601Sbill 	extern	char	genref[10];
382601Sbill 
383601Sbill 	extern	struct	exp	*dotp;		/* the current dot location */
384601Sbill 	extern	int	loctr;
385601Sbill 
386601Sbill 	extern	struct	exec	hdr;		/* a.out header */
387601Sbill 	extern	u_long	tsize;			/* total text size */
388601Sbill 	extern	u_long	dsize;			/* total data size */
389601Sbill 	extern	u_long	trsize;			/* total text relocation size */
390601Sbill 	extern	u_long	drsize;			/* total data relocation size */
391601Sbill 	extern	u_long	datbase;		/* base of the data segment */
392601Sbill 	/*
393601Sbill 	 *	Bitoff and bitfield keep track of the packing into
394601Sbill 	 *	bytes mandated by the expression syntax <expr> ':' <expr>
395601Sbill 	 */
396601Sbill 	extern	int	bitoff;
397601Sbill 	extern	long	bitfield;
398601Sbill 
399601Sbill 	/*
400601Sbill 	 *	The lexical analyzer builds up symbols in yytext.  Lookup
401601Sbill 	 *	expects its argument in this buffer
402601Sbill 	 */
40313461Srrh 	extern	char	yytext[NCPName+2];	/* text buffer for lexical */
404601Sbill 	/*
405601Sbill 	 *	Variables to manage the input assembler source file
406601Sbill 	 */
407601Sbill 	extern	int	lineno;			/*the line number*/
408601Sbill 	extern	char	*dotsname;		/*the name of the as source*/
409601Sbill 
41013515Srrh 	extern	FILE	*tokfile;		/* temp token communication*/
41113515Srrh 	extern	FILE	*strfile;		/* temp string file*/
41213515Srrh 	extern	char	tokfilename[TNAMESIZE];	/* token file name */
41313515Srrh 	extern	char	strfilename[TNAMESIZE];	/* string file name */
41413515Srrh 	extern	int	strfilepos;		/* position in string file */
415601Sbill 
416601Sbill 	extern	int	passno;			/* 1 or 2 */
417601Sbill 
4185829Srrh 	extern	int	anyerrs;		/*errors as'ing arguments*/
4195829Srrh 	extern	int	anywarnings;		/*warnings as'ing arguments*/
420601Sbill 	extern	int	silent;			/*don't mention the errors*/
421601Sbill 	extern	int	savelabels;		/*save labels in a.out*/
422601Sbill 	extern	int	orgwarn;		/* questionable origin ? */
423601Sbill 	extern	int	useVM;			/*use virtual memory temp file*/
424637Shenry 	extern	int	jxxxJUMP;		/*use jmp instead of brw for jxxx */
425639Sbill 	extern	int	readonlydata;		/*initialized data into text space*/
4265829Srrh 	extern	int	nGHnumbers;		/* GH numbers used */
4275829Srrh 	extern	int	nGHopcodes;		/* GH opcodes used */
4285829Srrh 	extern	int	nnewopcodes;		/* new opcodes used */
429601Sbill #ifdef DEBUG
430601Sbill 	extern	int	debug;
431601Sbill 	extern	int	toktrace;
432601Sbill #endif
433601Sbill 	/*
434601Sbill 	 *	Information about the instructions
435601Sbill 	 */
4365829Srrh 	extern	struct	instab	**itab[NINST];	/*maps opcodes to instructions*/
437635Shenry 	extern  readonly struct Instab instab[];
438601Sbill 
439601Sbill 	extern	int	curlen;			/*current literal storage size*/
440601Sbill 	extern	int	d124;			/*current pointer storage size*/
44115561Srrh 	extern	int	maxalign;		/*maximum .align allowed*/
442601Sbill 
443601Sbill 	struct	symtab	**lookup();		/*argument in yytext*/
444601Sbill 	struct 	symtab	*symalloc();
445601Sbill 
4465829Srrh 	char	*Calloc();
4475829Srrh 	char	*ClearCalloc();
4485829Srrh 
449635Shenry #define outb(val) {dotp->e_xvalue++; if (passno==2) bputc((val), (txtfil));}
450601Sbill 
451635Shenry #define outs(cp, lg) dotp->e_xvalue += (lg); if (passno == 2) bwrite((cp), (lg), (txtfil))
452601Sbill 
4535829Srrh #define	Outb(o)	outb(o)
454601Sbill /*
455601Sbill  *	Most of the time, the argument to flushfield is a power of two constant,
456601Sbill  *	the calculations involving it can be optimized to shifts.
457601Sbill  */
458601Sbill #define flushfield(n) if (bitoff != 0)  Flushfield( ( (bitoff+n-1) /n ) * n)
459601Sbill 
460601Sbill /*
461601Sbill  * The biobuf structure and associated routines are used to write
462601Sbill  * into one file at several places concurrently.  Calling bopen
463601Sbill  * with a biobuf structure sets it up to write ``biofd'' starting
464601Sbill  * at the specified offset.  You can then use ``bwrite'' and/or ``bputc''
465601Sbill  * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
466601Sbill  * Calling bflush drains all the buffers and MUST be done before exit.
467601Sbill  */
468601Sbill struct	biobuf {
469601Sbill 	short	b_nleft;		/* Number free spaces left in b_buf */
470601Sbill /* Initialize to be less than BUFSIZ initially, to boundary align in file */
471601Sbill 	char	*b_ptr;			/* Next place to stuff characters */
47216069Sralph 	char	*b_buf;			/* Pointer to the buffer */
473601Sbill 	off_t	b_off;			/* Current file offset */
474601Sbill 	struct	biobuf *b_link;		/* Link in chain for bflush() */
475601Sbill };
476601Sbill #define	bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
477601Sbill 		       : bflushc(b, c))
478601Sbill #define BFILE	struct biobuf
479601Sbill 
480601Sbill 	extern	BFILE	*biobufs;	/* head of the block I/O buffer chain */
481601Sbill 	extern	int	biofd;		/* file descriptor for block I/O file */
48216069Sralph 	extern	int	biobufsize;	/* optimal block size for I/O */
483601Sbill 	extern	off_t	boffset;	/* physical position in logical file */
484601Sbill 
485601Sbill 	/*
486601Sbill 	 *	For each of the named .text .data segments
487601Sbill 	 *	(introduced by .text <expr>), we maintain
488601Sbill 	 *	the current value of the dot, and the BFILE where
489601Sbill 	 *	the information for each of the segments is placed
490601Sbill 	 *	during the second pass.
491601Sbill 	 */
492601Sbill 	extern	struct	exp	usedot[NLOC + NLOC];
493601Sbill 	extern		BFILE	*usefile[NLOC + NLOC];
494601Sbill 	extern		BFILE	*txtfil;/* file for text and data: into usefile */
495601Sbill 	/*
496601Sbill 	 *	Relocation information for each segment is accumulated
497601Sbill 	 *	seperately from the others.  Writing the relocation
498601Sbill 	 *	information is logically viewed as writing to one
499601Sbill 	 *	relocation saving file for  each segment; physically
500601Sbill 	 *	we have a bunch of buffers allocated internally that
501601Sbill 	 *	contain the relocation information.
502601Sbill 	 */
503601Sbill 	struct	relbufdesc	*rusefile[NLOC + NLOC];
504601Sbill 	struct	relbufdesc	*relfil;
505