mojoshader_preprocessor.c
changeset 652 3333a0774ccc
parent 650 9c91067da49d
child 654 9210bd7eb2e2
equal deleted inserted replaced
651:05ad72d120a5 652:3333a0774ccc
   668     Context *ctx = (Context *) _ctx;
   668     Context *ctx = (Context *) _ctx;
   669     return ctx->out_of_memory;
   669     return ctx->out_of_memory;
   670 } // preprocessor_outofmemory
   670 } // preprocessor_outofmemory
   671 
   671 
   672 
   672 
       
   673 static inline void pushback(IncludeState *state)
       
   674 {
       
   675     #if DEBUG_PREPROCESSOR
       
   676     printf("PREPROCESSOR PUSHBACK\n");
       
   677     #endif
       
   678     assert(!state->pushedback);
       
   679     state->pushedback = 1;
       
   680 } // pushback
       
   681 
       
   682 
       
   683 static Token lexer(IncludeState *state)
       
   684 {
       
   685     if (!state->pushedback)
       
   686         return preprocessor_lexer(state);
       
   687     state->pushedback = 0;
       
   688     return state->tokenval;
       
   689 } // lexer
       
   690 
       
   691 
   673 // !!! FIXME: parsing fails on preprocessor directives should skip rest of line.
   692 // !!! FIXME: parsing fails on preprocessor directives should skip rest of line.
   674 static int require_newline(IncludeState *state)
   693 static int require_newline(IncludeState *state)
   675 {
   694 {
   676     const char *source = state->source;
   695     const Token token = lexer(state);
   677     const unsigned int bytes_left = state->bytes_left;
   696     pushback(state);  // rewind no matter what.
   678     const unsigned int linenum = state->line;
   697     return ( (token == TOKEN_INCOMPLETE_COMMENT) // call it an eol.
   679     const Token token = preprocessor_lexer(state);
   698              (token == ((Token) '\n')) || (token == TOKEN_EOI) );
   680     state->source = source;  // rewind no matter what.
       
   681     state->bytes_left = bytes_left;
       
   682     state->line = linenum;
       
   683     if (token == TOKEN_INCOMPLETE_COMMENT)
       
   684         return 1; // call it an eol.
       
   685     return ( (token == ((Token) '\n')) || (token == TOKEN_EOI) );
       
   686 } // require_newline
   699 } // require_newline
   687 
   700 
   688 
   701 
   689 static void handle_pp_include(Context *ctx)
   702 static void handle_pp_include(Context *ctx)
   690 {
   703 {
   691     IncludeState *state = ctx->include_stack;
   704     IncludeState *state = ctx->include_stack;
   692     Token token = preprocessor_lexer(state);
   705     Token token = lexer(state);
   693     MOJOSHADER_includeType incltype;
   706     MOJOSHADER_includeType incltype;
   694     char *filename = NULL;
   707     char *filename = NULL;
   695     int bogus = 0;
   708     int bogus = 0;
   696 
   709 
   697     if (token == TOKEN_STRING_LITERAL)
   710     if (token == TOKEN_STRING_LITERAL)
   761     IncludeState *state = ctx->include_stack;
   774     IncludeState *state = ctx->include_stack;
   762     char *filename = NULL;
   775     char *filename = NULL;
   763     int linenum = 0;
   776     int linenum = 0;
   764     int bogus = 0;
   777     int bogus = 0;
   765 
   778 
   766     if (preprocessor_lexer(state) != TOKEN_INT_LITERAL)
   779     if (lexer(state) != TOKEN_INT_LITERAL)
   767         bogus = 1;
   780         bogus = 1;
   768     else
   781     else
   769     {
   782     {
   770         char *buf = (char *) alloca(state->tokenlen+1);
   783         char *buf = (char *) alloca(state->tokenlen+1);
   771         memcpy(buf, state->token, state->tokenlen);
   784         memcpy(buf, state->token, state->tokenlen);
   772         buf[state->tokenlen] = '\0';
   785         buf[state->tokenlen] = '\0';
   773         linenum = atoi(buf);
   786         linenum = atoi(buf);
   774     } // else
   787     } // else
   775 
   788 
   776     if (!bogus)
   789     if (!bogus)
   777         bogus = (preprocessor_lexer(state) != TOKEN_STRING_LITERAL);
   790         bogus = (lexer(state) != TOKEN_STRING_LITERAL);
   778 
   791 
   779     if (!bogus)
   792     if (!bogus)
   780     {
   793     {
   781         state->token++;  // skip '\"'...
   794         state->token++;  // skip '\"'...
   782         filename = (char *) alloca(state->tokenlen);
   795         filename = (char *) alloca(state->tokenlen);
   799 
   812 
   800 
   813 
   801 static void handle_pp_error(Context *ctx)
   814 static void handle_pp_error(Context *ctx)
   802 {
   815 {
   803     IncludeState *state = ctx->include_stack;
   816     IncludeState *state = ctx->include_stack;
   804     unsigned int bytes_left = 0;
       
   805     char *ptr = ctx->failstr;
   817     char *ptr = ctx->failstr;
   806     int avail = sizeof (ctx->failstr) - 1;
   818     int avail = sizeof (ctx->failstr) - 1;
   807     int cpy = 0;
   819     int cpy = 0;
   808     int done = 0;
   820     int done = 0;
   809 
   821 
   812     strcpy(ctx->failstr, prefix);
   824     strcpy(ctx->failstr, prefix);
   813     avail -= prefixlen;
   825     avail -= prefixlen;
   814     ptr += prefixlen;
   826     ptr += prefixlen;
   815 
   827 
   816     state->report_whitespace = 1;
   828     state->report_whitespace = 1;
   817     const char *source = NULL;
       
   818     while (!done)
   829     while (!done)
   819     {
   830     {
   820         bytes_left = state->bytes_left;
   831         const Token token = lexer(state);
   821         source = state->source;
       
   822         const Token token = preprocessor_lexer(state);
       
   823         switch (token)
   832         switch (token)
   824         {
   833         {
   825             case ((Token) '\n'):
   834             case ((Token) '\n'):
   826                 state->line--;  // make sure error is on the right line.
   835                 state->line--;  // make sure error is on the right line.
   827                 // fall through!
   836                 // fall through!
   828             case TOKEN_INCOMPLETE_COMMENT:
   837             case TOKEN_INCOMPLETE_COMMENT:
   829             case TOKEN_EOI:
   838             case TOKEN_EOI:
   830                 state->bytes_left = bytes_left;
   839                 pushback(state);  // move back so we catch this later.
   831                 state->source = source;  // move back so we catch this later.
       
   832                 done = 1;
   840                 done = 1;
   833                 break;
   841                 break;
   834 
   842 
   835             case ' ':
   843             case ' ':
   836                 if (!avail)
   844                 if (!avail)
   857 
   865 
   858 static void handle_pp_define(Context *ctx)
   866 static void handle_pp_define(Context *ctx)
   859 {
   867 {
   860     IncludeState *state = ctx->include_stack;
   868     IncludeState *state = ctx->include_stack;
   861 
   869 
   862     if (preprocessor_lexer(state) != TOKEN_IDENTIFIER)
   870     if (lexer(state) != TOKEN_IDENTIFIER)
   863     {
   871     {
   864         fail(ctx, "Macro names must be indentifiers");
   872         fail(ctx, "Macro names must be indentifiers");
   865         return;
   873         return;
   866     } // if
   874     } // if
   867 
   875 
   875     Buffer buffer;
   883     Buffer buffer;
   876     init_buffer(&buffer);
   884     init_buffer(&buffer);
   877 
   885 
   878     int done = 0;
   886     int done = 0;
   879     const char *source = NULL;
   887     const char *source = NULL;
   880     unsigned int bytes_left = 0;
       
   881     state->report_whitespace = 1;
   888     state->report_whitespace = 1;
   882     while ((!done) && (!ctx->out_of_memory))
   889     while ((!done) && (!ctx->out_of_memory))
   883     {
   890     {
   884         bytes_left = state->bytes_left;
   891         bytes_left = state->bytes_left;
   885         source = state->source;
   892         const Token token = lexer(state);
   886         const Token token = preprocessor_lexer(state);
       
   887         switch (token)
   893         switch (token)
   888         {
   894         {
   889             case TOKEN_INCOMPLETE_COMMENT:
   895             case TOKEN_INCOMPLETE_COMMENT:
   890             case TOKEN_EOI:
   896             case TOKEN_EOI:
   891                 state->bytes_left = bytes_left;
   897                 pushback(state);  // move back so we catch this later.
   892                 state->source = source;  // move back so we catch this later.
       
   893                 // fall through!
   898                 // fall through!
   894             case ((Token) '\n'):
   899             case ((Token) '\n'):
   895                 done = 1;
   900                 done = 1;
   896                 break;
   901                 break;
   897 
   902 
   930 
   935 
   931 static void handle_pp_undef(Context *ctx)
   936 static void handle_pp_undef(Context *ctx)
   932 {
   937 {
   933     IncludeState *state = ctx->include_stack;
   938     IncludeState *state = ctx->include_stack;
   934 
   939 
   935     if (preprocessor_lexer(state) != TOKEN_IDENTIFIER)
   940     if (lexer(state) != TOKEN_IDENTIFIER)
   936     {
   941     {
   937         fail(ctx, "Macro names must be indentifiers");
   942         fail(ctx, "Macro names must be indentifiers");
   938         return;
   943         return;
   939     } // if
   944     } // if
   940 
   945 
   956 {
   961 {
   957     IncludeState *state = ctx->include_stack;
   962     IncludeState *state = ctx->include_stack;
   958 
   963 
   959     assert((type == TOKEN_PP_IFDEF) || (type == TOKEN_PP_IFNDEF));
   964     assert((type == TOKEN_PP_IFDEF) || (type == TOKEN_PP_IFNDEF));
   960 
   965 
   961     if (preprocessor_lexer(state) != TOKEN_IDENTIFIER)
   966     if (lexer(state) != TOKEN_IDENTIFIER)
   962     {
   967     {
   963         fail(ctx, "Macro names must be indentifiers");
   968         fail(ctx, "Macro names must be indentifiers");
   964         return NULL;
   969         return NULL;
   965     } // if
   970     } // if
   966 
   971 
  1125         // TOKEN_PP_ELIF,
  1130         // TOKEN_PP_ELIF,
  1126 
  1131 
  1127         const Conditional *cond = state->conditional_stack;
  1132         const Conditional *cond = state->conditional_stack;
  1128         const int skipping = ((cond != NULL) && (cond->skipping));
  1133         const int skipping = ((cond != NULL) && (cond->skipping));
  1129 
  1134 
  1130         Token token = preprocessor_lexer(state);
  1135         Token token = lexer(state);
  1131         if (token == TOKEN_EOI)
  1136         if (token == TOKEN_EOI)
  1132         {
  1137         {
  1133             assert(state->bytes_left == 0);
  1138             assert(state->bytes_left == 0);
  1134             if (state->conditional_stack != NULL)
  1139             if (state->conditional_stack != NULL)
  1135             {
  1140             {