ref: 7a32845fcd3b08eb599634ef26bfd963944d630c
parent: 669e2ebc23002ffab0e05b1e9c97bf54a7ad9f4d
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri May 8 08:12:38 EDT 2015
Add nextchar() and backchar() These functions do the same job than getc and ungetc, but they work with Input elements.
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -10,15 +10,22 @@
#include "../inc/cc.h"
#include "cc1.h"
+#define INPUTSIZ 128
+
typedef struct input Input;
struct input {
char *fname;
unsigned short nline;
+ int8_t cnt;
FILE *fp;
+ char *line, *ptr;
struct input *next;
};
+#define nextchar() ((--input->cnt >= 0) ? \
+ (unsigned char) *input->ptr++ : readline())
+
uint8_t lex_ns = NS_IDEN;
uint8_t yytoken;
@@ -31,28 +38,29 @@
void
addinput(char *fname)
{
- Input *ip;
+ Input *ip, *oip = input;
ip = xmalloc(sizeof(Input));
ip->next = input;
+ ip->line = NULL;
+ ip->cnt = 0;
+ ip->nline = 1;
+ input = ip;
if (fname) {
if ((ip->fp = fopen(fname, "r")) == NULL)
die("file '%s' not found", fname);
ip->fname = xstrdup(fname);
- } else if (!input) {
+ next();
+ } else if (!oip) {
ip->fp = stdin;
ip->fname = "(stdin)";
+ next();
} else {
- ip->fname = input->fname;
+ ip->fname = oip->fname;
ip->fp = NULL;
ip->nline = input->nline;
- return;
}
-
- ip->nline = 1;
- input = ip;
- next();
}
void
@@ -64,10 +72,11 @@
if (fp) {
if (fclose(fp))
die("error reading from input file '%s'", ip->fname);
- if (strcmp("(stdin)", input->fname))
+ if (ip->fp != stdin)
free(ip->fname);
}
input = ip->next;
+ free(ip->line);
free(ip);
}
@@ -87,9 +96,54 @@
newline(void)
{
if (++input->nline == 0)
- die("input file too long");
+ die("input file '%s' too long", input->fname);
}
+static int
+readline(void)
+{
+ char *bp, *ptr;
+ uint8_t n;
+ int c;
+ FILE *fp = input->fp;
+
+ if (!input->line)
+ input->line = xmalloc(INPUTSIZ);
+ ptr = input->line;
+
+ while ((c = getc(fp)) != EOF && isspace(c)) {
+ if (c == '\n')
+ newline();
+ }
+ if (c == EOF)
+ return EOF;
+ ungetc(c, fp);
+
+ for (bp = ptr; (c = getc(fp)) != EOF && c != '\n'; ) {
+ if (c == '\\') {
+ if ((c = getc(fp)) == '\n')
+ continue;
+ ungetc(c, fp);
+ c = '\\';
+ }
+ if (bp == &ptr[INPUTSIZ])
+ die("line %d too big in file '%s'",
+ input->nline, input->fname);
+ *bp++ = c;
+ }
+ *bp = ' ';
+ input->cnt = bp - ptr;
+ input->ptr = ptr;
+ return *input->ptr++;
+}
+
+static int
+backchar(int c)
+{
+ ++input->cnt;
+ return *--input->ptr = c;
+}
+
static uint8_t
integer(char *s, char base)
{
@@ -100,7 +154,7 @@
size = sign = 0;
type:
- switch (ch = toupper(getc(input->fp))) {
+ switch (ch = toupper(nextchar())) {
case 'L':
if (size == LLONG)
goto wrong_type;
@@ -111,7 +165,7 @@
goto wrong_type;
goto type;
default:
- ungetc(ch, input->fp);
+ backchar(ch);
tp = ctype(INT, sign, size);
break;
wrong_type:
@@ -133,7 +187,7 @@
char ch, *bp;
for (bp = yytext ; bp < &yytext[IDENTSIZ]; *bp++ = ch) {
- ch = getc(input->fp);
+ ch = nextchar();
switch (base) {
case 8:
if (ch >= '7')
@@ -153,7 +207,7 @@
if (bp == &yytext[IDENTSIZ])
error("number too long %s", yytext);
*bp = '\0';
- ungetc(ch, input->fp);
+ backchar(ch);
return yytext;
}
@@ -160,19 +214,19 @@
static uint8_t
number(void)
{
- char ch;
+ int ch;
static char base;
- if ((ch = getc(input->fp)) == '0') {
- if (toupper(ch = getc(input->fp)) == 'X') {
+ if ((ch = nextchar()) == '0') {
+ if (toupper(ch = nextchar()) == 'X') {
base = 16;
} else {
base = 8;
- ungetc(ch, input->fp);
+ backchar(ch);
}
} else {
base = 10;
- ungetc(ch, input->fp);
+ backchar(ch);
}
return integer(digits(base), base);
@@ -185,7 +239,7 @@
int c;
repeat:
- switch (getc(input->fp)) {
+ switch (nextchar()) {
case '\\': c = '\''; break;
case 'a': c = '\a'; break;
case 'f': c = '\f'; break;
@@ -208,7 +262,7 @@
break;
case '\n':
newline();
- if ((c = getc(input->fp)) == '\\')
+ if ((c = nextchar()) == '\\')
goto repeat;
break;
default:
@@ -226,11 +280,11 @@
static char c;
Symbol *sym;
- getc(input->fp); /* discard the initial ' */
- c = getc(input->fp);
+ nextchar(); /* discard the initial ' */
+ c = nextchar();
if (c == '\\')
escape(&c);
- if (getc(input->fp) != '\'')
+ if (nextchar() != '\'')
error("invalid character constant");
sym = install("", NS_IDEN);
sym->u.i = c;
@@ -247,10 +301,10 @@
int c;
static Symbol *sym;
- getc(input->fp); /* discard the initial " */
+ nextchar(); /* discard the initial " */
for (bp = buf; bp < &buf[STRINGSIZ]; ) {
- switch (c = getc(input->fp)) {
+ switch (c = nextchar()) {
case EOF:
error("found EOF while parsing");
case '"':
@@ -282,13 +336,13 @@
Symbol *sym;
for (bp = yytext; bp < &yytext[IDENTSIZ]; *bp++ = c) {
- if (!isalnum(c = getc(input->fp)) && c != '_')
+ if (!isalnum(c = nextchar()) && c != '_')
break;
}
if (bp == &yytext[IDENTSIZ])
error("identifier too long %s", yytext);
*bp = '\0';
- ungetc(c, input->fp);
+ backchar(c);
sym = yylval.sym = lookup(yytext, lex_ns);
if (!sym || sym->token == IDEN)
@@ -300,7 +354,7 @@
static uint8_t
follow(int expect, int ifyes, int ifno)
{
- int c = getc(input->fp);
+ int c = nextchar();
if (c == expect) {
yytext[1] = c;
@@ -307,7 +361,7 @@
yytext[2] = 0;
return ifyes;
}
- ungetc(c, input->fp);
+ backchar(c);
return ifno;
}
@@ -314,7 +368,7 @@
static uint8_t
minus(void)
{
- int c = getc(input->fp);
+ int c = nextchar();
yytext[1] = c;
yytext[2] = '\0';
@@ -324,7 +378,7 @@
case '=': return SUB_EQ;
default:
yytext[1] = '\0';
- ungetc(c, input->fp);
+ backchar(c);
return '-';
}
}
@@ -332,7 +386,7 @@
static uint8_t
plus(void)
{
- int c = getc(input->fp);
+ int c = nextchar();
yytext[1] = c;
yytext[2] = '\0';
@@ -341,7 +395,7 @@
case '=': return ADD_EQ;
default:
yytext[1] = '\0';
- ungetc(c, input->fp);
+ backchar(c);
return '+';
}
}
@@ -349,7 +403,7 @@
static uint8_t
relational(uint8_t op, uint8_t equal, uint8_t shift, uint8_t assig)
{
- int c = getc(input->fp);
+ int c = nextchar();
yytext[1] = c;
yytext[2] = '\0';
@@ -358,7 +412,7 @@
return equal;
if (c == op)
return follow('=', assig, shift);
- ungetc(c, input->fp);
+ backchar(c);
yytext[1] = '\0';
return op;
}
@@ -366,7 +420,7 @@
static uint8_t
logic(uint8_t op, uint8_t equal, uint8_t logic)
{
- int c = getc(input->fp);
+ int c = nextchar();
yytext[1] = c;
yytext[2] = '\0';
@@ -375,7 +429,7 @@
return equal;
if (c == op)
return logic;
- ungetc(c, input->fp);
+ backchar(c);
yytext[1] = '\0';
return op;
}
@@ -385,10 +439,10 @@
{
int c;
- if ((c = getc(input->fp)) != '.') {
- ungetc(c, input->fp);
+ if ((c = nextchar()) != '.') {
+ backchar(c);
return '.';
- } else if ((c = getc(input->fp)) != '.') {
+ } else if ((c = nextchar()) != '.') {
error("incorrect token '%s'", yytext);
} else {
yytext[2] = yytext[1] = '.';
@@ -400,7 +454,7 @@
static uint8_t
operator(void)
{
- uint8_t c = getc(input->fp);
+ uint8_t c = nextchar();
yytext[0] = c;
yytext[1] = '\0';
@@ -427,7 +481,7 @@
int c;
- while (isspace(c = getc(input->fp))) {
+ while (isspace(c = nextchar())) {
if (c == '\n')
newline();
}
@@ -439,7 +493,7 @@
{
int c;
- ungetc(c = skipspaces(), input->fp);
+ backchar(c = skipspaces());
if (isalpha(c) || c == '_') {
yytoken = iden();
@@ -475,9 +529,9 @@
ahead(void)
{
int c;
-
- ungetc(c = skipspaces(), input->fp);
+ backchar(c = skipspaces());
+
return c;
}
@@ -513,7 +567,7 @@
goto jump;
break;
}
- } while ((c = getc(input->fp)) != EOF);
+ } while ((c = nextchar()) != EOF);
c = EOFTOK;
jump: