mojoshader_preprocessor.c
changeset 865 4eb06464212d
parent 864 aa3bec973a21
child 867 f5f491d2b82b
equal deleted inserted replaced
864:aa3bec973a21 865:4eb06464212d
   144         TOKENCASE(TOKEN_OROR);
   144         TOKENCASE(TOKEN_OROR);
   145         TOKENCASE(TOKEN_LEQ);
   145         TOKENCASE(TOKEN_LEQ);
   146         TOKENCASE(TOKEN_GEQ);
   146         TOKENCASE(TOKEN_GEQ);
   147         TOKENCASE(TOKEN_EQL);
   147         TOKENCASE(TOKEN_EQL);
   148         TOKENCASE(TOKEN_NEQ);
   148         TOKENCASE(TOKEN_NEQ);
       
   149         TOKENCASE(TOKEN_HASH);
   149         TOKENCASE(TOKEN_HASHHASH);
   150         TOKENCASE(TOKEN_HASHHASH);
   150         TOKENCASE(TOKEN_PP_INCLUDE);
   151         TOKENCASE(TOKEN_PP_INCLUDE);
   151         TOKENCASE(TOKEN_PP_LINE);
   152         TOKENCASE(TOKEN_PP_LINE);
   152         TOKENCASE(TOKEN_PP_DEFINE);
   153         TOKENCASE(TOKEN_PP_DEFINE);
   153         TOKENCASE(TOKEN_PP_UNDEF);
   154         TOKENCASE(TOKEN_PP_UNDEF);
   531 } // put_all_defines
   532 } // put_all_defines
   532 
   533 
   533 
   534 
   534 static int push_source(Context *ctx, const char *fname, const char *source,
   535 static int push_source(Context *ctx, const char *fname, const char *source,
   535                        unsigned int srclen, unsigned int linenum,
   536                        unsigned int srclen, unsigned int linenum,
   536                        MOJOSHADER_includeClose close_callback, Define *defs)
   537                        MOJOSHADER_includeClose close_callback, Define *defs,
       
   538                        const int is_macro)
   537 {
   539 {
   538     if (srclen == 0)
   540     if (srclen == 0)
   539         return 1;  // nothing to do: just pretend you did it.
   541         return 1;  // nothing to do: just pretend you did it.
   540 
   542 
   541     IncludeState *state = get_include(ctx);
   543     IncludeState *state = get_include(ctx);
   562     state->bytes_left = srclen;
   564     state->bytes_left = srclen;
   563     state->line = linenum;
   565     state->line = linenum;
   564     state->defines = defs;
   566     state->defines = defs;
   565     state->next = ctx->include_stack;
   567     state->next = ctx->include_stack;
   566     state->asm_comments = ctx->asm_comments;
   568     state->asm_comments = ctx->asm_comments;
       
   569     state->is_macro = is_macro;
   567 
   570 
   568     print_debug_lexing_position(state);
   571     print_debug_lexing_position(state);
   569 
   572 
   570     ctx->include_stack = state;
   573     ctx->include_stack = state;
   571 
   574 
   679                                defines[i].definition);
   682                                defines[i].definition);
   680             } // for
   683             } // for
   681         } // else
   684         } // else
   682     } // if
   685     } // if
   683 
   686 
   684     if ((okay) && (!push_source(ctx, fname, source, sourcelen, 1, NULL, NULL)))
   687     if ((okay) && (!push_source(ctx,fname,source,sourcelen,1,NULL,NULL,0)))
   685         okay = 0;
   688         okay = 0;
   686 
   689 
   687     if ((okay) && (define_include != NULL))
   690     if ((okay) && (define_include != NULL))
   688     {
   691     {
   689         okay = push_source(ctx, "<predefined macros>", define_include,
   692         okay = push_source(ctx, "<predefined macros>", define_include,
   690                            define_include_len, 1, close_define_include, NULL);
   693                            define_include_len, 1, close_define_include,
       
   694                            NULL, 0);
   691     } // if
   695     } // if
   692 
   696 
   693     if (!okay)
   697     if (!okay)
   694     {
   698     {
   695         preprocessor_end((Preprocessor *) ctx);
   699         preprocessor_end((Preprocessor *) ctx);
   835         fail(ctx, "Include callback failed");  // !!! FIXME: better error
   839         fail(ctx, "Include callback failed");  // !!! FIXME: better error
   836         return;
   840         return;
   837     } // if
   841     } // if
   838 
   842 
   839     MOJOSHADER_includeClose callback = ctx->close_callback;
   843     MOJOSHADER_includeClose callback = ctx->close_callback;
   840     if (!push_source(ctx, filename, newdata, newbytes, 1, callback, NULL))
   844     if (!push_source(ctx, filename, newdata, newbytes, 1, callback, NULL, 0))
   841     {
   845     {
   842         assert(ctx->out_of_memory);
   846         assert(ctx->out_of_memory);
   843         ctx->close_callback(newdata, ctx->malloc, ctx->free, ctx->malloc_data);
   847         ctx->close_callback(newdata, ctx->malloc, ctx->free, ctx->malloc_data);
   844     } // if
   848     } // if
   845 } // handle_pp_include
   849 } // handle_pp_include
  1218     } // if
  1222     } // if
  1219 
  1223 
  1220     const char *fname = NULL;
  1224     const char *fname = NULL;
  1221     const char *val = NULL;
  1225     const char *val = NULL;
  1222     size_t vallen = 0;
  1226     size_t vallen = 0;
  1223 
  1227     int is_macro = 0;
  1224     IncludeState *state = ctx->include_stack;
  1228     IncludeState *state = ctx->include_stack;
  1225     char *sym = (char *) alloca(state->tokenlen+1);
  1229     char *sym = (char *) alloca(state->tokenlen+1);
  1226     memcpy(sym, state->token, state->tokenlen);
  1230     memcpy(sym, state->token, state->tokenlen);
  1227     sym[state->tokenlen] = '\0';
  1231     sym[state->tokenlen] = '\0';
  1228 
  1232 
  1241     if (def == NULL)
  1245     if (def == NULL)
  1242     {
  1246     {
  1243         def = find_define(ctx, sym);
  1247         def = find_define(ctx, sym);
  1244         if (def == NULL)
  1248         if (def == NULL)
  1245             return 0;   // just send the token through unchanged.
  1249             return 0;   // just send the token through unchanged.
       
  1250 
       
  1251         is_macro = 1;
  1246 
  1252 
  1247         if (def->paramcount != 0)
  1253         if (def->paramcount != 0)
  1248         {
  1254         {
  1249             const int expected = (def->paramcount < 0) ? 0 : def->paramcount;
  1255             const int expected = (def->paramcount < 0) ? 0 : def->paramcount;
  1250             int saw_params = 0;
  1256             int saw_params = 0;
  1337     } // if
  1343     } // if
  1338 
  1344 
  1339     val = def->definition;
  1345     val = def->definition;
  1340     vallen = strlen(val);
  1346     vallen = strlen(val);
  1341     fname = state->filename;
  1347     fname = state->filename;
  1342     if (!push_source(ctx, fname, val, vallen, state->line, NULL, params))
  1348     if (!push_source(ctx,fname,val,vallen,state->line,NULL,params,is_macro))
  1343     {
  1349     {
  1344         assert(ctx->out_of_memory);
  1350         assert(ctx->out_of_memory);
  1345         goto handle_pp_identifier_failed;
  1351         goto handle_pp_identifier_failed;
  1346     } // if
  1352     } // if
  1347 
  1353 
  1765         put_conditional(ctx, cond);
  1771         put_conditional(ctx, cond);
  1766     } // else
  1772     } // else
  1767 } // handle_pp_endif
  1773 } // handle_pp_endif
  1768 
  1774 
  1769 
  1775 
       
  1776 static void handle_pp_stringify(Context *ctx)
       
  1777 {
       
  1778     IncludeState *state = ctx->include_stack;
       
  1779     const Define *def = NULL;
       
  1780 
       
  1781     assert(state->is_macro);
       
  1782 
       
  1783     if (lexer(state) == TOKEN_IDENTIFIER)
       
  1784     {
       
  1785         char *sym = (char *) alloca(state->tokenlen+1);
       
  1786         memcpy(sym, state->token, state->tokenlen);
       
  1787         sym[state->tokenlen] = '\0';
       
  1788 
       
  1789         for (def = state->defines; def != NULL; def = def->next)
       
  1790         {
       
  1791             assert(def->paramcount == 0);  // args can't have args!
       
  1792             if (strcmp(def->identifier, sym) == 0)
       
  1793                 break;
       
  1794         } // while
       
  1795     } // if
       
  1796 
       
  1797     if (def == NULL)
       
  1798     {
       
  1799         pushback(state);
       
  1800         fail(ctx, "'#' is not followed by a macro parameter");
       
  1801         return;  // we just fail(), drop the '#' token and continue on.
       
  1802     } // if
       
  1803 
       
  1804     const size_t deflen = strlen(def->definition);
       
  1805     char *litstring = (char *) Malloc(ctx, deflen + 2);
       
  1806     if (!litstring)
       
  1807         return;
       
  1808 
       
  1809     litstring[0] = '\"';
       
  1810     memcpy(litstring + 1, def->definition, deflen);
       
  1811     litstring[deflen + 1] = '\"';
       
  1812     const char *filename = state->filename;
       
  1813     push_source(ctx, filename, litstring, deflen + 2, state->line,
       
  1814                 close_define_include, NULL, 0);
       
  1815 } // handle_pp_stringify
       
  1816 
       
  1817 
  1770 static void unterminated_pp_condition(Context *ctx)
  1818 static void unterminated_pp_condition(Context *ctx)
  1771 {
  1819 {
  1772     IncludeState *state = ctx->include_stack;
  1820     IncludeState *state = ctx->include_stack;
  1773     Conditional *cond = state->conditional_stack;
  1821     Conditional *cond = state->conditional_stack;
  1774 
  1822 
  1814         } // if
  1862         } // if
  1815 
  1863 
  1816         const Conditional *cond = state->conditional_stack;
  1864         const Conditional *cond = state->conditional_stack;
  1817         const int skipping = ((cond != NULL) && (cond->skipping));
  1865         const int skipping = ((cond != NULL) && (cond->skipping));
  1818 
  1866 
  1819         Token token = lexer(state);
  1867         const Token token = lexer(state);
  1820 
  1868 
  1821         if (token != TOKEN_IDENTIFIER)
  1869         if (token != TOKEN_IDENTIFIER)
  1822             ctx->recursion_count = 0;
  1870             ctx->recursion_count = 0;
  1823 
  1871 
  1824         if (token == TOKEN_EOI)
  1872         if (token == TOKEN_EOI)
  1906 
  1954 
  1907         else if (token == TOKEN_PP_UNDEF)
  1955         else if (token == TOKEN_PP_UNDEF)
  1908         {
  1956         {
  1909             handle_pp_undef(ctx);
  1957             handle_pp_undef(ctx);
  1910             continue;  // will return at top of loop.
  1958             continue;  // will return at top of loop.
       
  1959         } // else if
       
  1960 
       
  1961         // stringify operator ("#") ... only during macro replacement.
       
  1962         else if ((token == TOKEN_HASH) && (state->is_macro))
       
  1963         {
       
  1964             handle_pp_stringify(ctx);
       
  1965             continue;
  1911         } // else if
  1966         } // else if
  1912 
  1967 
  1913         else if (token == TOKEN_IDENTIFIER)
  1968         else if (token == TOKEN_IDENTIFIER)
  1914         {
  1969         {
  1915             if (handle_pp_identifier(ctx))
  1970             if (handle_pp_identifier(ctx))