mojoshader_preprocessor.c
changeset 755 6a7aa96c51c7
parent 754 d405cfa22392
child 798 5dd67cc04cf9
equal deleted inserted replaced
754:d405cfa22392 755:6a7aa96c51c7
   397     return (uint8) hash_string_djbxor(sym);
   397     return (uint8) hash_string_djbxor(sym);
   398 } // hash_define
   398 } // hash_define
   399 
   399 
   400 
   400 
   401 static int add_define(Context *ctx, const char *sym, const char *val,
   401 static int add_define(Context *ctx, const char *sym, const char *val,
   402                       char **parameters, unsigned int paramcount)
   402                       char **parameters, int paramcount)
   403 {
   403 {
   404     const uint8 hash = hash_define(sym);
   404     const uint8 hash = hash_define(sym);
   405     Define *bucket = ctx->define_hashtable[hash];
   405     Define *bucket = ctx->define_hashtable[hash];
   406     while (bucket)
   406     while (bucket)
   407     {
   407     {
   427 } // add_define
   427 } // add_define
   428 
   428 
   429 
   429 
   430 static void free_define(Context *ctx, Define *def)
   430 static void free_define(Context *ctx, Define *def)
   431 {
   431 {
   432     unsigned int i;
   432     int i;
   433     for (i = 0; i < def->paramcount; i++)
   433     for (i = 0; i < def->paramcount; i++)
   434         Free(ctx, (void *) def->parameters[i]);
   434         Free(ctx, (void *) def->parameters[i]);
   435     Free(ctx, (void *) def->parameters);
   435     Free(ctx, (void *) def->parameters);
   436     Free(ctx, (void *) def->identifier);
   436     Free(ctx, (void *) def->identifier);
   437     Free(ctx, (void *) def->definition);
   437     Free(ctx, (void *) def->definition);
   944 
   944 
   945 
   945 
   946 static void handle_pp_define(Context *ctx)
   946 static void handle_pp_define(Context *ctx)
   947 {
   947 {
   948     IncludeState *state = ctx->include_stack;
   948     IncludeState *state = ctx->include_stack;
   949     unsigned int i;
       
   950 
   949 
   951     if (lexer(state) != TOKEN_IDENTIFIER)
   950     if (lexer(state) != TOKEN_IDENTIFIER)
   952     {
   951     {
   953         fail(ctx, "Macro names must be identifiers");
   952         fail(ctx, "Macro names must be identifiers");
   954         return;
   953         return;
   971     // #define a(b) is different than #define a (b)    :(
   970     // #define a(b) is different than #define a (b)    :(
   972     state->report_whitespace = 1;
   971     state->report_whitespace = 1;
   973     lexer(state);
   972     lexer(state);
   974     state->report_whitespace = 0;
   973     state->report_whitespace = 0;
   975 
   974 
   976     unsigned int params = 0;
   975     int params = 0;
   977     char **idents = NULL;
   976     char **idents = NULL;
   978 
   977 
   979     if (state->tokenval == ((Token) ' '))
   978     if (state->tokenval == ((Token) ' '))
   980         lexer(state);  // skip it.
   979         lexer(state);  // skip it.
   981     else if (state->tokenval == ((Token) '('))
   980     else if (state->tokenval == ((Token) '('))
   995         {
   994         {
   996             fail(ctx, "syntax error in macro parameter list");
   995             fail(ctx, "syntax error in macro parameter list");
   997             goto handle_pp_define_failed;
   996             goto handle_pp_define_failed;
   998         } // if
   997         } // if
   999 
   998 
  1000         if (params > 0)
   999         if (params == 0)  // special case for void args: "#define a() b"
       
  1000             params = -1;
       
  1001         else
  1001         {
  1002         {
  1002             idents = (char **) Malloc(ctx, sizeof (char *) * params);
  1003             idents = (char **) Malloc(ctx, sizeof (char *) * params);
  1003             if (idents == NULL)
  1004             if (idents == NULL)
  1004                 goto handle_pp_define_failed;
  1005                 goto handle_pp_define_failed;
  1005         } // if
  1006 
  1006 
  1007             // roll all the way back, do it again.
  1007         // roll all the way back, do it again.
  1008             memcpy(state, &saved, sizeof (IncludeState));
  1008         memcpy(state, &saved, sizeof (IncludeState));
  1009             memset(idents, '\0', sizeof (char *) * params);
  1009         memset(idents, '\0', sizeof (char *) * params);
  1010 
  1010         
  1011             int i;
  1011         for (i = 0; i < params; i++)
  1012             for (i = 0; i < params; i++)
  1012         {
       
  1013             lexer(state);
       
  1014             assert(state->tokenval == TOKEN_IDENTIFIER);
       
  1015 
       
  1016             char *dst = (char *) Malloc(ctx, state->tokenlen+1);
       
  1017             if (dst == NULL)
       
  1018                 break;
       
  1019 
       
  1020             memcpy(dst, state->token, state->tokenlen);
       
  1021             dst[state->tokenlen] = '\0';
       
  1022             idents[i] = dst;
       
  1023 
       
  1024             if (i < (params-1))
       
  1025             {
  1013             {
  1026                 lexer(state);
  1014                 lexer(state);
  1027                 assert(state->tokenval == ((Token) ','));
  1015                 assert(state->tokenval == TOKEN_IDENTIFIER);
       
  1016 
       
  1017                 char *dst = (char *) Malloc(ctx, state->tokenlen+1);
       
  1018                 if (dst == NULL)
       
  1019                     break;
       
  1020 
       
  1021                 memcpy(dst, state->token, state->tokenlen);
       
  1022                 dst[state->tokenlen] = '\0';
       
  1023                 idents[i] = dst;
       
  1024 
       
  1025                 if (i < (params-1))
       
  1026                 {
       
  1027                     lexer(state);
       
  1028                     assert(state->tokenval == ((Token) ','));
       
  1029                 } // if
       
  1030             } // for
       
  1031 
       
  1032             if (i != params)
       
  1033             {
       
  1034                 assert(ctx->out_of_memory);
       
  1035                 goto handle_pp_define_failed;
  1028             } // if
  1036             } // if
  1029         } // for
  1037 
  1030 
  1038             lexer(state);
  1031         if (i != params)
  1039             assert(state->tokenval == ((Token) ')'));
  1032         {
  1040         } // else
  1033             assert(ctx->out_of_memory);
  1041 
  1034             goto handle_pp_define_failed;
       
  1035         } // if
       
  1036 
       
  1037         lexer(state);
       
  1038         assert(state->tokenval == ((Token) ')'));
       
  1039         lexer(state);
  1042         lexer(state);
  1040     } // else if
  1043     } // else if
  1041 
  1044 
  1042     pushback(state);
  1045     pushback(state);
  1043 
  1046 
  1096     return;
  1099     return;
  1097 
  1100 
  1098 handle_pp_define_failed:
  1101 handle_pp_define_failed:
  1099     Free(ctx, sym);
  1102     Free(ctx, sym);
  1100     Free(ctx, definition);
  1103     Free(ctx, definition);
  1101     for (i = 0; i < params; i++)
  1104     while (params--)
  1102         Free(ctx, idents[i]);
  1105         Free(ctx, idents[params]);
  1103     Free(ctx, idents);
  1106     Free(ctx, idents);
  1104 } // handle_pp_define
  1107 } // handle_pp_define
  1105 
  1108 
  1106 
  1109 
  1107 static void handle_pp_undef(Context *ctx)
  1110 static void handle_pp_undef(Context *ctx)
  1214     {
  1217     {
  1215         def = find_define(ctx, sym);
  1218         def = find_define(ctx, sym);
  1216         if (def == NULL)
  1219         if (def == NULL)
  1217             return 0;   // just send the token through unchanged.
  1220             return 0;   // just send the token through unchanged.
  1218 
  1221 
  1219         if (def->paramcount > 0)
  1222         if (def->paramcount != 0)
  1220         {
  1223         {
       
  1224             const int expected = (def->paramcount < 0) ? 0 : def->paramcount;
       
  1225             int saw_params = 0;
  1221             IncludeState saved;  // can't pushback, we need the original token.
  1226             IncludeState saved;  // can't pushback, we need the original token.
  1222             memcpy(&saved, state, sizeof (IncludeState));
  1227             memcpy(&saved, state, sizeof (IncludeState));
  1223             if (lexer(state) != ((Token) '('))
  1228             if (lexer(state) != ((Token) '('))
  1224             {
  1229             {
  1225                 memcpy(state, &saved, sizeof (IncludeState));
  1230                 memcpy(state, &saved, sizeof (IncludeState));
  1226                 return 0;  // gcc abandons replacement in this case, too.
  1231                 return 0;  // gcc abandons replacement in this case, too.
  1227             } // if
  1232             } // if
  1228 
  1233 
  1229             unsigned int i;
  1234             int void_call = 0;
  1230             for (i = 0; i < def->paramcount; i++)
  1235             int paren = 1;
       
  1236             while (paren > 0)
  1231             {
  1237             {
  1232                 const char *expr = state->source;
  1238                 const char *expr = NULL;
  1233                 const char *exprend = NULL;
  1239                 const char *exprend = NULL;
  1234                 int paren = 0;
  1240                 assert(!void_call);
  1235                 while (1)
  1241                 while (1)
  1236                 {
  1242                 {
  1237                     exprend = state->source;
  1243                     exprend = state->source;
  1238                     const Token t = lexer(state);
  1244                     const Token t = lexer(state);
  1239                     if (t == '(')
  1245                     if (t == '(')
  1240                         paren++;
  1246                         paren++;
  1241                     else if (t == ')')
  1247                     else if (t == ')')
  1242                     {
  1248                     {
  1243                         assert(paren >= 0);
  1249                         paren--;
  1244                         if (paren == 0)
  1250                         if (paren < 1)  // end of macro?
  1245                         {
       
  1246                             if (i != def->paramcount-1)
       
  1247                             {
       
  1248                                 fail(ctx, "Too few macro arguments");
       
  1249                                 goto handle_pp_identifier_failed;
       
  1250                             } // if
       
  1251                             break;
  1251                             break;
  1252                         } // if
       
  1253 
       
  1254                         paren--;
       
  1255                     } // else if
  1252                     } // else if
  1256                     else if (t == ',')
  1253                     else if (t == ',')
  1257                     {
  1254                     {
  1258                         if (paren == 0)
  1255                         if (paren == 1)  // new macro arg?
  1259                             break;
  1256                             break;
  1260                     } // else if
  1257                     } // else if
  1261                     else if ((t == TOKEN_INCOMPLETE_COMMENT) || (t == TOKEN_EOI))
  1258                     else if ((t == TOKEN_INCOMPLETE_COMMENT) || (t == TOKEN_EOI))
  1262                     {
  1259                     {
  1263                         pushback(state);
  1260                         pushback(state);
  1264                         fail(ctx, "Unterminated macro list");
  1261                         fail(ctx, "Unterminated macro list");
  1265                         goto handle_pp_identifier_failed;
  1262                         goto handle_pp_identifier_failed;
  1266                     } // else if
  1263                     } // else if
       
  1264 
       
  1265                     if (expr == NULL)
       
  1266                         expr = state->token;
  1267                 } // while
  1267                 } // while
  1268 
  1268 
  1269                 Define *p = get_define(ctx);
  1269                 if (expr == NULL)
  1270                 if (p == NULL)
  1270                 {
  1271                     goto handle_pp_identifier_failed;
  1271                     expr = exprend = "";
  1272 
  1272                     void_call = ((saw_params == 0) && (paren == 0));
  1273                 p->next = params;
  1273                 } // if
  1274                 params = p;
  1274 
  1275 
  1275                 if (saw_params < expected)
  1276                 const unsigned int exprlen = (unsigned int) (exprend - expr);
  1276                 {
  1277                 char *definition = (char *) Malloc(ctx, exprlen + 1);
  1277                     Define *p = get_define(ctx);
  1278                 if (definition == NULL)
  1278                     if (p == NULL)
  1279                     goto handle_pp_identifier_failed;
  1279                         goto handle_pp_identifier_failed;
  1280                 memcpy(definition, expr, exprlen);
  1280 
  1281                 definition[exprlen] = '\0';
  1281                     p->next = params;
  1282                 p->identifier = def->parameters[i];
  1282                     params = p;
  1283                 p->definition = definition;
  1283 
  1284             } // for
  1284                     const unsigned int exprlen = (unsigned int) (exprend - expr);
       
  1285                     char *definition = (char *) Malloc(ctx, exprlen + 1);
       
  1286                     if (definition == NULL)
       
  1287                         goto handle_pp_identifier_failed;
       
  1288                     memcpy(definition, expr, exprlen);
       
  1289                     definition[exprlen] = '\0';
       
  1290                     p->identifier = def->parameters[saw_params];
       
  1291                     p->definition = definition;
       
  1292                 } // if
       
  1293 
       
  1294                 saw_params++;
       
  1295             } // while
       
  1296             assert(paren == 0);  // make sure it's not negative.
       
  1297 
       
  1298             // "a()" should match "#define a()" ...
       
  1299             if ((expected == 0) && (saw_params == 1) && (void_call))
       
  1300             {
       
  1301                 assert(params == NULL);
       
  1302                 saw_params = 0;
       
  1303             } // if
       
  1304 
       
  1305             if (saw_params != expected)
       
  1306             {
       
  1307                 failf(ctx, "macro '%s' passed %d arguments, but requires %d",
       
  1308                       sym, saw_params, expected);
       
  1309                 goto handle_pp_identifier_failed;
       
  1310             } // if
  1285         } // if
  1311         } // if
  1286     } // if
  1312     } // if
  1287 
  1313 
  1288     const char *val = def->definition;
  1314     const char *val = def->definition;
  1289     const size_t vallen = strlen(val);
  1315     const size_t vallen = strlen(val);