mojoshader_assembler.c
changeset 939 64cc93ee5a56
parent 840 84a0c6807aa8
child 940 bc2a5efade5e
equal deleted inserted replaced
938:fc5240c4f197 939:64cc93ee5a56
    38     int isfail;
    38     int isfail;
    39     int out_of_memory;
    39     int out_of_memory;
    40     MOJOSHADER_malloc malloc;
    40     MOJOSHADER_malloc malloc;
    41     MOJOSHADER_free free;
    41     MOJOSHADER_free free;
    42     void *malloc_data;
    42     void *malloc_data;
    43     int error_count;
       
    44     ErrorList *errors;
    43     ErrorList *errors;
    45     Preprocessor *preprocessor;
    44     Preprocessor *preprocessor;
    46     MOJOSHADER_parsePhase parse_phase;
    45     MOJOSHADER_parsePhase parse_phase;
    47     MOJOSHADER_shaderType shader_type;
    46     MOJOSHADER_shaderType shader_type;
    48     uint8 major_ver;
    47     uint8 major_ver;
    88     return retval;
    87     return retval;
    89 } // StrDup
    88 } // StrDup
    90 
    89 
    91 static inline void Free(Context *ctx, void *ptr)
    90 static inline void Free(Context *ctx, void *ptr)
    92 {
    91 {
    93     if (ptr != NULL)  // check for NULL in case of dumb free() impl.
    92     ctx->free(ptr, ctx->malloc_data);
    94         ctx->free(ptr, ctx->malloc_data);
       
    95 } // Free
    93 } // Free
       
    94 
       
    95 static void *MallocBridge(int bytes, void *data)
       
    96 {
       
    97     return Malloc((Context *) data, (size_t) bytes);
       
    98 } // MallocBridge
       
    99 
       
   100 static void FreeBridge(void *ptr, void *data)
       
   101 {
       
   102     Free((Context *) data, ptr);
       
   103 } // FreeBridge
    96 
   104 
    97 static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
   105 static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
    98 static void failf(Context *ctx, const char *fmt, ...)
   106 static void failf(Context *ctx, const char *fmt, ...)
    99 {
   107 {
   100     const char *fname = NULL;
   108     const char *fname = NULL;
   101     unsigned int linenum = 0;
   109     unsigned int linenum = 0;
   102     int error_position = 0;
       
   103 
   110 
   104     ctx->isfail = 1;
   111     ctx->isfail = 1;
   105 
   112     if (ctx->out_of_memory)
       
   113         return;
       
   114 
       
   115     int errpos = 0;
   106     switch (ctx->parse_phase)
   116     switch (ctx->parse_phase)
   107     {
   117     {
   108         case MOJOSHADER_PARSEPHASE_NOTSTARTED:
   118         case MOJOSHADER_PARSEPHASE_NOTSTARTED:
   109             error_position = -2;
   119             errpos = -2;
   110             break;
   120             break;
   111         case MOJOSHADER_PARSEPHASE_WORKING:
   121         case MOJOSHADER_PARSEPHASE_WORKING:
   112             fname = preprocessor_sourcepos(ctx->preprocessor, &linenum);
   122             fname = preprocessor_sourcepos(ctx->preprocessor, &linenum);
   113             error_position = (int) linenum;
   123             errpos = (int) linenum;
   114             break;
   124             break;
   115         case MOJOSHADER_PARSEPHASE_DONE:
   125         case MOJOSHADER_PARSEPHASE_DONE:
   116             error_position = -1;
   126             errpos = -1;
   117             break;
   127             break;
   118         default:
   128         default:
   119             assert(0 && "Unexpected value");
   129             assert(0 && "Unexpected value");
   120             return;
   130             return;
   121     } // switch
   131     } // switch
   122 
   132 
   123     ErrorList *error = (ErrorList *) Malloc(ctx, sizeof (ErrorList));
       
   124     if (error == NULL)
       
   125         return;
       
   126 
       
   127     char scratch = 0;
       
   128     va_list ap;
   133     va_list ap;
   129     va_start(ap, fmt);
   134     va_start(ap, fmt);
   130     const int len = vsnprintf(&scratch, sizeof (scratch), fmt, ap);
   135     errorlist_add_va(ctx->errors, fname, errpos, fmt, ap);
   131     va_end(ap);
   136     va_end(ap);
   132 
       
   133     char *failstr = (char *) Malloc(ctx, len + 1);
       
   134     if (failstr == NULL)
       
   135         Free(ctx, error);
       
   136     else
       
   137     {
       
   138         va_start(ap, fmt);
       
   139         vsnprintf(failstr, len + 1, fmt, ap);  // rebuild it.
       
   140         va_end(ap);
       
   141 
       
   142         error->error.error = failstr;
       
   143         error->error.filename = fname ? StrDup(ctx, fname) : NULL;
       
   144         error->error.error_position = error_position;
       
   145         error->next = NULL;
       
   146 
       
   147         ErrorList *prev = NULL;
       
   148         ErrorList *item = ctx->errors;
       
   149         while (item != NULL)
       
   150         {
       
   151             prev = item;
       
   152             item = item->next;
       
   153         } // while
       
   154 
       
   155         if (prev == NULL)
       
   156             ctx->errors = error;
       
   157         else
       
   158             prev->next = error;
       
   159 
       
   160         ctx->error_count++;
       
   161     } // else
       
   162 } // failf
   137 } // failf
   163 
   138 
   164 static inline void fail(Context *ctx, const char *reason)
   139 static inline void fail(Context *ctx, const char *reason)
   165 {
   140 {
   166     failf(ctx, "%s", reason);
   141     failf(ctx, "%s", reason);
  1466     memset(ctx, '\0', sizeof (Context));
  1441     memset(ctx, '\0', sizeof (Context));
  1467     ctx->malloc = m;
  1442     ctx->malloc = m;
  1468     ctx->free = f;
  1443     ctx->free = f;
  1469     ctx->malloc_data = d;
  1444     ctx->malloc_data = d;
  1470     ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
  1445     ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED;
       
  1446 
       
  1447     ctx->errors = errorlist_create(MallocBridge, FreeBridge, ctx);
       
  1448     if (ctx->errors == NULL)
       
  1449     {
       
  1450         f(ctx, d);
       
  1451         return NULL;
       
  1452     } // if
       
  1453 
  1471     ctx->preprocessor = preprocessor_start(filename, source, sourcelen,
  1454     ctx->preprocessor = preprocessor_start(filename, source, sourcelen,
  1472                                            include_open, include_close,
  1455                                            include_open, include_close,
  1473                                            defines, define_count, 1, m, f, d);
  1456                                            defines, define_count, 1,
       
  1457                                            MallocBridge, FreeBridge, ctx);
  1474 
  1458 
  1475     if (ctx->preprocessor == NULL)
  1459     if (ctx->preprocessor == NULL)
  1476     {
  1460     {
       
  1461         errorlist_destroy(ctx->errors);
  1477         f(ctx, d);
  1462         f(ctx, d);
  1478         return NULL;
  1463         return NULL;
  1479     } // if
  1464     } // if
  1480 
  1465 
  1481     return ctx;
  1466     return ctx;
  1482 } // build_context
  1467 } // build_context
  1483 
  1468 
  1484 
  1469 
  1485 static void free_error_list(MOJOSHADER_free f, void *d, ErrorList *item)
       
  1486 {
       
  1487     while (item != NULL)
       
  1488     {
       
  1489         ErrorList *next = item->next;
       
  1490         f((void *) item->error.error, d);
       
  1491         f((void *) item->error.filename, d);
       
  1492         f(item, d);
       
  1493         item = next;
       
  1494     } // while
       
  1495 } // free_error_list
       
  1496 
       
  1497 
       
  1498 static void destroy_context(Context *ctx)
  1470 static void destroy_context(Context *ctx)
  1499 {
  1471 {
  1500     if (ctx != NULL)
  1472     if (ctx != NULL)
  1501     {
  1473     {
  1502         MOJOSHADER_free f = ((ctx->free != NULL) ? ctx->free : MOJOSHADER_internal_free);
  1474         MOJOSHADER_free f = ((ctx->free != NULL) ? ctx->free : MOJOSHADER_internal_free);
  1503         void *d = ctx->malloc_data;
  1475         void *d = ctx->malloc_data;
  1504         free_error_list(f, d, ctx->errors);
  1476         if (ctx->errors != NULL)
       
  1477             errorlist_destroy(ctx->errors);
  1505         if (ctx->preprocessor != NULL)
  1478         if (ctx->preprocessor != NULL)
  1506             preprocessor_end(ctx->preprocessor);
  1479             preprocessor_end(ctx->preprocessor);
  1507         if (ctx->output != NULL)
  1480         if (ctx->output != NULL)
  1508             f(ctx->output, d);
  1481             f(ctx->output, d);
  1509         if (ctx->token_to_source != NULL)
  1482         if (ctx->token_to_source != NULL)
  1513         f(ctx, d);
  1486         f(ctx, d);
  1514     } // if
  1487     } // if
  1515 } // destroy_context
  1488 } // destroy_context
  1516 
  1489 
  1517 
  1490 
  1518 static MOJOSHADER_error *build_errors(Context *ctx)
       
  1519 {
       
  1520     int total = 0;
       
  1521     MOJOSHADER_error *retval = (MOJOSHADER_error *)
       
  1522             Malloc(ctx, sizeof (MOJOSHADER_error) * ctx->error_count);
       
  1523     if (retval == NULL)
       
  1524         return NULL;
       
  1525 
       
  1526     ErrorList *item = ctx->errors;
       
  1527     while (item != NULL)
       
  1528     {
       
  1529         ErrorList *next = item->next;
       
  1530         // reuse the string allocations
       
  1531         memcpy(&retval[total], &item->error, sizeof (MOJOSHADER_error));
       
  1532         Free(ctx, item);
       
  1533         item = next;
       
  1534         total++;
       
  1535     } // while
       
  1536     ctx->errors = NULL;
       
  1537 
       
  1538     assert(total == ctx->error_count);
       
  1539     return retval;
       
  1540 } // build_errors
       
  1541 
       
  1542 
       
  1543 static const MOJOSHADER_parseData *build_failed_assembly(Context *ctx)
  1491 static const MOJOSHADER_parseData *build_failed_assembly(Context *ctx)
  1544 {
  1492 {
  1545     assert(isfail(ctx));
  1493     assert(isfail(ctx));
  1546 
  1494 
  1547     if (ctx->out_of_memory)
  1495     if (ctx->out_of_memory)
  1555     memset(retval, '\0', sizeof (MOJOSHADER_parseData));
  1503     memset(retval, '\0', sizeof (MOJOSHADER_parseData));
  1556     retval->malloc = (ctx->malloc == MOJOSHADER_internal_malloc) ? NULL : ctx->malloc;
  1504     retval->malloc = (ctx->malloc == MOJOSHADER_internal_malloc) ? NULL : ctx->malloc;
  1557     retval->free = (ctx->free == MOJOSHADER_internal_free) ? NULL : ctx->free;
  1505     retval->free = (ctx->free == MOJOSHADER_internal_free) ? NULL : ctx->free;
  1558     retval->malloc_data = ctx->malloc_data;
  1506     retval->malloc_data = ctx->malloc_data;
  1559 
  1507 
  1560     retval->error_count = ctx->error_count;
  1508     retval->error_count = ctx->errors->count;
  1561     retval->errors = build_errors(ctx);
  1509     retval->errors = errorlist_flatten(ctx->errors);
  1562     if ((retval->errors == NULL) && (ctx->error_count > 0))
  1510     if (ctx->out_of_memory)
  1563     {
  1511     {
  1564         Free(ctx, retval);
  1512         Free(ctx, retval);
  1565         return &MOJOSHADER_out_of_mem_data;
  1513         return &MOJOSHADER_out_of_mem_data;
  1566     } // if
  1514     } // if
  1567 
  1515