X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=ftepp.c;h=21669a8aa6a492910c23b12dcb3d8482c4fb09a8;hp=96c20bf4f937f7ad0d55c9050e31b6813a3ab1a3;hb=c7280fca5285463dd68395f322004d249cfbbdb3;hpb=3c003bc168fe47f3e7ce08328782f969b59d89a3 diff --git a/ftepp.c b/ftepp.c index 96c20bf..21669a8 100644 --- a/ftepp.c +++ b/ftepp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 + * Copyright (C) 2012, 2013 * Wolfgang Bumiller * Dale Weiler * @@ -68,6 +68,77 @@ typedef struct { char *includename; } ftepp_t; +typedef struct { + const char *name; + char *(*func)(lex_file *); +} predef_t; + +/* + * Implement the predef subsystem now. We can do this safely with the + * help of lexer contexts. + */ +static uint32_t ftepp_predef_countval = 0; +static uint32_t ftepp_predef_randval = 0; + +/* __LINE__ */ +char *ftepp_predef_line(lex_file *context) { + char *value; + util_asprintf(&value, "%d", (int)context->line); + return value; +} +/* __FILE__ */ +char *ftepp_predef_file(lex_file *context) { + size_t length = strlen(context->name) + 3; /* two quotes and a terminator */ + char *value = (char*)mem_a(length); + memset (value, 0, length); + sprintf(value, "\"%s\"", context->name); + + return value; +} +/* __COUNTER_LAST__ */ +char *ftepp_predef_counterlast(lex_file *context) { + char *value; + util_asprintf(&value, "%u", ftepp_predef_countval); + + (void)context; + return value; +} +/* __COUNTER__ */ +char *ftepp_predef_counter(lex_file *context) { + char *value; + ftepp_predef_countval ++; + util_asprintf(&value, "%u", ftepp_predef_countval); + (void)context; + + return value; +} +/* __RANDOM__ */ +char *ftepp_predef_random(lex_file *context) { + char *value; + ftepp_predef_randval = (util_rand() % 0xFF) + 1; + util_asprintf(&value, "%u", ftepp_predef_randval); + + (void)context; + return value; +} +/* __RANDOM_LAST__ */ +char *ftepp_predef_randomlast(lex_file *context) { + char *value; + util_asprintf(&value, "%u", ftepp_predef_randval); + + (void)context; + return value; +} + +static const predef_t ftepp_predefs[] = { + { "__LINE__", &ftepp_predef_line }, + { "__FILE__", &ftepp_predef_file }, + { "__COUNTER__", &ftepp_predef_counter }, + { "__COUNTER_LAST__", &ftepp_predef_counterlast }, + { "__RANDOM__", &ftepp_predef_random }, + { "__RANDOM_LAST__", &ftepp_predef_randomlast }, +}; + #define ftepp_tokval(f) ((f)->lex->tok.value) #define ftepp_ctx(f) ((f)->lex->tok.ctx) @@ -163,6 +234,7 @@ static ftepp_t* ftepp_new() static void ftepp_delete(ftepp_t *self) { size_t i; + ftepp_flush(self); if (self->itemname) mem_d(self->itemname); if (self->includename) @@ -575,6 +647,8 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param goto cleanup; } ftepp->output_string = old_string; + inlex->line = ftepp->lex->line; + inlex->sline = ftepp->lex->sline; ftepp->lex = inlex; ftepp_recursion_header(ftepp); if (!ftepp_preprocess(ftepp)) { @@ -991,9 +1065,9 @@ static char *ftepp_include_find_path(const char *file, const char *pathfile) memcpy(vec_add(filename, len+1), file, len); vec_last(filename) = 0; - fp = util_fopen(filename, "rb"); + fp = file_open(filename, "rb"); if (fp) { - fclose(fp); + file_close(fp); return filename; } vec_free(filename); @@ -1010,14 +1084,15 @@ static char *ftepp_include_find(ftepp_t *ftepp, const char *file) return filename; } -static void ftepp_directive_warning(ftepp_t *ftepp) { +static bool ftepp_directive_warning(ftepp_t *ftepp) { char *message = NULL; if (!ftepp_skipspace(ftepp)) - return; + return false; /* handle the odd non string constant case so it works like C */ if (ftepp->token != TOKEN_STRINGCONST) { + bool store = false; vec_upload(message, "#warning", 8); ftepp_next(ftepp); while (ftepp->token != TOKEN_EOL) { @@ -1025,13 +1100,13 @@ static void ftepp_directive_warning(ftepp_t *ftepp) { ftepp_next(ftepp); } vec_push(message, '\0'); - (void)!!ftepp_warn(ftepp, WARN_CPP, message); + store = ftepp_warn(ftepp, WARN_CPP, message); vec_free(message); - return; + return store; } unescape (ftepp_tokval(ftepp), ftepp_tokval(ftepp)); - (void)!!ftepp_warn(ftepp, WARN_CPP, "#warning %s", ftepp_tokval(ftepp)); + return ftepp_warn(ftepp, WARN_CPP, "#warning %s", ftepp_tokval(ftepp)); } static void ftepp_directive_error(ftepp_t *ftepp) { @@ -1297,6 +1372,10 @@ static bool ftepp_preprocess(ftepp_t *ftepp) ppmacro *macro; bool newline = true; + /* predef stuff */ + char *expand = NULL; + size_t i; + ftepp->lex->flags.preprocessing = true; ftepp->lex->flags.mergelines = false; ftepp->lex->flags.noops = true; @@ -1314,10 +1393,25 @@ static bool ftepp_preprocess(ftepp_t *ftepp) case TOKEN_KEYWORD: case TOKEN_IDENT: case TOKEN_TYPENAME: + /* is it a predef? */ + if (OPTS_FLAG(FTEPP_PREDEFS)) { + for (i = 0; i < sizeof(ftepp_predefs) / sizeof (*ftepp_predefs); i++) { + if (!strcmp(ftepp_predefs[i].name, ftepp_tokval(ftepp))) { + expand = ftepp_predefs[i].func(ftepp->lex); + ftepp_out(ftepp, expand, false); + ftepp_next(ftepp); /* skip */ + + mem_d(expand); /* free memory */ + break; + } + } + } + if (ftepp->output_on) macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp)); else macro = NULL; + if (!macro) { ftepp_out(ftepp, ftepp_tokval(ftepp), false); ftepp_next(ftepp);