home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume13 / ansi-c_su / part01 next >
Text File  |  1990-06-15  |  25KB  |  1,317 lines

  1. Newsgroups: comp.sources.misc
  2. From: shankar@hpclscu.cup.hp.com (Shankar Unni)
  3. subject: v13i052: Skeleton Parser and Lexer for ANSI C
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 13, Issue 52
  7. Submitted-by: shankar@hpclscu.cup.hp.com (Shankar Unni)
  8. Archive-name: ansi-c_su/part01
  9.  
  10. The following shar file is a set of source files (and test cases) for a
  11. small, portable parser and lexer for ANSI C. This stuff originally came to
  12. me from Vick Khera (@CMU), and I have beefed it up to handle typedef's
  13. properly, and do some rudimentary line-control.
  14.  
  15. If you have any enhancements, bug-fixes or requests, send it to me
  16. (shankar%hpclscu@hpda.hp.com).
  17.  
  18.  
  19. # This is a shell archive.  Remove anything before this line,
  20. # then unpack it by saving it in a file and typing "sh file".
  21. #
  22. # Wrapped by Shankar Unni <shankar@hpclscu> on Wed Jun 13 19:35:25 1990
  23. #
  24. # This archive contains:
  25. #    Makefile    README        TEST1.C        TEST2.C        
  26. #    gram.y        main.c        misctypes.h    scan.l        
  27. #    scanaux.c    scanaux.h    
  28. #
  29.  
  30. LANG=""; export LANG
  31. PATH=/bin:/usr/bin:$PATH; export PATH
  32.  
  33. echo x - Makefile
  34. cat >Makefile <<'@EOF'
  35. YFLAGS    = -d
  36. CFLAGS    = -g
  37. LFLAGS    =
  38.  
  39. SRC    = gram.y scan.l main.c scanaux.c misctypes.h scanaux.h
  40. OBJ    = main.o gram.o scan.o scanaux.o
  41. TESTS   = TEST1.C TEST2.C
  42. BIN    = ansi_c
  43.  
  44. $(BIN)    :    $(OBJ)
  45.     cc $(CFLAGS) $(OBJ) -o $(BIN)
  46.  
  47. scan.o    : y.tab.h
  48.  
  49. clean    :
  50.     rm -f y.tab.h y.output *.o
  51.  
  52. test: ansi_c $(TESTS)
  53.     for fn in $(TESTS); do echo " "; echo $$fn: ; ansi_c < $$fn ; done
  54.  
  55. shar: CGRAM.SHAR
  56.  
  57. CGRAM.SHAR: README Makefile $(SRC) $(TESTS)
  58.     shar -c README Makefile $(SRC) $(TESTS) > $@
  59. @EOF
  60.  
  61. chmod 664 Makefile
  62.  
  63. echo x - README
  64. cat >README <<'@EOF'
  65. This grammar implements the latest ANSI C grammar. I'm not sure if there
  66. are any omissions. This stuff came to me from outside HP (via Vick Khera
  67. of CMU), and I have sort of fixed it up to conform to the latest draft of
  68. the standard (Dec 88). I'm not sure if I missed out on anything..
  69.  
  70. I added all the typedef-handling code (scanaux.c). It can handle nested
  71. re-declarations of typedefs and all that jazz.
  72.  
  73. Notes:
  74.  
  75. 1. To make the parser, type "make". This should produce a program file
  76.    called "ansi_c".
  77.  
  78. 2. The scanner recognizes the cpp line specificiers of the form
  79.    "# <number> [ <filename> ]", and sets internal variables accordingly.
  80.    Any other line starting with "#" is ignored (this includes pragmas).
  81.    If you need to do something with these, change the function line_number.
  82.  
  83. 3. By default, the parse is silent. However, if the "ansi_c" skeleton is
  84.    run with the "-L" option, then the input is echoed to the output. In
  85.    general, if you want the input echoed, set the global variable "input_echo".
  86.  
  87. 4. There are a couple of test cases to make sure that ansi_c compiled
  88.    correctly. After making the parser, try "make test".
  89.  
  90. ----
  91. Shankar.
  92. shankar%hpclscu@hpda.hp.com
  93.  
  94. P.S. If you do make any improvements to this, I'd appreciate a copy of the
  95. changes.
  96. @EOF
  97.  
  98. chmod 664 README
  99.  
  100. echo x - TEST1.C
  101. cat >TEST1.C <<'@EOF'
  102. extern int fum(const char *);
  103. typedef int FOO;
  104. int BAR;
  105.  
  106. FOO junk;
  107.  
  108. func1()
  109. {
  110.     char *FOO;
  111.     typedef char *BAR;
  112.     BAR junk;
  113.  
  114.     FOO = 0;
  115. }
  116.  
  117. struct {
  118.     int FOO;
  119.     int BAR;
  120.     struct {
  121.     FOO junk;
  122.     } junk;
  123. } xxx;
  124.  
  125. struct {
  126.     FOO BAR;
  127. } yyy;
  128.  
  129. func2()
  130. {
  131.     FOO junk;
  132.  
  133.     BAR = 0;
  134. }
  135. @EOF
  136.  
  137. chmod 664 TEST1.C
  138.  
  139. echo x - TEST2.C
  140. cat >TEST2.C <<'@EOF'
  141. struct foo {int a;};
  142. typedef int foo;
  143. struct foo bar;
  144. foo fum;
  145. int foo();
  146. foo bar;
  147. @EOF
  148.  
  149. chmod 664 TEST2.C
  150.  
  151. echo x - gram.y
  152. cat >gram.y <<'@EOF'
  153. %{
  154. #include "misctypes.h"
  155. #include "scanaux.h"
  156. extern char yytext[];
  157. extern int yyleng;
  158. %}
  159. %token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF
  160. %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
  161. %token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
  162. %token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
  163. %token XOR_ASSIGN OR_ASSIGN TYPE_NAME
  164.  
  165. %token TYPEDEF EXTERN STATIC AUTO REGISTER
  166. %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
  167. %token STRUCT UNION ENUM ELLIPSIS
  168.  
  169. %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
  170.  
  171. %start translation_unit
  172. %%
  173.  
  174. primary_expr
  175.     : identifier
  176.     | CONSTANT
  177.     | STRING_LITERAL
  178.     | '(' expr ')'
  179.     ;
  180.  
  181. postfix_expr
  182.     : primary_expr
  183.     | postfix_expr '[' expr ']'
  184.     | postfix_expr '(' ')'
  185.     | postfix_expr '(' argument_expr_list ')'
  186.     | postfix_expr '.' identifier
  187.     | postfix_expr PTR_OP identifier
  188.     | postfix_expr INC_OP
  189.     | postfix_expr DEC_OP
  190.     ;
  191.  
  192. argument_expr_list
  193.     : assignment_expr
  194.     | argument_expr_list ',' assignment_expr
  195.     ;
  196.  
  197. unary_expr
  198.     : postfix_expr
  199.     | INC_OP unary_expr
  200.     | DEC_OP unary_expr
  201.     | unary_operator cast_expr
  202.     | SIZEOF unary_expr
  203.     | SIZEOF '(' type_name ')'
  204.     ;
  205.  
  206. unary_operator
  207.     : '&'
  208.     | '*'
  209.     | '+'
  210.     | '-'
  211.     | '~'
  212.     | '!'
  213.     ;
  214.  
  215. cast_expr
  216.     : unary_expr
  217.     | '(' type_name ')' cast_expr
  218.     ;
  219.  
  220. multiplicative_expr
  221.     : cast_expr
  222.     | multiplicative_expr '*' cast_expr
  223.     | multiplicative_expr '/' cast_expr
  224.     | multiplicative_expr '%' cast_expr
  225.     ;
  226.  
  227. additive_expr
  228.     : multiplicative_expr
  229.     | additive_expr '+' multiplicative_expr
  230.     | additive_expr '-' multiplicative_expr
  231.     ;
  232.  
  233. shift_expr
  234.     : additive_expr
  235.     | shift_expr LEFT_OP additive_expr
  236.     | shift_expr RIGHT_OP additive_expr
  237.     ;
  238.  
  239. relational_expr
  240.     : shift_expr
  241.     | relational_expr '<' shift_expr
  242.     | relational_expr '>' shift_expr
  243.     | relational_expr LE_OP shift_expr
  244.     | relational_expr GE_OP shift_expr
  245.     ;
  246.  
  247. equality_expr
  248.     : relational_expr
  249.     | equality_expr EQ_OP relational_expr
  250.     | equality_expr NE_OP relational_expr
  251.     ;
  252.  
  253. and_expr
  254.     : equality_expr
  255.     | and_expr '&' equality_expr
  256.     ;
  257.  
  258. exclusive_or_expr
  259.     : and_expr
  260.     | exclusive_or_expr '^' and_expr
  261.     ;
  262.  
  263. inclusive_or_expr
  264.     : exclusive_or_expr
  265.     | inclusive_or_expr '|' exclusive_or_expr
  266.     ;
  267.  
  268. logical_and_expr
  269.     : inclusive_or_expr
  270.     | logical_and_expr AND_OP inclusive_or_expr
  271.     ;
  272.  
  273. logical_or_expr
  274.     : logical_and_expr
  275.     | logical_or_expr OR_OP logical_and_expr
  276.     ;
  277.  
  278. conditional_expr
  279.     : logical_or_expr
  280.     | logical_or_expr '?' expr ':' conditional_expr
  281.     ;
  282.  
  283. assignment_expr
  284.     : conditional_expr
  285.     | unary_expr assignment_operator assignment_expr
  286.     ;
  287.  
  288. assignment_operator
  289.     : '='
  290.     | MUL_ASSIGN
  291.     | DIV_ASSIGN
  292.     | MOD_ASSIGN
  293.     | ADD_ASSIGN
  294.     | SUB_ASSIGN
  295.     | LEFT_ASSIGN
  296.     | RIGHT_ASSIGN
  297.     | AND_ASSIGN
  298.     | XOR_ASSIGN
  299.     | OR_ASSIGN
  300.     ;
  301.  
  302. expr
  303.     : assignment_expr
  304.     | expr ',' assignment_expr
  305.     ;
  306.  
  307. constant_expr
  308.     : conditional_expr
  309.     ;
  310.  
  311. declaration
  312.     : declaration_specifiers ';'
  313.       {reset_in_typedef(); set_typedef_recognition(); }
  314.     | declaration_specifiers init_declarator_list ';'
  315.       {reset_in_typedef(); set_typedef_recognition(); }
  316.     ;
  317.  
  318. declaration_specifiers
  319.     : storage_class_specifier
  320.     | storage_class_specifier declaration_specifiers
  321.     | type_specifier
  322.     | type_specifier declaration_specifiers
  323.     | type_qualifier
  324.     | type_qualifier declaration_specifiers
  325.     ;
  326.  
  327. init_declarator_list
  328.     : init_declarator
  329.     | init_declarator_list ',' init_declarator
  330.     ;
  331.  
  332. init_declarator
  333.     : declarator
  334.     | declarator '=' initializer
  335.     ;
  336.  
  337. storage_class_specifier
  338.     : TYPEDEF { set_in_typedef(); }
  339.     | EXTERN
  340.     | STATIC
  341.     | AUTO
  342.     | REGISTER
  343.     ;
  344.  
  345. type_specifier
  346.     : { reset_typedef_recognition(); } type_specifier2
  347.     ;
  348.  
  349. type_specifier2
  350.     : VOID
  351.     | CHAR
  352.     | SHORT
  353.     | INT
  354.     | LONG
  355.     | FLOAT
  356.     | DOUBLE
  357.     | SIGNED
  358.     | UNSIGNED
  359.     | struct_or_union_specifier
  360.     | enum_specifier
  361.     | typedef_name
  362.     ;
  363.  
  364. struct_or_union_specifier
  365.     : struct_or_union identifier struct_body
  366.     | struct_or_union struct_body
  367.     | struct_or_union identifier
  368.     ;
  369.  
  370. struct_body
  371.     : { push_in_memberlist();
  372.         push_in_typedef();
  373.         set_in_memberlist();
  374.         reset_in_typedef(); 
  375.         set_typedef_recognition(); }
  376.       '{' struct_declaration_list '}'
  377.       { reset_typedef_recognition();
  378.         pop_in_typedef();
  379.         pop_in_memberlist(); }
  380.  
  381. struct_or_union
  382.     : STRUCT { reset_typedef_recognition(); }
  383.     | UNION { reset_typedef_recognition(); }
  384.     ;
  385.  
  386. struct_declaration_list
  387.     : struct_declaration
  388.     | struct_declaration_list struct_declaration
  389.     ;
  390.  
  391. struct_declaration
  392.     : { set_typedef_recognition(); }
  393.       struct_declaration2
  394.     ;
  395.  
  396. struct_declaration2
  397.     : specifier_qualifier_list struct_declarator_list ';'
  398.     ;
  399.  
  400. specifier_qualifier_list
  401.     : type_specifier
  402.     | type_specifier specifier_qualifier_list
  403.     | type_qualifier
  404.     | type_qualifier specifier_qualifier_list
  405.     ;
  406.  
  407. struct_declarator_list
  408.     : struct_declarator
  409.     | struct_declarator_list ',' struct_declarator
  410.     ;
  411.  
  412. struct_declarator
  413.     : declarator
  414.     | ':' constant_expr
  415.     | declarator ':' constant_expr
  416.     ;
  417.  
  418. enum_specifier
  419.     : enum_head '{' enumerator_list '}'
  420.     | enum_head identifier '{' enumerator_list '}'
  421.     | enum_head identifier
  422.     ;
  423.  
  424. enum_head
  425.     : ENUM { reset_typedef_recognition(); }
  426.     ;
  427.  
  428. enumerator_list
  429.     : enumerator
  430.     | enumerator_list ',' enumerator
  431.     ;
  432.  
  433. enumerator
  434.     : identifier
  435.     | identifier '=' constant_expr
  436.     ;
  437.  
  438. type_qualifier
  439.     : CONST
  440.     | VOLATILE
  441.     ;
  442.  
  443. declarator
  444.     : direct_declarator
  445.     | pointer direct_declarator
  446.     ;
  447.  
  448. direct_declarator
  449.     : identifier { enter_tdname (yytext, yyleng); }
  450.     | '(' declarator ')'
  451.     | direct_declarator '[' ']'
  452.     | direct_declarator '[' constant_expr ']'
  453.     | direct_declarator '(' ')'
  454.     | direct_declarator '(' parameter_type_list ')'
  455.     | direct_declarator '(' identifier_list ')'
  456.     ;
  457.  
  458. pointer
  459.     : '*'
  460.     | '*' type_qualifier_list
  461.     | '*' pointer
  462.     | '*' type_qualifier_list pointer
  463.     ;
  464.  
  465. type_qualifier_list
  466.     : type_qualifier
  467.     | type_qualifier_list type_qualifier
  468.     ;
  469.  
  470. identifier_list
  471.     : identifier
  472.     | identifier_list ',' identifier
  473.     ;
  474.  
  475. parameter_type_list
  476.     : { push_in_typedef();
  477.         set_typedef_recognition();
  478.         reset_in_typedef(); }
  479.       parameter_type_list2
  480.       { pop_in_typedef();
  481.         reset_typedef_recognition(); }
  482.  
  483. parameter_type_list2
  484.     : parameter_list
  485.     | parameter_list ',' ELLIPSIS
  486.     ;
  487.  
  488. parameter_list
  489.     : parameter_declaration
  490.     | parameter_list ',' parameter_declaration
  491.     ;
  492.  
  493. parameter_declaration
  494.     : declaration_specifiers declarator
  495.     | declaration_specifiers
  496.     | declaration_specifiers abstract_declarator
  497.     ;
  498.  
  499. type_name
  500.     : specifier_qualifier_list
  501.     | specifier_qualifier_list abstract_declarator
  502.     ;
  503.  
  504. abstract_declarator
  505.     : pointer
  506.     | direct_abstract_declarator
  507.     | pointer direct_abstract_declarator
  508.     ;
  509.  
  510. direct_abstract_declarator
  511.     : '(' abstract_declarator ')'
  512.     | '[' ']'
  513.     | '[' constant_expr ']'
  514.     | direct_abstract_declarator '[' ']'
  515.     | direct_abstract_declarator '[' constant_expr ']'
  516.     | '(' ')'
  517.     | '(' parameter_type_list ')'
  518.     | direct_abstract_declarator '(' ')'
  519.     | direct_abstract_declarator '(' parameter_type_list ')'
  520.     ;
  521.  
  522. typedef_name
  523.     : TYPE_NAME
  524.     ;
  525.  
  526. initializer
  527.     : assignment_expr
  528.     | '{' initializer_list '}'
  529.     | '{' initializer_list ',' '}'
  530.     ;
  531.  
  532. initializer_list
  533.     : initializer
  534.     | initializer_list ',' initializer
  535.     ;
  536.  
  537. statement
  538.     : labeled_statement
  539.     | compound_statement
  540.     | expression_statement
  541.     | selection_statement
  542.     | iteration_statement
  543.     | jump_statement
  544.     ;
  545.  
  546. labeled_statement
  547.     : identifier ':' statement
  548.     | CASE constant_expr ':' statement
  549.     | DEFAULT ':' statement
  550.     ;
  551.  
  552. compound_statement
  553.     : '{' cs_decl_list cs_stmt_list '}'
  554.     ;
  555.  
  556. cs_decl_list
  557.     : { enter_TD_scope(); }
  558.       declaration_list
  559.       { exit_TD_scope(); }
  560.     |
  561.     ;
  562.  
  563. cs_stmt_list
  564.     : { reset_typedef_recognition(); }
  565.       statement_list
  566.     |
  567.     ;
  568.  
  569. declaration_list
  570.     : declaration
  571.     | declaration_list declaration
  572.     ;
  573.  
  574. statement_list
  575.     : statement
  576.     | statement_list statement
  577.     ;
  578.  
  579. expression_statement
  580.     : ';'
  581.     | expr ';'
  582.     ;
  583.  
  584. selection_statement
  585.     : IF '(' expr ')' statement
  586.     | IF '(' expr ')' statement ELSE statement
  587.     | SWITCH '(' expr ')' statement
  588.     ;
  589.  
  590. iteration_statement
  591.     : WHILE '(' expr ')' statement
  592.     | DO statement WHILE '(' expr ')' ';'
  593.     | FOR '(' ';' ';' ')' statement
  594.     | FOR '(' ';' ';' expr ')' statement
  595.     | FOR '(' ';' expr ';' ')' statement
  596.     | FOR '(' ';' expr ';' expr ')' statement
  597.     | FOR '(' expr ';' ';' ')' statement
  598.     | FOR '(' expr ';' ';' expr ')' statement
  599.     | FOR '(' expr ';' expr ';' ')' statement
  600.     | FOR '(' expr ';' expr ';' expr ')' statement
  601.     ;
  602.  
  603. jump_statement
  604.     : GOTO identifier ';'
  605.     | CONTINUE ';'
  606.     | BREAK ';'
  607.     | RETURN ';'
  608.     | RETURN expr ';'
  609.     ;
  610.  
  611. translation_unit
  612.     : external_declaration
  613.     | translation_unit external_declaration
  614.     ;
  615.  
  616. external_declaration
  617.     : { set_typedef_recognition(); reset_in_typedef(); }
  618.       external_declaration2
  619.     ;
  620.  
  621. external_declaration2
  622.     : function_definition
  623.     | declaration
  624.     ;
  625.  
  626. function_definition
  627.     : declarator function_body
  628.     | declaration_specifiers declarator function_body
  629.     ;
  630.  
  631. function_body
  632.     : compound_statement
  633.     | declaration_list  compound_statement
  634.     ;
  635.  
  636. identifier
  637.     : IDENTIFIER
  638.     ;
  639. %%
  640.  
  641. #include <stdio.h>
  642.  
  643. extern int yycolumn, yylineno;
  644. extern unsigned char yyfilename[];
  645.  
  646. yyerror(s)
  647. char *s;
  648. {
  649.     fflush(stdout);
  650.     if (input_echo) {
  651.         printf("\n%*s\n", yycolumn, "^");
  652.     }
  653.     printf ("%s, line %d: %s\n", yyfilename, yylineno, s);
  654. }
  655. @EOF
  656.  
  657. chmod 664 gram.y
  658.  
  659. echo x - main.c
  660. cat >main.c <<'@EOF'
  661. #include "scanaux.h"
  662.  
  663. int input_echo = 0;
  664.  
  665. main(argc, argv)
  666. int argc;
  667. char **argv;
  668. {
  669.     int yyparse();
  670.  
  671.     if ((argc >=2) && (strcmp (argv[1], "-L") == 0)) {
  672.         input_echo = 1;
  673.     }
  674.     init_scanner();
  675.     return(yyparse());
  676. }
  677. @EOF
  678.  
  679. chmod 664 main.c
  680.  
  681. echo x - misctypes.h
  682. cat >misctypes.h <<'@EOF'
  683. #define TRUE 1
  684. #define FALSE 0
  685. @EOF
  686.  
  687. chmod 664 misctypes.h
  688.  
  689. echo x - scan.l
  690. cat >scan.l <<'@EOF'
  691. D            [0-9]
  692. L            [a-zA-Z_]
  693. H            [a-fA-F0-9]
  694. E            [Ee][+-]?{D}+
  695. FS            (f|F|l|L)
  696. IS            (u|U|l|L)*
  697.  
  698. %{
  699. #include <stdio.h>
  700. #include "scanaux.h"
  701. #include "y.tab.h"
  702.  
  703. #undef input
  704. extern int input();
  705.  
  706. unsigned char yyfilename[256] = "stdin";
  707. %}
  708.  
  709. %%
  710.  
  711. "#"            { line_number(); }
  712. "/*"            { comment(); }
  713.  
  714. "auto"            { return(AUTO); }
  715. "break"            { return(BREAK); }
  716. "case"            { return(CASE); }
  717. "char"            { return(CHAR); }
  718. "const"            { return(CONST); }
  719. "continue"        { return(CONTINUE); }
  720. "default"        { return(DEFAULT); }
  721. "do"            { return(DO); }
  722. "double"        { return(DOUBLE); }
  723. "else"            { return(ELSE); }
  724. "enum"            { return(ENUM); }
  725. "extern"        { return(EXTERN); }
  726. "float"            { return(FLOAT); }
  727. "for"            { return(FOR); }
  728. "goto"            { return(GOTO); }
  729. "if"            { return(IF); }
  730. "int"            { return(INT); }
  731. "long"            { return(LONG); }
  732. "register"        { return(REGISTER); }
  733. "return"        { return(RETURN); }
  734. "short"            { return(SHORT); }
  735. "signed"        { return(SIGNED); }
  736. "sizeof"        { return(SIZEOF); }
  737. "static"        { return(STATIC); }
  738. "struct"        { return(STRUCT); }
  739. "switch"        { return(SWITCH); }
  740. "typedef"        { return(TYPEDEF); }
  741. "union"            { return(UNION); }
  742. "unsigned"        { return(UNSIGNED); }
  743. "void"            { return(VOID); }
  744. "volatile"        { return(VOLATILE); }
  745. "while"            { return(WHILE); }
  746.  
  747. {L}({L}|{D})*        { return(check_type()); }
  748.  
  749. 0[xX]{H}+{IS}?        { return(CONSTANT); }
  750. 0[xX]{H}+{IS}?        { return(CONSTANT); }
  751. 0{D}+{IS}?        { return(CONSTANT); }
  752. 0{D}+{IS}?        { return(CONSTANT); }
  753. {D}+{IS}?        { return(CONSTANT); }
  754. {D}+{IS}?        { return(CONSTANT); }
  755. '(\\.|[^\\'])+'        { return(CONSTANT); }
  756.  
  757. {D}+{E}{FS}?        { return(CONSTANT); }
  758. {D}*"."{D}+({E})?{FS}?    { return(CONSTANT); }
  759. {D}+"."{D}*({E})?{FS}?    { return(CONSTANT); }
  760.  
  761. \"(\\.|[^\\"])*\"    { return(STRING_LITERAL); }
  762.  
  763. "..."                   { return(ELLIPSIS); }
  764. ">>="            { return(RIGHT_ASSIGN); }
  765. "<<="            { return(LEFT_ASSIGN); }
  766. "+="            { return(ADD_ASSIGN); }
  767. "-="            { return(SUB_ASSIGN); }
  768. "*="            { return(MUL_ASSIGN); }
  769. "/="            { return(DIV_ASSIGN); }
  770. "%="            { return(MOD_ASSIGN); }
  771. "&="            { return(AND_ASSIGN); }
  772. "^="            { return(XOR_ASSIGN); }
  773. "|="            { return(OR_ASSIGN); }
  774. ">>"            { return(RIGHT_OP); }
  775. "<<"            { return(LEFT_OP); }
  776. "++"            { return(INC_OP); }
  777. "--"            { return(DEC_OP); }
  778. "->"            { return(PTR_OP); }
  779. "&&"            { return(AND_OP); }
  780. "||"            { return(OR_OP); }
  781. "<="            { return(LE_OP); }
  782. ">="            { return(GE_OP); }
  783. "=="            { return(EQ_OP); }
  784. "!="            { return(NE_OP); }
  785. ";"            { return(';'); }
  786. "{"            { return('{'); }
  787. "}"            { return('}'); }
  788. ","            { return(','); }
  789. ":"            { return(':'); }
  790. "="            { return('='); }
  791. "("            { return('('); }
  792. ")"            { return(')'); }
  793. "["            { return('['); }
  794. "]"            { return(']'); }
  795. "."            { return('.'); }
  796. "&"            { return('&'); }
  797. "!"            { return('!'); }
  798. "~"            { return('~'); }
  799. "-"            { return('-'); }
  800. "+"            { return('+'); }
  801. "*"            { return('*'); }
  802. "/"            { return('/'); }
  803. "%"            { return('%'); }
  804. "<"            { return('<'); }
  805. ">"            { return('>'); }
  806. "^"            { return('^'); }
  807. "|"            { return('|'); }
  808. "?"            { return('?'); }
  809.  
  810. [ \t\v\n\f]        { }
  811. .            { /* ignore bad characters */ }
  812.  
  813. %%
  814.  
  815. int yycolumn = 0;
  816.  
  817. yywrap()
  818. {
  819.     return(1);
  820. }
  821.  
  822. int input()
  823. {
  824.     if (yysptr > yysbuf) {
  825.         /* retrieve pushed-back character */
  826.         yytchar = *--yysptr;
  827.     } else {
  828.         yytchar = getc(yyin);
  829.         if (yytchar == EOF) {
  830.             return 0;
  831.         } else if (input_echo) {
  832.             output(yytchar);
  833.         }
  834.     }
  835.  
  836.     /* count yycolumn and yylineno */
  837.     if (yytchar == '\n') {
  838.         yylineno++;
  839.         yycolumn = 0;
  840.     } else if (yytchar == '\t') {
  841.         yycolumn += 8 - (yycolumn % 8);
  842.     } else {
  843.         yycolumn++;
  844.     }
  845.  
  846.     return yytchar;
  847. }
  848.  
  849. comment()
  850. {
  851.     char c, c1;
  852.  
  853. loop:
  854.     /* we have already seen a / and a * */
  855.     while ((c = input()) != '*' && c != 0) /* NOTHING */;
  856.  
  857.     if (c != 0 && (c1 = input()) != '/' )
  858.     {
  859.         unput(c1);
  860.         goto loop;
  861.     }
  862. }
  863.  
  864. #define READWHILE(cond)    while(cond) c = input();
  865. line_number()
  866. {
  867.     char c;
  868.     /* skip spaces */
  869.     c = input();
  870.     READWHILE ((c == ' ' || c == '\t'));
  871.  
  872.     if (c >= '0' && c <= '9') {
  873.         /* line number specification */
  874.         int line_num = 0;
  875.         while (c >= '0' && c <= '9') {
  876.             line_num = line_num * 10 + c - '0';
  877.             c = input();
  878.         }
  879.         if (line_num > 0)
  880.             yylineno = line_num - 1;
  881.         READWHILE ((c == ' ' || c == '\t'));
  882.         if (c == '"') {
  883.             unsigned char *yf = yyfilename;
  884.             do {
  885.                 *yf++ = c;
  886.                 c = input();
  887.             } while (c != '"');
  888.             *yf++ = c;
  889.             *yf = '\0';
  890.         }
  891.     }
  892.  
  893.     /* flush rest of line */
  894.     READWHILE ((c != '\n'));
  895. }
  896.  
  897. int check_type()
  898. {
  899.  
  900.     if (lookup_tdname(yytext, yyleng))
  901.     return (TYPE_NAME);
  902.     else
  903.     return (IDENTIFIER);
  904. }
  905. @EOF
  906.  
  907. chmod 664 scan.l
  908.  
  909. echo x - scanaux.c
  910. cat >scanaux.c <<'@EOF'
  911. #include <assert.h>
  912. #include <stdio.h>
  913. #include "misctypes.h"
  914.  
  915. #define TYPEDEF_UNKNOWN    -1
  916. #define TYPEDEF_FALSE    0
  917. #define TYPEDEF_TRUE    1
  918.  
  919. static int in_typedef = FALSE;
  920. static int typedef_recognition = TRUE;
  921. static int in_memberlist = FALSE;
  922.  
  923. extern char *malloc();
  924. extern char *realloc();
  925. extern char *calloc();
  926.  
  927. /* TSS types */
  928.  
  929. #define TSS_INCR 16
  930. static struct typedef_state_stack {
  931.     int TOS;
  932.     int MAX;
  933.     int *values;
  934. } TSS, RDS;
  935. /*
  936.  * TSS is used to push values of state variables like in_typedef and
  937.  *      typedef_recognition
  938.  *
  939.  * RDS is used to keep track of identifiers re-defined in inner scopes.
  940.  */
  941.  
  942. /* Typedef Table types */
  943. static struct TypedefTable {
  944.     char **tab;
  945.     int cur;
  946.     int max;
  947. } TDT;
  948.  
  949. /* ID Hash Tbl types */
  950.  
  951. #define IDHASH_INCR 32
  952. #define HASHSIZE 509
  953.  
  954. struct hashbucket {
  955.     int nxt_entry;
  956.     int max_entry;
  957.     int entry[1];
  958. };
  959.  
  960. static struct hashbucket *HTBL [HASHSIZE];    /* hopefully zeros? */
  961.  
  962. /* Char pool */
  963.  
  964. #define CHARBLOCKSIZE 1024
  965. struct charpool_block {
  966.     int next_ch;
  967.     char chars[CHARBLOCKSIZE];
  968. };
  969.  
  970. #define CHARPOOL_INCR 128
  971. static struct charpool {
  972.     struct charpool_block **char_pool;
  973.     int maxind;
  974.     int curind;
  975. } CP;
  976.  
  977. static char *recalloc (ptr, oldnumelems, newnumelems, elemsize)
  978. char *ptr;
  979. int oldnumelems;
  980. int newnumelems;
  981. int elemsize;
  982. {
  983.     char *t = calloc (newnumelems, elemsize);
  984.     memcpy (t, ptr, oldnumelems * elemsize);
  985.     free (ptr);
  986.     return t;
  987. }
  988.  
  989. void init_scanner()
  990. {
  991.     TSS.TOS = -1;
  992.     TSS.MAX = TSS_INCR;
  993.     TSS.values = (int *)malloc (TSS_INCR * sizeof(int *));
  994.  
  995.     RDS.TOS = -1;
  996.     RDS.MAX = TSS_INCR;
  997.     RDS.values = (int *)malloc (TSS_INCR * sizeof(int *));
  998.  
  999.     CP.char_pool = (struct charpool_block **)
  1000.             malloc (CHARPOOL_INCR * sizeof (struct charpool_block *));
  1001.     CP.char_pool[0] = (struct charpool_block *)
  1002.                       malloc (sizeof (struct charpool_block));
  1003.     CP.char_pool[0]->next_ch = 0;
  1004.     CP.maxind = CHARPOOL_INCR;
  1005.     CP.curind = 0;
  1006.  
  1007.     TDT.tab = (char **) calloc (CHARPOOL_INCR, sizeof (char *));
  1008.     TDT.cur = -1;
  1009.     TDT.max = CHARPOOL_INCR;
  1010. }
  1011.  
  1012. static void push_TSS (val)
  1013. int val;
  1014. {
  1015.     if (++TSS.TOS > TSS.MAX) {
  1016.     TSS.MAX += TSS_INCR;
  1017.     TSS.values = (int *) realloc (TSS.values, TSS.MAX * sizeof(int *));
  1018.     if (! TSS.values) {
  1019.         fprintf (stderr, "realloc failed in push_TSS\n");
  1020.         exit(1);
  1021.     }
  1022.     }
  1023.     TSS.values[TSS.TOS] = val;
  1024. }
  1025.  
  1026. static int pop_TSS ()
  1027. {
  1028.     if (TSS.TOS < 0) {
  1029.     fprintf (stderr, "TSS underflow\n");
  1030.     exit(1);
  1031.     }
  1032.     return (TSS.values[TSS.TOS--]);
  1033. }
  1034.  
  1035. static void push_RDS (val)
  1036. int val;
  1037. {
  1038.     if (++RDS.TOS > RDS.MAX) {
  1039.     RDS.MAX += TSS_INCR;
  1040.     RDS.values = (int *) realloc (RDS.values, RDS.MAX * sizeof(int *));
  1041.     if (! RDS.values) {
  1042.         fprintf (stderr, "realloc failed in push_RDS\n");
  1043.         exit(1);
  1044.     }
  1045.     }
  1046.     RDS.values[RDS.TOS] = val;
  1047. }
  1048.  
  1049. static int pop_RDS ()
  1050. {
  1051.     if (RDS.TOS < 0) {
  1052.     fprintf (stderr, "RDS underflow\n");
  1053.     exit(1);
  1054.     }
  1055.     return (RDS.values[RDS.TOS--]);
  1056. }
  1057.  
  1058. int IDhash (text, leng)
  1059. char *text;
  1060. int leng;
  1061. {
  1062.     short sum = 0, temp;
  1063.  
  1064.     while (leng > 0) {
  1065.     temp = *text++;
  1066.     temp <<= 8;
  1067.     temp |= *text++;
  1068.     leng -= 2;
  1069.     sum ^= temp;
  1070.     }
  1071.     return (sum %= HASHSIZE);
  1072. }
  1073.  
  1074. static int add_charpool (text, leng)
  1075. {
  1076.     int start;
  1077.     struct charpool_block *tcpb;
  1078.  
  1079.     if ((CHARBLOCKSIZE - CP.char_pool[CP.curind]->next_ch) < (leng+1)) {
  1080.     if (CP.curind++ > CP.maxind) {
  1081.         CP.maxind += CHARPOOL_INCR;
  1082.         CP.char_pool = (struct charpool_block **) realloc (CP.char_pool,
  1083.                   CP.maxind * sizeof (struct charpool_block *));
  1084.     }
  1085.     CP.char_pool[CP.curind] = (struct charpool_block *)
  1086.                       malloc (sizeof (struct charpool_block));
  1087.     CP.char_pool[CP.curind]->next_ch = 0;
  1088.     }
  1089.  
  1090.     tcpb = CP.char_pool[CP.curind];
  1091.     start = CP.curind * CHARBLOCKSIZE + tcpb->next_ch;
  1092.     memcpy (tcpb->chars + tcpb->next_ch, text, leng);
  1093.     tcpb->next_ch += (leng + 1);
  1094.     tcpb->chars[tcpb->next_ch - 1] = '\0';
  1095.     return start;
  1096. }
  1097.  
  1098. static int cpcmp (text, leng, index)
  1099. char *text;
  1100. int leng;
  1101. int index;
  1102. {
  1103.     int high = index / CHARBLOCKSIZE;
  1104.     int low = index % CHARBLOCKSIZE;
  1105.     char *start = CP.char_pool[high]->chars + low;
  1106.  
  1107.     return (memcmp (text, start, leng));
  1108. }
  1109.  
  1110. static int enterIDhash (text, leng)
  1111. char *text;
  1112. int leng;
  1113. {
  1114.     int i;
  1115.     int hval = IDhash (text, leng);
  1116.     struct hashbucket *htmp;
  1117.  
  1118.     /* search in hash tbl */
  1119.     if (!HTBL[hval]) {
  1120.     HTBL[hval] = (struct hashbucket *)
  1121.                      malloc ((IDHASH_INCR + 2) * sizeof(int));
  1122.     HTBL[hval]->nxt_entry = 0;
  1123.     HTBL[hval]->max_entry = IDHASH_INCR;
  1124.     }
  1125.  
  1126.     htmp = HTBL[hval];
  1127.     for (i = 0; i < htmp->nxt_entry; i++) {
  1128.     if (!cpcmp (text, leng, htmp->entry[i])) {
  1129.         return htmp->entry[i];
  1130.     }
  1131.     }
  1132.     
  1133.     if (htmp->nxt_entry > htmp->max_entry) {
  1134.     htmp->max_entry += IDHASH_INCR;
  1135.     HTBL[hval] = (struct hashbucket *)
  1136.             realloc (htmp, (htmp->max_entry + 2) * sizeof(int));
  1137.     htmp = HTBL[hval];
  1138.     }
  1139.     htmp->entry[htmp->nxt_entry++] = add_charpool (text, leng);
  1140. }
  1141.  
  1142. static void set_typedef (index, val)
  1143. int index;
  1144. int val;
  1145. {
  1146.     int low, high;
  1147.  
  1148.     high = index / CHARBLOCKSIZE;
  1149.     low = index % CHARBLOCKSIZE;
  1150.  
  1151.     if (high >  TDT.cur) {
  1152.     assert (high == (TDT.cur + 1));
  1153.     if (++TDT.cur > TDT.max) {
  1154.         TDT.tab = (char **) recalloc (TDT.tab, TDT.max,
  1155.                     TDT.max+CHARPOOL_INCR, sizeof (char *));
  1156.         TDT.max += CHARPOOL_INCR;
  1157.     }
  1158.     }
  1159.     if (! TDT.tab[high]) {
  1160.     TDT.tab[high] = (char *) malloc (CHARBLOCKSIZE * sizeof(char));
  1161.     memset (TDT.tab[high], TYPEDEF_UNKNOWN, CHARBLOCKSIZE);
  1162.     }
  1163.  
  1164.     TDT.tab[high][low] = val;
  1165. }
  1166.  
  1167. static int lookup_typedef (index)
  1168. int index;
  1169. {
  1170.     int low, high;
  1171.  
  1172.     high = index / CHARBLOCKSIZE;
  1173.     low = index % CHARBLOCKSIZE;
  1174.     return (TDT.tab[high] ? TDT.tab[high][low] : TYPEDEF_UNKNOWN);
  1175. }
  1176.  
  1177. int lookup_tdname(text, leng)
  1178. char *text;
  1179. int leng;
  1180. {
  1181.     int IDindex;
  1182.  
  1183.     if (typedef_recognition) {
  1184.     IDindex = enterIDhash (text, leng);
  1185.     return (lookup_typedef(IDindex) == TYPEDEF_TRUE);
  1186.     } else {
  1187.     return FALSE;
  1188.     }
  1189. }
  1190.  
  1191. void enter_tdname(text, leng)
  1192. char *text;
  1193. int leng;
  1194. {
  1195.     int IDindex, oldval;
  1196.  
  1197.     IDindex = enterIDhash (text, leng);
  1198.     oldval = lookup_typedef (IDindex);
  1199.     if (in_typedef) {
  1200.     if (RDS.TOS >= 0 && oldval == TYPEDEF_FALSE)
  1201.         push_RDS (IDindex);
  1202.     set_typedef (IDindex, TYPEDEF_TRUE);
  1203.     } else if (! in_memberlist) {
  1204.     if (RDS.TOS >= 0 && oldval == TYPEDEF_TRUE)
  1205.         push_RDS (IDindex);
  1206.     set_typedef (IDindex, TYPEDEF_FALSE);
  1207.     }
  1208. }
  1209.  
  1210. void enter_TD_scope()
  1211. {
  1212.     push_RDS (-1);
  1213. }
  1214.  
  1215. void exit_TD_scope()
  1216. {
  1217.     int k;
  1218.  
  1219.     while ((k = pop_RDS()) != -1) {
  1220.     if (lookup_typedef(k)) {
  1221.         set_typedef (k, FALSE);
  1222.     } else {
  1223.         set_typedef (k, TRUE);
  1224.     }
  1225.     }
  1226. }
  1227.  
  1228. void set_in_memberlist()
  1229. {
  1230.     in_memberlist = TRUE;
  1231. }
  1232.  
  1233. void reset_in_memberlist()
  1234. {
  1235.     in_memberlist = FALSE;
  1236. }
  1237.  
  1238. void push_in_memberlist()
  1239. {
  1240.     push_TSS(in_memberlist);
  1241. }
  1242.  
  1243. void pop_in_memberlist()
  1244. {
  1245.     in_memberlist = pop_TSS();
  1246. }
  1247.  
  1248. void set_in_typedef()
  1249. {
  1250.     in_typedef = TRUE;
  1251. }
  1252.  
  1253. void reset_in_typedef()
  1254. {
  1255.     in_typedef = FALSE;
  1256. }
  1257.  
  1258. void push_in_typedef()
  1259. {
  1260.     push_TSS(in_typedef);
  1261. }
  1262.  
  1263. void pop_in_typedef()
  1264. {
  1265.     in_typedef = pop_TSS();
  1266. }
  1267.  
  1268. void set_typedef_recognition()
  1269. {
  1270.     typedef_recognition = TRUE;
  1271. }
  1272.  
  1273. void reset_typedef_recognition()
  1274. {
  1275.     typedef_recognition = FALSE;
  1276. }
  1277. @EOF
  1278.  
  1279. chmod 664 scanaux.c
  1280.  
  1281. echo x - scanaux.h
  1282. cat >scanaux.h <<'@EOF'
  1283. void init_scanner();
  1284. void push_TSS ();
  1285. int pop_TSS ();
  1286.  
  1287. extern void set_in_memberlist(),
  1288.         reset_in_memberlist(),
  1289.         push_in_memberlist(),
  1290.         pop_in_memberlist(),
  1291.         set_in_typedef(),
  1292.         reset_in_typedef(),
  1293.         push_in_typedef(),
  1294.         pop_in_typedef(),
  1295.         set_typedef_recognition(),
  1296.         reset_typedef_recognition();
  1297.  
  1298. extern int  lookup_tdname();
  1299.  
  1300. extern int  input_echo;
  1301. @EOF
  1302.  
  1303. chmod 664 scanaux.h
  1304.  
  1305. exit 0
  1306.  
  1307. -----
  1308. Shankar Unni                                   E-Mail: 
  1309. Hewlett-Packard California Language Lab.     Internet: shankar@hpda.hp.com
  1310. Phone : (408) 447-5797                           UUCP: ...!hplabs!hpda!shankar
  1311.  
  1312. DISCLAIMER:
  1313. This response does not represent the official position of, or statement by,
  1314. the Hewlett-Packard Company.  The above data is provided for informational
  1315. purposes only.  It is supplied without warranty of any kind.
  1316.  
  1317.