xref: /csrg-svn/old/as.vax/asscan.c (revision 599)
1 /* Copyright (c) 1980 Regents of the University of California */
2 static	char sccsid[] = "@(#)asscan.c 4.1 08/13/80";
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include "as.h"
6 #include "asscan.h"
7 
8 /*
9  *	NOTE:
10  *		This version of the assembler does not use fread and fwrite
11  *	for the token buffering.  The token buffers are integrals of BUFSIZ
12  *	at all times, so we use direct read and write.  fread and fwrite
13  *	as supplied from BTL in stdio are HORRENDOUSLY inefficient,
14  *	as they use putchar for each character, nested two deep in loops.
15  */
16 #define writeTEST(pointer, size, nelements, ioptr) \
17 	write(ioptr->_file, pointer, nelements * size) != nelements * size
18 
19 #define readTEST(pointer, size, nelements, ioptr) \
20 	read(ioptr->_file, pointer, nelements * size) != nelements * size
21 /*
22  *	Variables to manage the token buffering.
23  *	We scan (lexically analyze) a large number of tokens, and
24  *	then parse all of the tokens in the scan buffer.
25  *	This reduces procedure call overhead when the parser
26  *	demands a token, allows for an efficient reread during
27  *	the second pass, and confuses the line number reporting
28  *	for errors encountered in the scanner and in the parser.
29  */
30 #define TOKDALLOP	8
31 struct	tokbufdesc *bufstart;	/*where the buffer list begins*/
32 struct	tokbufdesc *buftail;	/*last one on the list*/
33 struct	tokbufdesc *emptybuf;	/*the one being filled*/
34 /*
35  *	If we are using VM, during the second pass we reclaim the used
36  *	token buffers for saving the relocation information
37  */
38 struct	tokbufdesc *tok_free;	/* free pool */
39 struct	tokbufdesc *tok_temp;	/* temporary for doing list manipulation */
40 /*
41  *	Other token buffer managers
42  */
43 int	bufno;			/*which buffer number: 0,1 for tmp file*/
44 struct 	tokbufdesc tokbuf[2];	/*our initial increment of buffers*/
45 ptrall	tokptr;			/*where the current token comes from*/
46 ptrall	tokub;			/*the last token in the current token buffer*/
47 
48 /*
49  *	Variables to manage the string buffering
50  *	declared in asscan.h.
51  */
52 int	strno;			/*the current string being filled*/
53 struct	strdesc	strbuf[3];	/*the string buffers; the first for nulls*/
54 struct	strdesc	*strptr;	/*current string buffer being filled*/
55 
56 inittmpfile()
57 {
58 	if (passno == 1){
59 		if (useVM){
60 			bufstart = &tokbuf[0];
61 			buftail = &tokbuf[1];
62 			bufstart->tok_next = buftail;
63 			buftail->tok_next = 0;
64 		}
65 		tokbuf[0].tok_count = -1;
66 		tokbuf[1].tok_count = -1;
67 	}
68 	tok_temp = 0;
69 	tok_free = 0;
70 	bufno = 0;
71 	emptybuf = &tokbuf[bufno];
72 	tokptr = 0;
73 	tokub = 0;
74 }
75 
76 closetmpfile()
77 {
78 	if (passno == 1){
79 		if (useVM){
80 			emptybuf->toks[emptybuf->tok_count++] = PARSEEOF;
81 		} else {
82 			/*
83 			 *	Clean up the buffers that haven't been
84 			 *	written out yet
85 			 */
86 			if (tokbuf[bufno ^ 1].tok_count >= 0){
87 				if (writeTEST((char *)&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tmpfil)){
88 				  badwrite:
89 					yyerror("Unexpected end of file writing the interpass tmp file");
90 				exit(2);
91 				}
92 			}
93 			/*
94 			 *	Ensure that we will read an End of file,
95 			 *	if there are more than one file names
96 			 *	in the argument list
97 			 */
98 			tokbuf[bufno].toks[tokbuf[bufno].tok_count++] = PARSEEOF;
99 			if (writeTEST((char *)&tokbuf[bufno], sizeof *emptybuf, 1, tmpfil))
100 				goto badwrite;
101 		}
102 	}	/*end of being pass 1*/
103 }
104 
105 #define bstrlg(from, length) \
106 	*(lgtype *)from = length; \
107 	(char *)from += sizeof(lgtype) + length
108 
109 #define bstrfromto(from,to) \
110 	*(lgtype *)from = (char *)to - (char *)from - sizeof(lgtype); \
111 	(char *)from += sizeof(lgtype) + (char *)to - (char *)from
112 
113 #define eatstrlg(from) \
114 	(char *)from +=  sizeof(lgtype) + *(lgtype *)from
115 
116 #define bskiplg(from, length) \
117 	*(lgtype *)from = length; \
118 	(char *)from += sizeof(lgtype) + length
119 
120 #define bskipfromto(from, to) \
121 	*(lgtype *)from = (toktype *)to - (toktype *)from - sizeof(lgtype); \
122 	(char *)from += sizeof (lgtype) + (toktype *)to - (toktype *)from
123 
124 #define eatskiplg(from) \
125 	(toktype *)from += sizeof(lgtype) + *(lgtype *)from
126 
127 #ifdef DEBUG
128 	ptrall	firsttoken;
129 #endif DEBUG
130 
131 extern	int		yylval;		/*global communication with parser*/
132 
133 toktype yylex()
134 {
135 	register	ptrall	bufptr;
136 	register	toktype		val;
137 	register	struct	exp	*locxp;
138 
139 	bufptr = tokptr;		/*copy in the global value*/
140    top:
141 	if (bufptr < tokub){
142 		gtoken(val, bufptr);
143 		switch(yylval = val){
144 		case	PARSEEOF :
145 				yylval = val = PARSEEOF;
146 				break;
147 		case	BFINT:
148 		case	INT:
149 				if (xp >= &explist[NEXP])
150 				     yyerror("Too many expressions; try simplyfing");
151 				else
152 				    locxp = xp++;
153 				glong(locxp->xvalue, bufptr);
154 				locxp->yvalue = 0;
155 			  makevalue:
156 				locxp->xtype = XABS;
157 				locxp->xloc = 0;
158 				locxp->xname = NULL;
159 				yylval = (int)locxp;
160 				break;
161 		case	FLTNUM:
162 				if (xp >= &explist[NEXP])
163 				     yyerror("Too many expressions; try simplyfing");
164 				else
165 				    locxp = xp++;
166 				gdouble( ( (union Double *)locxp)->dvalue, bufptr);
167 				goto makevalue;
168 		case	QUAD:
169 				if (xp >= &explist[NEXP])
170 				     yyerror("Too many expressions; try simplyfing");
171 				else
172 				    locxp = xp++;
173 				glong(locxp->xvalue, bufptr);
174 				glong(locxp->yvalue, bufptr);
175 				yylval = val = INT;
176 				goto makevalue;
177 		case	NAME:
178 				gptr(yylval, bufptr);
179 				lastnam = (struct symtab *)yylval;
180 				break;
181 		case	SIZESPEC:
182 		case 	REG:
183 		case	INSTn:
184 		case	INST0:
185 				gchar(yylval, bufptr);
186 				break;
187 		case	IJXXX:
188 				gchar(yylval, bufptr);
189 				gptr(lastjxxx, bufptr);
190 				break;
191 		case	ILINESKIP:
192 				gint(yylval, bufptr);
193 				lineno += yylval;
194 				goto top;
195 		case	SKIP:
196 				eatskiplg(bufptr);
197 				goto top;
198 		case	VOID:
199 				goto top;
200 		case 	STRING:
201 				strptr = &strbuf[strno ^= 1];
202 				strptr->str_lg = *((lgtype *)bufptr);
203 				movestr(&strptr->str[0],
204 					(char *)bufptr + sizeof(lgtype),
205 					strptr->str_lg);
206 				eatstrlg(bufptr);
207 				yylval = (int)strptr;
208 				break;
209 		case 	ISTAB:
210 		case	ISTABSTR:
211 		case	ISTABNONE:
212 		case	ISTABDOT:
213 		case	IALIGN:
214 				gptr(yylval, bufptr);
215 				break;
216 		}
217 #ifdef DEBUG
218 		if (toktrace){
219 		char	*tok_to_name();
220 		printf("P: %d T#: %4d, %s ",
221 			passno, bufptr -  firsttoken, tok_to_name(val));
222 		switch(val){
223 		case 	INT:	printf("val %d",
224 					((struct exp *)yylval)->xvalue);
225 				break;
226 		case	BFINT:	printf("val %d",
227 					((struct exp *)yylval)->xvalue);
228 				break;
229 		case	QUAD:	printf("val[msd] = 0x%x, val[lsd] = 0x%x.",
230 				((struct exp *)yylval)->xvalue,
231 				((struct exp *)yylval)->yvalue);
232 				break;
233 		case 	FLTNUM: printf("value %20.17f",
234 				((union Double *)yylval)->dvalue);
235 				break;
236 		case	NAME:	printf("\"%.8s\"",
237 					((struct symtab *)yylval)->name);
238 				break;
239 		case	REG:	printf(" r%d",
240 					yylval);
241 				break;
242 		case	IJXXX:
243 		case	INST0:
244 		case	INSTn:	printf("%.8s",
245 					itab[0xFF &yylval]->name);
246 				break;
247 		case	STRING:	printf("length %d ",
248 					((struct strdesc *)yylval)->str_lg);
249 				printf("value\"%s\"",
250 					((struct strdesc *)yylval)->str);
251 				break;
252 		}  		/*end of the debug switch*/
253 		printf("\n");
254 		}
255 #endif DEBUG
256 
257 	} else {	/* start a new buffer */
258 	    if (useVM){
259 		if (passno == 2){
260 			tok_temp = emptybuf->tok_next;
261 			emptybuf->tok_next = tok_free;
262 			tok_free = emptybuf;
263 			emptybuf = tok_temp;
264 		} else {
265 			emptybuf = emptybuf->tok_next;
266 		}
267 		bufno += 1;
268 		if (emptybuf == 0){
269 			struct	tokbufdesc *newdallop;
270 			int	i;
271 			if (passno == 2)
272 				goto badread;
273 			emptybuf = newdallop = (struct tokbufdesc *)
274 			  Calloc(TOKDALLOP, sizeof (struct tokbufdesc));
275 			for (i=0; i < TOKDALLOP; i++){
276 				buftail->tok_next = newdallop;
277 				buftail = newdallop;
278 				newdallop += 1;
279 			}
280 			buftail->tok_next = 0;
281 		}	/*end of need to get more buffers*/
282 		(toktype *)bufptr = &(emptybuf->toks[0]);
283 		if (passno == 1)
284 			scan_dot_s(emptybuf);
285 	    } else {	/*don't use VM*/
286 		bufno ^= 1;
287 		emptybuf = &tokbuf[bufno];
288 		((toktype *)bufptr) = &(emptybuf->toks[0]);
289 		if (passno == 1){
290 			/*
291 			 *	First check if there are things to write
292 			 *	out at all
293 			 */
294 			if (emptybuf->tok_count >= 0){
295 			    if (writeTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){
296 			      badwrite:
297 				yyerror("Unexpected end of file writing the interpass tmp file");
298 				exit(2);
299 			    }
300 			}
301 			scan_dot_s(emptybuf);
302 		} else {	/*pass 2*/
303 		    if (readTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){
304 			 badread:
305 			     yyerror("Unexpected end of file while reading the interpass tmp file");
306 			     exit(1);
307 		    }
308 		}
309 	    }	/*end of using a real live file*/
310 	    (char *)tokub = (char *)bufptr + emptybuf->tok_count;
311 #ifdef DEBUG
312 	    firsttoken = bufptr;
313 	    if (debug)
314 		printf("created buffernumber %d with %d tokens\n",
315 			bufno, emptybuf->tok_count);
316 #endif DEBUG
317 	    goto top;
318 	}	/*end of reading/creating a new buffer*/
319 	tokptr = bufptr;		/*copy back the global value*/
320 	return(val);
321 }	/*end of yylex*/
322 
323 
324 buildskip(from, to)
325 	register	ptrall	from, to;
326 {
327 	int	diff;
328 	register	int	frombufno;
329 	register	struct	tokbufdesc *middlebuf;
330 	/*
331 	 *	check if from and to are in the same buffer
332 	 *	from and to DIFFER BY AT MOST 1 buffer and to is
333 	 *	always ahead of from, with to being in the buffer emptybuf
334 	 *	points to.
335 	 *	The hard part here is accounting for the case where the
336 	 *	skip is to cross a buffer boundary; we must construct
337 	 *	two skips.
338 	 *
339 	 *	Figure out where the buffer boundary between from and to is
340 	 *	It's easy in VM, as buffers increase to high memory, but
341 	 *	w/o VM, we alternate between two buffers, and want
342 	 *	to look at the exact middle of the contiguous buffer region.
343 	 */
344 	middlebuf = useVM ? emptybuf : &tokbuf[1];
345 	if (  ( (toktype *)from > (toktype *)middlebuf)
346 	    ^ ( (toktype *)to > (toktype *)middlebuf)
347 	   ){	/*split across a buffer boundary*/
348 		ptoken(from, SKIP);
349 		/*
350 		 *	Set the skip so it lands someplace beyond
351 		 *	the end of this buffer.
352 		 *	When we pull this skip out in the second pass,
353 		 *	we will temporarily move the current pointer
354 		 *	out beyond the end of the buffer, but immediately
355 		 *	do a compare and fail the compare, and then reset
356 		 *	all the pointers correctly to point into the next buffer.
357 		 */
358 		bskiplg(from,  TOKBUFLG + 1);
359 		/*
360 		 *	Now, force from to be in the same buffer as to
361 		 */
362 		(toktype *)from = (toktype *)&(emptybuf->toks[0]);
363 	}
364 	/*
365 	 *	Now, to and from are in the same buffer
366 	 */
367 	if (from > to)
368 		yyerror("Internal error: bad skip construction");
369 	else {
370 		if ( (diff = (toktype *)to - (toktype *)from) >=
371 			(sizeof(toktype) + sizeof(lgtype) + 1)) {
372 				ptoken(from, SKIP);
373 				bskipfromto(from, to);
374 		} else {
375 			for ( ; diff > 0; --diff)
376 				ptoken(from, VOID);
377 		}
378 	}
379 }
380 
381 movestr(to, from, lg)
382 	register	char	*to, *from;
383 	register	int	lg;
384 {
385 	if (lg <= 0) return;
386 	do
387 		*to++ = *from++;
388 	while (--lg);
389 }
390 static	int	newfflag = 0;
391 static	char	*newfname;
392 int	scanlineno;		/*the scanner's linenumber*/
393 
394 new_dot_s(namep)
395 	char	*namep;
396 {
397 	newfflag = 1;
398 	newfname = namep;
399 	dotsname = namep;
400 	lineno = 1;
401 	scanlineno = 1;
402 }
403 
404 /*
405  *	Maps characters to their use in assembly language
406  */
407 #define EOFCHAR	(-1)
408 #define	NEEDCHAR (-2)
409 
410 readonly short type[] = {
411 	NEEDSBUF,		/*fill up the input buffer*/
412 	SCANEOF,		/*hit the hard end of file*/
413 	SP,	BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,   /*\0..^G*/
414 	BADCHAR,SP,	NL,	BADCHAR,BADCHAR,SP,	BADCHAR,BADCHAR,   /*BS..SI*/
415 	BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,   /*DLE..ETB*/
416 	BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,   /*CAN..US*/
417 	SP,	ORNOT,	DQ,	SH,	LITOP,	REGOP,	AND,	SQ,  /*sp .. '*/
418 	LP,	RP,	MUL,	PLUS,	CM,	MINUS,	ALPH,	DIV, /*( .. /*/
419 	DIG,	DIG,	DIG,	DIG,	DIG,	DIG,	DIG,	DIG, /*0 .. 7*/
420 	DIG,	DIG,	COLON,	SEMI,	LSH,	BADCHAR,RSH,	BADCHAR, /*8 .. ?*/
421 	BADCHAR,ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,/*@ .. G*/
422 	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,/*H .. BADCHAR*/
423 	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,/*P .. V*/
424 	ALPH,	ALPH,	ALPH,	LB,	BADCHAR,RB,	XOR,	ALPH,/*W .. _*/
425 	SIZEQUOTE,ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,/*` .. g*/
426 	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,/*h .. o*/
427 	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,	ALPH,/*p .. v*/
428 	ALPH,	ALPH,	ALPH,	BADCHAR,IOR,	BADCHAR,TILDE,	BADCHAR,/*x .. del*/
429 };
430 
431 /*
432  *	The table of possible uses for each character to test set inclusion.
433  *	Different than the above table, which knows about tokens yylex
434  *	is to return.
435  */
436 #define	HEXFLAG		01		/* 'x' or 'X' */
437 #define	HEXLDIGIT	02		/* 'a' .. 'f' */
438 #define HEXUDIGIT	04		/* 'A' .. 'F' */
439 #define	ALPHA		010		/* 'A' .. 'Z', 'a' .. 'z', '_'*/
440 #define DIGIT		020		/* '0' .. '9' */
441 #define	FLOATEXP	040		/* 'd' 'e' 'D' 'E' */
442 						/*exponent field*/
443 #define SIGN		0100		/* '+' .. '-'*/
444 #define REGDIGIT	0200		/* '0' .. '5' */
445 #define SZSPECBEGIN	0400		/* 'b', 'B', 'l', 'L', 'w', 'W' */
446 #define POINT		01000		/* '.' */
447 #define SPACE		02000		/* '\t' or ' ' */
448 #define BSESCAPE	04000		/* bnrtf */
449 #define STRESCAPE	010000		/* '"', '\\', '\n' */
450 #define OCTDIGIT	020000		/* '0' .. '7' */
451 #define	FLOATFLAG	040000		/* 'd', 'D', 'f', 'F' */
452 						/*after leading 0*/
453 
454 readonly short charsets[] = {
455 	0,	0,	0,	0,	0,	0,	0,	0,   /*\0..^G*/
456 	0,	SPACE,	STRESCAPE,0,	0,	0,	0,	0,   /*BS..SI*/
457 	0,	0,	0,	0,	0,	0,	0,	0,   /*DLE..ETB*/
458 	0,	0,	0,	0,	0,	0,	0,	0,   /*CAN..US*/
459 /* dollar is an alpha character */
460 	SPACE,	0,	STRESCAPE,0,	ALPHA,	0,	0,	0,   /*sp.. '*/
461 	0,	0,	0,	SIGN,	0,	SIGN,	POINT+ALPHA,0, /*( .. /*/
462 	DIGIT+REGDIGIT+OCTDIGIT,	DIGIT+REGDIGIT+OCTDIGIT,     /*0..1*/
463 	DIGIT+REGDIGIT+OCTDIGIT,	DIGIT+REGDIGIT+OCTDIGIT,     /*2..3*/
464 	DIGIT+REGDIGIT+OCTDIGIT,	DIGIT+REGDIGIT+OCTDIGIT,     /*4..5*/
465 	DIGIT+OCTDIGIT,			DIGIT+OCTDIGIT,		     /*6..7*/
466 	DIGIT,	DIGIT,	0,	0,	0,	0,	0,	0,   /*8..?*/
467 	0,							     /*@*/
468 	ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+SZSPECBEGIN,		     /*A..B*/
469 	ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+FLOATEXP+FLOATFLAG,	     /*C..D*/
470 	ALPHA+HEXUDIGIT+FLOATEXP,ALPHA+HEXUDIGIT+FLOATFLAG,	     /*E..F*/
471 	ALPHA,							     /*G*/
472 	ALPHA,			ALPHA,	ALPHA, 	ALPHA,		     /*H..K*/
473 	ALPHA+SZSPECBEGIN, 	ALPHA,	ALPHA,	ALPHA,		     /*L..O*/
474 	ALPHA,			ALPHA,	ALPHA,	ALPHA,		     /*P..S*/
475 	ALPHA,			ALPHA,	ALPHA,	ALPHA+SZSPECBEGIN,   /*T..W*/
476 	ALPHA+HEXFLAG,	ALPHA,	ALPHA,	0,STRESCAPE,0,	0,	ALPHA,/*X.._*/
477 
478 	0,
479 	ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+BSESCAPE+SZSPECBEGIN,	      /*a..b*/
480 	ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+FLOATEXP+FLOATFLAG,	      /*c..d*/
481 	ALPHA+HEXLDIGIT+FLOATEXP,ALPHA+HEXLDIGIT+BSESCAPE+FLOATFLAG,  /*e..f*/
482 	ALPHA,							      /*g*/
483 	ALPHA,			ALPHA,	ALPHA,		ALPHA,	      /*h..k*/
484 	ALPHA+SZSPECBEGIN,	ALPHA,	ALPHA+BSESCAPE,	ALPHA,	      /*l..o*/
485 	ALPHA,			ALPHA,	ALPHA+BSESCAPE,	ALPHA,	      /*p..s*/
486 	ALPHA+BSESCAPE,		ALPHA,	ALPHA,		ALPHA+SZSPECBEGIN,/*t..w*/
487 	ALPHA+HEXFLAG,	ALPHA,	ALPHA,	0,0,	0,	0,	0,    /*x..del*/
488 0};
489 
490 #define INCHARSET(val, kind) (charsets[val] & (kind) )
491 static	toktype	oval = NL;
492 
493 #define	NINBUFFERS	2
494 #define	INBUFLG		NINBUFFERS*BUFSIZ + 2
495 	/*
496 	 *	We have two input buffers; the first one is reserved
497 	 *	for catching the tail of a line split across a buffer
498 	 *	boundary; the other one are used for snarfing a buffer
499 	 *	worth of .s source.
500 	 */
501 static	char	inbuffer[INBUFLG];
502 static	char	*InBufPtr = 0;
503 
504 #ifdef  getchar
505 #undef	getchar
506 #endif
507 #define getchar() *inbufptr++
508 
509 #ifdef  ungetc
510 #undef	ungetc
511 #endif
512 #define	ungetc(char) *--inbufptr = char
513 
514 /*
515  *	fill the inbuffer from the standard input.
516  *	Assert: there are always n COMPLETE! lines in the buffer area.
517  *	Assert: there is always a \n terminating the last line
518  *		in the buffer area.
519  *	Assert: after the \n, there is an EOFCHAR (hard end of file)
520  *		or a NEEDCHAR (end of buffer)
521  *	Assert:	fgets always null pads the string it reads.
522  *	Assert:	no ungetc's are done at the end of a line or at the
523  *		beginning of a line.
524  *
525  *	We read a complete buffer of characters in one single read.
526  *	We then back scan within this buffer to find the end of the
527  *	last complete line, and force the assertions, and save a pointer
528  *	to the incomplete line.
529  *	The next call to fillinbuffer will move the unread characters
530  *	to the end of the first buffer, and then read another two buffers,
531  *	completing the cycle.
532  */
533 
534 static	char	p_swapped = '\0';
535 static	char	*p_start = &inbuffer[NINBUFFERS * BUFSIZ];
536 static	char	*p_stop = &inbuffer[NINBUFFERS * BUFSIZ];
537 char *fillinbuffer()
538 {
539 	register	char	*to;
540 	register	char	*from;
541 			char	*inbufptr;
542 	int		nread;
543 
544 	*p_start = p_swapped;
545 	inbufptr = &inbuffer[1*BUFSIZ] - (p_stop - p_start);
546 
547 	for (to = inbufptr, from = p_start; from < p_stop;)
548 		*to++ = *from++;
549 	/*
550 	 *	Now, go read two full buffers (hopefully)
551 	 */
552 	nread = read(stdin->_file, &inbuffer[1*BUFSIZ], (NINBUFFERS - 1)*BUFSIZ);
553 	if (nread == 0)
554 		return(0);
555 	p_stop = from = &inbuffer[1*BUFSIZ + nread];
556 	*from = '\0';
557 	while (*--from != '\n')		/* back over the partial line */
558 		continue;
559 	from++;				/* first char of partial line */
560 	p_start = from;
561 	p_swapped = *p_start;
562 	*p_start = NEEDCHAR;		/* force assertion */
563 	return(inbufptr);
564 }
565 
566 scan_dot_s(bufferbox)
567 	struct tokbufdesc *bufferbox;
568 {
569 	register int		yylval;/*lexical value*/
570 	register toktype	val;	/*the value returned; the character read*/
571 	register int	base;		/*the base of the number also counter*/
572 	register	char	*cp;
573 	register	char	*inbufptr;
574 	register	struct 		symtab	*op;
575 	register	unsigned	char	tag;
576 	int		forb;
577 
578 	register	ptrall	bufptr;		/*where to stuff tokens*/
579 			ptrall	lgbackpatch;	/*where to stuff a string length*/
580 			ptrall	bufub;		/*where not to stuff tokens*/
581 	register	int	maxstrlg;	/*how long a string can be*/
582 			long	intval;		/*value of int*/
583 			char	fltchr[64];	/*buffer for floating values*/
584 		union	Double	fltval;		/*floating value returned*/
585 		struct	Quad	quadval;	/*quad returned from immediate constant */
586 			int	linescrossed;	/*when doing strings and comments*/
587 
588 	(toktype *)bufptr = (toktype *) & (bufferbox->toks[0]);
589 	(toktype *)bufub = &(bufferbox->toks[AVAILTOKS]);
590 
591 	inbufptr = InBufPtr;
592 	if (inbufptr == 0){
593 		inbufptr = fillinbuffer();
594 		if (inbufptr == 0){	/*end of file*/
595    		  endoffile:
596 			inbufptr = 0;
597 			ptoken(bufptr, PARSEEOF);
598 			goto done;
599 		}
600 	}
601 
602 	if (newfflag){
603 		ptoken(bufptr, IFILE);
604 		ptoken(bufptr, STRING);
605 		val = strlen(newfname) + 1;
606 		movestr( (char *)&( ( (lgtype *)bufptr)[1]), newfname, val);
607 		bstrlg(bufptr, val);
608 
609 		ptoken(bufptr, ILINENO);
610 		ptoken(bufptr, INT);
611 		pint(bufptr,  1);
612 		newfflag = 0;
613 	}
614 
615 	while (bufptr < bufub){
616    loop:
617         switch(yylval = (type+2)[val = getchar()]) {
618 	case SCANEOF:
619 		inbufptr = 0;
620 		goto endoffile;
621 
622 	case NEEDSBUF:
623 		inbufptr = fillinbuffer();
624 		if (inbufptr == 0)
625 			goto endoffile;
626 		goto loop;
627 
628 	case DIV:		/*process C style comments*/
629 		if ( (val = getchar()) == '*') {  /*comment prelude*/
630 			int	incomment;
631 			linescrossed = 0;
632 			incomment = 1;
633 			val = getchar();	/*skip over the * */
634 			do{
635 				while ( (val != '*') &&
636 					(val != '\n') &&
637 					(val != EOFCHAR) &&
638 					(val != NEEDCHAR))
639 						val = getchar();
640 				if (val == '\n'){
641 					scanlineno++;
642 					linescrossed++;
643 				} else
644 				if (val == EOFCHAR)
645 					goto endoffile;
646 				if (val == NEEDCHAR){
647 					inbufptr = fillinbuffer();
648 					if (inbufptr == 0)
649 						goto endoffile;
650 					lineno++;
651 					incomment = 1;
652 					val = getchar(); /*pull in the new char*/
653 				} else { 	/*its a star */
654 					val = getchar();
655 					incomment = val != '/';
656 				}
657 			} while (incomment);
658 			val = ILINESKIP;
659 			yylval = linescrossed;
660 			goto ret;
661 		} else {	/*just an ordinary DIV*/
662 			ungetc(val);
663 			val = yylval = DIV;
664 			goto ret;
665 		}
666 	case SH:
667 		if (oval == NL){
668 			/*
669 			 *	Attempt to recognize a C preprocessor
670 			 *	style comment '^#[ \t]*[0-9]*[ \t]*".*"
671 			 */
672 			val = getchar();	/*bump the #*/
673 			while (INCHARSET(val, SPACE))
674 				val = getchar();/*bump white */
675 			if (INCHARSET(val, DIGIT)){
676 				intval = 0;
677 				while(INCHARSET(val, DIGIT)){
678 					intval = intval *10 + val - '0';
679 					val = getchar();
680 				}
681 				while (INCHARSET(val, SPACE))
682 					val = getchar();
683 				if (val == '"'){
684 					ptoken(bufptr, ILINENO);
685 					ptoken(bufptr, INT);
686 					pint(bufptr, intval - 1);
687 					ptoken(bufptr, IFILE);
688 					/*
689 					 *	The '"' has already been
690 					 *	munched
691 					 *
692 					 *	eatstr will not eat
693 					 *	the trailing \n, so
694 					 *	it is given to the parser
695 					 *	and counted.
696 					 */
697 					goto eatstr;
698 				}
699 			}
700 		}
701 		/*
702 		 *	Well, its just an ordinary decadent comment
703 		 */
704 		while ((val != '\n') && (val != EOFCHAR))
705 			val = getchar();
706 		if (val == EOFCHAR)
707 			goto endoffile;
708 		val = yylval = oval = NL;
709 		scanlineno++;
710 		goto ret;
711 
712 	case NL:
713 		scanlineno++;
714 		val = yylval;
715 		goto ret;
716 
717 	case SP:
718 		oval = SP;	/*invalidate ^# meta comments*/
719 		goto loop;
720 
721 	case REGOP:		/* % , could be used as modulo, or register*/
722 		val = getchar();
723 		if (INCHARSET(val, DIGIT)){
724 			yylval = val-'0';
725 			if (val=='1') {
726 				if (INCHARSET( (val = getchar()), REGDIGIT))
727 					yylval = 10+val-'0';
728 				else
729 					ungetc(val);
730 			}
731 			/*
732 			 *	God only knows what the original author
733 			 *	wanted this undocumented feature to
734 			 *	do.
735 			 *		%5++ is really  r7
736 			 */
737 			while(INCHARSET( (val = getchar()), SIGN)) {
738 				if (val=='+')
739 					yylval++;
740 				else
741 					yylval--;
742 			}
743 			ungetc(val);
744 			val = REG;
745 		} else {
746 			ungetc(val);
747 			val = REGOP;
748 		}
749 		goto ret;
750 
751 	case ALPH:
752 		yylval = val;
753 		if (INCHARSET(val, SZSPECBEGIN)){
754 			if( (val = getchar()) == '`' || val == '^'){
755 				yylval |= 0100;	/*convert to lower*/
756 				if (yylval == 'b') yylval = 1;
757 				else if (yylval == 'w') yylval = 2;
758 				else if (yylval == 'l') yylval = 4;
759 				else			yylval = d124;
760 				val = SIZESPEC;
761 				goto ret;
762 			} else {
763 				ungetc(val);
764 				val = yylval;	/*restore first character*/
765 			}
766 		}
767 		cp = yytext;
768 		do {
769 			if (cp < &yytext[NCPS])
770 				*cp++ = val;
771 		} while (INCHARSET ( (val = getchar()), ALPHA | DIGIT));
772 		*cp = '\0';
773 		while (INCHARSET(val, SPACE))
774 			val = getchar();
775 		ungetc(val);
776 	doit:
777 		tag = (op = *lookup(1))->tag;
778 		if (tag && tag != LABELID){
779 			yylval = ( (struct instab *)op)->opcode;
780 			val = op->tag ;
781 			goto ret;
782 		} else {
783 			/*
784 			 *	Its a name... (Labels are subsets ofname)
785 			 */
786 			yylval = (int)op;
787 			val = NAME;
788 			goto ret;
789 		}
790 
791 	case DIG:
792 		base = 10;
793 		cp = fltchr;
794 		intval = 0;
795 		if (val=='0') {
796 			val = getchar();
797 			if (val == 'b') {
798 				yylval = -1;
799 				val = BFINT;
800 				goto ret;
801 			}
802 			if (INCHARSET(val, HEXFLAG)){
803 				base = 16;
804 			} else
805 			if (INCHARSET(val, FLOATFLAG)){
806 				double atof();
807 				while ( (cp < &fltchr[63]) &&
808 				        INCHARSET(
809 						(val=getchar()),
810 						(DIGIT|SIGN|FLOATEXP|POINT)
811 					      )
812 				      ) *cp++ = val;
813 				if (cp == fltchr) {
814 					yylval = 1;
815 					val = BFINT;
816 					goto ret;
817 				}
818 				ungetc(val);
819 				*cp++ = '\0';
820 				fltval.dvalue = atof(fltchr);
821 				val = FLTNUM;
822 				goto ret;
823 			} else {
824 				ungetc(val);
825 				base = 8;
826 			}
827 		} else {
828 			forb = getchar();
829 			if (forb == 'f' || forb == 'b') {
830 				yylval = val - '0' + 1;
831 				if (forb == 'b')
832 					yylval = -yylval;
833 				val = BFINT;
834 				goto ret;
835 			}
836 			ungetc(forb);	/* put back non zero */
837 			goto middle;
838 		}
839 		while ( (val = getchar()) == '0')
840 			continue;
841 		ungetc(val);
842 		while ( INCHARSET( (val = getchar()), DIGIT) ||
843 		    	(base==16 && (INCHARSET(val, HEXLDIGIT|HEXUDIGIT) )
844 		      	   )
845 		      ){
846 			if (base==8)
847 				intval <<= 3;
848 			else if (base==10)
849 				intval *= 10;
850 			else {
851 				intval <<= 4;
852 				if (INCHARSET(val, HEXLDIGIT))
853 					val -= 'a' - 10 - '0';
854 				else if (INCHARSET(val, HEXUDIGIT))
855 					val -= 'A' - 10 - '0';
856 			}
857 middle:
858 			*cp++ = (val -= '0');
859 			intval += val;
860 		}
861 		ungetc(val);
862 		*cp = 0;
863 		maxstrlg = cp - fltchr;
864 		if (   (maxstrlg > 8)
865 		    && (   (   (base == 8)
866 			    && (   (maxstrlg>11)
867 				|| (   (maxstrlg == 11)
868 				    && (*fltchr > 3)
869 				   )
870 				)
871 			   )
872 			|| (   (base == 16)
873 			    && (maxstrlg > 8)
874 			   )
875 			|| (   (base == 10)
876 			    && (maxstrlg >= 10)
877 			   )
878 			)
879 		) {
880 			val = QUAD;
881 			get_quad(base, fltchr, cp, &quadval);
882 		} else
883 			val = INT;
884 		goto ret;
885 
886 	case LSH:
887 	case RSH:
888 		/*
889 		 *	We allow the C style operators
890 		 *	<< and >>, as well as < and >
891 		 */
892 		if ( (base = getchar()) != val)
893 			ungetc(base);
894 		val = yylval;
895 		goto ret;
896 
897 	case MINUS:
898 		if ( (val = getchar()) =='(')
899 			yylval=val=MP;
900 		else {
901 			ungetc(val);
902 			val=MINUS;
903 		}
904 		goto ret;
905 
906 	case SQ:
907 		if ((yylval = getchar()) == '\n')
908 			scanlineno++;		/*not entirely correct*/
909 		intval = yylval;
910 		val = INT;
911 		goto ret;
912 
913 	case DQ:
914 	   eatstr:
915 		linescrossed = 0;
916 		maxstrlg = (char *)bufub - (char *)bufptr;
917 
918 		if (maxstrlg < MAXSTRLG) {
919 			ungetc('"');
920 			*(toktype *)bufptr = VOID ;
921 			bufub = bufptr;
922 			goto done;
923 		}
924 		if (maxstrlg > MAXSTRLG)
925 			maxstrlg = MAXSTRLG;
926 
927 		ptoken(bufptr, STRING);
928 		lgbackpatch = bufptr;	/*this is where the size goes*/
929 		bufptr += sizeof(lgtype);
930 		/*
931 		 *	bufptr is now set to
932 		 *	be stuffed with characters from
933 		 *	the input
934 		 */
935 
936 		while (   (maxstrlg > 0)
937 		       && !(INCHARSET( (val = getchar()), STRESCAPE))
938 		      ){
939 			stuff:
940 				maxstrlg-= 1;
941 				pchar(bufptr, val);
942 			}
943 		if (maxstrlg <= 0){	/*enough characters to fill a string buffer*/
944 			ungetc('"');		/*will read it next*/
945 		}
946 		else if (val == '"');		/*done*/
947 		else if (val == '\n'){
948 			scanlineno++;
949 			linescrossed++;
950 			val = getchar();
951 			if (val == EOFCHAR){
952 			  do_eof:
953 				pchar(bufptr, '\n');
954 				ungetc(EOFCHAR);
955 			} else
956 			if (val == NEEDCHAR){
957 				if ( (inbufptr = fillinbuffer()) == 0)
958 					goto do_eof;
959 				val = '\n';
960 				goto stuff;
961 			} else {	/* simple case */
962 				ungetc(val);
963 				val = '\n';
964 				goto stuff;
965 			}
966 		} else {
967 			val = getchar();		/*skip the '\\'*/
968 			if ( INCHARSET(val, BSESCAPE)){
969 				switch (val){
970 				  case 'b':  val = '\b'; goto stuff;
971 				  case 'f':  val = '\f'; goto stuff;
972 				  case 'n':  val = '\n'; goto stuff;
973 				  case 'r':  val = '\r'; goto stuff;
974 				  case 't':  val = '\t'; goto stuff;
975 				}
976 			}
977 			if ( !(INCHARSET(val,OCTDIGIT)) )  goto stuff;
978 			base = 0;
979 			intval = 0;
980 			while ( (base < 3) && (INCHARSET(val, OCTDIGIT))){
981 				base++;intval <<= 3;intval += val - '0';
982 				val = getchar();
983 			}
984 			ungetc(val);
985 			val = (char)intval;
986 			goto stuff;
987 		}
988 		/*
989 		 *	bufptr now points at the next free slot
990 		 */
991 		bstrfromto(lgbackpatch, bufptr);
992 		if (linescrossed){
993 			val = ILINESKIP;
994 			yylval = linescrossed;
995 			goto ret;
996 		} else
997 			goto builtval;
998 
999 	case BADCHAR:
1000 		linescrossed = lineno;
1001 		lineno = scanlineno;
1002 		yyerror("Illegal character mapped: %d, char read:(octal) %o",
1003 			yylval, val);
1004 		lineno = linescrossed;
1005 		val = BADCHAR;
1006 		goto ret;
1007 
1008 	default:
1009 		val = yylval;
1010 		goto ret;
1011 	}	/*end of the switch*/
1012 	/*
1013 	 *	here with one token, so stuff it
1014 	 */
1015 	ret:
1016 	oval = val;
1017 	ptoken(bufptr, val);
1018 	switch(val){
1019 		case	ILINESKIP:
1020 				pint(bufptr, yylval);
1021 				break;
1022 		case	SIZESPEC:
1023 				pchar(bufptr, yylval);
1024 				break;
1025 		case	BFINT:	plong(bufptr, yylval);
1026 				break;
1027 		case	INT:	plong(bufptr, intval);
1028 				break;
1029 		case	QUAD:	plong(bufptr, quadval.quad_low_long);
1030 				plong(bufptr, quadval.quad_high_long);
1031 				break;
1032 		case 	FLTNUM:	pdouble(bufptr, fltval.dvalue);
1033 				break;
1034 		case	NAME:	pptr(bufptr, (int)(struct symtab *)yylval);
1035 				break;
1036 		case	REG:	pchar(bufptr, yylval);
1037 				break;
1038 		case	INST0:
1039 		case	INSTn:
1040 				pchar(bufptr, yylval);
1041 				break;
1042 		case 	IJXXX:
1043 				pchar(bufptr, yylval);
1044 				pptr(bufptr, (int)(struct symtab *)symalloc());
1045 				break;
1046 		case	ISTAB:
1047 		case	ISTABSTR:
1048 		case	ISTABNONE:
1049 		case	ISTABDOT:
1050 		case	IALIGN:
1051 				pptr(bufptr, (int)(struct symtab *)symalloc());
1052 				break;
1053 	/*
1054 	 *	default:
1055 	 */
1056 	 }
1057 	 builtval: ;
1058    }			/*end of the while to stuff the buffer*/
1059    done:
1060 	bufferbox->tok_count = (toktype *)bufptr - &(bufferbox->toks[0]);
1061 
1062 	/*
1063 	 *	This is a real kludge:
1064 	 *
1065 	 *	We put the last token in the buffer to be  a MINUS
1066 	 *	symbol.  This last token will never be picked up
1067 	 *	in the normal way, but can be looked at during
1068 	 *	a peekahead look that the short circuit expression
1069 	 *	evaluator uses to see if an expression is complicated.
1070 	 *
1071 	 *	Consider the following situation:
1072 	 *
1073 	 *	.word	45		+	47
1074 	 *        buffer 1      |  buffer 0
1075 	 *	the peekahead would want to look across the buffer,
1076 	 *	but will look in the buffer end zone, see the minus, and
1077 	 *	fail.
1078 	 */
1079 	ptoken(bufptr, MINUS);
1080 	InBufPtr = inbufptr;		/*copy this back*/
1081 }
1082 
1083 struct	Quad _quadtemp;
1084 get_quad(radix, cp_start, cp_end, quadptr)
1085 	int	radix;
1086 	char	*cp_start, *cp_end;
1087 	struct	Quad *quadptr;
1088 {
1089 	register		char	*cp = cp_start;	/* r11 */
1090 	register	struct	Quad	*qp = quadptr;	/* r10 */
1091 	register	long	temp;			/* r9 */
1092 
1093 	asm("clrq (r10)");
1094 	for (; cp < cp_end; cp++){
1095 		switch (radix) {
1096 			case 8:
1097 				asm ("ashq $3, (r10), (r10)");
1098 				break;
1099 			case 16:
1100 				asm ("ashq $4, (r10), (r10)");
1101 				break;
1102 			case 10:
1103 				asm ("ashq	$1, (r10), __quadtemp");
1104 				asm ("ashq	$3, (r10), (r10)");
1105 				asm ("addl2	__quadtemp, (r10)");
1106 				asm ("adwc	__quadtemp+4, 4(r10)");
1107 				break;
1108 		}
1109 		asm ("cvtbl	(r11), r9");
1110 		asm ("addl2	r9, (r10)");
1111 		asm ("adwc	$0, 4(r10)");
1112 	}
1113 }
1114