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