Cleaned up error position reporting.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 11 Nov 2010 04:13:08 -0500
changeset 947 16af6e2b2ada
parent 946 16fec3a3f687
child 948 6423e569624c
Cleaned up error position reporting.
mojoshader.c
mojoshader.h
mojoshader_assembler.c
mojoshader_internal.h
--- a/mojoshader.c	Wed Nov 10 00:52:01 2010 -0500
+++ b/mojoshader.c	Thu Nov 11 04:13:08 2010 -0500
@@ -70,10 +70,10 @@
     MOJOSHADER_malloc malloc;
     MOJOSHADER_free free;
     void *malloc_data;
+    int current_position;
     const uint32 *orig_tokens;
     const uint32 *tokens;
     uint32 tokencount;
-    MOJOSHADER_parsePhase parse_phase;
     const MOJOSHADER_swizzle *swizzles;
     unsigned int swizzles_count;
     Buffer *output;
@@ -368,8 +368,6 @@
 } // isfail
 
 
-// !!! FIXME: move the errpos calculation into Context, and we can move this
-// !!! FIXME:  to mojoshader_common.c
 static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
 static void failf(Context *ctx, const char *fmt, ...)
 {
@@ -377,27 +375,10 @@
     if (ctx->out_of_memory)
         return;
 
-    int errpos = 0;
-    switch (ctx->parse_phase)
-    {
-        case MOJOSHADER_PARSEPHASE_NOTSTARTED:
-            errpos = -2;
-            break;
-        case MOJOSHADER_PARSEPHASE_WORKING:
-            errpos = (ctx->tokens - ctx->orig_tokens) * sizeof (uint32);
-            break;
-        case MOJOSHADER_PARSEPHASE_DONE:
-            errpos = -1;
-            break;
-        default:
-            assert(0 && "Unexpected value");
-            return;
-    } // switch
-
     // no filename at this level (we pass a NULL to errorlist_add_va()...)
     va_list ap;
     va_start(ap, fmt);
-    errorlist_add_va(ctx->errors, NULL, errpos, fmt, ap);
+    errorlist_add_va(ctx->errors, NULL, ctx->current_position, fmt, ap);
     va_end(ap);
 } // failf
 
@@ -666,6 +647,13 @@
     return ctx->assigned_branch_labels++;
 } // allocate_branch_label
 
+static inline void adjust_token_position(Context *ctx, const int incr)
+{
+    ctx->tokens += incr;
+    ctx->tokencount -= incr;
+    ctx->current_position += incr * sizeof (uint32);
+} // adjust_token_position
+
 
 // D3D stuff that's used in more than just the d3d profile...
 
@@ -5285,8 +5273,8 @@
         info->regnum += 6144;
     } // else if
 
-    ctx->tokens++;  // swallow token for now, for multiple calls in a row.
-    ctx->tokencount--;  // swallow token for now, for multiple calls in a row.
+    // swallow token for now, for multiple calls in a row.
+    adjust_token_position(ctx, 1);
 
     if (reserved1 != 0x0)
         fail(ctx, "Reserved bit #1 in destination token must be zero");
@@ -5517,8 +5505,8 @@
     info->swizzle_z = ((info->swizzle >> 4) & 0x3);
     info->swizzle_w = ((info->swizzle >> 6) & 0x3);
 
-    ctx->tokens++;  // swallow token for now, for multiple calls in a row.
-    ctx->tokencount--;  // swallow token for now, for multiple calls in a row.
+    // swallow token for now, for multiple calls in a row.
+    adjust_token_position(ctx, 1);
 
     if (reserved1 != 0x0)
         fail(ctx, "Reserved bits #1 in source token must be zero");
@@ -5538,8 +5526,8 @@
             fail(ctx, "Relative addressing in pixel shader version < 3.0");
 
         const uint32 reltoken = SWAP32(*(ctx->tokens));
-        ctx->tokens++;  // swallow token for now, for multiple calls in a row.
-        ctx->tokencount--;  // swallow token for now, for multiple calls in a row.
+        // swallow token for now, for multiple calls in a row.
+        adjust_token_position(ctx, 1);
 
         const int relswiz = (int) ((reltoken >> 16) & 0xFF);
         info->relative_regnum = (int) (reltoken & 0x7ff);
@@ -5756,8 +5744,7 @@
         fail(ctx, "Bit #31 in DCL token must be one");
 
     ctx->centroid_allowed = 1;
-    ctx->tokens++;
-    ctx->tokencount--;
+    adjust_token_position(ctx, 1);
     parse_destination_token(ctx, &ctx->dest_arg);
     ctx->centroid_allowed = 0;
 
