xref: /csrg-svn/old/as.vax/asscan2.c (revision 13516)
1 /*
2  *	Copyright (c) 1982 Regents of the University of California
3  */
4 #ifndef lint
5 static char sccsid[] = "@(#)asscan2.c 4.10 06/30/83";
6 #endif not lint
7 
8 #include "asscanl.h"
9 
10 static	inttoktype	oval = NL;
11 
12 char	inbufunget[8];
13 char	inbuffer[ASINBUFSIZ];
14 char	*Ginbufptr = inbuffer;
15 int	Ginbufcnt = 0;
16 
17 fillinbuffer()
18 {
19 		int	nread;
20 	static	int	hadeof;
21 		int	goal;
22 		int	got;
23 
24 	nread = 0;
25 	if (hadeof == 0){
26 		goal = sizeof(inbuffer);
27 		do {
28 			got = read(stdin->_file, inbuffer + nread, goal);
29 			if (got == 0)
30 				hadeof = 1;
31 			if (got <= 0)
32 				break;
33 			nread += got;
34 			goal -= got;
35 		} while (goal);
36 	}
37 	/*
38 	 *	getchar assumes that Ginbufcnt and Ginbufptr
39 	 *	are adjusted as if one character has been removed
40 	 *	from the input.
41 	 */
42 	if (nread == 0){
43 		inbuffer[0] = EOFCHAR;
44 		nread = 1;
45 	}
46 	Ginbufcnt = nread - 1;
47 	Ginbufptr = inbuffer + 1;
48 }
49 
50 #ifndef FLEXNAMES
51 char	strtext[NCPString + 1];
52 #else FLEXNAMES
53 # if NCPName < NCPString
54 char	strtext[NCPString + 1];
55 # else
56 #define	strtext yytext
57 # endif
58 #endif FLEXNAMES
59 
60 scan_dot_s(bufferbox)
61 	struct tokbufdesc *bufferbox;
62 {
63 	reg	char	*inbufptr;
64 	reg	int	inbufcnt;
65 	reg	int	ryylval;	/* local copy of lexical value */
66 	extern	int	yylval;		/* global copy of lexical value */
67 	reg	int	val;		/* the value returned */
68 		int	i;		/* simple counter */
69 	reg	char	*rcp;
70 		int	ch;		/* treated as a character */
71 		int	ch1;		/* shadow value */
72 		struct 	symtab	*op;
73 		ptrall	lgbackpatch;	/* where to stuff a string length */
74 	reg	ptrall	bufptr;		/* where to stuff tokens */
75 		ptrall	bufub;		/* where not to stuff tokens */
76 	reg	int	strlg;		/* the length of a string */
77 		long	intval;		/* value of int */
78 		int	linescrossed;	/* when doing strings and comments */
79 		struct	Opcode		opstruct;
80 		struct	strdesc	strd;	/* for building DQ strings */
81 
82 	(bytetoktype *)bufptr = (bytetoktype *) & (bufferbox->toks[0]);
83 	(bytetoktype *)bufub = &(bufferbox->toks[AVAILTOKS]);
84 
85 	MEMTOREGBUF;
86 	if (newfflag){
87 		newfflag = 0;
88 		strd.sd_stroff = strfilepos;
89 		strd.sd_place = STR_BOTH;
90 		strd.sd_strlen = strlen(newfname) + 1;
91 		fputs(newfname, strfile);
92 		putc(0, strfile);
93 		strfilepos += strd.sd_strlen;
94 		ryylval = (int)savestr(newfname, &strd);
95 
96 		ptoken(bufptr, IFILE);
97 		ptoken(bufptr, STRING);
98 		pptr(bufptr, ryylval);
99 
100 		ptoken(bufptr, ILINENO);
101 		ptoken(bufptr, INT);
102 		pint(bufptr,  1);
103 	}
104 
105 	while (bufptr < bufub){
106    loop:
107         switch(ryylval = (type+1)[ch = getchar()]) {
108 	case SCANEOF:
109 	endoffile: ;
110 		inbufptr = 0;
111 		ptoken(bufptr, PARSEEOF);
112 		goto done;
113 
114 	case DIV:		/*process C style comments*/
115 		if ( (ch = getchar()) == '*') {  /*comment prelude*/
116 			int	incomment;
117 			linescrossed = 0;
118 			incomment = 1;
119 			ch = getchar();	/*skip over the * */
120 			while(incomment){
121 				switch(ch){
122 				case '*':
123 					ch = getchar();
124 					incomment = (ch != '/');
125 					break;
126 				case '\n':
127 					scanlineno++;
128 					linescrossed++;
129 					ch = getchar();
130 					break;
131 				case EOFCHAR:
132 					goto endoffile;
133 				default:
134 					ch = getchar();
135 					break;
136 				}
137 			}
138 			val = ILINESKIP;
139 			ryylval = linescrossed;
140 			goto ret;
141 		} else {	/*just an ordinary DIV*/
142 			ungetc(ch);
143 			val = ryylval = DIV;
144 			goto ret;
145 		}
146 	case SH:
147 		if (oval == NL){
148 			/*
149 			 *	Attempt to recognize a C preprocessor
150 			 *	style comment '^#[ \t]*[0-9]*[ \t]*".*"
151 			 */
152 			ch = getchar();	/*bump the #*/
153 			while (INCHARSET(ch, SPACE))
154 				ch = getchar();/*bump white */
155 			if (INCHARSET(ch, DIGIT)){
156 				intval = 0;
157 				while(INCHARSET(ch, DIGIT)){
158 					intval = intval*10 + ch - '0';
159 					ch = getchar();
160 				}
161 				while (INCHARSET(ch, SPACE))
162 					ch = getchar();
163 				if (ch == '"'){
164 					ptoken(bufptr, ILINENO);
165 					ptoken(bufptr, INT);
166 					pint(bufptr, intval - 1);
167 					ptoken(bufptr, IFILE);
168 					/*
169 					 *	The '"' has already been
170 					 *	munched
171 					 *
172 					 *	eatstr will not eat
173 					 *	the trailing \n, so
174 					 *	it is given to the parser
175 					 *	and counted.
176 					 */
177 					goto eatstr;
178 				}
179 			}
180 		}
181 		/*
182 		 *	Well, its just an ordinary decadent comment
183 		 */
184 		while ((ch != '\n') && (ch != EOFCHAR))
185 			ch = getchar();
186 		if (ch == EOFCHAR)
187 			goto endoffile;
188 		val = ryylval = oval = NL;
189 		scanlineno++;
190 		goto ret;
191 
192 	case NL:
193 		scanlineno++;
194 		val = ryylval;
195 		goto ret;
196 
197 	case SP:
198 		oval = SP;	/*invalidate ^# meta comments*/
199 		goto loop;
200 
201 	case REGOP:		/* % , could be used as modulo, or register*/
202 		ch = getchar();
203 		if (INCHARSET(ch, DIGIT)){
204 			ryylval = ch-'0';
205 			if (ch=='1') {
206 				if (INCHARSET( (ch = getchar()), REGDIGIT))
207 					ryylval = 10+ch-'0';
208 				else
209 					ungetc(ch);
210 			}
211 			/*
212 			 *	God only knows what the original author
213 			 *	wanted this undocumented feature to
214 			 *	do.
215 			 *		%5++ is really  r7
216 			 */
217 			while(INCHARSET( (ch = getchar()), SIGN)) {
218 				if (ch=='+')
219 					ryylval++;
220 				else
221 					ryylval--;
222 			}
223 			ungetc(ch);
224 			val = REG;
225 		} else {
226 			ungetc(ch);
227 			val = REGOP;
228 		}
229 		goto ret;
230 
231 	case ALPH:
232 		ch1 = ch;
233 		if (INCHARSET(ch, SZSPECBEGIN)){
234 			if( (ch = getchar()) == '`' || ch == '^'){
235 				ch1 |= 0100;	/*convert to lower*/
236 				switch(ch1){
237 				case 'b':	ryylval = 1;	break;
238 				case 'w':	ryylval = 2;	break;
239 				case 'l':	ryylval = 4;	break;
240 				default:	ryylval = d124;	break;
241 				}
242 				val = SIZESPEC;
243 				goto ret;
244 			} else {
245 				ungetc(ch);
246 				ch = ch1;	/*restore first character*/
247 			}
248 		}
249 		rcp = yytext;
250 		do {
251 			if (rcp < &yytext[NCPName])
252 				*rcp++ = ch;
253 		} while (INCHARSET ( (ch = getchar()), ALPHA | DIGIT));
254 		*rcp = '\0';
255 		while (INCHARSET(ch, SPACE))
256 			ch = getchar();
257 		ungetc(ch);
258 
259 		switch((op = *lookup(1))->s_tag){
260 		case 0:
261 		case LABELID:
262 			/*
263 			 *	Its a name... (Labels are subsets of name)
264 			 */
265 			ryylval = (int)op;
266 			val = NAME;
267 			break;
268 		case INST0:
269 		case INSTn:
270 		case IJXXX:
271 			opstruct.Op_popcode = ( (struct instab *)op)->i_popcode;
272 			opstruct.Op_eopcode = ( (struct instab *)op)->i_eopcode;
273 			val = op->s_tag;
274 			break;
275 		default:
276 			ryylval = ( (struct instab *)op)->i_popcode;
277 			val = op->s_tag;
278 			break;
279 		}
280 		goto ret;
281 
282 	case DIG:
283 		/*
284 		 *	restore local inbufptr and inbufcnt
285 		 */
286 		REGTOMEMBUF;
287 		val = number(ch);
288 		MEMTOREGBUF;
289 		/*
290 		 *	yylval or yybignum has been stuffed as a side
291 		 *	effect to number(); get the global yylval
292 		 *	into our fast local copy in case it was an INT.
293 		 */
294 		ryylval = yylval;
295 		goto ret;
296 
297 	case LSH:
298 	case RSH:
299 		/*
300 		 *	We allow the C style operators
301 		 *	<< and >>, as well as < and >
302 		 */
303 		if ( (ch1 = getchar()) != ch)
304 			ungetc(ch1);
305 		val = ryylval;
306 		goto ret;
307 
308 	case MINUS:
309 		if ( (ch = getchar()) =='(')
310 			ryylval=val=MP;
311 		else {
312 			ungetc(ch);
313 			val=MINUS;
314 		}
315 		goto ret;
316 
317 	case SQ:
318 		if ((ryylval = getchar()) == '\n')
319 			scanlineno++;		/*not entirely correct*/
320 		val = INT;
321 		goto ret;
322 
323 	case DQ:
324 	   eatstr:
325 		linescrossed = 0;
326 		strd.sd_stroff = strfilepos;
327 		strd.sd_place = STR_FILE;
328 		for (strd.sd_strlen = 0; /*VOID*/; strd.sd_strlen++){
329 		    switch(ch = getchar()){
330 		    case '"':
331 			goto tailDQ;
332 		    default:
333 		    stuff:
334 			putc(ch, strfile);
335 			break;
336 		    case '\n':
337 			yywarning("New line in a string constant");
338 			scanlineno++;
339 			linescrossed++;
340 			ch = getchar();
341 			switch(ch){
342 			case EOFCHAR:
343 				putc('\n', strfile);
344 				ungetc(EOFCHAR);
345 				goto tailDQ;
346 			default:
347 				ungetc(ch);
348 				ch = '\n';
349 				goto stuff;
350 			}
351 			break;
352 
353 		    case '\\':
354 			ch = getchar();		/*skip the '\\'*/
355 			if ( INCHARSET(ch, BSESCAPE)){
356 				switch (ch){
357 				  case 'b':  ch = '\b'; goto stuff;
358 				  case 'f':  ch = '\f'; goto stuff;
359 				  case 'n':  ch = '\n'; goto stuff;
360 				  case 'r':  ch = '\r'; goto stuff;
361 				  case 't':  ch = '\t'; goto stuff;
362 				}
363 			}
364 			if ( !(INCHARSET(ch, OCTDIGIT)) )
365 				goto stuff;
366 			i = 0;
367 			intval = 0;
368 			while ( (i < 3) && (INCHARSET(ch, OCTDIGIT))){
369 				i++;
370 				intval <<= 3;
371 				intval += ch - '0';
372 				ch = getchar();
373 			}
374 			ungetc(ch);
375 			ch = (char)intval;
376 			goto stuff;
377 		    }
378 		}
379 	tailDQ: ;
380 		/*
381 		 *	account for any lines that were crossed
382 		 */
383 		if (linescrossed){
384 			ptoken(bufptr, ILINESKIP);
385 			pint(bufptr, linescrossed);
386 		}
387 		/*
388 		 *	put the string in strtext into the string pool
389 		 *
390 		 *	Cheat: append a trailing null to the string
391 		 *	and then adjust the string length to ignore
392 		 *	the trailing null.  If any STRING client requires
393 		 *	the trailing null, the client can just change STRLEN
394 		 */
395 		val = STRING;
396 		putc(0, strfile);
397 		strd.sd_strlen += 1;
398 		strfilepos += strd.sd_strlen;
399 		ryylval = (int)savestr(strtext, &strd);
400 		((struct strdesc *)ryylval)->sd_strlen -= 1;
401 		goto ret;
402 
403 	case BADCHAR:
404 		linescrossed = lineno;
405 		lineno = scanlineno;
406 		yyerror("Illegal character mapped: %d, char read:(octal) %o",
407 			ryylval, ch);
408 		lineno = linescrossed;
409 		val = BADCHAR;
410 		goto ret;
411 
412 	default:
413 		val = ryylval;
414 		goto ret;
415 	}	/*end of the switch*/
416 	/*
417 	 *	here with one token, so stuff it
418 	 */
419    ret:
420 	oval = val;
421 	ptoken(bufptr, val);
422 	switch(val){
423 		case	ILINESKIP:
424 				pint(bufptr, ryylval);
425 				break;
426 		case	SIZESPEC:
427 				pchar(bufptr, ryylval);
428 				break;
429 		case	BFINT:	plong(bufptr, ryylval);
430 				break;
431 		case	INT:	plong(bufptr, ryylval);
432 				break;
433 		case 	BIGNUM:	pnumber(bufptr, yybignum);
434 				break;
435 		case	STRING:	pptr(bufptr, (int)(char *)ryylval);
436 				break;
437 		case	NAME:	pptr(bufptr, (int)(struct symtab *)ryylval);
438 				break;
439 		case	REG:	pchar(bufptr, ryylval);
440 				break;
441 		case	INST0:
442 		case	INSTn:
443 				popcode(bufptr, opstruct);
444 				break;
445 		case 	IJXXX:
446 				popcode(bufptr, opstruct);
447 				pptr(bufptr, (int)(struct symtab *)symalloc());
448 				break;
449 		case	ISTAB:
450 		case	ISTABSTR:
451 		case	ISTABNONE:
452 		case	ISTABDOT:
453 		case	IALIGN:
454 				pptr(bufptr, (int)(struct symtab *)symalloc());
455 				break;
456 	/*
457 	 *	default:
458 	 */
459 	 }
460 	 builtval: ;
461    }			/*end of the while to stuff the buffer*/
462    done:
463 	bufferbox->tok_count = (bytetoktype *)bufptr - &(bufferbox->toks[0]);
464 	/*
465 	 *	This is a real kludge:
466 	 *
467 	 *	We put the last token in the buffer to be  a MINUS
468 	 *	symbol.  This last token will never be picked up
469 	 *	in the normal way, but can be looked at during
470 	 *	a peekahead look that the short circuit expression
471 	 *	evaluator uses to see if an expression is complicated.
472 	 *
473 	 *	Consider the following situation:
474 	 *
475 	 *	.word	45		+	47
476 	 *        buffer 1      |  buffer 0
477 	 *	the peekahead would want to look across the buffer,
478 	 *	but will look in the buffer end zone, see the minus, and
479 	 *	fail.
480 	 */
481 	ptoken(bufptr, MINUS);
482 	REGTOMEMBUF;
483 }
484