Allow errors to specify post-processing problems.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 19 Dec 2008 00:05:20 -0500
changeset 523 699696afd731
parent 522 3c08f4d2aa2e
child 524 03eea2f0762c
Allow errors to specify post-processing problems. This can happen if the entire shader is valid but we have a problem when parsing uniforms, etc.
mojoshader.c
mojoshader.h
mojoshader_assembler.c
mojoshader_internal.h
--- a/mojoshader.c	Sun Dec 14 16:27:40 2008 -0500
+++ b/mojoshader.c	Fri Dec 19 00:05:20 2008 -0500
@@ -164,7 +164,7 @@
     const uint32 *orig_tokens;
     const uint32 *tokens;
     uint32 tokencount;
-    int started_parsing;
+    MOJOSHADER_parsePhase parse_phase;
     const MOJOSHADER_swizzle *swizzles;
     unsigned int swizzles_count;
     OutputList *output;
@@ -6712,6 +6712,7 @@
     ctx->ignore.tail = &ctx->ignore.head;
     ctx->output = &ctx->mainline;
     ctx->last_address_reg_component = -1;
+    ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
 
     const int profileid = find_profile_id(profile);
     ctx->profileid = profileid;
@@ -7155,16 +7156,25 @@
             Free(ctx, samplers);
         } // if
 
-        if (ctx->started_parsing)
-            retval->error_position = (ctx->tokens - ctx->orig_tokens) * sizeof (uint32);
-        else
-            retval->error_position = -1;
+        switch (ctx->parse_phase)
+        {
+            case MOJOSHADER_PARSEPHASE_NOTSTARTED:
+                retval->error_position = -2;
+                break;
+            case MOJOSHADER_PARSEPHASE_WORKING:
+                retval->error_position = (ctx->tokens - ctx->orig_tokens) * sizeof (uint32);
+                break;
+            case MOJOSHADER_PARSEPHASE_DONE:
+                retval->error_position = -1;
+                break;
+        } // switch
+
         retval->error = ctx->failstr;  // we recycle.  :)
         ctx->failstr = NULL;  // don't let this get free()'d too soon.
     } // if
     else
     {
-        retval->error_position = -2;
+        retval->error_position = -3;
         retval->profile = ctx->profile->name;
         retval->output = output;
         retval->output_len = ctx->output_len;
@@ -7375,7 +7385,7 @@
     // Version token always comes first.
     if (!isfail(ctx))
     {
-        ctx->started_parsing = 1;
+        ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING;
         rc = parse_version_token(ctx, profile);
     } // if
 
@@ -7396,7 +7406,10 @@
     } // while
 
     if (!isfail(ctx))
+    {
+        ctx->parse_phase = MOJOSHADER_PARSEPHASE_DONE;
         process_definitions(ctx);
+    } // if
 
     if (!isfail(ctx))
         ctx->profile->finalize_emitter(ctx);
--- a/mojoshader.h	Sun Dec 14 16:27:40 2008 -0500
+++ b/mojoshader.h	Fri Dec 19 00:05:20 2008 -0500
@@ -251,9 +251,10 @@
      */
     const char *error;
 
