home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / cproto-3.0 / lex.l < prev    next >
Encoding:
Lex Description  |  1995-05-03  |  13.3 KB  |  597 lines

  1. %{
  2. /* $Id: lex.l 3.10 1993/05/26 01:36:04 cthuang Exp $
  3.  *
  4.  * Lexical analyzer for C function prototype generator
  5.  */
  6.  
  7. static int curly;    /* number of curly brace nesting levels */
  8. static int ly_count;    /* number of occurances of %% */
  9.  
  10. #ifdef FLEX_SCANNER
  11. /* flex scanner state */
  12. static YY_BUFFER_STATE buffer_stack[MAX_INC_DEPTH];
  13. #endif
  14.  
  15. static int inc_depth;                /* include nesting level */
  16. static IncludeStack inc_stack[MAX_INC_DEPTH];    /* stack of included files */
  17. static SymbolTable *included_files;        /* files already included */
  18.  
  19. static void update_line_num();
  20. static void save_text();
  21. static void save_text_offset();
  22. static void get_comment();
  23. static void get_cpp_directive();
  24. static void do_include();
  25.  
  26. extern void yyerror();
  27. #ifdef yywrap
  28. #undef yywrap
  29. #endif
  30. %}
  31.  
  32. WS        [ \t]
  33. LETTER        [A-Za-z_]
  34. DIGIT        [0-9]
  35. ID        {LETTER}({LETTER}|{DIGIT})*
  36. STRING        \"(\\.|\\\n|[^"\\])*\"
  37. QUOTED        ({STRING}|\'(\\\'|[^'\n])*\'|\\.)
  38.  
  39. %s CPP1 INIT1 INIT2 CURLY LEXYACC ASM
  40. %%
  41.  
  42. \n            { save_text(); cur_file->line_num++;
  43.                 cur_declarator = NULL; }
  44.  
  45. "/*"            { save_text(); get_comment(); }
  46. "//".*$         save_text();
  47.  
  48. <LEXYACC>^"%%"        { save_text(); if (++ly_count >= 2) BEGIN INITIAL; }
  49. <LEXYACC>^"%{"        { save_text(); BEGIN INITIAL; }
  50. <LEXYACC>{QUOTED}    { save_text(); update_line_num(); }
  51. <LEXYACC>.        save_text();
  52. <INITIAL>^"%}"        { save_text(); BEGIN LEXYACC; }
  53.  
  54. <INITIAL>#{WS}*     { save_text(); BEGIN CPP1; }
  55. <INITIAL>"??="{WS}*     { save_text(); BEGIN CPP1; }
  56.  
  57. <CPP1>define{WS}+{ID}    {
  58.                 char name[MAX_TEXT_SIZE], value[MAX_TEXT_SIZE];
  59.  
  60.                 save_text();
  61.                 sscanf(yytext, "define %s", name);
  62.                 get_cpp_directive(buf, sizeof(buf));
  63.                 sscanf(buf, "%s", value);
  64.                 new_symbol(define_names, name, value, DS_NONE);
  65.             }
  66.  
  67. <CPP1>include{WS}*    {
  68.                 save_text();
  69.                 get_cpp_directive(buf, sizeof(buf));
  70.                 if (buf[0] != '"' && buf[0] != '<') {
  71.                 Symbol *sym = find_symbol(define_names, buf);
  72.                 if (sym != NULL && sym->value != NULL) {
  73.                     strcpy(buf, sym->value);
  74.                 } else {
  75.                     buf[0] = '\0';
  76.                 }
  77.                 }
  78.                 if (buf[0] != '\0')
  79.                 do_include(buf);
  80.             }
  81.  
  82. <CPP1>line{WS}+[0-9]+{WS}+\".*$  {
  83.                 save_text();
  84.                 sscanf(yytext, "line %d \"%[^\"]\"",
  85.                  &cur_file->line_num, cur_file->file_name);
  86.                 cur_file->line_num--;
  87.                 BEGIN INITIAL;
  88.             }
  89. <CPP1>[0-9]+{WS}+\".*$  {
  90.                 save_text();
  91.                 sscanf(yytext, "%d \"%[^\"]\"", &cur_file->line_num,
  92.                  cur_file->file_name);
  93.                 cur_file->line_num--;
  94.                 BEGIN INITIAL;
  95.             }
  96. <CPP1>[0-9]+.*$     {
  97.                 save_text();
  98.                 sscanf(yytext, "%d ", &cur_file->line_num);
  99.                 cur_file->line_num--;
  100.                 BEGIN INITIAL;
  101.             }
  102.  
  103. <CPP1>.         { save_text(); get_cpp_directive(NULL, 0); }
  104.  
  105. <INITIAL>"("        { save_text_offset(); return '('; }
  106. <INITIAL>")"        {
  107.                 save_text();
  108.                 if (cur_file->convert)
  109.                 cur_file->begin_comment =
  110.                  ftell(cur_file->tmp_file);
  111.                 return ')';
  112.             }
  113. <INITIAL>"*"        { save_text_offset(); return '*'; }
  114. <INITIAL>","        { save_text(); return ','; }
  115. <INITIAL>";"        {
  116.                 save_text();
  117.                 if (cur_file->convert)
  118.                 cur_file->begin_comment =
  119.                  ftell(cur_file->tmp_file);
  120.                 return ';';
  121.             }
  122. <INITIAL>"..."        { save_text(); return T_ELLIPSIS; }
  123. <INITIAL>{STRING}    {
  124.                 save_text();
  125.                 update_line_num();
  126.                 return T_STRING_LITERAL;
  127.             }
  128.  
  129. <INITIAL>asm        { save_text(); BEGIN ASM; return T_ASM; }
  130. <ASM>"("        save_text();
  131. <ASM>")"        { save_text(); BEGIN INITIAL; return T_ASMARG; }
  132. <ASM>{QUOTED}         { save_text(); update_line_num(); }
  133. <ASM>.             save_text();
  134.  
  135. <INITIAL>__?based[^(]*\([^)]*\)    { save_text_offset(); return T_TYPE_QUALIFIER; }
  136.  
  137. <INITIAL>auto        { save_text_offset(); return T_AUTO; }
  138. <INITIAL>extern     { save_text_offset(); return T_EXTERN; }
  139. <INITIAL>register    { save_text_offset(); return T_REGISTER; }
  140. <INITIAL>static     { save_text_offset(); return T_STATIC; }
  141. <INITIAL>typedef    { save_text_offset(); return T_TYPEDEF; }
  142. <INITIAL>inline     { save_text_offset(); return T_INLINE; }
  143. <INITIAL>char        { save_text_offset(); return T_CHAR; }
  144. <INITIAL>double     { save_text_offset(); return T_DOUBLE; }
  145. <INITIAL>float        { save_text_offset(); return T_FLOAT; }
  146. <INITIAL>int        { save_text_offset(); return T_INT; }
  147. <INITIAL>void        { save_text_offset(); return T_VOID; }
  148. <INITIAL>long        { save_text_offset(); return T_LONG; }
  149. <INITIAL>short        { save_text_offset(); return T_SHORT; }
  150. <INITIAL>signed     { save_text_offset(); return T_SIGNED; }
  151. <INITIAL>unsigned    { save_text_offset(); return T_UNSIGNED; }
  152. <INITIAL>enum        { save_text_offset(); return T_ENUM; }
  153. <INITIAL>struct     { save_text_offset(); return T_STRUCT; }
  154. <INITIAL>union        { save_text_offset(); return T_UNION; }
  155. <INITIAL>va_dcl        { save_text_offset(); return T_VA_DCL; }
  156.  
  157. <INITIAL>{ID}        {
  158.                 save_text_offset();
  159.                 if (find_symbol(type_qualifiers, yytext) != NULL)
  160.                 return T_TYPE_QUALIFIER;
  161.                 else if (find_symbol(typedef_names, yytext) != NULL)
  162.                 return T_TYPEDEF_NAME;
  163.                 else if (find_symbol(define_names, yytext) != NULL)
  164.                 return T_DEFINE_NAME;
  165.                 else
  166.                 return T_IDENTIFIER;
  167.             }
  168.  
  169. <INITIAL>\[[^\]]*\]    {
  170.                 /* This can't handle the case where a comment
  171.                  * containing a ] appears between the brackets.
  172.                  */
  173.                 save_text_offset();
  174.                 update_line_num();
  175.                 return T_BRACKETS;
  176.             }
  177. <INITIAL>"??("[^?]*"??)"    {
  178.                 save_text_offset();
  179.                 update_line_num();
  180.                 return T_BRACKETS;
  181.             }
  182.  
  183. <INITIAL>"="        { save_text(); BEGIN INIT1; return '='; }
  184. <INIT1>"{"        { save_text(); curly = 1; BEGIN INIT2; }
  185. <INIT1>[,;]        {
  186.                 unput(yytext[yyleng-1]);
  187.                 BEGIN INITIAL;
  188.                 return T_INITIALIZER;
  189.             }
  190. <INIT1>{QUOTED}        { save_text(); update_line_num(); }
  191. <INIT1>.        save_text();
  192.  
  193. <INIT2>"{"        { save_text(); ++curly; }
  194. <INIT2>"}"        {
  195.                 save_text();
  196.                 if (--curly == 0) {
  197.                 BEGIN INITIAL;
  198.                 return T_INITIALIZER;
  199.                 }
  200.             }
  201. <INIT2>{QUOTED}        { save_text(); update_line_num(); }
  202. <INIT2>.        save_text();
  203.  
  204. <INITIAL>"{"        {
  205.                 save_text();
  206.                 curly = 1;
  207.                 BEGIN CURLY;
  208.                 return T_LBRACE;
  209.             }
  210. <CURLY>"{"        { save_text(); ++curly; }
  211. <CURLY>"}"        {
  212.                 save_text();
  213.                 if (--curly == 0) {
  214.                 BEGIN INITIAL;
  215.                 return T_MATCHRBRACE;
  216.                 }
  217.             }
  218. <CURLY>{QUOTED}        { save_text(); update_line_num(); }
  219. <CURLY>.        save_text();
  220.  
  221. [ \t\f]+        save_text();
  222. .            {
  223.                 save_text();
  224.                 put_error();
  225.                 fprintf(stderr, "bad character '%c'\n", yytext[0]);
  226.             }
  227. %%
  228.  
  229. /* If the matched text contains any new line characters, then update the
  230.  * current line number.
  231.  */
  232. static void
  233. update_line_num ()
  234. {
  235.     char *p = yytext;
  236.     while (*p != '\0') {
  237.     if (*p++ == '\n')
  238.         cur_file->line_num++;
  239.     }
  240. }
  241.  
  242. /* Save the matched text in the temporary file.
  243.  */
  244. static void
  245. save_text ()
  246. {
  247.     if (cur_file->convert) {
  248.     fputs(yytext, cur_file->tmp_file);
  249.     }
  250. }
  251.  
  252. /* Record the current position in the temporary file and write the matched text
  253.  * to the file.
  254.  */
  255. static void
  256. save_text_offset ()
  257. {
  258.     strcpy(yylval.text.text, yytext);
  259.     if (cur_file->convert) {
  260.     yylval.text.begin = ftell(cur_file->tmp_file);
  261.     fputs(yytext, cur_file->tmp_file);
  262.     }
  263. }
  264.  
  265. /* Scan to end of comment.
  266.  */
  267. static void
  268. get_comment ()
  269. {
  270.     int c, lastc = '\0';
  271.  
  272.     while ((c = input()) != 0) {
  273.     if (cur_file->convert)
  274.         fputc(c, cur_file->tmp_file);
  275.     switch (c) {
  276.     case '\n':
  277.         cur_file->line_num++;
  278.         break;
  279.     case '/':
  280.         if (lastc == '*') {
  281.         if (cur_file->convert) {
  282.             if (func_params && cur_declarator) {
  283.             cur_declarator->begin_comment = cur_file->begin_comment;
  284.             cur_file->begin_comment = ftell(cur_file->tmp_file);
  285.             cur_declarator->end_comment = cur_file->begin_comment;
  286.             cur_declarator = NULL;
  287.             } else {
  288.             cur_file->end_comment = ftell(cur_file->tmp_file);
  289.             }
  290.         }
  291.         return;
  292.         }
  293.         break;
  294.     }
  295.     lastc = c;
  296.     }
  297. }
  298.  
  299. /* Scan rest of preprocessor directive.  If <dest> is not NULL, then store
  300.  * the text in the buffer pointed to by <dest> having size <n>.
  301.  */
  302. static void
  303. get_cpp_directive (dest, n)
  304. char *dest;        /* buffer to store directive text */
  305. unsigned n;        /* size of buffer to store directive text */
  306. {
  307.     char c, lastc[4];
  308.     
  309.     lastc[0] = lastc[1] = lastc[2] = lastc[3] = '\0';
  310.     if (dest != NULL)
  311.     *dest = '\0';
  312.  
  313.     while ((c = input()) != 0) {
  314.     if (cur_file->convert)
  315.         fputc(c, cur_file->tmp_file);
  316.  
  317.     switch (c) {
  318.     case '\n':
  319.         cur_file->line_num++;
  320.         if (lastc[2] != '\\' && strcmp(lastc, "?\?/") != 0) {
  321.         BEGIN INITIAL;
  322.         return;
  323.         }
  324.         break;
  325.     case '*':
  326.         if (lastc[2] == '/')
  327.         get_comment();
  328.         break;
  329.     }
  330.     lastc[0] = lastc[1];
  331.     lastc[1] = lastc[2];
  332.     lastc[2] = c;
  333.  
  334.     if (dest != NULL && n > 1) {
  335.         *dest++ = c;
  336.         *dest = '\0';
  337.         --n;
  338.     }
  339.     }
  340. }
  341.  
  342. /* Return a pointer to the current file name.
  343.  */
  344. char *
  345. cur_file_name ()
  346. {
  347.     return cur_file->file_name;
  348. }
  349.  
  350. /* Return the current line number.
  351.  */
  352. unsigned
  353. cur_line_num ()
  354. {
  355.     return cur_file->line_num;
  356. }
  357.  
  358. /* Return the current temporary output file.
  359.  */
  360. FILE *
  361. cur_tmp_file ()
  362. {
  363.     return cur_file->tmp_file;
  364. }
  365.  
  366. /* Set the modify flag for the current file.
  367.  */
  368. void
  369. cur_file_changed ()
  370. {
  371.     cur_file->changed = TRUE;
  372. }
  373.  
  374. /* Return the temporary file offset of beginning of the current comment.
  375.  */
  376. long
  377. cur_begin_comment ()
  378. {
  379.     return cur_file->begin_comment;
  380. }
  381.  
  382. /* Return the text of the current lexical token.
  383.  */
  384. char *
  385. cur_text ()
  386. {
  387.     return yytext;
  388. }
  389.  
  390. #ifdef NEED_tmpfile
  391. /*
  392.  * tmpfile() - return a FILE* for a temporary file that will be
  393.  * removed automatically when the program exits.
  394.  * 
  395.  * Not all systems have the ANSI tmpfile() function yet...
  396.  *
  397.  * DaviD W. Sanderson (dws@cs.wisc.edu)
  398.  */
  399. FILE *
  400. tmpfile ()
  401. {
  402.     char name[MAX_TEXT_SIZE];
  403.     char *tmpdir;
  404.     FILE *f;
  405.  
  406.     if ((tmpdir = getenv("TMPDIR")) == (char *)0)
  407.     {
  408.     tmpdir = "/tmp";
  409.     }
  410.     sprintf(name, "%s/TfXXXXXX", tmpdir);
  411.     mktemp(name);
  412.  
  413.     if ((f = fopen(name, "w+")) == (FILE *)0)
  414.     {
  415.     return (FILE *)0;
  416.     }
  417.  
  418.     if (unlink(name) == -1)
  419.     {
  420.     fclose(f);
  421.     return (FILE *)0;
  422.     }
  423.  
  424.     return f;
  425. }
  426. #endif /* NEED_tmpfile */
  427.  
  428. /* Push a file onto the include stack.    The stream yyin must already
  429.  * point to the file.
  430.  */
  431. static void
  432. include_file (name, convert)
  433. char *name;        /* file name */
  434. boolean convert;    /* if TRUE, convert function definitions */
  435. {
  436.     ++inc_depth;
  437.     cur_file = inc_stack + inc_depth;
  438.     cur_file->file = yyin;
  439.     cur_file->base_name = xstrdup(name);
  440.     cur_file->file_name = strcpy(xmalloc(MAX_TEXT_SIZE), name);
  441.     cur_file->line_num = 1;
  442.     cur_file->convert = convert;
  443.     cur_file->changed = FALSE;
  444.  
  445. #ifdef FLEX_SCANNER
  446.     buffer_stack[inc_depth] = yy_create_buffer(yyin, YY_BUF_SIZE);
  447.     yy_switch_to_buffer(buffer_stack[inc_depth]);
  448. #endif
  449.  
  450.     if (convert) {
  451.     cur_file->begin_comment = cur_file->end_comment = 0;
  452.     cur_file->tmp_file = tmpfile();
  453.     if (cur_file->tmp_file == NULL) {
  454.         fprintf(stderr, "%s: cannot create temporary file\n", progname);
  455.         cur_file->convert = FALSE;
  456.     }
  457.     }
  458. }
  459.  
  460. #define BLOCK_SIZE 2048
  461.  
  462. /* Copy converted C source from the temporary file to the output stream.
  463.  */
  464. static void
  465. put_file (outf)
  466. FILE *outf;
  467. {
  468.     char block[BLOCK_SIZE];
  469.     long filesize;
  470.     unsigned nread, count;
  471.  
  472.     filesize = ftell(cur_file->tmp_file);
  473.     fseek(cur_file->tmp_file, 0L, 0);
  474.     while (filesize > 0) {
  475.     count = (filesize < BLOCK_SIZE) ? (unsigned)filesize : BLOCK_SIZE;
  476.     nread = fread(block, sizeof(char), count, cur_file->tmp_file);
  477.     if (nread == 0)
  478.         break;
  479.     fwrite(block, sizeof(char), nread, outf);
  480.     filesize -= nread;
  481.     }
  482. }
  483.  
  484. /* Remove the top of the include stack.
  485.  */
  486. void
  487. pop_file ()
  488. {
  489.     FILE *outf;
  490.  
  491.     if (yyin != stdin)
  492.     fclose(yyin);
  493.  
  494.     if (cur_file->convert) {
  495.     if (yyin == stdin) {
  496.         put_file(stdout);
  497.     } else if (cur_file->changed) {
  498.         if ((outf = fopen(cur_file->base_name, "w")) != NULL) {
  499.         put_file(outf);
  500.         fclose(outf);
  501.         } else {
  502.         fprintf(stderr, "%s: cannot create file %s\n", progname,
  503.          cur_file->base_name);
  504.         }
  505.     }
  506.  
  507.     fclose(cur_file->tmp_file);
  508.     }
  509.     free(cur_file->base_name);
  510.     free(cur_file->file_name);
  511.  
  512. #ifdef FLEX_SCANNER
  513.     yy_delete_buffer(YY_CURRENT_BUFFER);
  514. #endif
  515.  
  516.     if (--inc_depth >= 0) {
  517.     cur_file = inc_stack + inc_depth;
  518.     yyin = cur_file->file;
  519.  
  520. #ifdef FLEX_SCANNER
  521.     yy_switch_to_buffer(buffer_stack[inc_depth]);
  522. #endif
  523.     }
  524. }
  525.  
  526. /* Process include directive.
  527.  */
  528. static void
  529. do_include (file_spec)
  530. char *file_spec;     /* path surrounded by "" or <> */
  531. {
  532.     int stdinc;     /* 1 = path surrounded by <> */
  533.     char file[MAX_TEXT_SIZE], path[MAX_TEXT_SIZE];
  534.     char match, *s;
  535.     int i;
  536.     unsigned n;
  537.     FILE *fp;
  538.  
  539.     if (inc_depth >= MAX_INC_DEPTH-1) {
  540.     put_error();
  541.     fprintf(stderr, "includes too deeply nested\n");
  542.     return;
  543.     }
  544.  
  545.     if (file_spec[0] == '"') {
  546.     match = '"';
  547.     stdinc = 0;
  548.     } else if (file_spec[0] == '<') {
  549.     match = '>';
  550.     stdinc = 1;
  551.     } else {
  552.     return;
  553.     }
  554.     s = strchr(file_spec+1, match);
  555.     n = (s != NULL) ? (unsigned)(s - file_spec - 1) : 0;
  556.     strncpy(file, file_spec+1, n);
  557.     file[n] = '\0';
  558.  
  559.     /* Do nothing if the file was already included. */
  560.     sprintf(path, stdinc ? "<%s>" : "\"%s\"", file);
  561.     if (find_symbol(included_files, path) != NULL)
  562.     return;
  563.     new_symbol(included_files, path, NULL, DS_NONE);
  564.  
  565.     for (i = stdinc != 0; i < num_inc_dir; ++i) {
  566.     if (strlen(inc_dir[i]) == 0) {
  567.         strcpy(path, file);
  568.     } else {
  569.         sprintf(path, "%s/%s", inc_dir[i], file);
  570.     }
  571.     if ((fp = fopen(path, "r")) != NULL) {
  572.         yyin = fp;
  573.         include_file(path, func_style != FUNC_NONE && !stdinc);
  574.         return;
  575.     }
  576.     }
  577.  
  578.     if (!quiet) {
  579.     put_error();
  580.     fprintf(stderr, "cannot read file %s\n", file_spec);
  581.     }
  582. }
  583.  
  584. /* When the end of the current input file is reached, pop a
  585.  * nested include file.
  586.  */
  587. int
  588. yywrap ()
  589. {
  590.     if (inc_depth > 0) {
  591.     pop_file();
  592.     return 0;
  593.     } else {
  594.     return 1;
  595.     }
  596. }
  597.