scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

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:
Mcc1/cc1.h | 4+++-
Mcc1/lex.c | 172++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mcc1/main.c | 10++++------
Mcc1/symbol.c | 38++++++++++++++++++++++++++++++++------
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; }