-    /* !!! FIXME: needs a -3 for post-processing.
-     * Position of error, if there is one. Will be -2 if there was no
-     *  error, and -1 if there was an error before processing started. If >= 0,
+    /*
+     * 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).
--- a/mojoshader_assembler.c	Sun Dec 14 16:27:40 2008 -0500
+++ b/mojoshader_assembler.c	Fri Dec 19 00:05:20 2008 -0500
@@ -35,7 +35,7 @@
     void *malloc_data;
     const char *failstr;
     TokenizerContext tctx;
-    int started_parsing;
+    MOJOSHADER_parsePhase parse_phase;
     MOJOSHADER_shaderType shader_type;
     uint8 major_ver;
     uint8 minor_ver;
@@ -1620,6 +1620,7 @@
     ctx->malloc = m;
     ctx->free = f;
     ctx->malloc_data = d;
+    ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
     ctx->tctx.source = source;
     ctx->tctx.linenum = 1;
 
@@ -1661,15 +1662,138 @@
     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->tctx.linenum;
-    else
-        retval->error_position = -1;
+    switch (ctx->parse_phase)
+    {
+        case MOJOSHADER_PARSEPHASE_NOTSTARTED:
+            retval->error_position = -2;
+            break;
+        case MOJOSHADER_PARSEPHASE_WORKING:
+            retval->error_position = ctx->tctx.linenum;
+            break;
+        case MOJOSHADER_PARSEPHASE_DONE:
+            retval->error_position = -1;
+            break;
+    } // switch
 
     return retval;
 } // build_failed_assembly
 
 
+typedef struct CTabTypeInfo
+{
+    uint16 parameter_class;
+    uint16 parameter_type;
+    uint16 rows;
+    uint16 columns;
+    uint16 elements;
+    uint16 structMembers;
+    uint32 structMemberInfo;
+} CTabTypeInfo;
+
+
+FUCK THIS CODE.
+static void output_ctab(Context *ctx, const MOJOSHADER_symbol *symbols,
+                        unsigned int symbol_count)
+{
+    if (symbol_count == 0)
+        return;
+
+    unsigned int i;
+    uint8 *bytes = NULL;
+    const char *creator = "MojoShader revision " MOJOSHADER_CHANGESET;
+    const size_t creatorlen = strlen(creator) + 1;
+    add_ctab_bytes(ctx, &bytes, &offset, creator, creatorlen);
+    add_ctab_bytes(ctx, &bytes, &offset, "", 1);  // !!! FIXME: target
+
+    // build all the unique D3DXSHADER_TYPEINFO structs into the bytes.
+    CTabTypeInfo *tinfo;
+    tinfo = (CTabTypeInfo *) Malloc(sizeof (CTabTypeInfo) * symbol_count);
+    if (tinfo == NULL)
+    {
+        Free(ctx, bytes);
+        return;
+    } // if
+
+    for (i = 0; i < symbol_count; i++)
+    {
+        // !!! FIXME: struct packing!
+        tinfo[i].parameter_class = SWAP16(symbols[i].parameter_class);
+        tinfo[i].parameter_type = SWAP16(symbols[i].parameter_type);
+        tinfo[i].rows = SWAP16(symbols[i].rows);
+        tinfo[i].columns = SWAP16(symbols[i].columns);
+        tinfo[i].elements = SWAP16(symbols[i].elements);
+        tinfo[i].structMembers = SWAP16(symbols[i].structMembers);
+        tinfo[i].structMembersInfo = SWAP32(0);  // !!! FIXME: points to DWORD name, DWORD typeinfo
+        add_ctab_bytes(ctx, &bytes, &offset, &tinfo[i], sizeof (tinfo[i]));
+    } // for
+
+
+    uint8 ctab = sdfkjsldkfjsdlkf;
+    uint32 *table = (uint32 *) ctab;
+    uint32 offset = CTAB_SIZE + (CINFO_SIZE * symbol_count);
+    uint8 *data = ctab + offset + sizeof (uint32);
+    union { uint8 *ui8; uint16 *ui16; uint32 *ui32; } info;
+    info.ui8 = ctab + CTAB_SIZE + sizeof (uint32);
+
+    *(table++) = SWAP32(CTAB_ID);
+    *(table++) = SWAP32(28);
+    *(table++) = SWAP32(find_ctab_bytes(ctx, bytes, creator, creatorlen));
+    *(table++) = SWAP32(ctx->version_token);
+    *(table++) = SWAP32(((uint32) symbol_count));
+    *(table++) = SWAP32(CTAB_SIZE);  // info array right after table.
+    *(table++) = SWAP32(0);
+    *(table++) = SWAP32(find_ctab_bytes(ctx, bytes, "", 1));  // !!! FIXME: target?
+
+    assert( ((uint8 *) table) == info.ui8 );
+    for (i = 0; i < symbol_count; i++)
+    {
+        const char *name = symbols[i].name;
+        const size_t namelen = strlen(symbols[i].name) + 1;
+        add_ctab_bytes(bytes, &offset, name, namelen);
+        *(info.ui32++) = SWAP32(add_ctab_string(ctx, &data, &offset, symbols[i].name));
+        *(info.ui16++) = SWAP16((uint16) symbols[i].register_set);
+        *(info.ui16++) = SWAP16((uint16) symbols[i].register_index);
+        *(info.ui16++) = SWAP16((uint16) symbols[i].register_count);
+        *(info.ui16++) = SWAP16(0);  // reserved
+
+    MOJOSHADER_symbolClass parameter_class;
+    MOJOSHADER_symbolType parameter_type;
+    unsigned int rows;
+    unsigned int columns;
+    unsigned int elements;
+    unsigned int structMembers;
+    unsigned int bytes;
+    void *default_value;
+
+    } // for
+
+    assert( info.ui8 == origdata);
+
+    output_comment_bytes(ctx, ctab, (size_t) (ptr - ctab));
+} // output_ctab
+
+
+static void output_comments(Context *ctx, const char **comments,
+                            unsigned int comment_count,
+                            const MOJOSHADER_symbol *symbols,
+                            unsigned int symbol_count)
+{
+    if (isfail(ctx))
+        return;
+
+    // make error messages sane if CTAB fails, etc.
+    ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
+
+    output_ctab(ctx, symbols, symbol_count);
+
+    int i;
+    for (i = 0; i < comment_count; i++)
+        output_comment_string(ctx, comments[i]);
+
+    if (!isfail(ctx))
+        ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING;
+} // output_comments
+
 
 // API entry point...
 
@@ -1687,7 +1811,7 @@
         return &out_of_mem_data;
 
     // Version token always comes first.
-    ctx->started_parsing = 1;
+    ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING;
     parse_version_token(ctx);
 
     ctx->started_parsing = 0;  // make error messages sane if CTAB fails, etc.
@@ -1698,8 +1822,6 @@
 
     // !!! 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);
--- a/mojoshader_internal.h	Sun Dec 14 16:27:40 2008 -0500
+++ b/mojoshader_internal.h	Fri Dec 19 00:05:20 2008 -0500
@@ -256,6 +256,13 @@
     return 0;
 } // scalar_register
 
+typedef enum
+{
+    MOJOSHADER_PARSEPHASE_NOTSTARTED,
+    MOJOSHADER_PARSEPHASE_WORKING,
+    MOJOSHADER_PARSEPHASE_DONE,
+} MOJOSHADER_parsePhase;
+
 extern MOJOSHADER_parseData out_of_mem_data;
 extern const char *out_of_mem_str;