commit 8fb3ee51e2eacdf956288a5434dbd2cd57a161ec
parent 7a32845fcd3b08eb599634ef26bfd963944d630c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Fri, 8 May 2015 18:15:43 +0200
Add include handler
It is the first version of the preprocessor handler, and it
does the correct work for include of local files.
Diffstat:
4 files changed, 187 insertions(+), 37 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -40,6 +40,7 @@ struct symbol {
int i;
char *s;
uint8_t token;
+ void (*fun)(char *);
} u;
struct symbol *next;
struct symbol *hash;
@@ -96,6 +97,7 @@ enum {
NS_IDEN,
NS_TAG,
NS_LABEL,
+ NS_CPP,
NS_STRUCTS,
NR_NAMESPACES
};
@@ -264,7 +266,7 @@ extern void expect(uint8_t tok);
extern void discard(void);
extern char *filename(void);
extern unsigned short fileline(void);
-extern void addinput(char *fname);
+extern bool addinput(char *fname);
extern void delinput(void);
#define accept(t) ((yytoken == (t)) ? next() : 0)
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -1,4 +1,5 @@
+#include <assert.h>
#include <inttypes.h>
#include <setjmp.h>
#include <stdio.h>
@@ -10,14 +11,14 @@
#include "../inc/cc.h"
#include "cc1.h"
-#define INPUTSIZ 128
+#define INPUTSIZ 120
typedef struct input Input;
struct input {
char *fname;
unsigned short nline;
- int8_t cnt;
+ int cnt;
FILE *fp;
char *line, *ptr;
struct input *next;
@@ -35,32 +36,35 @@ static uint8_t safe;
static Input *input;
-void
+bool
addinput(char *fname)
{
- Input *ip, *oip = input;
+ Input *ip;
+ FILE *fp;
+ unsigned short nline = 1;
+
+ if (fname) {
+ if ((fp = fopen(fname, "r")) == NULL)
+ return 0;
+ fname = xstrdup(fname);
+ } else if (!input) {
+ fp = stdin;
+ fname = "(stdin)";
+ } else {
+ fname = input->fname;
+ nline = input->nline;
+ fp = NULL;
+ }
ip = xmalloc(sizeof(Input));
+ ip->fname = fname;
ip->next = input;
ip->line = NULL;
ip->cnt = 0;
- ip->nline = 1;
+ ip->nline = nline;
+ ip->fp = fp;
input = ip;
-
- if (fname) {
- if ((ip->fp = fopen(fname, "r")) == NULL)
- die("file '%s' not found", fname);
- ip->fname = xstrdup(fname);
- next();
- } else if (!oip) {
- ip->fp = stdin;
- ip->fname = "(stdin)";
- next();
- } else {
- ip->fname = oip->fname;
- ip->fp = NULL;
- ip->nline = input->nline;
- }
+ return 1;
}
void
@@ -99,14 +103,122 @@ newline(void)
die("input file '%s' too long", input->fname);
}
+/* TODO: preprocessor error must not rise recover */
+static void
+preprocessor(void)
+{
+ char str[IDENTSIZ+1], *p, *q;
+ unsigned short cnt, n;
+ Symbol *sym;
+
+ p = input->ptr;
+ q = &p[input->cnt-1];
+ while (q > p && isspace(*q))
+ ++q;
+ while (isspace(*p))
+ ++p;
+ for (q = p; isalpha(*q); ++q)
+ /* nothing */;
+ if ((n = q - p) > IDENTSIZ)
+ goto bad_directive;
+ strncpy(str, p, n);
+ str[n] = '\0';
+
+ /* discard this line for the lexer */
+ input->cnt = 0;
+ if ((sym = lookup(str, NS_CPP)) == NULL)
+ goto bad_directive;
+ (*sym->u.fun)(q);
+ return;
+
+bad_directive:
+ error("incorrect preprocessor directive");
+}
+
+void
+include(char *s)
+{
+ char fname[FILENAME_MAX], delim, c, *p;
+ size_t len;
+
+ while (isspace(*s))
+ ++s;
+ if ((c = *s++) == '>')
+ delim = '>';
+ else if (c == '"')
+ delim = '"';
+ else
+ goto bad_include;
+
+ for (p = s; (c = *p) && c != delim; ++p)
+ /* nothing */;
+ if (c == '\0')
+ goto bad_include;
+
+ len = p - s;
+ if (delim == '"') {
+ if (len >= FILENAME_MAX)
+ goto too_long;
+ strncpy(fname, s, len);
+ fname[len] = '\0';
+ if (!addinput(fname))
+ goto not_found;
+ return;
+ }
+ abort();
+
+ return;
+
+not_found:
+ error("included file '%s' not found", fname);
+too_long:
+ error("file name in include too long");
+bad_include:
+ error("#include expects \"FILENAME\" or <FILENAME>");
+}
+
+void
+define(char *str)
+{
+
+}
+
+void
+undef(char *str)
+{
+ fprintf(stderr, "Esto en un undef\n");
+}
+
+void
+ifdef(char *str)
+{
+ fprintf(stderr, "Esto en un ifdef\n");
+}
+
+void
+ifndef(char *str)
+{
+ fprintf(stderr, "Esto en un ifndef\n");
+}
+
+void
+endif(char *str)
+{
+ fprintf(stderr, "Esto en un endif\n");
+}
+
static int
readline(void)
{
char *bp, *ptr;
uint8_t n;
int c;
- FILE *fp = input->fp;
+ FILE *fp;
+repeat:
+ if (!input)
+ return EOF;
+ fp = input->fp;
if (!input->line)
input->line = xmalloc(INPUTSIZ);
ptr = input->line;
@@ -115,8 +227,10 @@ readline(void)
if (c == '\n')
newline();
}
- if (c == EOF)
- return EOF;
+ if (c == EOF) {
+ delinput();
+ goto repeat;
+ }
ungetc(c, fp);
for (bp = ptr; (c = getc(fp)) != EOF && c != '\n'; ) {
@@ -134,12 +248,22 @@ readline(void)
*bp = ' ';
input->cnt = bp - ptr;
input->ptr = ptr;
- return *input->ptr++;
+
+ if ((c = *input->ptr++) == '#') {
+ *bp = '\0';
+ preprocessor();
+ goto repeat;
+ }
+ return c;
}
static int
backchar(int c)
{
+ if (!input) {
+ assert(c == EOF);
+ return c;
+ }
++input->cnt;
return *--input->ptr = c;
}
diff --git a/cc1/main.c b/cc1/main.c
@@ -67,12 +67,10 @@ main(int argc, char *argv[])
ikeywords();
- addinput(*argv);
- while (yytoken != EOFTOK)
- extdecl();
- delinput();
+ if (!addinput(*argv))
+ die("error opening input file '%s'", *argv);
+ for (next(); yytoken != EOFTOK; extdecl())
+ /* nothing */;
- if (fclose(stdout))
- die("error writing in output:%s", strerror(errno));
return 0;
}
diff --git a/cc1/symbol.c b/cc1/symbol.c
@@ -107,10 +107,13 @@ install(char *s, uint8_t ns)
void
ikeywords(void)
{
- static struct {
+ extern void include(char *), define(char *), undef(char *);
+ extern void ifdef(char *), ifndef(char *), endif(char *);
+ static struct words {
char *str;
uint8_t token, value;
- } *bp, buff[] = {
+ void (*fun)(char *);
+ } ccwords[] = {
{"auto", SCLASS, AUTO},
{"break", BREAK, BREAK},
{"_Bool", TYPE, BOOL},
@@ -146,13 +149,36 @@ ikeywords(void)
{"volatile", TQUALIFIER, VOLATILE},
{"while", WHILE, WHILE},
{NULL, 0, 0},
+ }, cppwords[] = {
+ {"include", 0, 0, include},
+ {"define", 0, 0, define},
+ {"undef", 0, 0, undef},
+ {"ifdef", 0, 0, ifdef},
+ {"ifndef", 0, 0, ifndef},
+ {"endif", 0, 0, endif},
+ {NULL, 0, 0}
};
+ static struct wordlist {
+ struct words *words;
+ uint8_t ns;
+ } wordlist [] = {
+ {ccwords, NS_IDEN},
+ {cppwords, NS_CPP},
+ {NULL, 0}
+ };
+ struct wordlist *lp;
+ struct words *bp;
Symbol *sym;
- for (bp = buff; bp->str; ++bp) {
- sym = install(bp->str, NS_IDEN);
- sym->token = bp->token;
- sym->u.token = bp->value;
+ for (lp = wordlist; lp->words; ++lp) {
+ for (bp = lp->words; bp->str; ++bp) {
+ sym = install(bp->str, lp->ns);
+ sym->token = bp->token;
+ if (bp->fun)
+ sym->u.fun = bp->fun;
+ else
+ sym->u.token = bp->value;
+ }
}
globalcnt = 0;
}