xref: /csrg-svn/old/as.vax/asscan.c (revision 627)
1 /* Copyright (c) 1980 Regents of the University of California */
2 static	char sccsid[] = "@(#)asscan.c 4.2 08/15/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 #define	SIGN		0100		/* '+' .. '-'*/
443 #define	REGDIGIT	0200		/* '0' .. '5' */
444 #define	SZSPECBEGIN	0400		/* 'b', 'B', 'l', 'L', 'w', 'W' */
445 #define	POINT		01000		/* '.' */
446 #define	SPACE		02000		/* '\t' or ' ' */
447 #define	BSESCAPE	04000		/* bnrtf */
448 #define	STRESCAPE	010000		/* '"', '\\', '\n' */
449 #define	OCTDIGIT	020000		/* '0' .. '7' */
450 #define	FLOATFLAG	040000		/* 'd', 'D', 'f', 'F' */
451 						/*after leading 0*/
452 
453 readonly short charsets[] = {
454 	0,	0,	0,	0,	0,	0,	0,	0,   /*\0..^G*/
455 	0,	SPACE,	STRESCAPE,0,	0,	0,	0,	0,   /*BS..SI*/
456 	0,	0,	0,	0,	0,	0,	0,	0,   /*DLE..ETB*/
457 	0,	0,	0,	0,	0,	0,	0,	0,   /*CAN..US*/
458 /* dollar is an alpha character */
459 	SPACE,	0,	STRESCAPE,0,	ALPHA,	0,	0,	0,   /*sp.. '*/
460 	0,	0,	0,	SIGN,	0,	SIGN,	POINT+ALPHA,0, /*( .. /*/
461 	DIGIT+REGDIGIT+OCTDIGIT,	DIGIT+REGDIGIT+OCTDIGIT,     /*0..1*/
462 	DIGIT+REGDIGIT+OCTDIGIT,	DIGIT+REGDIGIT+OCTDIGIT,     /*2..3*/
463 	DIGIT+REGDIGIT+OCTDIGIT,	DIGIT+REGDIGIT+OCTDIGIT,     /*4..5*/
464 	DIGIT+OCTDIGIT,			DIGIT+OCTDIGIT,		     /*6..7*/
465 	DIGIT,	DIGIT,	0,	0,	0,	0,	0,	0,   /*8..?*/
466 	0,							     /*@*/
467 	ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+SZSPECBEGIN,		     /*A..B*/
468 	ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+FLOATEXP+FLOATFLAG,	     /*C..D*/
469 	ALPHA+HEXUDIGIT+FLOATEXP,ALPHA+HEXUDIGIT+FLOATFLAG,	     /*E..F*/
470 	ALPHA,							     /*G*/
471 	ALPHA,			ALPHA,	ALPHA, 	ALPHA,		     /*H..K*/
472 	ALPHA+SZSPECBEGIN, 	ALPHA,	ALPHA,	ALPHA,		     /*L..O*/
473 	ALPHA,			ALPHA,	ALPHA,	ALPHA,		     /*P..S*/
474 	ALPHA,			ALPHA,	ALPHA,	ALPHA+SZSPECBEGIN,   /*T..W*/
475 	ALPHA+HEXFLAG,	ALPHA,	ALPHA,	0,STRESCAPE,0,	0,	ALPHA,/*X.._*/
476 
477 	0,
478 	ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+BSESCAPE+SZSPECBEGIN,	      /*a..b*/
479 	ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+FLOATEXP+FLOATFLAG,	      /*c..d*/
480 	ALPHA+HEXLDIGIT+FLOATEXP,ALPHA+HEXLDIGIT+BSESCAPE+FLOATFLAG,  /*e..f*/
481 	ALPHA,							      /*g*/
482 	ALPHA,			ALPHA,	ALPHA,		ALPHA,	      /*h..k*/
483 	ALPHA+SZSPECBEGIN,	ALPHA,	ALPHA+BSESCAPE,	ALPHA,	      /*l..o*/
484 	ALPHA,			ALPHA,	ALPHA+BSESCAPE,	ALPHA,	      /*p..s*/
485 	ALPHA+BSESCAPE,		ALPHA,	ALPHA,		ALPHA+SZSPECBEGIN,/*t..w*/
486 	ALPHA+HEXFLAG,	ALPHA,	ALPHA,	0,0,	0,	0,	0,    /*x..del*/
487 0};
488 
489 #define	INCHARSET(val, kind) (charsets[val] & (kind) )
490 static	toktype	oval = NL;
491 
492 #define	NINBUFFERS	2
493 #define	INBUFLG		NINBUFFERS*BUFSIZ + 2
494 	/*
495 	 *	We have two input buffers; the first one is reserved
496 	 *	for catching the tail of a line split across a buffer
497 	 *	boundary; the other one are used for snarfing a buffer
498 	 *	worth of .s source.
499 	 */
500 static	char	inbuffer[INBUFLG];
501 static	char	*InBufPtr = 0;
502 
503 #ifdef	getchar
504 #undef		getchar
505 #endif
506 #define	getchar() *inbufptr++
507 
508 #ifdef	ungetc
509 #undef		ungetc
510 #endif
511 #define	ungetc(char) *--inbufptr = char
512 
513 /*
514  *	fill the inbuffer from the standard input.
515  *	Assert: there are always n COMPLETE! lines in the buffer area.
516  *	Assert: there is always a \n terminating the last line
517  *		in the buffer area.
518  *	Assert: after the \n, there is an EOFCHAR (hard end of file)
519  *		or a NEEDCHAR (end of buffer)
520  *	Assert:	fgets always null pads the string it reads.
521  *	Assert:	no ungetc's are done at the end of a line or at the
522  *		beginning of a line.
523  *
524  *	We read a complete buffer of characters in one single read.
525  *	We then back scan within this buffer to find the end of the
526  *	last complete line, and force the assertions, and save a pointer
527  *	to the incomplete line.
528  *	The next call to fillinbuffer will move the unread characters
529  *	to the end of the first buffer, and then read another two buffers,
530  *	completing the cycle.
531  */
532 
533 static	char	p_swapped = '\0';
534 static	char	*p_start = &inbuffer[NINBUFFERS * BUFSIZ];
535 static	char	*p_stop = &inbuffer[NINBUFFERS * BUFSIZ];
536 char *fillinbuffer()
537 {
538 	register	char	*to;
539 	register	char	*from;
540 			char	*inbufptr;
541 	int		nread;
542 
543 	*p_start = p_swapped;
544 	inbufptr = &inbuffer[1*BUFSIZ] - (p_stop - p_start);
545 
546 	for (to = inbufptr, from = p_start; from < p_stop;)
547 		*to++ = *from++;
548 	/*
549 	 *	Now, go read two full buffers (hopefully)
550 	 */
551 	nread = read(stdin->_file, &inbuffer[1*BUFSIZ], (NINBUFFERS - 1)*BUFSIZ);
552 	if (nread == 0)
553 		return(0);
554 	p_stop = from = &inbuffer[1*BUFSIZ + nread];
555 	*from = '\0';
556 	while (*--from != '\n')		/* back over the partial line */
557 		continue;
558 	from++;				/* first char of partial line */
559 	p_start = from;
560 	p_swapped = *p_start;
561 	*p_start = NEEDCHAR;		/* force assertion */
562 	return(inbufptr);
563 }
564 
565 scan_dot_s(bufferbox)
566 	struct tokbufdesc *bufferbox;
567 {
568 	register int		yylval;/*lexical value*/
569 	register toktype	val;	/*the value returned; the character read*/
570 	register int	base;		/*the base of the number also counter*/
571 	register	char	*cp;
572 	register	char	*inbufptr;
573 	register	struct 		symtab	*op;
574 	register	unsigned	char	tag;
575 	int		forb;
576 
577 	register	ptrall	bufptr;		/*where to stuff tokens*/
578 			ptrall	lgbackpatch;	/*where to stuff a string length*/
579 			ptrall	bufub;		/*where not to stuff tokens*/
580 	register	int	maxstrlg;	/*how long a string can be*/
581 			long	intval;		/*value of int*/
582 			char	fltchr[64];	/*buffer for floating values*/
583 		union	Double	fltval;		/*floating value returned*/
584 		struct	Quad	quadval;	/*quad returned from immediate constant */
585 			int	linescrossed;	/*when doing strings and comments*/
586 
587 	(toktype *)bufptr = (toktype *) & (bufferbox->toks[0]);
588 	(toktype *)bufub = &(bufferbox->toks[AVAILTOKS]);
589 
590 	inbufptr = InBufPtr;
591 	if (inbufptr == 0){
592 		inbufptr = fillinbuffer();
593 		if (inbufptr == 0){	/*end of file*/
594    		  endoffile:
595 			inbufptr = 0;
596 			ptoken(bufptr, PARSEEOF);
597 			goto done;
598 		}
599 	}
600 
601 	if (newfflag){
602 		ptoken(bufptr, IFILE);
603 		ptoken(bufptr, STRING);
604 		val = strlen(newfname) + 1;
605 		movestr( (char *)&( ( (lgtype *)bufptr)[1]), newfname, val);
606 		bstrlg(bufptr, val);
607 
608 		ptoken(bufptr, ILINENO);
609 		ptoken(bufptr, INT);
610 		pint(bufptr,  1);
611 		newfflag = 0;
612 	}
613 
614 	while (bufptr < bufub){
615    loop:
616         switch(yylval = (type+2)[val = getchar()]) {
617 	case SCANEOF:
618 		inbufptr = 0;
619 		goto endoffile;
620 
621 	case NEEDSBUF:
622 		inbufptr = fillinbuffer();
623 		if (inbufptr == 0)
624 			goto endoffile;
625 		goto loop;
626 
627 	case DIV:		/*process C style comments*/
628 		if ( (val = getchar()) == '*') {  /*comment prelude*/
629 			int	incomment;
630 			linescrossed = 0;
631 			incomment = 1;
632 			val = getchar();	/*skip over the * */
633 			do{
634 				while ( (val != '*') &&
635 					(val != '\n') &&
636 					(val != EOFCHAR) &&
637 					(val != NEEDCHAR))
638 						val = getchar();
639 				if (val == '\n'){
640 					scanlineno++;
641 					linescrossed++;
642 				} else
643 				if (val == EOFCHAR)
644 					goto endoffile;
645 				if (val == NEEDCHAR){
646 					inbufptr = fillinbuffer();
647 					if (inbufptr == 0)
648 						goto endoffile;
649 					lineno++;
650 					incomment = 1;
651 					val = getchar(); /*pull in the new char*/
652 				} else { 	/*its a star */
653 					val = getchar();
654 					incomment = val != '/';
655 				}
656 			} while (incomment);
657 			val = ILINESKIP;
658 			yylval = linescrossed;
659 			goto ret;
660 		} else {	/*just an ordinary DIV*/
661 			ungetc(val);
662 			val = yylval = DIV;
663 			goto ret;
664 		}
665 	case SH:
666 		if (oval == NL){
667 			/*
668 			 *	Attempt to recognize a C preprocessor
669 			 *	style comment '^#[ \t]*[0-9]*[ \t]*".*"
670 			 */
671 			val = getchar();	/*bump the #*/
672 			while (INCHARSET(val, SPACE))
673 				val = getchar();/*bump white */
674 			if (INCHARSET(val, DIGIT)){
675 				intval = 0;
676 				while(INCHARSET(val, DIGIT)){
677 					intval = intval *10 + val - '0';
678 					val = getchar();
679 				}
680 				while (INCHARSET(val, SPACE))
681 					val = getchar();
682 				if (val == '"'){
683 					ptoken(bufptr, ILINENO);
684 					ptoken(bufptr, INT);
685 					pint(bufptr, intval - 1);
686 					ptoken(bufptr, IFILE);
687 					/*
688 					 *	The '"' has already been
689 					 *	munched
690 					 *
691 					 *	eatstr will not eat
692 					 *	the trailing \n, so
693 					 *	it is given to the parser
694 					 *	and counted.
695 					 */
696 					goto eatstr;
697 				}
698 			}
699 		}
700 		/*
701 		 *	Well, its just an ordinary decadent comment
702 		 */
703 		while ((val != '\n') && (val != EOFCHAR))
704 			val = getchar();
705 		if (val == EOFCHAR)
706 			goto endoffile;
707 		val = yylval = oval = NL;
708 		scanlineno++;
709 		goto ret;
710 
711 	case NL:
712 		scanlineno++;
713 		val = yylval;
714 		goto ret;
715 
716 	case SP:
717 		oval = SP;	/*invalidate ^# meta comments*/
718 		goto loop;
719 
720 	case REGOP:		/* % , could be used as modulo, or register*/
721 		val = getchar();
722 		if (INCHARSET(val, DIGIT)){
723 			yylval = val-'0';
724 			if (val=='1') {
725 				if (INCHARSET( (val = getchar()), REGDIGIT))
726 					yylval = 10+val-'0';
727 				else
728 					ungetc(val);
729 			}
730 			/*
731 			 *	God only knows what the original author
732 			 *	wanted this undocumented feature to
733 			 *	do.
734 			 *		%5++ is really  r7
735 			 */
736 			while(INCHARSET( (val = getchar()), SIGN)) {
737 				if (val=='+')
738 					yylval++;
739 				else
740 					yylval--;
741 			}
742 			ungetc(val);
743 			val = REG;
744 		} else {
745 			ungetc(val);
746 			val = REGOP;
747 		}
748 		goto ret;
749 
750 	case ALPH:
751 		yylval = val;
752 		if (INCHARSET(val, SZSPECBEGIN)){
753 			if( (val = getchar()) == '`' || val == '^'){
754 				yylval |= 0100;	/*convert to lower*/
755 				if (yylval == 'b') yylval = 1;
756 				else if (yylval == 'w') yylval = 2;
757 				else if (yylval == 'l') yylval = 4;
758 				else			yylval = d124;
759 				val = SIZESPEC;
760 				goto ret;
761 			} else {
762 				ungetc(val);
763 				val = yylval;	/*restore first character*/
764 			}
765 		}
766 		cp = yytext;
767 		do {
768 			if (cp < &yytext[NCPS])
769 				*cp++ = val;
770 		} while (INCHARSET ( (val = getchar()), ALPHA | DIGIT));
771 		*cp = '\0';
772 		while (INCHARSET(val, SPACE))
773 			val = getchar();
774 		ungetc(val);
775 	doit:
776 		tag = (op = *lookup(1))->tag;
777 		if (tag && tag != LABELID){
778 			yylval = ( (struct instab *)op)->opcode;
779 			val = op->tag ;
780 			goto ret;
781 		} else {
782 			/*
783 			 *	Its a name... (Labels are subsets ofname)
784 			 */
785 			yylval = (int)op;
786 			val = NAME;
787 			goto ret;
788 		}
789 
790 	case DIG:
791 		base = 10;
792 		cp = fltchr;
793 		intval = 0;
794 		if (val=='0') {
795 			val = getchar();
796 			if (val == 'b') {
797 				yylval = -1;
798 				val = BFINT;
799 				goto ret;
800 			}
801 			if (INCHARSET(val, HEXFLAG)){
802 				base = 16;
803 			} else
804 			if (INCHARSET(val, FLOATFLAG)){
805 				double atof();
806 				while ( (cp < &fltchr[63]) &&
807 				        INCHARSET(
808 						(val=getchar()),
809 						(DIGIT|SIGN|FLOATEXP|POINT)
810 					      )
811 				      ) *cp++ = val;
812 				if (cp == fltchr) {
813 					yylval = 1;
814 					val = BFINT;
815 					goto ret;
816 				}
817 				ungetc(val);
818 				*cp++ = '\0';
819 				fltval.dvalue = atof(fltchr);
820 				val = FLTNUM;
821 				goto ret;
822 			} else {
823 				ungetc(val);
824 				base = 8;
825 			}
826 		} else {
827 			forb = getchar();
828 			if (forb == 'f' || forb == 'b') {
829 				yylval = val - '0' + 1;
830 				if (forb == 'b')
831 					yylval = -yylval;
832 				val = BFINT;
833 				goto ret;
834 			}
835 			ungetc(forb);	/* put back non zero */
836 			goto middle;
837 		}
838 		while ( (val = getchar()) == '0')
839 			continue;
840 		ungetc(val);
841 		while ( INCHARSET( (val = getchar()), DIGIT) ||
842 		    	(base==16 && (INCHARSET(val, HEXLDIGIT|HEXUDIGIT) )
843 		      	   )
844 		      ){
845 			if (base==8)
846 				intval <<= 3;
847 			else if (base==10)
848 				intval *= 10;
849 			else {
850 				intval <<= 4;
851 				if (INCHARSET(val, HEXLDIGIT))
852 					val -= 'a' - 10 - '0';
853 				else if (INCHARSET(val, HEXUDIGIT))
854 					val -= 'A' - 10 - '0';
855 			}
856 middle:
857 			*cp++ = (val -= '0');
858 			intval += val;
859 		}
860 		ungetc(val);
861 		*cp = 0;
862 		maxstrlg = cp - fltchr;
863 		if (   (maxstrlg > 8)
864 		    && (   (   (base == 8)
865 			    && (   (maxstrlg>11)
866 				|| (   (maxstrlg == 11)
867 				    && (*fltchr > 3)
868 				   )
869 				)
870 			   )
871 			|| (   (base == 16)
872 			    && (maxstrlg > 8)
873 			   )
874 			|| (   (base == 10)
875 			    && (maxstrlg >= 10)
876 			   )
877 			)
878 		) {
879 			val = QUAD;
880 			get_quad(base, fltchr, cp, &quadval);
881 		} else
882 			val = INT;
883 		goto ret;
884 
885 	case LSH:
886 	case RSH:
887 		/*
888 		 *	We allow the C style operators
889 		 *	<< and >>, as well as < and >
890 		 */
891 		if ( (base = getchar()) != val)
892 			ungetc(base);
893 		val = yylval;
894 		goto ret;
895 
896 	case MINUS:
897 		if ( (val = getchar()) =='(')
898 			yylval=val=MP;
899 		else {
900 			ungetc(val);
901 			val=MINUS;
902 		}
903 		goto ret;
904 
905 	case SQ:
906 		if ((yylval = getchar()) == '\n')
907 			scanlineno++;		/*not entirely correct*/
908 		intval = yylval;
909 		val = INT;
910 		goto ret;
911 
912 	case DQ:
913 	   eatstr:
914 		linescrossed = 0;
915 		maxstrlg = (char *)bufub - (char *)bufptr;
916 
917 		if (maxstrlg < MAXSTRLG) {
918 			ungetc('"');
919 			*(toktype *)bufptr = VOID ;
920 			bufub = bufptr;
921 			goto done;
922 		}
923 		if (maxstrlg > MAXSTRLG)
924 			maxstrlg = MAXSTRLG;
925 
926 		ptoken(bufptr, STRING);
927 		lgbackpatch = bufptr;	/*this is where the size goes*/
928 		bufptr += sizeof(lgtype);
929 		/*
930 		 *	bufptr is now set to
931 		 *	be stuffed with characters from
932 		 *	the input
933 		 */
934 
935 		while (   (maxstrlg > 0)
936 		       && !(INCHARSET( (val = getchar()), STRESCAPE))
937 		      ){
938 			stuff:
939 				maxstrlg-= 1;
940 				pchar(bufptr, val);
941 			}
942 		if (maxstrlg <= 0){	/*enough characters to fill a string buffer*/
943 			ungetc('"');		/*will read it next*/
944 		}
945 		else if (val == '"');		/*done*/
946 		else if (val == '\n'){
947 			scanlineno++;
948 			linescrossed++;
949 			val = getchar();
950 			if (val == EOFCHAR){
951 			  do_eof:
952 				pchar(bufptr, '\n');
953 				ungetc(EOFCHAR);
954 			} else
955 			if (val == NEEDCHAR){
956 				if ( (inbufptr = fillinbuffer()) == 0)
957 					goto do_eof;
958 				val = '\n';
959 				goto stuff;
960 			} else {	/* simple case */
961 				ungetc(val);
962 				val = '\n';
963 				goto stuff;
964 			}
965 		} else {
966 			val = getchar();		/*skip the '\\'*/
967 			if ( INCHARSET(val, BSESCAPE)){
968 				switch (val){
969 				  case 'b':  val = '\b'; goto stuff;
970 				  case 'f':  val = '\f'; goto stuff;
971 				  case 'n':  val = '\n'; goto stuff;
972 				  case 'r':  val = '\r'; goto stuff;
973 				  case 't':  val = '\t'; goto stuff;
974 				}
975 			}
976 			if ( !(INCHARSET(val,OCTDIGIT)) )  goto stuff;
977 			base = 0;
978 			intval = 0;
979 			while ( (base < 3) && (INCHARSET(val, OCTDIGIT))){
980 				base++;intval <<= 3;intval += val - '0';
981 				val = getchar();
982 			}
983 			ungetc(val);
984 			val = (char)intval;
985 			goto stuff;
986 		}
987 		/*
988 		 *	bufptr now points at the next free slot
989 		 */
990 		bstrfromto(lgbackpatch, bufptr);
991 		if (linescrossed){
992 			val = ILINESKIP;
993 			yylval = linescrossed;
994 			goto ret;
995 		} else
996 			goto builtval;
997 
998 	case BADCHAR:
999 		linescrossed = lineno;
1000 		lineno = scanlineno;
1001 		yyerror("Illegal character mapped: %d, char read:(octal) %o",
1002 			yylval, val);
1003 		lineno = linescrossed;
1004 		val = BADCHAR;
1005 		goto ret;
1006 
1007 	default:
1008 		val = yylval;
1009 		goto ret;
1010 	}	/*end of the switch*/
1011 	/*
1012 	 *	here with one token, so stuff it
1013 	 */
1014 	ret:
1015 	oval = val;
1016 	ptoken(bufptr, val);
1017 	switch(val){
1018 		case	ILINESKIP:
1019 				pint(bufptr, yylval);
1020 				break;
1021 		case	SIZESPEC:
1022 				pchar(bufptr, yylval);
1023 				break;
1024 		case	BFINT:	plong(bufptr, yylval);
1025 				break;
1026 		case	INT:	plong(bufptr, intval);
1027 				break;
1028 		case	QUAD:	plong(bufptr, quadval.quad_low_long);
1029 				plong(bufptr, quadval.quad_high_long);
1030 				break;
1031 		case 	FLTNUM:	pdouble(bufptr, fltval.dvalue);
1032 				break;
1033 		case	NAME:	pptr(bufptr, (int)(struct symtab *)yylval);
1034 				break;
1035 		case	REG:	pchar(bufptr, yylval);
1036 				break;
1037 		case	INST0:
1038 		case	INSTn:
1039 				pchar(bufptr, yylval);
1040 				break;
1041 		case 	IJXXX:
1042 				pchar(bufptr, yylval);
1043 				pptr(bufptr, (int)(struct symtab *)symalloc());
1044 				break;
1045 		case	ISTAB:
1046 		case	ISTABSTR:
1047 		case	ISTABNONE:
1048 		case	ISTABDOT:
1049 		case	IALIGN:
1050 				pptr(bufptr, (int)(struct symtab *)symalloc());
1051 				break;
1052 	/*
1053 	 *	default:
1054 	 */
1055 	 }
1056 	 builtval: ;
1057    }			/*end of the while to stuff the buffer*/
1058    done:
1059 	bufferbox->tok_count = (toktype *)bufptr - &(bufferbox->toks[0]);
1060 
1061 	/*
1062 	 *	This is a real kludge:
1063 	 *
1064 	 *	We put the last token in the buffer to be  a MINUS
1065 	 *	symbol.  This last token will never be picked up
1066 	 *	in the normal way, but can be looked at during
1067 	 *	a peekahead look that the short circuit expression
1068 	 *	evaluator uses to see if an expression is complicated.
1069 	 *
1070 	 *	Consider the following situation:
1071 	 *
1072 	 *	.word	45		+	47
1073 	 *        buffer 1      |  buffer 0
1074 	 *	the peekahead would want to look across the buffer,
1075 	 *	but will look in the buffer end zone, see the minus, and
1076 	 *	fail.
1077 	 */
1078 	ptoken(bufptr, MINUS);
1079 	InBufPtr = inbufptr;		/*copy this back*/
1080 }
1081 
1082 struct	Quad _quadtemp;
1083 get_quad(radix, cp_start, cp_end, quadptr)
1084 	int	radix;
1085 	char	*cp_start, *cp_end;
1086 	struct	Quad *quadptr;
1087 {
1088 	register		char	*cp = cp_start;	/* r11 */
1089 	register	struct	Quad	*qp = quadptr;	/* r10 */
1090 	register	long	temp;			/* r9 */
1091 
1092 	asm("clrq (r10)");
1093 	for (; cp < cp_end; cp++){
1094 		switch (radix) {
1095 			case 8:
1096 				asm ("ashq $3, (r10), (r10)");
1097 				break;
1098 			case 16:
1099 				asm ("ashq $4, (r10), (r10)");
1100 				break;
1101 			case 10:
1102 				asm ("ashq	$1, (r10), __quadtemp");
1103 				asm ("ashq	$3, (r10), (r10)");
1104 				asm ("addl2	__quadtemp, (r10)");
1105 				asm ("adwc	__quadtemp+4, 4(r10)");
1106 				break;
1107 		}
1108 		asm ("cvtbl	(r11), r9");
1109 		asm ("addl2	r9, (r10)");
1110 		asm ("adwc	$0, 4(r10)");
1111 	}
1112 }
1113