Exemple #1
0
static void
identstmt(void)
{
	struct iobuf *ob = NULL;
	struct symtab *sp;
	usch *bp;
	int ch;

	if (ISID0(ch = fastspc())) {
		bp = readid(ch);
		if ((sp = lookup(bp, FIND)))
			ob = kfind(sp);
		if (ob->buf[0] != '\"')
			goto bad;
		if (ob)
			bufree(ob);
	} else if (ch == '\"') {
		bufree(faststr(ch, NULL));
		
	} else
		goto bad;
	chknl(1);
	return;
bad:
	error("bad #ident directive");
}
Exemple #2
0
int
yylex(void)
{
	static int ifdef, noex;
	struct symtab *nl;
	int ch, c2;

	while ((ch = sloscan()) == WSPACE)
		;
	if (ch < 128 && (spechr[ch] & C_2))
		c2 = inch();
	else
		c2 = 0;

	switch (ch) {
	case '=':
		if (c2 == '=') return EQ;
		break;
	case '!':
		if (c2 == '=') return NE;
		break;
	case '|':
		if (c2 == '|') return OROR;
		break;
	case '&':
		if (c2 == '&') return ANDAND;
		break;
	case '<':
		if (c2 == '<') return LS;
		if (c2 == '=') return LE;
		break;
	case '>':
		if (c2 == '>') return RS;
		if (c2 == '=') return GE;
		break;
	case '+':
	case '-':
		if (ch == c2)
			error("invalid preprocessor operator %c%c", ch, c2);
		break;

	case '/':
		if (Cflag == 0 || c2 != '*')
			break;
		/* Found comment that need to be skipped */
		for (;;) {
			ch = inch();
		c1:	if (ch != '*')
				continue;
			if ((ch = inch()) == '/')
				break;
			goto c1;
		}
		return yylex();

	case NUMBER:
		if (yytext[0] == '\'') {
			yylval.node.op = NUMBER;
			yylval.node.nd_val = charcon(yytext);
		} else
			cvtdig(yytext[0] != '0' ? 10 :
			    yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
		return NUMBER;

	case IDENT:
		if (strcmp((char *)yytext, "defined") == 0) {
			ifdef = 1;
			return DEFINED;
		}
		nl = lookup(yytext, FIND);
		if (ifdef) {
			yylval.node.nd_val = nl != NULL;
			ifdef = 0;
		} else if (nl && noex == 0) {
			usch *och = stringbuf;
			int i;

			i = kfind(nl);
			unch(WARN);
			if (i)
				unpstr(stringbuf);
			else
				unpstr(nl->namep);
			stringbuf = och;
			noex = 1;
			return yylex();
		} else {
			yylval.node.nd_val = 0;
		}
		yylval.node.op = NUMBER;
		return NUMBER;
	case WARN:
		noex = 0;
		/* FALLTHROUGH */
	case PHOLD:
		return yylex();
	default:
		return ch;
	}
	unch(c2);
	return ch;
}
Exemple #3
0
/*
 * Scan quickly the input file searching for:
 *	- '#' directives
 *	- keywords (if not flslvl)
 *	- comments
 *
 *	Handle strings, numbers and trigraphs with care.
 *	Only data from pp files are scanned here, never any rescans.
 *	TODO: Only print out strings before calling other functions.
 */
static void
fastscan(void)
{
	struct symtab *nl;
	int ch, i;
	usch *cp;

	goto run;
	for (;;) {
		ch = inch();
xloop:		if (ch == -1)
			return;
#ifdef PCC_DEBUG
		if (dflag>1)
			printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
#endif
		if ((spechr[ch] & C_SPEC) == 0) {
			PUTCH(ch);
			continue;
		}
		switch (ch) {
		case EBLOCK:
		case WARN:
		case CONC:
			error("bad char passed");
			break;

		case '/': /* Comments */
			if ((ch = inch()) == '/') {
cppcmt:				if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
				do {
					if (Cflag) PUTCH(ch);
					ch = inch();
				} while (ch != -1 && ch != '\n');
				goto xloop;
			} else if (ch == '*') {
				eatcmnt();
			} else {
				PUTCH('/');
				goto xloop;
			}
			break;

		case '\n': /* newlines, for pp directives */
			i = ifiles->escln + 1;
			ifiles->lineno += i;
			ifiles->escln = 0;
			while (i-- > 0)
				putch('\n');
run:			for(;;) {
				ch = inch();
				if (ch == '/') {
					ch = inch();
					if (ch == '/')
						goto cppcmt;
					if (ch == '*') {
						eatcmnt();
						continue;
					}
					unch(ch);
					ch = '/';
				}
				if (ch != ' ' && ch != '\t')
					break;
				PUTCH(ch);
			}
			if (ch == '#') {
				ppdir();
				continue;
			} else if (ch == '%') {
				ch = inch();
				if (ch == ':') {
					ppdir();
					continue;
				}
				unch(ch);
				ch = '%';
			}
			goto xloop;

		case '\"': /* strings */
str:			PUTCH(ch);
			while ((ch = inch()) != '\"') {
				if (ch == '\\') {
					PUTCH('\\');
					ch = inch();
				}
				if (ch == '\n') {
					warning("unterminated string literal");
					goto xloop;
				}
				if (ch == -1)
					return;
				PUTCH(ch);
			}
			PUTCH(ch);
			break;

		case '.':  /* for pp-number */
			PUTCH(ch);
			ch = inch();
			if (ch < '0' || ch > '9')
				goto xloop;

			/* FALLTHROUGH */
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			do {
nxp:				PUTCH(ch);
				ch = inch();
				if (ch == -1)
					return;
				if (spechr[ch] & C_EP) {
					PUTCH(ch);
					ch = inch();
					if (ch == '-' || ch == '+')
						goto nxp;
					if (ch == -1)
						return;
				}
			} while ((spechr[ch] & C_ID) || (ch == '.'));
			goto xloop;

		case '\'': /* character constant */
con:			PUTCH(ch);
			if (tflag)
				break; /* character constants ignored */
			while ((ch = inch()) != '\'') {
				if (ch == '\\') {
					PUTCH('\\');
					ch = inch();
				}
				if (ch == '\n') {
					warning("unterminated character constant");
					goto xloop;
				}
				if (ch == -1)
					return;
				PUTCH(ch);
			}
			PUTCH(ch);
			break;

		case 'L':
			ch = inch();
			if (ch == '\"') {
				PUTCH('L');
				goto str;
			}
			if (ch == '\'') {
				PUTCH('L');
				goto con;
			}
			unch(ch);
			ch = 'L';

			/* FALLTHROUGH */
		default:
#ifdef PCC_DEBUG
			if ((spechr[ch] & C_ID) == 0)
				error("fastscan");
#endif
			i = 0;
			do {
				yytext[i++] = (usch)ch;
				ch = inch();
			} while (ch != -1 && (spechr[ch] & C_ID));

			if (flslvl)
				goto xloop;

			yytext[i] = 0;
			unch(ch);

			cp = stringbuf;
			if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
				putstr(stringbuf);
			} else
				putstr(yytext);
			stringbuf = cp;

			break;
		}
	}
}
Exemple #4
0
static int
exprline(void)
{
	extern int nbufused;
	struct iobuf *ob, *rb;
	struct symtab *nl;
	int oCflag = Cflag;
	usch *dp;
	int c, d, ifdef;

	rb = getobuf(BNORMAL);
	nbufused--;
	Cflag = ifdef = 0;

	for (;;) {
		c = qcchar();
xloop:		if (c == '\n')
			break;
		if (c == '.') {
			putob(rb, '.');
			if ((spechr[c = qcchar()] & C_DIGIT) == 0)
				goto xloop;
		}
		if (ISDIGIT(c)) {
			c = fastnum(c, rb);
			goto xloop;
		}
		if (c == '\'' || c == '\"') {
			faststr(c, rb);
			continue;
		}
		if (c == 'L' || c == 'u' || c == 'U') {
			unch(d = qcchar());
			if (d == '\'')	/* discard wide designator */
				continue;
		}
		if (ISID0(c)) {
			dp = readid(c);
			nl = lookup(dp, FIND);
			if (nl && nl->type == DEFLOC) {
				ifdef = 1;
			} else if (ifdef) {
				putob(rb, nl ? '1' : '0');
				ifdef = 0;
			} else if (nl != NULL) {
				inexpr = 1;
				if ((ob = kfind(nl))) {
					ob->buf[ob->cptr] = 0;
					strtobuf(ob->buf, rb);
					bufree(ob);
				} else
					putob(rb, '0');
				inexpr = 0;
			} else
				putob(rb, '0');
		} else
			putob(rb, c);
	}
	rb->buf[rb->cptr] = 0;
	unch('\n');
	yyinp = rb->buf;
	c = yyparse();
	bufree(rb);
	nbufused++;
	Cflag = oCflag;
	return c;
}
Exemple #5
0
/*
 * Scan quickly the input file searching for:
 *	- '#' directives
 *	- keywords (if not flslvl)
 *	- comments
 *
 *	Handle strings, numbers and trigraphs with care.
 *	Only data from pp files are scanned here, never any rescans.
 *	This loop is always at trulvl.
 */