@@ -6648,6 +6635,7 @@
 static int parse_instruction_token(Context *ctx)
 {
     int retval = 0;
+    const int start_position = ctx->current_position;
     const uint32 *start_tokens = ctx->tokens;
     const uint32 start_tokencount = ctx->tokencount;
     const uint32 token = SWAP32(*(ctx->tokens));
@@ -6693,8 +6681,7 @@
     ctx->predicated = predicated;
 
     // Update the context with instruction's arguments.
-    ctx->tokens++;
-    ctx->tokencount--;
+    adjust_token_position(ctx, 1);
     retval = instruction->parse_args(ctx);
 
     if (predicated)
@@ -6703,6 +6690,7 @@
     // parse_args() moves these forward for convenience...reset them.
     ctx->tokens = start_tokens;
     ctx->tokencount = start_tokencount;
+    ctx->current_position = start_position;
 
     if (instruction->state != NULL)
         instruction->state(ctx);
@@ -6985,7 +6973,7 @@
     ctx->endline = ENDLINE_STR;
     ctx->endline_len = strlen(ctx->endline);
     ctx->last_address_reg_component = -1;
-    ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
+    ctx->current_position = MOJOSHADER_POSITION_BEFORE;
 
     ctx->errors = errorlist_create(MallocBridge, FreeBridge, ctx);
     if (ctx->errors == NULL)
@@ -7644,7 +7632,7 @@
     verify_swizzles(ctx);
 
     // Version token always comes first.
-    ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING;
+    ctx->current_position = 0;
     rc = parse_version_token(ctx, profile);
 
     // drop out now if this definitely isn't bytecode. Saves lots of
@@ -7662,8 +7650,7 @@
         ctx->tokencount = rc;
     } // if
 
-    ctx->tokens += rc;
-    ctx->tokencount -= rc;
+    adjust_token_position(ctx, rc);
 
     // parse out the rest of the tokens after the version token...
     while (ctx->tokencount > 0)
@@ -7682,11 +7669,10 @@
             break;
         } // if
 
-        ctx->tokens += rc;
-        ctx->tokencount -= rc;
+        adjust_token_position(ctx, rc);
     } // while
 
-    ctx->parse_phase = MOJOSHADER_PARSEPHASE_DONE;
+    ctx->current_position = MOJOSHADER_POSITION_AFTER;
 
     if (!failed)
     {
--- a/mojoshader.h	Wed Nov 10 00:52:01 2010 -0500
+++ b/mojoshader.h	Thu Nov 11 04:13:08 2010 -0500
@@ -319,6 +319,13 @@
 } MOJOSHADER_symbol;
 
 
+/*
+ * These are used with MOJOSHADER_error as special case positions.
+ */
+#define MOJOSHADER_POSITION_NONE (-3)
+#define MOJOSHADER_POSITION_BEFORE (-2)
+#define MOJOSHADER_POSITION_AFTER (-1)
+
 typedef struct MOJOSHADER_error
 {
     /*
@@ -335,12 +342,14 @@
     const char *filename;
 
     /*
-     * Position of error, if there is one. Will be -3 if there was no
-     *  error, -2 if there was an error before processing started, and
-     *  -1 if there was an error during final processing. If >= 0,
-     *  MOJOSHADER_parse() sets this to the byte offset (starting at zero) into
-     *  the bytecode you supplied, and MOJOSHADER_assemble() sets this to a
-     *  a line number in the source code you supplied (starting at one).
+     * Position of error, if there is one. Will be MOJOSHADER_POSITION_NONE if
+     *  there was no error, MOJOSHADER_POSITION_BEFORE if there was an error
+     *  before processing started, and MOJOSHADER_POSITION_AFTER if there was
+     *  an error during final processing. If >= 0, MOJOSHADER_parse() sets
+     *  this to the byte offset (starting at zero) into the bytecode you
+     *  supplied, and MOJOSHADER_assemble(), MOJOSHADER_parseAst(), and
+     *  MOJOSHADER_compile() sets this to a a line number in the source code
+     *  you supplied (starting at one).
      */
     int error_position;
 } MOJOSHADER_error;
--- a/mojoshader_assembler.c	Wed Nov 10 00:52:01 2010 -0500
+++ b/mojoshader_assembler.c	Thu Nov 11 04:13:08 2010 -0500
@@ -40,9 +40,10 @@
     MOJOSHADER_malloc malloc;
     MOJOSHADER_free free;
     void *malloc_data;
+    const char *current_file;
+    int current_position;
     ErrorList *errors;
     Preprocessor *preprocessor;
-    MOJOSHADER_parsePhase parse_phase;
     MOJOSHADER_shaderType shader_type;
     uint8 major_ver;
     uint8 minor_ver;
