From 83f57dc2e32aa8780cdf349767b03000c4c99743 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 10 Dec 2008 04:14:50 -0500 Subject: [PATCH] Added error_position to assembly results. --- assemble.c | 2 +- mojoshader_assembler.c | 57 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/assemble.c b/assemble.c index 9b510855..19f4a690 100644 --- a/assemble.c +++ b/assemble.c @@ -25,7 +25,7 @@ static int assemble(const char *buf, const char *outfile) pd = MOJOSHADER_assemble(buf, NULL, NULL, NULL); if (pd->error != NULL) - printf("ERROR: %s\n", pd->error); + printf("ERROR: (line %d) %s\n", pd->error_position, pd->error); else { if (pd->output != NULL) diff --git a/mojoshader_assembler.c b/mojoshader_assembler.c index 866ab71b..5b84aede 100644 --- a/mojoshader_assembler.c +++ b/mojoshader_assembler.c @@ -23,6 +23,7 @@ struct Context void *malloc_data; const char *failstr; const char *source; + int started_parsing; MOJOSHADER_shaderType shader_type; uint8 major_ver; uint8 minor_ver; @@ -36,6 +37,7 @@ struct Context int tokenbufpos; DestArgInfo dest_arg; uint32 *output; + uint32 *token_to_line; size_t output_len; size_t output_allocation; }; @@ -142,17 +144,30 @@ static void output_token_noswap(Context *ctx, const uint32 token) { const size_t output_alloc_bump = 1024; // that's tokens, not bytes. const size_t newsize = ctx->output_allocation + output_alloc_bump; - void *ptr = Malloc(ctx, newsize * sizeof (uint32)); + void *ptr; + + ptr = Malloc(ctx, newsize * sizeof (uint32)); if (ptr == NULL) return; if (ctx->output_len > 0) memcpy(ptr, ctx->output, ctx->output_len * sizeof (uint32)); Free(ctx, ctx->output); - ctx->output_allocation = newsize; ctx->output = (uint32 *) ptr; + + ptr = Malloc(ctx, newsize * sizeof (uint32)); + if (ptr == NULL) + return; + if (ctx->output_len > 0) + memcpy(ptr, ctx->token_to_line, ctx->output_len * sizeof (uint32)); + Free(ctx, ctx->token_to_line); + ctx->token_to_line = (uint32 *) ptr; + + ctx->output_allocation = newsize; } // if - ctx->output[ctx->output_len++] = token; + ctx->output[ctx->output_len] = token; + ctx->token_to_line[ctx->output_len] = ctx->linenum; + ctx->output_len++; } // output_token_noswap @@ -1454,7 +1469,6 @@ static Context *build_context(const char *source, MOJOSHADER_malloc m, ctx->free = f; ctx->malloc_data = d; ctx->source = source; - ctx->linenum = 1; return ctx; } // build_context @@ -1470,6 +1484,8 @@ static void destroy_context(Context *ctx) f((void *) ctx->failstr, d); if (ctx->output != NULL) f(ctx->output, d); + if (ctx->token_to_line != NULL) + f(ctx->token_to_line, d); f(ctx, d); } // if } // destroy_context @@ -1492,6 +1508,11 @@ static const MOJOSHADER_parseData *build_failed_assembly(Context *ctx) retval->error = ctx->failstr; // we recycle. :) ctx->failstr = NULL; // don't let this get free()'d too soon. + if (ctx->started_parsing) + retval->error_position = ctx->linenum; + else + retval->error_position = -1; + return retval; } // build_failed_assembly @@ -1502,7 +1523,7 @@ static const MOJOSHADER_parseData *build_failed_assembly(Context *ctx) const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *source, MOJOSHADER_malloc m, MOJOSHADER_free f, void *d) { - const MOJOSHADER_parseData *retval = NULL; + MOJOSHADER_parseData *retval = NULL; Context *ctx = NULL; if ( ((m == NULL) && (f != NULL)) || ((m != NULL) && (f == NULL)) ) @@ -1513,8 +1534,10 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *source, return &out_of_mem_data; // Version token always comes first. + ctx->started_parsing = 1; parse_version_token(ctx); + ctx->started_parsing = 0; // make error messages sane if CTAB fails, etc. const char *credit = "Generated by MojoShader assembler revision " MOJOSHADER_CHANGESET ", http://icculus.org/mojoshader/"; @@ -1522,6 +1545,8 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *source, // !!! FIXME: insert CTAB here. + ctx->started_parsing = 1; + // parse out the rest of the tokens after the version token... while (nexttoken(ctx, 1, 1, 0, 1) == NOFAIL) parse_token(ctx); @@ -1529,7 +1554,7 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *source, output_token(ctx, 0x0000FFFF); // end token always 0x0000FFFF. if (isfail(ctx)) - retval = build_failed_assembly(ctx); + retval = (MOJOSHADER_parseData *) build_failed_assembly(ctx); else { // This validates the shader; there are lots of things that are @@ -1538,10 +1563,22 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *source, // duplicate most of the validation here. // It also saves us the trouble of duplicating all the other work, // like setting up the uniforms list, etc. - retval = MOJOSHADER_parse(MOJOSHADER_PROFILE_BYTECODE, - (const unsigned char *) ctx->output, - ctx->output_len * sizeof (uint32), - NULL, 0, m, f, d); + retval = (MOJOSHADER_parseData *) + MOJOSHADER_parse(MOJOSHADER_PROFILE_BYTECODE, + (const unsigned char *) ctx->output, + ctx->output_len * sizeof (uint32), + NULL, 0, m, f, d); + + // on error, map the bytecode back to a line number. + if (retval->error_position >= 0) + { + assert(retval != &out_of_mem_data); + const int pos = retval->error_position / sizeof (uint32); + if (pos < ctx->output_len) + retval->error_position = ctx->token_to_line[pos]; + else + retval->error_position = -1; // oh well. + } // if } // if destroy_context(ctx);