From db73da9a6c28cf36481a9cfd08a0e88de92938ac Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 13 Feb 2009 23:38:21 -0500 Subject: [PATCH] Implemented #line preprocessor directive. --- mojoshader_preprocessor.c | 72 ++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/mojoshader_preprocessor.c b/mojoshader_preprocessor.c index cc8e2404..dddc917c 100644 --- a/mojoshader_preprocessor.c +++ b/mojoshader_preprocessor.c @@ -506,6 +506,19 @@ int preprocessor_outofmemory(Preprocessor *_ctx) } // preprocessor_outofmemory +static int require_newline(IncludeState *state) +{ + const char *source = state->source; + const Token token = preprocessor_internal_lexer(state); + if (token == TOKEN_INCOMPLETE_COMMENT) + { + state->source = source; // pick this up later. + return 1; // call it an eol. + } // if + return ( (token == ((Token) '\n')) || (token == TOKEN_EOI) ); +} // require_newline + + static void handle_pp_include(Context *ctx) { IncludeState *state = ctx->include_stack; @@ -549,13 +562,7 @@ static void handle_pp_include(Context *ctx) filename = (char *) alloca(len); memcpy(filename, state->token, len-1); filename[len-1] = '\0'; - - // make sure this is EOL. - const char *source = state->source; - token = preprocessor_internal_lexer(state); - if (token == TOKEN_INCOMPLETE_COMMENT) - state->source = source; // pick this up later. - bogus = ( (token != ((Token) '\n')) && (token != TOKEN_EOI) ); + bogus = !require_newline(state); } // if if (bogus) @@ -582,6 +589,50 @@ static void handle_pp_include(Context *ctx) } // handle_pp_include +static void handle_pp_line(Context *ctx) +{ + IncludeState *state = ctx->include_stack; + char *filename = NULL; + int linenum = 0; + int bogus = 0; + + if (preprocessor_internal_lexer(state) != TOKEN_INT_LITERAL) + bogus = 1; + else + { + const unsigned int len = ((unsigned int) (state->source-state->token)); + char *buf = (char *) alloca(len+1); + memcpy(buf, state->token, len); + buf[len] = '\0'; + linenum = atoi(buf); + } // else + + if (!bogus) + bogus = (preprocessor_internal_lexer(state) != TOKEN_STRING_LITERAL); + + if (!bogus) + { + state->token++; // skip '\"'... + const unsigned int len = ((unsigned int) (state->source-state->token)); + filename = (char *) alloca(len); + memcpy(filename, state->token, len-1); + filename[len-1] = '\0'; + bogus = !require_newline(state); + } // if + + if (bogus) + { + fail(ctx, "Invalid #line directive"); + return; + } // if + + const char *cached = cache_filename(ctx, filename); + assert((cached != NULL) || (ctx->out_of_memory)); + state->filename = cached; + state->line = linenum; +} // handle_pp_line + + static void handle_pp_error(Context *ctx) { IncludeState *state = ctx->include_stack; @@ -647,7 +698,6 @@ static inline const char *_preprocessor_nexttoken(Preprocessor *_ctx, } // if // !!! FIXME: todo. - // TOKEN_PP_LINE, // TOKEN_PP_DEFINE, // TOKEN_PP_UNDEF, // TOKEN_PP_IF, @@ -677,6 +727,12 @@ static inline const char *_preprocessor_nexttoken(Preprocessor *_ctx, continue; // will return error or use new top of include_stack. } // else if + else if (token == TOKEN_PP_LINE) + { + handle_pp_line(ctx); + continue; // get the next thing. + } // else if + else if (token == TOKEN_PP_ERROR) { handle_pp_error(ctx);