scc

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

commit c4e05cd31ffe16a2f49bd611d300841ef6435642
parent 272a09b4b4196efc5b059de9a2b5e82d835c4527
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 28 Sep 2015 15:47:55 +0200

Add flag -I and convert test001.c into an actual "hello world"

Diffstat:
Mcc1/cc1.h | 1+
Mcc1/cpp.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mcc1/main.c | 4++++
Mcc1/tests/chktest.sh | 2+-
Acc1/tests/stdio.h | 6++++++
Mcc1/tests/test001.c | 2+-
6 files changed, 68 insertions(+), 28 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -395,6 +395,7 @@ extern void initializer(Symbol *sym, Type *tp, int nelem); extern void icpp(void); extern bool cpp(void); extern bool expand(char *begin, Symbol *sym); +extern void incdir(char *dir); /* * Definition of global variables diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -19,6 +19,8 @@ static char *argp, *macroname; static unsigned arglen; static Symbol *symline, *symfile; static unsigned char ifstatus[NR_COND]; +static int ninclude; +static char **dirinclude; unsigned cppctx; int disexpand; @@ -358,16 +360,51 @@ delete: delmacro(sym); } +void +incdir(char *dir) +{ + if (!dir || *dir == '\0') + die("incorrect -I flag"); + ++ninclude; + dirinclude = xrealloc(dirinclude, sizeof(*dirinclude) * ninclude); + dirinclude[ninclude-1] = dir; +} + +static bool +includefile(char *dir, char *file, size_t filelen) +{ + size_t dirlen; + char path[FILENAME_MAX]; + + if (!dir) { + dirlen = 0; + if (filelen > FILENAME_MAX-1) + return 0; + } else { + dirlen = strlen(dir); + if (dirlen + filelen > FILENAME_MAX-2) + return 0; + memcpy(path, dir, dirlen); + if (dir[dirlen-1] != '/') + path[dirlen++] = '/'; + } + memcpy(path+dirlen, file, filelen); + path[dirlen + filelen] = '\0'; + + return addinput(path); +} + static void include(void) { - char **bp, *p, file[FILENAME_MAX], path[FILENAME_MAX]; + char *file, *p, **bp; + size_t filelen; static char *sysinclude[] = { PREFIX"/include/", PREFIX"/local/include/", NULL }; - size_t filelen, dirlen; + int n; if (cppoff) return; @@ -380,49 +417,41 @@ include(void) if ((p = strchr(input->begin, '>')) == NULL) goto bad_include; *p = '\0'; - if (p - input->begin >= FILENAME_MAX) - goto too_long; - strcpy(file, input->begin); + file = input->begin; + filelen = strlen(file); input->begin = input->p = p+1; - next(); break; case '"': if ((p = strchr(yytext + 1, '"')) == NULL) goto bad_include; *p = '\0'; - if (p - yytext + 1 >= FILENAME_MAX) - goto too_long; - strcpy(file, yytext + 1); - next(); - if (addinput(file)) - return; + file = yytext+1; + filelen = strlen(file); + if (includefile(NULL, file, filelen)) + goto its_done; break; default: goto bad_include; } - filelen = strlen(file); + n = ninclude; + for (bp = dirinclude; n--; ++bp) { + if (includefile(*bp, file, filelen)) + goto its_done; + } for (bp = sysinclude; *bp; ++bp) { - dirlen = strlen(*bp); - if (dirlen + filelen > FILENAME_MAX-1) - continue; - memcpy(path, *bp, dirlen); - memcpy(path+dirlen, file, filelen); - if (addinput(path)) - break; + if (includefile(*bp, file, filelen)) + goto its_done; } + cpperror("included file '%s' not found", file); - if (*bp) - cpperror("included file '%s' not found", file); - +its_done: + next(); return; bad_include: cpperror("#include expects \"FILENAME\" or <FILENAME>"); return; -too_long: - cpperror("#include FILENAME too long"); - return; } static void diff --git a/cc1/main.c b/cc1/main.c @@ -39,6 +39,7 @@ main(int argc, char *argv[]) atexit(clean); for (;;) { + nextiter: --argc, ++argv; if (!*argv || argv[0][0] != '-' || argv[0][1] == '-') break; @@ -50,6 +51,9 @@ main(int argc, char *argv[]) case 'E': onlycpp = 1; break; + case 'I': + incdir(cp+1); + goto nextiter; case 'o': if (!*++argv || argv[0][0] == '-') usage(); diff --git a/cc1/tests/chktest.sh b/cc1/tests/chktest.sh @@ -30,7 +30,7 @@ do print $0 >> chk } END { - system("../cc1 -w " test " > " out " 2>&1") + system("../cc1 -I. -w " test " > " out " 2>&1") cmd="diff -c " chk " " out " >> " err print test >> err print system(cmd) ? "[FAILED]" : "[OK]" diff --git a/cc1/tests/stdio.h b/cc1/tests/stdio.h @@ -0,0 +1,6 @@ +#ifndef _STDIO_H +#define _STDIO_H + +int printf(const char *fmt, ...); + +#endif diff --git a/cc1/tests/test001.c b/cc1/tests/test001.c @@ -13,7 +13,7 @@ G6 F5 main } */ -int printf(char *fmt, ...); +#include <stdio.h> int main(void)