mojoshader_preprocessor.c
changeset 894 1847405a16c6
parent 882 dd526bab5a51
child 895 a2aacb5796bc
equal deleted inserted replaced
893:e9f0f2feeb39 894:1847405a16c6
   453     bucket = get_define(ctx);
   453     bucket = get_define(ctx);
   454     if (bucket == NULL)
   454     if (bucket == NULL)
   455         return 0;
   455         return 0;
   456 
   456 
   457     bucket->definition = val;
   457     bucket->definition = val;
       
   458     bucket->original = NULL;
   458     bucket->identifier = sym;
   459     bucket->identifier = sym;
   459     bucket->parameters = (const char **) parameters;
   460     bucket->parameters = (const char **) parameters;
   460     bucket->paramcount = paramcount;
   461     bucket->paramcount = paramcount;
   461     bucket->next = ctx->define_hashtable[hash];
   462     bucket->next = ctx->define_hashtable[hash];
   462     ctx->define_hashtable[hash] = bucket;
   463     ctx->define_hashtable[hash] = bucket;
   470     for (i = 0; i < def->paramcount; i++)
   471     for (i = 0; i < def->paramcount; i++)
   471         Free(ctx, (void *) def->parameters[i]);
   472         Free(ctx, (void *) def->parameters[i]);
   472     Free(ctx, (void *) def->parameters);
   473     Free(ctx, (void *) def->parameters);
   473     Free(ctx, (void *) def->identifier);
   474     Free(ctx, (void *) def->identifier);
   474     Free(ctx, (void *) def->definition);
   475     Free(ctx, (void *) def->definition);
       
   476     Free(ctx, (void *) def->original);
   475     put_define(ctx, def);
   477     put_define(ctx, def);
   476 } // free_define
   478 } // free_define
   477 
   479 
   478 
   480 
   479 static int remove_define(Context *ctx, const char *sym)
   481 static int remove_define(Context *ctx, const char *sym)
   523     sym[state->tokenlen] = '\0';
   525     sym[state->tokenlen] = '\0';
   524     return find_define(ctx, sym);
   526     return find_define(ctx, sym);
   525 } // find_define_by_token
   527 } // find_define_by_token
   526 
   528 
   527 
   529 
   528 static const Define *find_macro_arg(const IncludeState *state)
   530 static const Define *find_macro_arg(const IncludeState *state,
       
   531                                     const Define *defines)
   529 {
   532 {
   530     const Define *def = NULL;
   533     const Define *def = NULL;
   531     char *sym = (char *) alloca(state->tokenlen + 1);
   534     char *sym = (char *) alloca(state->tokenlen + 1);
   532     memcpy(sym, state->token, state->tokenlen);
   535     memcpy(sym, state->token, state->tokenlen);
   533     sym[state->tokenlen] = '\0';
   536     sym[state->tokenlen] = '\0';
   534 
   537 
   535     for (def = state->defines; def != NULL; def = def->next)
   538     for (def = defines; def != NULL; def = def->next)
   536     {
   539     {
   537         assert(def->parameters == NULL);  // args can't have args!
   540         assert(def->parameters == NULL);  // args can't have args!
   538         assert(def->paramcount == 0);  // args can't have args!
   541         assert(def->paramcount == 0);  // args can't have args!
   539         if (strcmp(def->identifier, sym) == 0)
   542         if (strcmp(def->identifier, sym) == 0)
   540             break;
   543             break;
   561 } // put_all_defines
   564 } // put_all_defines
   562 
   565 
   563 
   566 
   564 static int push_source(Context *ctx, const char *fname, const char *source,
   567 static int push_source(Context *ctx, const char *fname, const char *source,
   565                        unsigned int srclen, unsigned int linenum,
   568                        unsigned int srclen, unsigned int linenum,
   566                        MOJOSHADER_includeClose close_callback, Define *defs,
   569                        MOJOSHADER_includeClose close_callback)
   567                        const int is_macro)
       
   568 {
   570 {
   569     if (srclen == 0)
   571     if (srclen == 0)
   570         return 1;  // nothing to do: just pretend you did it.
   572         return 1;  // nothing to do: just pretend you did it.
   571 
   573 
   572     IncludeState *state = get_include(ctx);
   574     IncludeState *state = get_include(ctx);
   590     state->token = source;
   592     state->token = source;
   591     state->tokenval = ((Token) '\n');
   593     state->tokenval = ((Token) '\n');
   592     state->orig_length = srclen;
   594     state->orig_length = srclen;
   593     state->bytes_left = srclen;
   595     state->bytes_left = srclen;
   594     state->line = linenum;
   596     state->line = linenum;
   595     state->defines = defs;
       
   596     state->next = ctx->include_stack;
   597     state->next = ctx->include_stack;
   597     state->asm_comments = ctx->asm_comments;
   598     state->asm_comments = ctx->asm_comments;
   598     state->is_macro = is_macro;
       
   599 
   599 
   600     print_debug_lexing_position(state);
   600     print_debug_lexing_position(state);
   601 
   601 
   602     ctx->include_stack = state;
   602     ctx->include_stack = state;
   603 
   603 
   623     while (cond)
   623     while (cond)
   624     {
   624     {
   625         Conditional *next = cond->next;
   625         Conditional *next = cond->next;
   626         put_conditional(ctx, cond);
   626         put_conditional(ctx, cond);
   627         cond = next;
   627         cond = next;
   628     } // while
       
   629 
       
   630     Define *def = state->defines;
       
   631     while (def)
       
   632     {
       
   633         Define *next = def->next;
       
   634         def->identifier = NULL;  // we reuse an allocation here, don't free!
       
   635         assert(def->parameters == NULL);
       
   636         assert(def->paramcount == 0);
       
   637         free_define(ctx, def);
       
   638         def = next;
       
   639     } // while
   628     } // while
   640 
   629 
   641     ctx->include_stack = state->next;
   630     ctx->include_stack = state->next;
   642 
   631 
   643     print_debug_lexing_position(ctx->include_stack);
   632     print_debug_lexing_position(ctx->include_stack);
   713                                defines[i].definition);
   702                                defines[i].definition);
   714             } // for
   703             } // for
   715         } // else
   704         } // else
   716     } // if
   705     } // if
   717 
   706 
   718     if ((okay) && (!push_source(ctx,fname,source,sourcelen,1,NULL,NULL,0)))
   707     if ((okay) && (!push_source(ctx,fname,source,sourcelen,1,NULL)))
   719         okay = 0;
   708         okay = 0;
   720 
   709 
   721     if ((okay) && (define_include != NULL))
   710     if ((okay) && (define_include != NULL))
   722     {
   711     {
   723         okay = push_source(ctx, "<predefined macros>", define_include,
   712         okay = push_source(ctx, "<predefined macros>", define_include,
   724                            define_include_len, 1, close_define_include,
   713                            define_include_len, 1, close_define_include);
   725                            NULL, 0);
       
   726     } // if
   714     } // if
   727 
   715 
   728     if (!okay)
   716     if (!okay)
   729     {
   717     {
   730         preprocessor_end((Preprocessor *) ctx);
   718         preprocessor_end((Preprocessor *) ctx);
   870         fail(ctx, "Include callback failed");  // !!! FIXME: better error
   858         fail(ctx, "Include callback failed");  // !!! FIXME: better error
   871         return;
   859         return;
   872     } // if
   860     } // if
   873 
   861 
   874     MOJOSHADER_includeClose callback = ctx->close_callback;
   862     MOJOSHADER_includeClose callback = ctx->close_callback;
   875     if (!push_source(ctx, filename, newdata, newbytes, 1, callback, NULL, 0))
   863     if (!push_source(ctx, filename, newdata, newbytes, 1, callback))
   876     {
   864     {
   877         assert(ctx->out_of_memory);
   865         assert(ctx->out_of_memory);
   878         ctx->close_callback(newdata, ctx->malloc, ctx->free, ctx->malloc_data);
   866         ctx->close_callback(newdata, ctx->malloc, ctx->free, ctx->malloc_data);
   879     } // if
   867     } // if
   880 } // handle_pp_include
   868 } // handle_pp_include
   953             case TOKEN_EOI:
   941             case TOKEN_EOI:
   954                 pushback(state);  // move back so we catch this later.
   942                 pushback(state);  // move back so we catch this later.
   955                 done = 1;
   943                 done = 1;
   956                 break;
   944                 break;
   957 
   945 
   958             case ' ':
   946             case ((Token) ' '):
   959                 if (!avail)
   947                 if (!avail)
   960                     break;
   948                     break;
   961                 *(ptr++) = ' ';
   949                 *(ptr++) = ' ';
   962                 avail--;
   950                 avail--;
   963                 break;
   951                 break;
  1278 {
  1266 {
  1279     _handle_pp_ifdef(ctx, TOKEN_PP_IFNDEF);
  1267     _handle_pp_ifdef(ctx, TOKEN_PP_IFNDEF);
  1280 } // handle_pp_ifndef
  1268 } // handle_pp_ifndef
  1281 
  1269 
  1282 
  1270 
       
  1271 static int replace_and_push_macro(Context *ctx, const Define *def,
       
  1272                                   const Define *params)
       
  1273 {
       
  1274     char *final = NULL;
       
  1275     MOJOSHADER_malloc m = ctx->malloc;
       
  1276     MOJOSHADER_free f = ctx->free;
       
  1277     void *d = ctx->malloc_data;
       
  1278 
       
  1279     // We push the #define and lex it, building a buffer with argument
       
  1280     //  replacement, stringification, and concatenation.
       
  1281     IncludeState *state = ctx->include_stack;
       
  1282     if (!push_source(ctx, state->filename, def->definition,
       
  1283                      strlen(def->definition), state->line, NULL))
       
  1284         return 0;
       
  1285 
       
  1286     Buffer buffer;
       
  1287     init_buffer(&buffer);
       
  1288 
       
  1289     state = ctx->include_stack;
       
  1290     while (lexer(state) != TOKEN_EOI)
       
  1291     {
       
  1292         int wantorig = 0;
       
  1293         const Define *arg = NULL;
       
  1294 
       
  1295         // put a space between tokens if we're not concatenating.
       
  1296         if (state->tokenval == TOKEN_HASHHASH)  // concatenate?
       
  1297         {
       
  1298             wantorig = 1;
       
  1299             lexer(state);
       
  1300             assert(state->tokenval != TOKEN_EOI);
       
  1301         } // if
       
  1302         else
       
  1303         {
       
  1304             if (buffer.total_bytes > 0)
       
  1305             {
       
  1306                 if (!add_to_buffer(&buffer, " ", 1, m, d))
       
  1307                     goto replace_and_push_macro_failed;
       
  1308             } // if
       
  1309         } // else
       
  1310 
       
  1311         const char *data = state->token;
       
  1312         unsigned int len = state->tokenlen;
       
  1313 
       
  1314         if (state->tokenval == TOKEN_HASH)  // stringify?
       
  1315         {
       
  1316             lexer(state);
       
  1317             assert(state->tokenval != TOKEN_EOI);  // we checked for this.
       
  1318 
       
  1319             if (!add_to_buffer(&buffer, "\"", 1, m, d))
       
  1320                 goto replace_and_push_macro_failed;
       
  1321 
       
  1322             if (state->tokenval == TOKEN_IDENTIFIER)
       
  1323             {
       
  1324                 arg = find_macro_arg(state, params);
       
  1325                 if (arg != NULL)
       
  1326                 {
       
  1327                     data = arg->original;
       
  1328                     len = strlen(data);
       
  1329                 } // if
       
  1330             } // if
       
  1331 
       
  1332             if (!add_to_buffer(&buffer, data, len, m, d))
       
  1333                 goto replace_and_push_macro_failed;
       
  1334 
       
  1335             if (!add_to_buffer(&buffer, "\"", 1, m, d))
       
  1336                 goto replace_and_push_macro_failed;
       
  1337 
       
  1338             continue;
       
  1339         } // if
       
  1340 
       
  1341         if (state->tokenval == TOKEN_IDENTIFIER)
       
  1342         {
       
  1343             arg = find_macro_arg(state, params);
       
  1344             if (arg != NULL)
       
  1345             {
       
  1346                 if (!wantorig)
       
  1347                 {
       
  1348                     wantorig = (lexer(state) == TOKEN_HASHHASH);
       
  1349                     pushback(state);
       
  1350                 } // if
       
  1351                 data = wantorig ? arg->original : arg->definition;
       
  1352                 len = strlen(data);
       
  1353             } // if
       
  1354         } // if
       
  1355 
       
  1356         if (!add_to_buffer(&buffer, data, len, m, d))
       
  1357             goto replace_and_push_macro_failed;
       
  1358     } // while
       
  1359 
       
  1360     final = flatten_buffer(&buffer, m, d);
       
  1361     if (!final)
       
  1362     {
       
  1363         out_of_memory(ctx);
       
  1364         goto replace_and_push_macro_failed;
       
  1365     } // if
       
  1366 
       
  1367     free_buffer(&buffer, f, d);
       
  1368     pop_source(ctx);  // ditch the macro.
       
  1369     state = ctx->include_stack;
       
  1370     if (!push_source(ctx, state->filename, final, strlen(final), state->line,
       
  1371                      close_define_include))
       
  1372     {
       
  1373         Free(ctx, final);
       
  1374         return 0;
       
  1375     } // if
       
  1376 
       
  1377     return 1;
       
  1378 
       
  1379 replace_and_push_macro_failed:
       
  1380     pop_source(ctx);
       
  1381     free_buffer(&buffer, f, d);
       
  1382     return 0;
       
  1383 } // replace_and_push_macro
       
  1384 
       
  1385 
       
  1386 static int handle_macro_args(Context *ctx, const char *sym, const Define *def)
       
  1387 {
       
  1388     int retval = 0;
       
  1389     MOJOSHADER_malloc m = ctx->malloc;
       
  1390     MOJOSHADER_free f = ctx->free;
       
  1391     void *d = ctx->malloc_data;
       
  1392     IncludeState *state = ctx->include_stack;
       
  1393     Define *params = NULL;
       
  1394     const int expected = (def->paramcount < 0) ? 0 : def->paramcount;
       
  1395     int saw_params = 0;
       
  1396     IncludeState saved;  // can't pushback, we need the original token.
       
  1397     memcpy(&saved, state, sizeof (IncludeState));
       
  1398     if (lexer(state) != ((Token) '('))
       
  1399     {
       
  1400         memcpy(state, &saved, sizeof (IncludeState));
       
  1401         goto handle_macro_args_failed;  // gcc abandons replacement, too.
       
  1402     } // if
       
  1403 
       
  1404     state->report_whitespace = 1;
       
  1405 
       
  1406     int void_call = 0;
       
  1407     int paren = 1;
       
  1408     while (paren > 0)
       
  1409     {
       
  1410         Buffer buffer;
       
  1411         Buffer origbuffer;
       
  1412         init_buffer(&buffer);
       
  1413         init_buffer(&origbuffer);
       
  1414 
       
  1415         Token t = lexer(state);
       
  1416 
       
  1417         assert(!void_call);
       
  1418 
       
  1419         while (1)
       
  1420         {
       
  1421             const char *origexpr = state->token;
       
  1422             unsigned int origexprlen = state->tokenlen;
       
  1423             const char *expr = state->token;
       
  1424             unsigned int exprlen = state->tokenlen;
       
  1425 
       
  1426             if (t == ((Token) '('))
       
  1427                 paren++;
       
  1428 
       
  1429             else if (t == ((Token) ')'))
       
  1430             {
       
  1431                 paren--;
       
  1432                 if (paren < 1)  // end of macro?
       
  1433                     break;
       
  1434             } // else if
       
  1435 
       
  1436             else if (t == ((Token) ','))
       
  1437             {
       
  1438                 if (paren == 1)  // new macro arg?
       
  1439                     break;
       
  1440             } // else if
       
  1441 
       
  1442             else if (t == ((Token) ' '))
       
  1443             {
       
  1444                 // don't add whitespace to the start, so we recognize
       
  1445                 //  void calls correctly.
       
  1446                 origexpr = expr = " ";
       
  1447                 origexprlen = (buffer.total_bytes == 0) ? 0 : 1;
       
  1448             } // else if
       
  1449 
       
  1450             else if (t == TOKEN_IDENTIFIER)
       
  1451             {
       
  1452                 const Define *def = find_define_by_token(ctx);
       
  1453                 if (def)
       
  1454                 {
       
  1455                     expr = def->definition;
       
  1456                     exprlen = strlen(def->definition);
       
  1457                 } // if
       
  1458             } // else if
       
  1459 
       
  1460             else if ((t == TOKEN_INCOMPLETE_COMMENT) || (t == TOKEN_EOI))
       
  1461             {
       
  1462                 pushback(state);
       
  1463                 fail(ctx, "Unterminated macro list");
       
  1464                 goto handle_macro_args_failed;
       
  1465             } // else if
       
  1466 
       
  1467             assert(expr != NULL);
       
  1468 
       
  1469             if (!add_to_buffer(&buffer, expr, exprlen, m, d))
       
  1470             {
       
  1471                 out_of_memory(ctx);
       
  1472                 goto handle_macro_args_failed;
       
  1473             } // if
       
  1474 
       
  1475             if (!add_to_buffer(&origbuffer, origexpr, origexprlen, m, d))
       
  1476             {
       
  1477                 out_of_memory(ctx);
       
  1478                 goto handle_macro_args_failed;
       
  1479             } // if
       
  1480 
       
  1481             t = lexer(state);
       
  1482         } // while
       
  1483 
       
  1484         if (buffer.total_bytes == 0)
       
  1485             void_call = ((saw_params == 0) && (paren == 0));
       
  1486 
       
  1487         if (saw_params < expected)
       
  1488         {
       
  1489             char *origdefinition = flatten_buffer(&origbuffer, m, d);
       
  1490             char *definition = flatten_buffer(&buffer, m, d);
       
  1491             Define *p = get_define(ctx);
       
  1492             if ((!origdefinition) || (!definition) || (!p))
       
  1493             {
       
  1494                 Free(ctx, origdefinition);
       
  1495                 Free(ctx, definition);
       
  1496                 free_buffer(&origbuffer, f, d);
       
  1497                 free_buffer(&buffer, f, d);
       
  1498                 free_define(ctx, p);
       
  1499                 goto handle_macro_args_failed;
       
  1500             } // if
       
  1501 
       
  1502             // trim any whitespace from the end of the string...
       
  1503             int i;
       
  1504             for (i = (int) buffer.total_bytes - 1; i >= 0; i--)
       
  1505             {
       
  1506                 if (definition[i] == ' ')
       
  1507                     definition[i] = '\0';
       
  1508                 else
       
  1509                     break;
       
  1510             } // for
       
  1511 
       
  1512             for (i = (int) origbuffer.total_bytes - 1; i >= 0; i--)
       
  1513             {
       
  1514                 if (origdefinition[i] == ' ')
       
  1515                     origdefinition[i] = '\0';
       
  1516                 else
       
  1517                     break;
       
  1518             } // for
       
  1519 
       
  1520             p->identifier = def->parameters[saw_params];
       
  1521             p->definition = definition;
       
  1522             p->original = origdefinition;
       
  1523             p->next = params;
       
  1524             params = p;
       
  1525         } // if
       
  1526 
       
  1527         free_buffer(&buffer, f, d);
       
  1528         free_buffer(&origbuffer, f, d);
       
  1529         saw_params++;
       
  1530     } // while
       
  1531 
       
  1532     assert(paren == 0);
       
  1533 
       
  1534     // "a()" should match "#define a()" ...
       
  1535     if ((expected == 0) && (saw_params == 1) && (void_call))
       
  1536     {
       
  1537         assert(params == NULL);
       
  1538         saw_params = 0;
       
  1539     } // if
       
  1540 
       
  1541     if (saw_params != expected)
       
  1542     {
       
  1543         failf(ctx, "macro '%s' passed %d arguments, but requires %d",
       
  1544               sym, saw_params, expected);
       
  1545         goto handle_macro_args_failed;
       
  1546     } // if
       
  1547 
       
  1548     // this handles arg replacement and the '##' and '#' operators.
       
  1549     retval = replace_and_push_macro(ctx, def, params);
       
  1550 
       
  1551 handle_macro_args_failed:
       
  1552     while (params)
       
  1553     {
       
  1554         Define *next = params->next;
       
  1555         params->identifier = NULL;
       
  1556         free_define(ctx, params);
       
  1557         params = next;
       
  1558     } // while
       
  1559 
       
  1560     state->report_whitespace = 0;
       
  1561     return retval;
       
  1562 } // handle_macro_args
       
  1563 
       
  1564 
  1283 static int handle_pp_identifier(Context *ctx)
  1565 static int handle_pp_identifier(Context *ctx)
  1284 {
  1566 {
  1285     if (ctx->recursion_count++ >= 256)
  1567     if (ctx->recursion_count++ >= 256)  // !!! FIXME: necessary now?
  1286     {
  1568     {
  1287         fail(ctx, "Recursing macros");
  1569         fail(ctx, "Recursing macros");
  1288         return 0;
  1570         return 0;
  1289     } // if
  1571     } // if
  1290 
  1572 
  1291     const char *fname = NULL;
       
  1292     const char *val = NULL;
       
  1293     size_t vallen = 0;
       
  1294     int is_macro = 0;
       
  1295     IncludeState *state = ctx->include_stack;
  1573     IncludeState *state = ctx->include_stack;
       
  1574     const char *fname = state->filename;
       
  1575     const unsigned int line = state->line;
  1296     char *sym = (char *) alloca(state->tokenlen+1);
  1576     char *sym = (char *) alloca(state->tokenlen+1);
  1297     memcpy(sym, state->token, state->tokenlen);
  1577     memcpy(sym, state->token, state->tokenlen);
  1298     sym[state->tokenlen] = '\0';
  1578     sym[state->tokenlen] = '\0';
  1299 
  1579 
  1300     Define *params = NULL;
       
  1301 
       
  1302     if ( (ctx->file_macro_special) && (strcmp(sym, "__FILE__") == 0) )
  1580     if ( (ctx->file_macro_special) && (strcmp(sym, "__FILE__") == 0) )
  1303     {
  1581     {
  1304         const char *fname = state->filename;
       
  1305         const unsigned int line = state->line;
       
  1306         const size_t len = strlen(fname) + 2;
  1582         const size_t len = strlen(fname) + 2;
  1307         char *str = (char *) Malloc(ctx, len);
  1583         char *str = (char *) Malloc(ctx, len);
  1308         if (!str)
  1584         if (!str)
  1309             return 0;
  1585             return 0;
  1310         str[0] = '\"';
  1586         str[0] = '\"';
  1311         memcpy(str + 1, fname, len - 2);
  1587         memcpy(str + 1, fname, len - 2);
  1312         str[len - 1] = '\"';
  1588         str[len - 1] = '\"';
  1313         if (!push_source(ctx,fname,str,len,line,close_define_include,NULL,1))
  1589         if (!push_source(ctx,fname,str,len,line,close_define_include))
  1314         {
  1590         {
  1315             assert(ctx->out_of_memory);
       
  1316             Free(ctx, str);
  1591             Free(ctx, str);
  1317             return 0;
  1592             return 0;
  1318         } // if
  1593         } // if
  1319         return 1;
  1594         return 1;
  1320     } // if
  1595     } // if
  1321 
  1596 
  1322     else if ( (ctx->line_macro_special) && (strcmp(sym, "__LINE__") == 0) )
  1597     else if ( (ctx->line_macro_special) && (strcmp(sym, "__LINE__") == 0) )
  1323     {
  1598     {
  1324         const char *fname = state->filename;
       
  1325         const unsigned int line = state->line;
       
  1326         const size_t bufsize = 32;
  1599         const size_t bufsize = 32;
  1327         char *str = (char *) Malloc(ctx, bufsize);
  1600         char *str = (char *) Malloc(ctx, bufsize);
  1328         if (!str)
  1601         if (!str)
  1329             return 0;
  1602             return 0;
  1330 
  1603 
  1331         const size_t len = snprintf(str, bufsize, "%u", line);
  1604         const size_t len = snprintf(str, bufsize, "%u", line);
  1332         assert(len < bufsize);
  1605         assert(len < bufsize);
  1333         if (!push_source(ctx,fname,str,len,line,close_define_include,NULL,1))
  1606         if (!push_source(ctx,fname,str,len,line,close_define_include))
  1334         {
  1607         {
  1335             assert(ctx->out_of_memory);
       
  1336             Free(ctx, str);
  1608             Free(ctx, str);
  1337             return 0;
  1609             return 0;
  1338         } // if
  1610         } // if
  1339         return 1;
  1611         return 1;
  1340     } // else
  1612     } // else
  1341 
  1613 
  1342     // IncludeState defines (macro args) take precedence over Context defines.
  1614     // Is this identifier #defined?
  1343     const Define *def = find_macro_arg(state);
  1615     const Define *def = find_define(ctx, sym);
  1344     if (def == NULL)
  1616     if (def == NULL)
  1345     {
  1617         return 0;   // just send the token through unchanged.
  1346         def = find_define(ctx, sym);
  1618     else if (def->paramcount != 0)
  1347         if (def == NULL)
  1619         return handle_macro_args(ctx, sym, def);
  1348             return 0;   // just send the token through unchanged.
  1620 
  1349 
  1621     const size_t deflen = strlen(def->definition);
  1350         is_macro = 1;
  1622     return push_source(ctx, fname, def->definition, deflen, line, NULL);
  1351 
       
  1352         if (def->paramcount != 0)
       
  1353         {
       
  1354             MOJOSHADER_malloc m = ctx->malloc;
       
  1355             MOJOSHADER_free f = ctx->free;
       
  1356             void *d = ctx->malloc_data;
       
  1357             const int expected = (def->paramcount < 0) ? 0 : def->paramcount;
       
  1358             int saw_params = 0;
       
  1359             IncludeState saved;  // can't pushback, we need the original token.
       
  1360             memcpy(&saved, state, sizeof (IncludeState));
       
  1361             if (lexer(state) != ((Token) '('))
       
  1362             {
       
  1363                 memcpy(state, &saved, sizeof (IncludeState));
       
  1364                 return 0;  // gcc abandons replacement in this case, too.
       
  1365             } // if
       
  1366 
       
  1367             int void_call = 0;
       
  1368             int paren = 1;
       
  1369             while (paren > 0)
       
  1370             {
       
  1371                 Buffer buffer;
       
  1372                 assert(!void_call);
       
  1373 
       
  1374                 init_buffer(&buffer);
       
  1375 
       
  1376                 while (1)
       
  1377                 {
       
  1378                     const Token t = lexer(state);
       
  1379                     const char *expr = state->token;
       
  1380                     unsigned int exprlen = state->tokenlen;
       
  1381                     if (t == '(')
       
  1382                         paren++;
       
  1383 
       
  1384                     else if (t == ')')
       
  1385                     {
       
  1386                         paren--;
       
  1387                         if (paren < 1)  // end of macro?
       
  1388                             break;
       
  1389                     } // else if
       
  1390 
       
  1391                     else if (t == ',')
       
  1392                     {
       
  1393                         if (paren == 1)  // new macro arg?
       
  1394                             break;
       
  1395                     } // else if
       
  1396 
       
  1397                     // see if a replacement is in order...
       
  1398                     // !!! FIXME: this fails if we get another macro with args:
       
  1399                     // !!! FIXME:  macro1(macro2(arg))
       
  1400                     else if (t == TOKEN_IDENTIFIER)
       
  1401                     {
       
  1402                         const Define *arg = NULL;
       
  1403                         if (state->is_macro)
       
  1404                             arg = find_macro_arg(state);
       
  1405                         if (arg == NULL)
       
  1406                             arg = find_define_by_token(ctx);
       
  1407                         if (arg)
       
  1408                         {
       
  1409                             expr = arg->definition;
       
  1410                             exprlen = strlen(arg->definition);
       
  1411                         } // if
       
  1412                     } // else if
       
  1413 
       
  1414                     else if ((t == TOKEN_INCOMPLETE_COMMENT) || (t == TOKEN_EOI))
       
  1415                     {
       
  1416                         pushback(state);
       
  1417                         fail(ctx, "Unterminated macro list");
       
  1418                         free_buffer(&buffer, f, d);
       
  1419                         goto handle_pp_identifier_failed;
       
  1420                     } // else if
       
  1421 
       
  1422                     assert(expr != NULL);
       
  1423 
       
  1424                     if (!add_to_buffer(&buffer, expr, exprlen, m, d))
       
  1425                     {
       
  1426                         out_of_memory(ctx);
       
  1427                         free_buffer(&buffer, f, d);
       
  1428                         goto handle_pp_identifier_failed;
       
  1429                     } // if
       
  1430                 } // while
       
  1431 
       
  1432                 if (buffer.total_bytes == 0)
       
  1433                     void_call = ((saw_params == 0) && (paren == 0));
       
  1434 
       
  1435                 if (saw_params < expected)
       
  1436                 {
       
  1437                     Define *p = get_define(ctx);
       
  1438                     if (p == NULL)
       
  1439                         goto handle_pp_identifier_failed;
       
  1440 
       
  1441                     p->next = params;
       
  1442                     params = p;
       
  1443 
       
  1444                     char *definition = flatten_buffer(&buffer, m, d);
       
  1445                     free_buffer(&buffer, f, d);
       
  1446                     if (definition == NULL)
       
  1447                     {
       
  1448                         out_of_memory(ctx);
       
  1449                         goto handle_pp_identifier_failed;
       
  1450                     } // if
       
  1451                     p->identifier = def->parameters[saw_params];
       
  1452                     p->definition = definition;
       
  1453                 } // if
       
  1454 
       
  1455                 saw_params++;
       
  1456             } // while
       
  1457             assert(paren == 0);  // make sure it's not negative.
       
  1458 
       
  1459             // "a()" should match "#define a()" ...
       
  1460             if ((expected == 0) && (saw_params == 1) && (void_call))
       
  1461             {
       
  1462                 assert(params == NULL);
       
  1463                 saw_params = 0;
       
  1464             } // if
       
  1465 
       
  1466             if (saw_params != expected)
       
  1467             {
       
  1468                 failf(ctx, "macro '%s' passed %d arguments, but requires %d",
       
  1469                       sym, saw_params, expected);
       
  1470                 goto handle_pp_identifier_failed;
       
  1471             } // if
       
  1472         } // if
       
  1473     } // if
       
  1474 
       
  1475     val = def->definition;
       
  1476     vallen = strlen(val);
       
  1477     fname = state->filename;
       
  1478     if (!push_source(ctx,fname,val,vallen,state->line,NULL,params,is_macro))
       
  1479     {
       
  1480         assert(ctx->out_of_memory);
       
  1481         goto handle_pp_identifier_failed;
       
  1482     } // if
       
  1483 
       
  1484     return 1;
       
  1485 
       
  1486 handle_pp_identifier_failed:
       
  1487     while (params)
       
  1488     {
       
  1489         Define *next = params->next;
       
  1490         params->identifier = NULL;
       
  1491         free_define(ctx, params);
       
  1492         params = next;
       
  1493     } // while
       
  1494     return 0;
       
  1495 } // handle_pp_identifier
  1623 } // handle_pp_identifier
  1496 
  1624 
  1497 
  1625 
  1498 static int find_precedence(const Token token)
  1626 static int find_precedence(const Token token)
  1499 {
  1627 {
  1901         put_conditional(ctx, cond);
  2029         put_conditional(ctx, cond);
  1902     } // else
  2030     } // else
  1903 } // handle_pp_endif
  2031 } // handle_pp_endif
  1904 
  2032 
  1905 
  2033 
  1906 static void handle_pp_stringify(Context *ctx)
       
  1907 {
       
  1908     IncludeState *state = ctx->include_stack;
       
  1909     const Define *def = NULL;
       
  1910 
       
  1911     assert(state->is_macro);
       
  1912 
       
  1913     if (lexer(state) == TOKEN_IDENTIFIER)
       
  1914         def = find_macro_arg(state);
       
  1915 
       
  1916     if (def == NULL)
       
  1917     {
       
  1918         pushback(state);
       
  1919         fail(ctx, "'#' is not followed by a macro parameter");
       
  1920         return;  // we just fail(), drop the '#' token and continue on.
       
  1921     } // if
       
  1922 
       
  1923     const size_t deflen = strlen(def->definition);
       
  1924     char *litstring = (char *) Malloc(ctx, deflen + 2);
       
  1925     if (!litstring)
       
  1926         return;
       
  1927 
       
  1928     litstring[0] = '\"';
       
  1929     memcpy(litstring + 1, def->definition, deflen);
       
  1930     litstring[deflen + 1] = '\"';
       
  1931     const char *filename = state->filename;
       
  1932     push_source(ctx, filename, litstring, deflen + 2, state->line,
       
  1933                 close_define_include, NULL, 0);
       
  1934 } // handle_pp_stringify
       
  1935 
       
  1936 
       
  1937 static int handle_pp_concat(Context *ctx)
       
  1938 {
       
  1939     MOJOSHADER_malloc m = ctx->malloc;
       
  1940     MOJOSHADER_free f = ctx->free;
       
  1941     void *d = ctx->malloc_data;
       
  1942     IncludeState *state = ctx->include_stack;
       
  1943     Buffer buffer;
       
  1944     int glued = 0;
       
  1945     int rc = 0;
       
  1946     const Define *def = NULL;
       
  1947 
       
  1948     assert(state->is_macro);
       
  1949 
       
  1950     init_buffer(&buffer);
       
  1951 
       
  1952     def = (state->tokenval == TOKEN_IDENTIFIER) ? find_macro_arg(state) : 0;
       
  1953     if (def)
       
  1954         rc = add_to_buffer(&buffer, def->definition, strlen(def->definition), m, d);
       
  1955     else
       
  1956         rc = add_to_buffer(&buffer, state->token, state->tokenlen, m, d);
       
  1957 
       
  1958     while (rc)
       
  1959     {
       
  1960         IncludeState saved;  // can't just pushback; we need all the state.
       
  1961         memcpy(&saved, state, sizeof (IncludeState));
       
  1962         if (lexer(state) != TOKEN_HASHHASH)  // concat operator ("##")
       
  1963         {
       
  1964             memcpy(state, &saved, sizeof (IncludeState));
       
  1965             break;
       
  1966         } // if
       
  1967 
       
  1968         lexer(state);  // step past ## token.
       
  1969 
       
  1970         // we checked these things when parsing the macro.
       
  1971         assert(state->is_macro);
       
  1972         assert(state->tokenval != TOKEN_EOI);
       
  1973         assert(state->tokenval != ((Token) ' '));
       
  1974 
       
  1975         def = (state->tokenval == TOKEN_IDENTIFIER) ? find_macro_arg(state) : 0;
       
  1976         if (def)
       
  1977             rc = add_to_buffer(&buffer, def->definition, strlen(def->definition), m, d);
       
  1978         else
       
  1979             rc = add_to_buffer(&buffer, state->token, state->tokenlen, m, d);
       
  1980 
       
  1981         glued = 1;
       
  1982     } // while
       
  1983 
       
  1984     if (!rc)
       
  1985     {
       
  1986         out_of_memory(ctx);
       
  1987         return 0;
       
  1988     } // if
       
  1989 
       
  1990     if (glued)
       
  1991     {
       
  1992         char *combined = flatten_buffer(&buffer, m, d);
       
  1993         if (combined == NULL)
       
  1994         {
       
  1995             out_of_memory(ctx);
       
  1996             glued = 0;
       
  1997         } // if
       
  1998         else
       
  1999         {
       
  2000             const char *filename = state->filename;
       
  2001             push_source(ctx, filename, combined, buffer.total_bytes,
       
  2002                         state->line, close_define_include, NULL, 0);
       
  2003         } // else
       
  2004     } // if
       
  2005 
       
  2006     free_buffer(&buffer, f, d);
       
  2007     return glued;
       
  2008 } // handle_pp_concat
       
  2009 
       
  2010 
       
  2011 static void unterminated_pp_condition(Context *ctx)
  2034 static void unterminated_pp_condition(Context *ctx)
  2012 {
  2035 {
  2013     IncludeState *state = ctx->include_stack;
  2036     IncludeState *state = ctx->include_stack;
  2014     Conditional *cond = state->conditional_stack;
  2037     Conditional *cond = state->conditional_stack;
  2015 
  2038 
  2148         else if (token == TOKEN_PP_UNDEF)
  2171         else if (token == TOKEN_PP_UNDEF)
  2149         {
  2172         {
  2150             handle_pp_undef(ctx);
  2173             handle_pp_undef(ctx);
  2151             continue;  // will return at top of loop.
  2174             continue;  // will return at top of loop.
  2152         } // else if
  2175         } // else if
  2153 
       
  2154         // stringify ("#") and concat ("##") only during macro replacement.
       
  2155         if (state->is_macro)
       
  2156         {
       
  2157             if (token == TOKEN_HASH)
       
  2158             {
       
  2159                 handle_pp_stringify(ctx);
       
  2160                 continue;
       
  2161             } // if
       
  2162 
       
  2163             if (handle_pp_concat(ctx))
       
  2164                 continue;
       
  2165         } // if
       
  2166 
  2176 
  2167         if (token == TOKEN_IDENTIFIER)
  2177         if (token == TOKEN_IDENTIFIER)
  2168         {
  2178         {
  2169             if (handle_pp_identifier(ctx))
  2179             if (handle_pp_identifier(ctx))
  2170                 continue;  // pushed the include_stack.
  2180                 continue;  // pushed the include_stack.