home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / command.l < prev    next >
Encoding:
Text File  |  2006-10-19  |  11.0 KB  |  496 lines

  1.  
  2. /*    scanner for configuration tokens  */
  3.  
  4. %{
  5.     #define YY_NEVER_INTERACTIVE 1
  6.     #define YY_INPUT(buf,result,maxsize) result = command_context_getstring(cf, buf, maxsize)
  7.  
  8.     #include <stdarg.h>
  9.     #include <stdlib.h>
  10.     #include <string.h>
  11.     #include "StringUtils.h"
  12.  
  13.     #define __COMMAND_L__
  14.  
  15.     #include "log.h"
  16.  
  17.     #define _L LOG_COMMANDS | LOG_INFO
  18.  
  19.     #include "xmalloc.h"
  20.     #include "moduledb.h"
  21.     #include "command.h"
  22.     #include "command_parser.h"
  23.     #include "command_lexer.h"
  24.     
  25.     #undef DEBUG
  26. //    #define DEBUG 1
  27.  
  28.  
  29.         /*    Utilities  */
  30.  
  31.     static int 
  32.     command_context_new_text(command_context **context,
  33.             const command_context *outer,
  34.             const char *name, const char *data, int len);
  35.  
  36.     static int 
  37.     command_context_new_file(command_context **context,
  38.             const command_context *outer,
  39.             const char *filename);
  40.  
  41.     static void 
  42.     command_context_free(command_context **context);
  43.  
  44.     static int 
  45.     command_context_getstring(command_context *context, 
  46.         char *buf, int maxsize);
  47.  
  48.     command_symbol_table *command_scope = NULL;
  49.  
  50.     #define TEST_MEMERR(x)  do { if ((x) != OS_NOERR) logger(_L | LOG_FATAL,"Out of memory\n"); } while (0)
  51.  
  52.     /*    Current command context being used by the scanner. */
  53.     static command_context *cf;
  54.     
  55.     /*    String buffer */
  56.     OSHandle lexer_string;
  57.  
  58.     #include "command.y.h"
  59.     
  60.         // F_V9t9 and F_TIFILES
  61.     #include "fiad.h"
  62. %}
  63.  
  64. %x  grouper
  65. %x    comment
  66. %x    preproc
  67. %x     string
  68.  
  69. DIGIT            [0-9]
  70. HEXDIG            [0-9a-fA-F]
  71. OCTDIG            [0-7]
  72. /*
  73. STRINGCHAR        [^\r\n\t +-\*]
  74. STRINGFIRST        [^\r\n\t 0123456789\"]
  75. */
  76. STRINGFIRST     [A-Za-z_/]
  77. /* STRINGCHAR        ({STRINGFIRST}|[:\\0-9\~]) */
  78. STRINGCHAR        [^ \t\r\n=()\";+\-*^&#]
  79. STRING            ({STRINGFIRST})({STRINGCHAR})*
  80. /*
  81. IDFIRST            [A-Za-z_\$]
  82. ID                 ({IDFIRST})({IDFIRST}|[0-9])*
  83. */
  84. EOLCH            [\r\n]
  85. EOL                ("\r\n"|"\r"|"\n")
  86. WS                [ \t]
  87. SIGN            ("-")*
  88.  
  89. %%
  90.  
  91.  
  92. {SIGN}"0x"{HEXDIG}+    {
  93.                     int sign = *yytext == '-';
  94.                 #ifdef DEBUG
  95.                     logger(_L | LOG_USER, "a hex number: %s\n", yytext);
  96.                 #endif
  97.                     yylval.expr.type = ca_NUM;
  98.                     yylval.expr.u.num = strtol(yytext+2+sign, NULL, 16);
  99.                     if (sign) yylval.expr.u.num = -yylval.expr.u.num;
  100.                     return NUM;
  101.                 }
  102.  
  103. {SIGN}"$"{HEXDIG}+    {
  104.                     int sign = *yytext == '-';
  105.                 #ifdef DEBUG
  106.                     logger(_L | LOG_USER, "a hex number: %s\n", yytext);
  107.                 #endif
  108.                     yylval.expr.type = ca_NUM;
  109.                     yylval.expr.u.num = strtol(yytext+1, NULL, 16);
  110.                     if (sign) yylval.expr.u.num = -yylval.expr.u.num;
  111.                     return NUM;
  112.                 }
  113.  
  114. {SIGN}"0"{OCTDIG}+     {
  115.                 #ifdef DEBUG
  116.                     logger(_L | LOG_USER, "an oct number: %s\n", yytext);
  117.                 #endif
  118.                     yylval.expr.type = ca_NUM;
  119.                     yylval.expr.u.num = strtol(yytext, NULL, 8);
  120.                     return NUM;
  121.                 }
  122.  
  123. {SIGN}{DIGIT}+        {
  124.                 #ifdef DEBUG
  125.                     logger(_L | LOG_USER, "a decimal number: %s\n", yytext);
  126.                 #endif
  127.                     yylval.expr.type = ca_NUM;
  128.                     yylval.expr.u.num = strtol(yytext, NULL, 10);
  129.                     return NUM;    
  130.                 } 
  131.  
  132.     /* boolean values */
  133. [tT][rR][uU][eE]|[oO][nN]|[yY][eE][sS] { 
  134.                     yylval.expr.type = ca_NUM; 
  135.                     yylval.expr.u.num = 1; 
  136.                     return NUM; 
  137.                     }
  138. [fF][aA][lL][sS][eE]|[oO][fF][fF]|[nN][oO] { 
  139.                     yylval.expr.type = ca_NUM; 
  140.                     yylval.expr.u.num = 0; 
  141.                     return NUM; 
  142.                     }
  143.  
  144. ">>"            return RSHIFT;
  145. "<<"            return LSHIFT;
  146. ">="            return COMPGE;
  147. "<="            return COMPLE;
  148. "=="             return COMPEQ;
  149. "!="|"<>"        return COMPNE;
  150. "&&"|"AND"        return COMPAND;
  151. "||"|"OR"        return COMPOR;
  152. "^^"|"XOR"        return COMPXOR;
  153. "and"            return '&';
  154. "or"            return '|';
  155. "xor"            return '^';
  156.  
  157. "print"            return PRINT;
  158.  
  159.         /* identifiers for modules.inf */
  160.  
  161. "MINIMEM"        yylval.expr.type = ca_NUM; yylval.expr.u.num = MOD_PART_MINIMEM; return NUM;
  162. "BANKED"        yylval.expr.type = ca_NUM; yylval.expr.u.num = MOD_PART_BANKED; return NUM;
  163. "GROM"            yylval.expr.type = ca_NUM; yylval.expr.u.num = MOD_PART_GROM; return NUM;
  164. "ROM"            yylval.expr.type = ca_NUM; yylval.expr.u.num = MOD_PART_ROM; return NUM;
  165. "GRAMKRACKER"   yylval.expr.type = ca_NUM; yylval.expr.u.num = MOD_PART_GRAMKRACKER; return NUM;
  166.  
  167.         /* identifiers for fileformat */
  168.  
  169. "F_V9T9"|"F_V9t9" yylval.expr.type = ca_NUM; yylval.expr.u.num = F_V9t9; return NUM;
  170. "F_TIFILES"        yylval.expr.type = ca_NUM; yylval.expr.u.num = F_TIFILES; return NUM;
  171.  
  172.  
  173. {EOL}            {
  174.                 #ifdef DEBUG
  175.                     logger(_L | LOG_USER, "line ending\n");
  176.                 #endif
  177.                     cf->line++;
  178.                     return '\n';
  179.                 }
  180.  
  181.  
  182. "#"                BEGIN(preproc);
  183.  
  184. <preproc>"include"{WS}+"\""([^\r\n]+)"\""{WS}* { 
  185.                     lexer_include(yytext);
  186.                     BEGIN(INITIAL);
  187.                 }
  188.  
  189. <preproc>"include"{WS}.* {
  190.                     lexer_error("incorrectly formed #include statement");
  191.                 }
  192.  
  193. <preproc>{EOL}    { BEGIN(INITIAL); cf->line++; }
  194.  
  195. <preproc>.        /* ignore rest of comment */
  196.  
  197. "//"[^\r\n]*{EOL} cf->line++;
  198.  
  199. {WS}            /* ignore whitespace */
  200.  
  201.  /* comment rules stolen from flex manual */
  202.  
  203. "/*"            BEGIN(comment);
  204.  
  205. <comment>[^*\r\n]*
  206. <comment>[^*\r\n]*{EOL}            cf->line++;
  207. <comment>"*"+[^*/\r\n]*
  208. <comment>"*"+[^*/\r\n]*{EOL}     cf->line++;
  209. <comment>"*"+"/"                 BEGIN(INITIAL);
  210.  
  211.  /* grouper */
  212.  
  213. "["            BEGIN(grouper);
  214.  
  215. <grouper>[^]\r\n]*
  216. <grouper>[^]\r\n]*{EOL}            cf->line++;
  217. <grouper>"]"                    BEGIN(INITIAL);
  218.  
  219. <<EOF>>            { if (!lexer_pop_context()) yyterminate(); }
  220.  
  221.    /* explicit string constant */
  222. "\""            { 
  223.                 #ifdef DEBUG
  224.                     logger(_L | LOG_USER, "a string: ");
  225.                 #endif
  226.                     BEGIN(string); 
  227.                     TEST_MEMERR(OS_NewHandle(0, &lexer_string)); 
  228.                 }
  229.  
  230. <string>"\\\""    TEST_MEMERR(OS_AppendHandle(&lexer_string, "\"", 1));
  231.  
  232. <string>"\\t"    TEST_MEMERR(OS_AppendHandle(&lexer_string, "\t", 1));
  233. <string>"\\b"    TEST_MEMERR(OS_AppendHandle(&lexer_string, "\b", 1));
  234. <string>"\\r"    TEST_MEMERR(OS_AppendHandle(&lexer_string, "\r", 1));
  235. <string>"\\n"    TEST_MEMERR(OS_AppendHandle(&lexer_string, "\n", 1));
  236. <string>"\\\\"    TEST_MEMERR(OS_AppendHandle(&lexer_string, "\\", 1));
  237.  
  238. <string>"\""    { 
  239.                     TEST_MEMERR(OS_AppendHandle(&lexer_string, "", 1)); 
  240.                     yylval.expr.u.str = strdup(OS_LockHandle(&lexer_string));
  241.                     OS_UnlockHandle(&lexer_string);
  242.                     OS_FreeHandle(&lexer_string);
  243.                 #ifdef DEBUG
  244.                     logger(_L | LOG_USER, "%s\n", yylval.expr.u.str);
  245.                 #endif
  246.                     BEGIN(INITIAL);
  247.                     return STRING;
  248.                 }
  249.  
  250. <string>{EOL}   
  251. <string><<EOF>>  {
  252.                     TEST_MEMERR(OS_AppendHandle(&lexer_string, "", 1)); 
  253.                     yylval.expr.u.str = xstrdup(OS_LockHandle(&lexer_string));
  254.                     OS_UnlockHandle(&lexer_string);
  255.                     OS_FreeHandle(&lexer_string);
  256.                     lexer_error("Unterminated string (%s)\n", yylval.expr.u.str);
  257.                     BEGIN(INITIAL);
  258.                     return STRING;
  259.                 }
  260. <string>.        TEST_MEMERR(OS_AppendHandle(&lexer_string, yytext, strlen(yytext)));
  261.  
  262.     /* implicit string constant */
  263.  
  264. {STRING}        {
  265. /*
  266.                 char *str;
  267.                 command_symbol *sym;
  268. #ifdef DEBUG
  269.                 logger(_L | LOG_USER, "an unquoted string: '%s'", yytext);
  270. #endif
  271.  
  272.                 if (command_match_symbol(command_scope, yytext, &sym))
  273.                 {
  274.                     yylval.expr.type = ca_SYM;        
  275.                     yylval.expr.u.str = xstrdup(yytext);
  276.                 #ifdef DEBUG
  277.                     logger(_L | L_0, "got an ID (%s)\n", yytext);
  278.                 #endif
  279.                     return IDSTRING;
  280.                 }
  281.                 else
  282. */
  283.                 {
  284.                     yylval.expr.type = ca_STRING;
  285.                     yylval.expr.u.str = xstrdup(yytext);
  286.                     return IDSTRING;
  287.                 }
  288.                 }
  289.  
  290. .                {
  291.                 //yylval.expr.type = ca_STRING;
  292.                 //yylval.expr.u.str = xstrdup(yytext);
  293.                 //return STRING;
  294.                 return *yytext;
  295.                 }
  296.  
  297. %%
  298.  
  299. static int 
  300. command_context_new_text(command_context **context,
  301.         const command_context *outer,
  302.         const char *name, const char *data, int len)
  303. {
  304.     my_assert(data != NULL);
  305.  
  306.     *context = (command_context *)xmalloc(sizeof(command_context));
  307.     
  308.     (*context)->outer = outer;
  309.  
  310.     if (name) (*context)->name = xstrdup(name); 
  311.     else (*context)->name = xstrdup("(unnamed)");
  312.     
  313.     if (!(*context) || !(*context)->name || 
  314.         OS_NewHandle(len, &(*context)->hand) != OS_NOERR)    
  315.         return 0;
  316.     
  317.     (*context)->len = len;
  318.     memcpy(OS_LockHandle(&(*context)->hand), data, len);
  319.     OS_UnlockHandle(&(*context)->hand);
  320.     
  321.     (*context)->offs = 0;
  322.     (*context)->line = 1;
  323.  
  324.     
  325.     return 1;
  326. }        
  327.  
  328. static int 
  329. command_context_new_file(command_context **context,
  330.         const command_context *outer,
  331.         const char *filename)
  332. {
  333.     OSFileHandle fhand;
  334.     OSError err;
  335.     OSSpec spec;
  336.  
  337.     my_assert(filename != NULL);
  338.  
  339.     *context = (command_context *)xmalloc(sizeof(command_context));
  340.     if (!*context)        return 0;
  341.     
  342.     (*context)->outer = outer;
  343.  
  344.     (*context)->name = (char *)xstrdup(filename); 
  345.     if (!(*context)->name)    return 0;
  346.  
  347.     if ((err = OS_MakeFileSpec(filename, &spec)) != OS_NOERR ||
  348.         (err = OS_NewFileHandle(&spec, NULL, false, &fhand)) != OS_NOERR ||
  349.         (err = OS_CopyHandle(&fhand.hand, &(*context)->hand)) != OS_NOERR ||
  350.         (err = OS_FreeFileHandle(&fhand)) != OS_NOERR)
  351.     {
  352.         logger(LOG_COMMANDS|LOG_ERROR|LOG_USER, "Couldn't get/copy file text from '%s':\n%s\n", filename, OS_GetErrText(err));
  353.         return 0;
  354.     }
  355.  
  356.     OS_GetHandleSize(&(*context)->hand, &(*context)->len);
  357.     
  358.     (*context)->offs = 0;
  359.     (*context)->line = 1;
  360.  
  361.     return 1;
  362. }
  363.  
  364. static void 
  365. command_context_free(command_context **context)
  366. {
  367.     if (context == NULL || *context == NULL)
  368.         return;
  369.         
  370.     if ((*context)->name)    xfree((*context)->name);
  371.     OS_FreeHandle(&(*context)->hand);
  372.     xfree(*context);
  373.     
  374.     *context = NULL;
  375. }
  376.  
  377.  
  378. /*    Routine to read text from our command buffer instead of stdin */    
  379. static int command_context_getstring(command_context *context, 
  380.     char *buf, int maxsize)
  381. {
  382.     void *ptr;
  383.     OSSize cpy;
  384. //    my_assert(context != NULL);
  385.  
  386.     if (context == NULL)
  387.         return 0;
  388.  
  389.     ptr = OS_LockHandle(&context->hand);
  390.  
  391.     cpy = ((context->len - context->offs) < maxsize) ? 
  392.         (context->len - context->offs) : 
  393.         maxsize;
  394.     memcpy(buf, ((char *)ptr) + context->offs, cpy);
  395.     context->offs += cpy;
  396.  
  397.     OS_UnlockHandle(&context->hand);
  398.     
  399.     return cpy;
  400. }
  401.  
  402. /******************************/
  403.  
  404. command_context *lexer_push_text(const char *name, const char *data, int len)
  405. {
  406.     command_context *cc;
  407. #ifdef DEBUG
  408.     logger(_L | LOG_USER, "lexer: reading from text '%s'\n", name);
  409. #endif
  410.     if (!command_context_new_text(&cc, cf, name, data, len))
  411.         return NULL;
  412.  
  413.     if (cf)
  414.     {
  415.         cf->yybuf = YY_CURRENT_BUFFER;
  416.         yy_switch_to_buffer(yy_create_buffer(NULL, cc->len));
  417.     }
  418.     
  419.     cf = cc;
  420.     return cf;
  421. }
  422.  
  423. command_context *lexer_push_file(const char *filename)
  424. {
  425.     command_context *cc;
  426. #ifdef DEBUG
  427.     logger(_L | LOG_USER, "lexer: reading from file '%s'\n", filename);
  428. #endif
  429.     if (!command_context_new_file(&cc, cf, filename))
  430.         return NULL;
  431.  
  432.     if (cf)
  433.     {
  434.         cf->yybuf = YY_CURRENT_BUFFER;
  435.         yy_switch_to_buffer(yy_create_buffer(NULL, cc->len));
  436.     }
  437.  
  438.     cf = cc;
  439.     return cf;
  440. }
  441.  
  442. command_context *lexer_pop_context(void)
  443. {
  444.     if (cf != NULL)
  445.     {
  446.         command_context *outer = (command_context *)cf->outer;
  447.         command_context_free(&cf);
  448.  
  449.         if (outer)
  450.         {
  451.             yy_delete_buffer(YY_CURRENT_BUFFER);
  452.             yy_switch_to_buffer(outer->yybuf);
  453.         }
  454.         
  455.         cf = outer;
  456.     #ifdef DEBUG
  457.         logger(_L | LOG_USER, "lexer: popping context to '%s'\n", cf ? cf->name : "<null>");
  458.     #endif
  459.         return cf;
  460.     }
  461.  
  462. #ifdef DEBUG
  463.     logger(LOG_FATAL,"popped null lexer context\n");
  464. #endif
  465.     return NULL;
  466. }
  467.  
  468. void    lexer_error(const char *comm, ...)
  469. {
  470.     va_list va;
  471.     static char buf[256], *bptr;
  472.     va_start(va, comm);
  473.     bptr = mvprintf(buf, sizeof(buf), comm, va);
  474.     logger(LOG_USER|LOG_ERROR, "%s:%d: %s\n", cf ? cf->name : "<unnamed>", 
  475.             cf ? cf->line : 0, bptr);
  476.     if (bptr != buf) free(bptr);
  477. }
  478.  
  479. void    lexer_include(char *yy)
  480. {
  481.     char extract[256];
  482.     
  483.     char *st = strchr(yy, '\"')+1;
  484.     char *en = strchr(st, '\"');
  485.     if (en-st > 256) en = st+256;
  486.     memcpy(extract, st, en-st);
  487.     extract[en-st] = 0;
  488.     
  489.     lexer_push_file(extract);
  490. }
  491.  
  492. int yywrap(void)
  493. {
  494.     return 1;
  495. }
  496.