void
fastscan(void)
{
	struct iobuf *ob, rbs, *rb = &rbs;
	extern struct iobuf pb;
	struct iobuf *ib = ifiles->ib;
	struct symtab *nl;
	int ch, c2;
	usch *dp;

#define	IDSIZE	128
	rb->buf = xmalloc(IDSIZE+1);
	rb->cptr = 0;
	rb->bsz = IDSIZE;

	goto run;

	for (;;) {
		/* tight loop to find special chars */
		/* should use getchar/putchar here */
		for (;;) {
			if (ib->cptr < ib->bsz)
				ch = ib->buf[ib->cptr++];
			else
				ch = qcchar();
xloop:			if (ch < 0) ch = 0; /* XXX */
			if ((spechr[ch] & C_SPEC) != 0)
				break;
			putch(ch);
		}

		switch (ch) {
		case 0:
			free(rb->buf);
			return;

		case WARN:
		case CONC:
			error("bad char passed");
			break;

		case '/': /* Comments */
			incmnt++;
			ch = qcchar();
			incmnt--;
			if (ch  == '/' || ch == '*') {
				if (Cflag == 0) {
					int n = ifiles->lineno;
					fastcmnt2(ch);
					if (n == ifiles->lineno)
						putch(' '); /* 5.1.1.2 p3 */
				} else
					Ccmnt2(&pb, ch);
			} else {
				putch('/');
				goto xloop;
			}
			break;

		case '\n': /* newlines, for pp directives */
			/* take care of leftover \n */
			while (ifiles->escln > 0) {
				putch('\n');
				ifiles->escln--;
				ifiles->lineno++;
			}
			putch('\n');
			ifiles->lineno++;

			/* search for a # */
run:			while ((ch = qcchar()) == '\t' || ch == ' ')
				putch(ch);
			if (ch == '%') {
				if ((c2 = qcchar()) != ':')
					unch(c2);
				else
					ch = '#';
			}
			if (ch  == '#')
				ppdir();
			else
				goto xloop;
			break;

		case '?':
			if (ib->cptr+1 >= ib->bsz)
				inpbuf(2);
			if (ib->buf[ib->cptr] == '?') {
				ib->cptr++;
				if ((ch = chktg2(ib->buf[ib->cptr++])))
					goto xloop;
				ib->cptr -= 2;
			}
			putch('?');
			break;

		case '\'': /* character constant */
			if (tflag) {
				putch(ch);
				break;	/* character constants ignored */
			}
			/* FALLTHROUGH */
		case '\"': /* strings */
			if (skpows)
				cntline();
			faststr(ch, &pb);
			break;

		case '.':  /* for pp-number */
			if ((spechr[c2 = qcchar()] & C_DIGIT) == 0) {
				putch('.');
				goto xloop;
			}
			unch(c2);
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			if (skpows)
				cntline();
			ch = fastnum(ch, &pb);
			goto xloop;

		case 'L':
		case 'U':
		case 'u':
			if (ib->cptr+2 >= ib->bsz)
				inpbuf(2);
			if ((c2 = ib->buf[ib->cptr]) == '\"' || c2 == '\'') {
				putch(ch);
				break;
			} else if (c2 == '8' && ch == 'u' &&
			    ib->buf[ib->cptr+1] == '\"') {
				ib->cptr++;
				putstr((usch *)"u8");
				break;
			}
			/* FALLTHROUGH */
		default:
#ifdef PCC_DEBUG
			if ((spechr[ch] & C_ID) == 0)
				error("fastscan");
#endif
			if (flslvl)
				error("fastscan flslvl");
			rb->cptr = 0;
			dp = bufid(ch, rb);
			if ((nl = lookup(dp, FIND)) != NULL) {
				if ((ob = kfind(nl)) != NULL) {
					if (*ob->buf == '-' || *ob->buf == '+')
						putch(' ');
					if (skpows)
						cntline();
					buftobuf(ob, &pb);
					if (ob->cptr > 0 &&
					    (ob->buf[ob->cptr-1] == '-' ||
					    ob->buf[ob->cptr-1] == '+'))
						putch(' ');
					bufree(ob);
				}
			} else {
				putstr(dp);
			}
			break;

		case '\\':
			ib->buf[--ib->cptr] = '\\';
			if ((ch = qcchar()) != '\\')
				goto xloop;
			putch('\\');
			break;
		}
	}
}
Exemple #6
0
int
yylex(void)
{
	static int ifdef, noex;
	struct symtab *nl;
	int ch, c2;

	while ((ch = sloscan()) == WSPACE)
		;
	if (ch < 128 && spechr[ch] & C_2)
		c2 = inpch();
	else
		c2 = 0;

#define	C2(a,b,c) case a: if (c2 == b) return c; break
	switch (ch) {
	C2('=', '=', EQ);
	C2('!', '=', NE);
	C2('|', '|', OROR);
	C2('&', '&', ANDAND);
	case '<':
		if (c2 == '<') return LS;
		if (c2 == '=') return LE;
		break;
	case '>':
		if (c2 == '>') return RS;
		if (c2 == '=') return GE;
		break;
	case '+':
	case '-':
		if (ch == c2)
			badop("");
		break;

	case '/':
		if (Cflag == 0 || c2 != '*')
			break;
		/* Found comment that need to be skipped */
		for (;;) {
			ch = inpch();
		c1:	if (ch != '*')
				continue;
			if ((ch = inpch()) == '/')
				break;
			goto c1;
		}
		return yylex();

	case NUMBER:
		if (yytext[0] == '\'') {
			yylval.node.op = NUMBER;
			yylval.node.nd_val = charcon((usch *)yytext);
		} else
			cvtdig(yytext[0] != '0' ? 10 :
			    yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
		return NUMBER;

	case IDENT:
		if (strcmp((char *)yytext, "defined") == 0) {
			ifdef = 1;
			return DEFINED;
		}
		nl = lookup((usch *)yytext, FIND);
		if (ifdef) {
			yylval.node.nd_val = nl != NULL;
			ifdef = 0;
		} else if (nl && noex == 0) {
			usch *och = stringbuf;
			int i;

			i = kfind(nl);
			unch(WARN);
			if (i)
				unpstr(stringbuf);
			else
				unpstr(nl->namep);
			stringbuf = och;
			noex = 1;
			return yylex();
		} else {
			yylval.node.nd_val = 0;
		}
		yylval.node.op = NUMBER;
		return NUMBER;
	case WARN:
		noex = 0;
		return yylex();
	default:
		return ch;
	}
	unch(c2);
	return ch;
}
Exemple #7
0
/*
 * Scan quickly the input file searching for:
 *	- '#' directives
 *	- keywords (if not flslvl)
 *	- comments
 *
 *	Handle strings, numbers and trigraphs with care.
 *	Only data from pp files are scanned here, never any rescans.
 *	TODO: Only print out strings before calling other functions.
 */
static void
fastscan(void)
{
	struct symtab *nl;
	int ch, i = 0;
	int nnl = 0;
	usch *cp;

	goto run;
	for (;;) {
		ch = NXTCH();
xloop:		if (ch == -1)
			return;
#ifdef PCC_DEBUG
		if (dflag>1)
			printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
#endif
		if ((spechr[ch] & C_SPEC) == 0) {
			PUTCH(ch);
			continue;
		}
		switch (ch) {
		case EBLOCK:
		case WARN:
		case CONC:
			error("bad char passed");
			break;

		case '/': /* Comments */
			if ((ch = inch()) == '/') {
cppcmt:				if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
				do {
					if (Cflag) PUTCH(ch);
					ch = inch();
				} while (ch != -1 && ch != '\n');
				goto xloop;
			} else if (ch == '*') {
				if (eatcmnt())
					return;
			} else {
				PUTCH('/');
				goto xloop;
			}
			break;

		case '?':  /* trigraphs */
			if ((ch = chktg()))
				goto xloop;
			PUTCH('?');
			break;

		case '\\':
			if ((ch = NXTCH()) == '\n') {
				ifiles->lineno++;
				continue;
			} else {
				PUTCH('\\');
			}
			goto xloop;

		case '\n': /* newlines, for pp directives */
			while (nnl > 0) { PUTCH('\n'); nnl--; }
run2:			ifiles->lineno++;
			do {
				PUTCH(ch);
run:				ch = NXTCH();
				if (ch == '/') {
					ch = NXTCH();
					if (ch == '/')
						goto cppcmt;
					if (ch == '*') {
						if (eatcmnt())
							return;
						goto run;
					} 
					unch(ch);
					ch = '/';
				}
			} while (ch == ' ' || ch == '\t');
			if (ch == '\\') {
				ch = NXTCH();
				if (ch == '\n')
					goto run2;
				unch(ch);
				ch = '\\';
			}
			if (ch == '#') {
				ppdir();
				continue;
			} else if (ch == '%') {
				ch = NXTCH();
				if (ch == ':') {
					ppdir();
					continue;
				} else {
					unch(ch);
					ch = '%';
				}
			} else if (ch == '?') {
				if ((ch = chktg()) == '#') {
					ppdir();
					continue;
				} else if (ch == 0) 
					ch = '?';
			}
			goto xloop;

		case '\"': /* strings */
str:			PUTCH(ch);
			while ((ch = NXTCH()) != '\"') {
				if (ch == '\n')
					goto xloop;
				if (ch == '\\') {
					if ((ch = NXTCH()) != '\n') {
						PUTCH('\\');
						PUTCH(ch);
					} else
						nnl++;
					continue;
                                }
				if (ch < 0)
					return;
				PUTCH(ch);
			}
			PUTCH(ch);
			break;

		case '.':  /* for pp-number */
			PUTCH(ch);
			ch = NXTCH();
			if (ch < '0' || ch > '9')
				goto xloop;
			/* FALLTHROUGH */
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			do {
				PUTCH(ch);
nxt:				ch = NXTCH();
				if (ch == '\\') {
					ch = NXTCH();
					if (ch == '\n') {
						goto nxt;
					} else {
						unch(ch);
						ch = '\\';
					}
				}
				if (spechr[ch] & C_EP) {
					PUTCH(ch);
					ch = NXTCH();
					if (ch == '-' || ch == '+')
						continue;
				}
			} while ((spechr[ch] & C_ID) || (ch == '.'));
			goto xloop;

		case '\'': /* character literal */
con:			PUTCH(ch);
			if (tflag)
				continue; /* character constants ignored */
			while ((ch = NXTCH()) != '\'') {
				if (ch == '\n')
					goto xloop;
				if (ch == '\\') {
					if ((ch = NXTCH()) != '\n') {
						PUTCH('\\');
						PUTCH(ch);
					} else
						nnl++;
					continue;
				}
				if (ch < 0)
					return;
				PUTCH(ch);
			}
			PUTCH(ch);
			break;

		case 'L':
			ch = NXTCH();
			if (ch == '\"') {
				PUTCH('L');
				goto str;
			}
			if (ch == '\'') {
				PUTCH('L');
				goto con;
			}
			unch(ch);
			ch = 'L';
			/* FALLTHROUGH */
		default:
			if ((spechr[ch] & C_ID) == 0)
				error("fastscan");
			if (flslvl) {
				while (spechr[ch] & C_ID)
					ch = NXTCH();
				goto xloop;
			}
			i = 0;
			do {
				yytext[i++] = (usch)ch;
				ch = NXTCH();
				if (ch == '\\') {
					ch = NXTCH();
					if (ch != '\n') {
						unch(ch);
						ch = '\\';
					} else {
						putch('\n');
						ifiles->lineno++;
						ch = NXTCH();
					}
				}
				if (ch < 0)
					return;
			} while (spechr[ch] & C_ID);

			yytext[i] = 0;
			unch(ch);

			cp = stringbuf;
			if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
				putstr(stringbuf);
			} else
				putstr((usch *)yytext);
			stringbuf = cp;

			break;
		}
	}
}