@@ -103,39 +104,16 @@
 } // FreeBridge
 
 
-// !!! FIXME: move the errpos calculation into Context, and we can move this
-// !!! FIXME:  to mojoshader_common.c
 static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
 static void failf(Context *ctx, const char *fmt, ...)
 {
-    const char *fname = NULL;
-    unsigned int linenum = 0;
-
     ctx->isfail = 1;
     if (ctx->out_of_memory)
         return;
 
-    int errpos = 0;
-    switch (ctx->parse_phase)
-    {
-        case MOJOSHADER_PARSEPHASE_NOTSTARTED:
-            errpos = -2;
-            break;
-        case MOJOSHADER_PARSEPHASE_WORKING:
-            fname = preprocessor_sourcepos(ctx->preprocessor, &linenum);
-            errpos = (int) linenum;
-            break;
-        case MOJOSHADER_PARSEPHASE_DONE:
-            errpos = -1;
-            break;
-        default:
-            assert(0 && "Unexpected value");
-            return;
-    } // switch
-
     va_list ap;
     va_start(ap, fmt);
-    errorlist_add_va(ctx->errors, fname, errpos, fmt, ap);
+    errorlist_add_va(ctx->errors, ctx->current_file, ctx->current_position, fmt, ap);
     va_end(ap);
 } // failf
 
@@ -197,14 +175,18 @@
 
             if (preprocessor_outofmemory(ctx->preprocessor))
             {
-                out_of_memory(ctx);
+                out_of_memory(ctx);  // !!! FIXME: this can go; we're bridged now!
                 ctx->tokenval = TOKEN_EOI;
                 ctx->token = NULL;
                 ctx->tokenlen = 0;
                 break;
             } // if
 
-            else if (ctx->tokenval == TOKEN_BAD_CHARS)
+            unsigned int line;
+            ctx->current_file = preprocessor_sourcepos(ctx->preprocessor,&line);
+            ctx->current_position = (int) line;
+
+            if (ctx->tokenval == TOKEN_BAD_CHARS)
             {
                 fail(ctx, "Bad characters in source file");
                 continue;
@@ -1436,7 +1418,7 @@
     ctx->malloc = m;
     ctx->free = f;
     ctx->malloc_data = d;
-    ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
+    ctx->current_position = MOJOSHADER_POSITION_BEFORE;
 
     const size_t outblk = sizeof (uint32) * 4 * 64; // 64 4-token instrs.
     ctx->output = buffer_create(outblk, MallocBridge, FreeBridge, ctx);
@@ -1642,7 +1624,10 @@
         return;
 
     // make error messages sane if CTAB fails, etc.
-    ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
+    const char *prev_fname = ctx->current_file;
+    const int prev_position = ctx->current_position;
+    ctx->current_file = NULL;
+    ctx->current_position = MOJOSHADER_POSITION_BEFORE;
 
     const char *creator = "MojoShader revision " MOJOSHADER_CHANGESET;
     if (symbol_count > 0)
@@ -1654,7 +1639,8 @@
     for (i = 0; i < comment_count; i++)
         output_comment_string(ctx, comments[i]);
 
-    ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING;
+    ctx->current_file = prev_fname;
+    ctx->current_position = prev_position;
 } // output_comments
 
 
@@ -1757,7 +1743,6 @@
         return &MOJOSHADER_out_of_mem_data;
 
     // Version token always comes first.
-    ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING;
     parse_version_token(ctx);
     output_comments(ctx, comments, comment_count, symbols, symbol_count);
 
@@ -1766,6 +1751,9 @@
     while ((token = nexttoken(ctx)) != TOKEN_EOI)
         parse_token(ctx, token);
 
+    ctx->current_file = NULL;
+    ctx->current_position = MOJOSHADER_POSITION_AFTER;
+
     output_token(ctx, 0x0000FFFF);   // end token always 0x0000FFFF.
 
     retval = build_final_assembly(ctx);
--- a/mojoshader_internal.h	Wed Nov 10 00:52:01 2010 -0500
+++ b/mojoshader_internal.h	Thu Nov 11 04:13:08 2010 -0500
@@ -392,12 +392,6 @@
     return 0;
 } // scalar_register
 
-typedef enum
-{
-    MOJOSHADER_PARSEPHASE_NOTSTARTED,
-    MOJOSHADER_PARSEPHASE_WORKING,
-    MOJOSHADER_PARSEPHASE_DONE,
-} MOJOSHADER_parsePhase;
 
 extern MOJOSHADER_error MOJOSHADER_out_of_mem_error;
 extern MOJOSHADER_parseData MOJOSHADER_out_of_mem_data;