home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume20 / cproto next >
Encoding:
Text File  |  1989-10-19  |  35.3 KB  |  1,692 lines

  1. Path: wuarchive!brutus.cs.uiuc.edu!uakari.primate.wisc.edu!xanth!bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v20i039:  Generate C function prototypes from C source
  5. Message-ID: <2037@prune.bbn.com>
  6. Date: 19 Oct 89 17:21:41 GMT
  7. Lines: 1682
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: Chin Huang <cthuang@watdragon.waterloo.edu>
  11. Posting-number: Volume 20, Issue 39
  12. Archive-name: cproto
  13.  
  14. [  Not to be confused with Ron Guilmette's protoize, which will also
  15.    appear here.  This takes a neat way out in that it avoids doing any
  16.    parsing of function bodies, which I think is really clever.  As Chin
  17.    says, you will need FLEX which is available from your nearest archive
  18.    site and is also distributed on most GNU sites.  /r$  ]
  19.  
  20. This is program automatically generates C function prototypes and
  21. variable declarations from C language source code.
  22.  
  23. You don't need the source to 4.2BSD lint to compile this program but
  24. you do need flex since the lexical analyzer specified in lex.l makes use
  25. of mutually exclusive start conditions. 
  26.  
  27. Chin Huang
  28. cthuang@watdragon.waterloo.edu
  29.  
  30. #
  31. # This is a shell archive.  Remove anything before this line,
  32. # then unpack it by saving it in a file and typing "sh file".
  33. #
  34. # Contents:  README Makefile cproto.1 cproto.sh grammar.y lex.l cproto.h
  35. #    patchlevel.h semantics.h symbol.h cproto1.c semantics.c string.c
  36. #    symbol.c
  37.  
  38. echo x - README
  39. sed 's/^@//' > "README" <<'@//E*O*F README//'
  40. This is program automatically generates C function prototypes and
  41. variable declarations from C language source code.
  42.  
  43. You don't need the source to 4.2BSD lint to compile this program but
  44. you do need flex since the lexical analyzer specified in lex.l makes use
  45. of mutually exclusive start conditions. 
  46.  
  47. Chin Huang
  48. cthuang@watdragon.waterloo.edu
  49. @//E*O*F README//
  50. chmod u=rw,g=r,o=r README
  51.  
  52. echo x - Makefile
  53. sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
  54. #
  55. # $Header: Makefile,v 1.1 89/03/14 20:58:56 cthuang Exp $
  56. #
  57. # Makefile for C prototype generator
  58.  
  59. LEX = flex
  60. YACC = yacc
  61. CFLAGS = -O
  62.  
  63. SOURCES =    README Makefile cproto.1 cproto.sh \
  64.         grammar.y lex.l \
  65.         cproto.h patchlevel.h semantics.h symbol.h \
  66.         cproto1.c semantics.c string.c symbol.c
  67. CSOURCES =    cproto1.c semantics.c string.c symbol.c y.tab.c
  68. OBJECTS =    cproto1.o semantics.o string.o symbol.o y.tab.o
  69.  
  70. all: cproto1
  71.  
  72. cproto1: $(OBJECTS)
  73.     $(CC) $(CFLAGS) -o $@ $(OBJECTS)
  74.  
  75. y.tab.o: y.tab.c lex.yy.c
  76.     $(CC) $(CFLAGS) -c $*.c
  77.  
  78. y.tab.c: grammar.y
  79.     $(YACC) grammar.y
  80.  
  81. lex.yy.c: lex.l grammar.y
  82.     $(LEX) lex.l
  83.  
  84. lint:
  85.     lint -B $(CSOURCES)
  86.  
  87. shar:
  88.     shar -c $(SOURCES) >shar.out
  89.  
  90. ci:
  91.     ci -u $(SOURCES)
  92.  
  93. main.o: symbol.h cproto.h
  94. semantics.o: symbol.h cproto.h semantics.h
  95. symbol.o: symbol.h
  96. y.tab.o: symbol.h cproto.h semantics.h
  97. @//E*O*F Makefile//
  98. chmod u=rw,g=r,o=r Makefile
  99.  
  100. echo x - cproto.1
  101. sed 's/^@//' > "cproto.1" <<'@//E*O*F cproto.1//'
  102. @.\" $Header: cproto.1,v 1.1 89/03/14 21:30:01 cthuang Exp $
  103. @.\"
  104. @.de EX          \"Begin example
  105. @.ne 5
  106. @.if n .sp 1
  107. @.if t .sp .5
  108. @.nf
  109. @.in +.5i
  110. @..
  111. @.de EE        \"End example
  112. @.fi
  113. @.in -.5i
  114. @.if n .sp 1
  115. @.if t .sp .5
  116. @..
  117. @.TH CPROTO 1 "March 14, 1989"
  118. @.SH NAME
  119. cproto \- generate C function prototypes from C source code
  120. @.SH SYNOPSIS
  121. @.B cproto
  122. @.I option \fP...\fI
  123. ] [
  124. @.I file
  125. ]
  126. @.SH DESCRIPTION
  127. @.B Cproto
  128. generates C function prototypes from a C language source file.
  129. For each function defined in the file,
  130. @.B cproto
  131. outputs to the standard output a line consisting of the prototype
  132. for that function.
  133. Optionally,
  134. @.B cproto
  135. also outputs declarations for any variables defined in the file.
  136. If no
  137. @.I file
  138. argument is given,
  139. @.B cproto
  140. takes its input from the standard input.
  141. @.SH OPTIONS
  142. @.TP
  143. @.B \-e
  144. On the output, prepend the keyword
  145. @.B extern
  146. to declarations that have global scope.
  147. @.TP
  148. @.B \-g
  149. Output only "global" declarations.
  150. Only declarations of functions and variables that can be accessed outside
  151. of the source file will be printed.
  152. @.TP
  153. @.BI \-p n
  154. Set the style of function prototype where
  155. @.I n
  156. is a number from 0 to 2.
  157. For example, consider the function definition
  158. @.EX
  159. main (argc, argv)
  160. int argc;
  161. char *argv[];
  162. {
  163.  ...
  164. }
  165. @.EE
  166. A value of 2 produces the full function prototype:
  167. @.EX
  168. int main(int argc, char *argv[]);
  169. @.EE
  170. For a value of 1, the output has the form:
  171. @.EX
  172. int main(int /*argc*/, char */*argv*/[]);
  173. @.EE
  174. When set to 0, the output is:
  175. @.EX
  176. int main(/*int argc, char *argv[]*/);
  177. @.EE
  178. The default value is 2.
  179. @.TP
  180. @.B \-v
  181. Also output declarations of variables defined in the file.
  182. @.TP
  183. @.BI \-D name\[=value\]
  184. This option is passed through to the preprocessor and is used to define 
  185. symbols for use with conditionals such as
  186. @.I #ifdef.
  187. @.TP
  188. @.BI \-U name
  189. This option is passed through to the preprocessor and is used to remove
  190. any definitions of this symbol.
  191. @.TP
  192. @.BI \-I directory
  193. This option is passed through to the preprocessor and is used to specify
  194. a directory to search for files that are referenced with 
  195. @.I #include.
  196. @.SH AUTHOR
  197. Chin Huang (cthuang@watdragon.waterloo.edu)
  198. @.SH CAVEATS
  199. Any error messages produced are minimal.
  200. If the C source code is accepted by the C compiler, then
  201. @.B cproto
  202. will probably accept it as well.
  203. @.SH "SEE ALSO"
  204. cc(1),
  205. cpp(1)
  206. @//E*O*F cproto.1//
  207. chmod u=r,g=r,o=r cproto.1
  208.  
  209. echo x - cproto.sh
  210. sed 's/^@//' > "cproto.sh" <<'@//E*O*F cproto.sh//'
  211. #!/bin/sh
  212. # $Header$
  213. #
  214. cpp_opt="-I."
  215. cproto_opt=""
  216. source=""
  217. for opt do
  218.     case $opt in
  219.     -D*|-U*|-I*)
  220.     cpp_opt="$cpp_opt $opt"
  221.     ;;
  222.     -*)
  223.     cproto_opt="$cproto_opt $opt"
  224.     ;;
  225.     *)
  226.     source=$opt
  227.     ;;
  228.     esac
  229. done
  230. /lib/cpp $cpp_opt $source | cproto1 $cproto_opt
  231. @//E*O*F cproto.sh//
  232. chmod u=rwx,g=r,o=r cproto.sh
  233.  
  234. echo x - grammar.y
  235. sed 's/^@//' > "grammar.y" <<'@//E*O*F grammar.y//'
  236. /*
  237.  * $Header: grammar.y,v 1.1 89/03/14 20:59:01 cthuang Exp $
  238.  *
  239.  * yacc grammar for C prototype generator
  240.  * This was derived from the grammar given in Appendix A of
  241.  * "The C Programming Language" by the Kernighan and Ritchie.
  242.  */
  243.  
  244. /* identifiers that are not reserved words */
  245. %token IDENTIFIER TYPEDEF_NAME
  246.  
  247. /* storage class */
  248. %token AUTO EXTERN REGISTER STATIC TYPEDEF
  249.  
  250. /* type specifiers */
  251. %token CHAR DOUBLE FLOAT INT VOID
  252. %token LONG SHORT SIGNED UNSIGNED
  253. %token ENUM STRUCT UNION
  254.  
  255. /* type qualifiers */
  256. %token CONST VOLATILE
  257.  
  258. /* paired braces and everything between them: { ... } */
  259. %token BRACES
  260.  
  261. /* paired square brackets and everything between them: [ ... ]*/
  262. %token BRACKETS
  263.  
  264. /* three periods */
  265. %token ELLIPSIS
  266.  
  267. /* equal sign followed by constant expression or stuff between braces */
  268. %token INITIALIZER
  269.  
  270. %type <decl_spec> decl_specs decl_spec_item
  271. %type <decl_spec> storage_class type_spec type_qualifier
  272. %type <decl_spec> struct_union_spec enum_spec
  273. %type <decl_list> init_decl_list
  274. %type <declarator> init_declarator declarator direct_decl
  275. %type <param_list> param_type_list param_list
  276. %type <parameter> param_decl
  277. %type <param_list> identifier_list ident_list
  278. %type <text> struct_or_union
  279. %type <text> pointer type_qual_list
  280. %type <text> IDENTIFIER TYPEDEF_NAME
  281. %type <text> BRACKETS
  282.  
  283. %{
  284. #include <stdio.h>
  285. #include "cproto.h"
  286. #include "semantics.h"
  287.  
  288. /* This variable is TRUE when the parameter declaration part of a function
  289.  * definition is currently being parsed.
  290.  * For example:
  291.  *    int
  292.  *    main (argc, argv)
  293.  *    int argc;        | TRUE when these lines
  294.  *    char **argv;        | are being scanned.
  295.  *    {             
  296.  *    ...              
  297.  *      }             
  298.  */
  299. static boolean func_decl = FALSE;
  300.  
  301. /* This points to the list of parameters for the current function definition. */
  302. static ParameterList *cur_params;
  303.  
  304. /* temporary string buffer */
  305. static char buf[MAX_TEXT_LENGTH];
  306.  
  307. /* Table of typedef names */
  308. SymbolTable *typedef_names;
  309. %}
  310. %%
  311.  
  312. program        : /* empty */
  313.         | translation_unit
  314.         ;
  315.  
  316. translation_unit : external_decl
  317.         | translation_unit external_decl
  318.         ;
  319.  
  320. external_decl    : declaration
  321.         | function_def
  322.         | error
  323.         ;
  324.  
  325. declaration    : decl_specs ';'
  326.         | decl_specs init_decl_list ';'
  327.         {
  328.             if (func_decl) {
  329.             set_param_types(cur_params, &$1, &$2);
  330.             } else {
  331.             output_declarations(&$1, &$2);
  332.             }
  333.             free_decl_spec(&$1);
  334.             free_decl_list(&$2);
  335.         }
  336.         | TYPEDEF decl_specs declarator ';'
  337.         {
  338.             (void)new_symbol(typedef_names, $3.name);
  339.             free_decl_spec(&$2);
  340.             free_declarator(&$3);
  341.         }
  342.         ;
  343.  
  344. function_def    : decl_specs
  345.           declarator
  346.         {
  347.             if ($2.func_def == FUNC_DEF_NONE) {
  348.             yyerror("syntax error");
  349.             YYERROR;
  350.             }
  351.             func_decl = TRUE;
  352.             cur_params = &($2.params);
  353.         }
  354.           opt_decl_list BRACES
  355.         {
  356.             func_decl = FALSE;
  357.  
  358.             output_prototype(&$1, &$2);
  359.             free_decl_spec(&$1);
  360.             free_declarator(&$2);
  361.         }
  362.         | declarator
  363.         {
  364.             if ($1.func_def == FUNC_DEF_NONE) {
  365.             yyerror("syntax error");
  366.             YYERROR;
  367.             }
  368.             func_decl = TRUE;
  369.             cur_params = &($1.params);
  370.         }
  371.           opt_decl_list BRACES
  372.         {
  373.             DeclSpec    decl_spec;
  374.  
  375.             func_decl = FALSE;
  376.  
  377.             new_decl_spec(&decl_spec, "int", DE_EXTERN);
  378.             output_prototype(&decl_spec, &$1);
  379.             free_decl_spec(&decl_spec);
  380.             free_declarator(&$1);
  381.         }
  382.         ;
  383.  
  384. decl_list    : declaration
  385.         | decl_list declaration
  386.         ;
  387.  
  388. decl_specs    : decl_spec_item
  389.         | decl_specs decl_spec_item
  390.         {
  391.             join_decl_specs(&$$, &$1, &$2);
  392.         }
  393.         ;
  394.  
  395. decl_spec_item    : storage_class
  396.         | type_spec
  397.         | type_qualifier
  398.         ;
  399.  
  400. opt_decl_list    : decl_list
  401.         | /* empty */
  402.         ;
  403.  
  404. storage_class    : AUTO
  405.         {
  406.             new_decl_spec(&$$, "auto", DE_JUNK);
  407.         }
  408.         | EXTERN
  409.         {
  410.             new_decl_spec(&$$, "extern", DE_EXTERN);
  411.         }
  412.         | REGISTER
  413.         {
  414.             new_decl_spec(&$$, "register", DE_JUNK);
  415.         }
  416.         | STATIC
  417.         {
  418.             new_decl_spec(&$$, "static", DE_STATIC);
  419.         }
  420.         ;
  421.  
  422. type_spec    : CHAR
  423.         {
  424.             new_decl_spec(&$$, "char", DE_EXTERN);
  425.         }
  426.         | DOUBLE
  427.         {
  428.             new_decl_spec(&$$, "double", DE_EXTERN);
  429.         }
  430.         | FLOAT
  431.         {
  432.             new_decl_spec(&$$, "float", DE_EXTERN);
  433.         }
  434.         | INT
  435.         {
  436.             new_decl_spec(&$$, "int", DE_EXTERN);
  437.         }
  438.         | LONG
  439.         {
  440.             new_decl_spec(&$$, "long", DE_EXTERN);
  441.         }
  442.         | SHORT
  443.         {
  444.             new_decl_spec(&$$, "short", DE_EXTERN);
  445.         }
  446.         | SIGNED
  447.         {
  448.             new_decl_spec(&$$, "signed", DE_EXTERN);
  449.         }
  450.         | UNSIGNED
  451.         {
  452.             new_decl_spec(&$$, "unsigned", DE_EXTERN);
  453.         }
  454.         | VOID
  455.         {
  456.             new_decl_spec(&$$, "void", DE_EXTERN);
  457.         }
  458.         | struct_union_spec
  459.         | enum_spec
  460.         | TYPEDEF_NAME
  461.         {
  462.             new_decl_spec(&$$, $1, DE_EXTERN);
  463.         }
  464.         ;
  465.  
  466. type_qualifier    : CONST
  467.         {
  468.             new_decl_spec(&$$, "const", DE_EXTERN);
  469.         }
  470.         | VOLATILE
  471.         {
  472.             new_decl_spec(&$$, "volatile", DE_EXTERN);
  473.         }
  474.         ;
  475.  
  476. struct_union_spec : struct_or_union IDENTIFIER BRACES
  477.         {
  478.             sprintf(buf, "%s %s {}", $1, $2);
  479.             new_decl_spec(&$$, buf, DE_EXTERN);
  480.         }
  481.         | struct_or_union BRACES
  482.         {
  483.             sprintf(buf, "%s {}", $1);
  484.             new_decl_spec(&$$, buf, DE_EXTERN);
  485.         }
  486.         | struct_or_union IDENTIFIER
  487.         {
  488.             sprintf(buf, "%s %s", $1, $2);
  489.             new_decl_spec(&$$, buf, DE_EXTERN);
  490.         }
  491.         ;
  492.  
  493. struct_or_union    : STRUCT
  494.         {
  495.             strcpy($$, "struct");
  496.         }
  497.         | UNION
  498.         {
  499.             strcpy($$, "union");
  500.         }
  501.         ;
  502.  
  503. init_decl_list    : init_declarator
  504.         {
  505.             new_decl_list(&$$, &$1);
  506.         }
  507.         | init_decl_list ',' init_declarator
  508.         {
  509.             add_decl_list(&$$, &$1, &$3);
  510.         }
  511.         ;
  512.  
  513. init_declarator    : declarator
  514.         | declarator INITIALIZER
  515.         ;
  516.  
  517. enum_spec    : ENUM IDENTIFIER BRACES
  518.         {
  519.             sprintf(buf, "enum %s {}", $2);
  520.             new_decl_spec(&$$, buf, DE_EXTERN);
  521.         }
  522.         | ENUM BRACES
  523.         {
  524.             new_decl_spec(&$$, "enum {}", DE_EXTERN);
  525.         }
  526.         | ENUM IDENTIFIER
  527.         {
  528.             sprintf(buf, "enum %s", $2);
  529.             new_decl_spec(&$$, buf, DE_EXTERN);
  530.         }
  531.         ;
  532.  
  533. declarator    : pointer direct_decl
  534.         {
  535.             sprintf(buf, "%s%s", $1, $2.text);
  536.             $$ = $2;
  537.             $$.text = strdup(buf);
  538.             free($2.text);
  539.         }
  540.         | direct_decl
  541.         ;
  542.  
  543. direct_decl    : IDENTIFIER
  544.         {
  545.             new_declarator(&$$, $1, $1);
  546.         }
  547.         | '(' declarator ')'
  548.         {
  549.             sprintf(buf, "(%s)", $2.text);
  550.             $$ = $2;
  551.             $$.text = strdup(buf);
  552.             free($2.text);
  553.         }
  554.         | direct_decl BRACKETS
  555.         {
  556.             sprintf(buf, "%s%s", $1.text, $2);
  557.             $$ = $1;
  558.             $$.text = strdup(buf);
  559.             free($1.text);
  560.         }
  561.         | direct_decl '(' param_type_list ')'
  562.         {
  563.             sprintf(buf, "%s(%%s)", $1.text);
  564.             $$ = $1;
  565.             $$.func_def = FUNC_DEF_NEW;
  566.             $$.params = $3;
  567.             $$.text = strdup(buf);
  568.             free($1.text);
  569.         }
  570.         | direct_decl '(' identifier_list ')'
  571.         {
  572.             sprintf(buf, "%s(%%s)", $1.text);
  573.             $$ = $1;
  574.             $$.func_def = FUNC_DEF_OLD;
  575.             $$.params = $3;
  576.             $$.text = strdup(buf);
  577.             free($1.text);
  578.         }
  579.         ;
  580.  
  581. pointer        : '*' type_qual_list
  582.         {
  583.             sprintf($$, "*%s", $2);
  584.         }
  585.         | '*' type_qual_list pointer
  586.         {
  587.             sprintf($$, "*%s%s", $2, $3);
  588.         }
  589.         ;
  590.  
  591. type_qual_list    : /* empty */
  592.         {
  593.             strcpy($$, "");
  594.         }
  595.         | type_qual_list type_qualifier
  596.         {
  597.             sprintf($$, "%s %s ", $1, $2.text);
  598.             free($2.text);
  599.         }
  600.         ;
  601.  
  602. param_type_list    : VOID
  603.         {
  604.             Parameter    p;
  605.  
  606.             new_parameter(&p, "void", " ", " ");
  607.             new_param_list(&$$, &p);
  608.         }
  609.         | param_list
  610.         | param_list ',' ELLIPSIS
  611.         {
  612.             Parameter    p;
  613.  
  614.             new_parameter(&p, "...", " ", " ");
  615.             add_param_list(&$$, &$1, &p);
  616.         }
  617.         ;
  618.  
  619. param_list    : param_decl
  620.         {
  621.             new_param_list(&$$, &$1);
  622.         }
  623.         | param_list ',' param_decl
  624.         {
  625.             add_param_list(&$$, &$1, &$3);
  626.         }
  627.         ;
  628.  
  629. param_decl    : decl_specs declarator
  630.         {
  631.             new_parameter(&$$, $1.text, $2.text, $2.name);
  632.         }
  633.         ;
  634.  
  635. identifier_list    : /* empty */
  636.         {
  637.             new_ident_list(&$$);
  638.         }
  639.         | ident_list
  640.         ;
  641.  
  642. ident_list    : IDENTIFIER
  643.         {
  644.             new_ident_list(&$$);
  645.             add_ident_list(&$$, &$$, $1);
  646.         }
  647.         | ident_list ',' IDENTIFIER
  648.         {
  649.             add_ident_list(&$$, &$1, $3);
  650.         }
  651.         ;
  652.  
  653. %%
  654. #include "lex.yy.c"
  655.  
  656. yyerror (msg)
  657. char *msg;
  658. {
  659.     print_error(msg);
  660. }
  661.  
  662. void
  663. parse_file ()
  664. {
  665.     typedef_names = create_symbol_table();
  666.     (void)yyparse();
  667. }
  668. @//E*O*F grammar.y//
  669. chmod u=rw,g=r,o=r grammar.y
  670.  
  671. echo x - lex.l
  672. sed 's/^@//' > "lex.l" <<'@//E*O*F lex.l//'
  673. /*
  674.  * $Header: lex.l,v 1.1 89/03/14 20:59:10 cthuang Exp $
  675.  *
  676.  * C function prototype generator
  677.  * Lexical analyzer specification for flex
  678.  */
  679.  
  680. WLF             ([ \t\n\f]*)
  681. LETTER        [a-zA-Z_]
  682. DIGIT        [0-9]
  683. ID        {LETTER}({LETTER}|{DIGIT})*
  684. SKIPQUOTED    (\"([^"\n]|\\\")*\"|\'.\'|\\.)
  685.  
  686. %{
  687. static int curly = 0;        /* number of curly brace nesting levels */
  688. int line_num = 1;
  689. %}
  690.  
  691. %x INIT1 INIT2 CURLY COMMENT
  692. %%
  693. \n        { ++line_num; }
  694.  
  695. #[ \t]*[0-9]+.*$    { sscanf(yytext, "# %d ", &line_num); --line_num; }
  696. #.*$            ;
  697.  
  698. "("        return '(';
  699. ")"        return ')';
  700. "*"        return '*';
  701. ","        return ',';
  702. ";"        return ';';
  703. "..."        return ELLIPSIS;
  704.  
  705. auto        return AUTO;
  706. extern        return EXTERN;
  707. register    return REGISTER;
  708. static        return STATIC;
  709. typedef        return TYPEDEF;
  710. char        return CHAR;
  711. double        return DOUBLE;
  712. float        return FLOAT;
  713. int        return INT;
  714. void        return VOID;
  715. long        return LONG;
  716. short        return SHORT;
  717. signed        return SIGNED;
  718. unsigned    return UNSIGNED;
  719. enum        return ENUM;
  720. struct        return STRUCT;
  721. union        return UNION;
  722. const        return CONST;
  723. volatile    return VOLATILE;
  724.  
  725. \[[^\]]*\]    {
  726.             strcpy(yylval.text, yytext);
  727.             return BRACKETS;
  728.         }
  729.  
  730. {ID}        {
  731.             strcpy(yylval.text, yytext);
  732.             if (is_typedef_name(yytext))
  733.             return TYPEDEF_NAME;
  734.             else
  735.             return IDENTIFIER;
  736.         }
  737.  
  738. "="{WLF}"{"        { curly = 1; BEGIN INIT1; }
  739. <INIT1>\n        { ++line_num; }
  740. <INIT1>"{"        ++curly;
  741. <INIT1>"}"        {
  742.                 if (--curly == 0) {
  743.                 BEGIN 0;
  744.                 return INITIALIZER;
  745.                 }
  746.             }
  747. <INIT1>{SKIPQUOTED}|.    ;
  748.  
  749. "="            { BEGIN INIT2; }
  750. <INIT2>\n        { ++line_num; }
  751. <INIT2>({SKIPQUOTED}|[^,;])+[,;]    {
  752.                 yyless(yyleng-1);
  753.                 BEGIN 0;
  754.                 return INITIALIZER;
  755.             }
  756.  
  757. "{"            { curly=1; BEGIN CURLY; }
  758. <CURLY>\n        { ++line_num; }
  759. <CURLY>"{"        { ++curly; }
  760. <CURLY>"}"        {
  761.                 --curly;
  762.                 if (curly == 0) {
  763.                 BEGIN 0;
  764.                 return BRACES;
  765.                 }
  766.             }
  767. <CURLY>{SKIPQUOTED}|.    ;
  768.  
  769. "/*"        BEGIN COMMENT;
  770. <COMMENT>\n    { ++line_num; }
  771. <COMMENT>"*/"    BEGIN 0;
  772. <COMMENT>.    ;
  773.  
  774. [ \t]+        ;
  775. @.        print_error("syntax error");
  776. @//E*O*F lex.l//
  777. chmod u=rw,g=r,o=r lex.l
  778.  
  779. echo x - cproto.h
  780. sed 's/^@//' > "cproto.h" <<'@//E*O*F cproto.h//'
  781. /*
  782.  * $Header: cproto.h,v 1.1 89/03/14 20:59:12 cthuang Exp $
  783.  *
  784.  * Definitions for C language prototype generator
  785.  */
  786. #include "symbol.h"
  787.  
  788. /* Boolean type */
  789. typedef char boolean;
  790. #define FALSE    0
  791. #define TRUE    1
  792.  
  793. /* maximum number of characters in a text buffer */
  794. #define MAX_TEXT_LENGTH    512
  795.  
  796. /* Declaration specifier flags */
  797. #define DE_EXTERN    0    /* default: declaration has global scope */
  798. #define DE_STATIC    1    /* visible only in current file */
  799. #define DE_JUNK        2    /* we're not interested in this declaration */
  800.  
  801. /* This structure stores information about a declaration specifier. */
  802. typedef struct _decl_spec {
  803.     unsigned short    flags;    /* flags defined above */
  804.     char        *text;    /* source text */
  805. } DeclSpec;
  806.  
  807. /* Types of function definitions
  808.  *
  809.  * FUNC_DEF_OLD        traditional style function definition
  810.  * FUNC_DEF_NEW        ANSI style
  811.  */
  812. typedef enum { FUNC_DEF_NONE, FUNC_DEF_OLD, FUNC_DEF_NEW } FuncDefType;
  813.  
  814. /* This structure stores information about a function parameter. */
  815. typedef struct _parameter {
  816.     char        *decl_spec;    /* declaration specifier text */
  817.     char        *declarator;    /* declarator text */
  818.     char        *name;        /* parameter name */
  819.     struct _parameter    *next;        /* next parameter in list */
  820. } Parameter;
  821.  
  822. /* This is a list of function parameters. */
  823. typedef struct _parameter_list {
  824.     Parameter        *first;    /* pointer to first parameter in list */
  825.     Parameter        *last;  /* pointer to last parameter in list */  
  826. } ParameterList;
  827.  
  828. /* This structure stores information about a declarator. */
  829. typedef struct _declarator {
  830.     char        *name;    /* name of declared variable or function */
  831.     char        *text;    /* source text */
  832.     FuncDefType        func_def;    /* style of function definition */
  833.     ParameterList    params;    /* list of parameters if this is a function */
  834.     struct _declarator    *next;    /* next declarator in list */
  835. } Declarator;
  836.  
  837. /* This is a list of declarators. */
  838. typedef struct _declarator_list {
  839.     Declarator        *first;    /* pointer to first declarator in list */
  840.     Declarator        *last;  /* pointer to last declarator in list */  
  841. } DeclaratorList;
  842.  
  843. /* parser stack entry type */
  844. typedef union {
  845.     char        text[MAX_TEXT_LENGTH];
  846.     DeclSpec        decl_spec;
  847.     Parameter        parameter;
  848.     ParameterList    param_list;
  849.     Declarator        declarator;
  850.     DeclaratorList    decl_list;
  851. } YYSTYPE;
  852.  
  853. /* Program options */
  854. extern boolean extern_out;
  855. extern boolean globals_only;
  856. extern int proto_style;
  857. extern boolean variables_out;
  858.  
  859. /* Global declarations */
  860. extern int line_num;
  861. extern SymbolTable *typedef_names;
  862. extern void print_error();
  863. extern void parse_file();
  864.  
  865. extern char *strdup(), *strstr();
  866. extern char *malloc();
  867. @//E*O*F cproto.h//
  868. chmod u=rw,g=r,o=r cproto.h
  869.  
  870. echo x - patchlevel.h
  871. sed 's/^@//' > "patchlevel.h" <<'@//E*O*F patchlevel.h//'
  872. #define PATCHLEVEL 0
  873. @//E*O*F patchlevel.h//
  874. chmod u=rw,g=r,o=r patchlevel.h
  875.  
  876. echo x - semantics.h
  877. sed 's/^@//' > "semantics.h" <<'@//E*O*F semantics.h//'
  878. /*
  879.  * $Header: semantics.h,v 1.1 89/03/14 20:59:16 cthuang Exp $
  880.  *
  881.  * Declarations for semantics action routines
  882.  */
  883.  
  884. extern boolean    is_typedef_name();
  885.  
  886. extern void    new_decl_spec();
  887. extern void    join_decl_specs();
  888. extern void    free_decl_spec();
  889.  
  890. extern void    new_parameter();
  891. extern void    free_parameter();
  892.  
  893. extern void    new_param_list();
  894. extern void    add_param_list();
  895. extern void    free_param_list();
  896.  
  897. extern void    new_ident_list();
  898. extern void    add_ident_list();
  899.  
  900. extern void    new_declarator();
  901. extern void    free_declarator();
  902.  
  903. extern void    new_decl_list();
  904. extern void    add_decl_list();
  905. extern void    free_decl_list();
  906.  
  907. extern void    set_param_types();
  908. extern void    output_declarations();
  909. extern void    output_prototype();
  910. @//E*O*F semantics.h//
  911. chmod u=rw,g=r,o=r semantics.h
  912.  
  913. echo x - symbol.h
  914. sed 's/^@//' > "symbol.h" <<'@//E*O*F symbol.h//'
  915. /*
  916.  * $Header: symbol.h,v 1.1 89/03/14 20:59:18 cthuang Exp $
  917.  *
  918.  * Definitions for a symbol table
  919.  */
  920. #ifndef _SYMBOL_H
  921. #define _SYMBOL_H
  922.  
  923. /* maximum length of symbols */
  924. #define SYM_MAX_LENGTH 64
  925.  
  926. typedef struct _symbol {
  927.     struct _symbol    *next;            /* next symbol in list */
  928.     char        name[SYM_MAX_LENGTH];    /* name of symbol */
  929. } Symbol;
  930.  
  931. /* hash table length */
  932. #define SYM_MAX_HASH 256
  933.  
  934. typedef struct _symbol_table {
  935.     Symbol        *bucket[SYM_MAX_HASH];    /* hash buckets */
  936. } SymbolTable;
  937.  
  938. extern SymbolTable    *create_symbol_table();    /* Create symbol table */
  939. extern Symbol        *find_symbol();        /* Lookup symbol name */
  940. extern Symbol        *new_symbol();        /* Define new symbol */
  941.  
  942. #endif
  943. @//E*O*F symbol.h//
  944. chmod u=rw,g=r,o=r symbol.h
  945.  
  946. echo x - cproto1.c
  947. sed 's/^@//' > "cproto1.c" <<'@//E*O*F cproto1.c//'
  948. /*
  949.  * $Header: cproto1.c,v 1.1 89/03/14 20:59:21 cthuang Exp $
  950.  *
  951.  * C prototype generator
  952.  * This filter reads C source code and outputs ANSI C function prototypes.
  953.  */
  954. #ifndef lint
  955. static char *rcsid = "$Header: cproto1.c,v 1.1 89/03/14 20:59:21 cthuang Exp $";
  956. #endif
  957. #include <stdio.h>
  958. #include "cproto.h"
  959.  
  960. /* getopt declarations */
  961. extern int getopt();
  962. extern char *optarg;
  963. extern int optind;
  964.  
  965. /* Name of the program */
  966. static char *progname = "cproto";
  967.  
  968. /* Program options */
  969.  
  970. /* TRUE when "extern" should appear to external declarations. */
  971. boolean extern_out = FALSE;
  972.  
  973. /* TRUE when only external declarations will be generated. */
  974. boolean globals_only = FALSE;
  975.  
  976. /* This variable controls the style of function prototype. */
  977. int proto_style = 2;
  978.  
  979. /* TRUE when variable declarations are printed also. */
  980. boolean variables_out = FALSE;
  981.  
  982. /* Output an error message along with the line number where it was found.
  983.  */
  984. void
  985. print_error (msg)
  986. char *msg;
  987. {
  988.     fprintf(stderr, "%s: line %d: %s\n", progname, line_num, msg);
  989. }
  990.  
  991. main (argc, argv)
  992. int argc;
  993. char **argv;
  994. {
  995.     int        c;
  996.     boolean    error_flag;
  997.  
  998.     error_flag = FALSE;
  999.     while ((c = getopt(argc, argv, "egp:v")) != EOF) {
  1000.     switch (c) {
  1001.     case 'e':
  1002.         extern_out = TRUE;
  1003.         break;
  1004.     case 'g':
  1005.         globals_only = TRUE;
  1006.         break;
  1007.     case 'p':
  1008.         proto_style = atoi(optarg);
  1009.         break;
  1010.     case 'v':
  1011.         variables_out = TRUE;
  1012.         break;
  1013.     case '?':
  1014.     default:
  1015.         error_flag = TRUE;
  1016.     }
  1017.     }
  1018.  
  1019.     if (optind == argc-1) {
  1020.     if (freopen(argv[optind], "r", stdin) == NULL) {
  1021.         fprintf(stderr, "%s: cannot open file %s\n", progname,
  1022.                 argv[optind]);
  1023.         exit(1);
  1024.     }
  1025.     } else {
  1026.     error_flag = (boolean)(optind < argc-1);
  1027.     }
  1028.  
  1029.     if (error_flag) {
  1030.     fprintf(stderr, "usage: %s [ -egv ] [ -p n ] [ file ]\n", progname);
  1031.     exit(1);
  1032.     }
  1033.  
  1034.     parse_file();
  1035. }
  1036. @//E*O*F cproto1.c//
  1037. chmod u=rw,g=r,o=r cproto1.c
  1038.  
  1039. echo x - semantics.c
  1040. sed 's/^@//' > "semantics.c" <<'@//E*O*F semantics.c//'
  1041. /*
  1042.  * $Header: semantics.c,v 1.1 89/03/14 20:59:22 cthuang Exp $
  1043.  *
  1044.  * C prototype generator
  1045.  * These routines implement the semantic actions executed by the yacc parser.
  1046.  * 
  1047.  */
  1048. #include <stdio.h>
  1049. #include <strings.h>
  1050. #include "cproto.h"
  1051. #include "semantics.h"
  1052.  
  1053. /* Create a new string by joining two strings with a space between them.
  1054.  * Return a pointer to the resultant string or NULL if an error occurred.
  1055.  */
  1056. static char *
  1057. concat_string (a, b)
  1058. char    *a, *b;
  1059. {
  1060.     char    *result;
  1061.  
  1062.     if ((result = malloc((unsigned)(strlen(a) + strlen(b) + 2))) != NULL) {
  1063.     strcpy(result, a);
  1064.     strcat(result, " ");
  1065.     strcat(result, b);
  1066.     }
  1067.     return result;
  1068. }
  1069.  
  1070. /* Delete the first occurence of a substring from a string.
  1071.  * Return a pointer to a static buffer containing the result.
  1072.  * If the substring is not found, then return the entire string.
  1073.  */
  1074. static char *
  1075. delete_string (src, key)
  1076. char    *src, *key;
  1077. {
  1078.     static char buf[MAX_TEXT_LENGTH];
  1079.     char    *s;
  1080.     int        n;
  1081.  
  1082.     if ((s = strstr(src, key)) == NULL) {
  1083.     strcpy(buf, src);
  1084.     } else {
  1085.     strcpy(buf, "");
  1086.     n = s - src;
  1087.     if (n > 0) strncat(buf, src, n);
  1088.     n = strlen(src) - n - strlen(key);
  1089.     if (n > 0) strncat(buf, s+strlen(key), n);
  1090.     }
  1091.     return buf;
  1092. }
  1093.  
  1094. /* Check if the given identifier is really a typedef name by searching the
  1095.  * symbol table.
  1096.  * Return TRUE if it is a typedef name.
  1097.  */
  1098. boolean
  1099. is_typedef_name (name)
  1100. char *name;
  1101. {
  1102.     return (boolean)(find_symbol(typedef_names, name) != NULL);
  1103. }
  1104.  
  1105. /* Initialize a new declaration specifier part.
  1106.  */
  1107. void
  1108. new_decl_spec (decl_spec, text, flags)
  1109. DeclSpec    *decl_spec;
  1110. char        *text;
  1111. unsigned short    flags;
  1112. {
  1113.     decl_spec->text = strdup(text);
  1114.     decl_spec->flags = flags;
  1115. }
  1116.  
  1117. /* Append two declaration specifier parts together.
  1118.  */
  1119. void
  1120. join_decl_specs (result, a, b)
  1121. DeclSpec    *result, *a, *b;
  1122. {
  1123.     result->text = concat_string(a->text, b->text);
  1124.     result->flags = a->flags | b->flags;
  1125.     free(a->text);
  1126.     free(b->text);
  1127. }
  1128.  
  1129. /* Free storage used by a declaration specifier part.
  1130.  */
  1131. void
  1132. free_decl_spec (decl_spec)
  1133. DeclSpec    *decl_spec;
  1134. {
  1135.     if (decl_spec->text != NULL)
  1136.     free(decl_spec->text);
  1137. }
  1138.  
  1139. /* Initialize the parameter structure.
  1140.  */
  1141. void
  1142. new_parameter (param, decl_spec, declarator, name)
  1143. Parameter    *param;
  1144. char        *decl_spec, *declarator, *name;
  1145. {
  1146.     param->decl_spec = strdup(decl_spec);
  1147.     param->declarator = strdup(delete_string(declarator, "%s"));
  1148.     param->name = strdup(name);
  1149. }
  1150.  
  1151. /* Free the storage used by the parameter.
  1152.  */
  1153. void
  1154. free_parameter (param)
  1155. Parameter    *param;
  1156. {
  1157.     if (param->decl_spec != NULL)
  1158.     free(param->decl_spec);
  1159.     if (param->declarator != NULL)
  1160.     free(param->declarator);
  1161.     free(param->name);
  1162. }
  1163.  
  1164. /* Initialize an empty list of function parameters.
  1165.  */
  1166. void
  1167. new_param_list (param_list, param)
  1168. ParameterList    *param_list;
  1169. Parameter    *param;
  1170. {
  1171.     Parameter    *p;
  1172.  
  1173.     p = (Parameter *)malloc(sizeof(Parameter));
  1174.     *p = *param;
  1175.     
  1176.     param_list->first = param_list->last = p;
  1177.     p->next = NULL;
  1178. }
  1179.  
  1180. /* Add the function parameter declaration to the list.
  1181.  */
  1182. void
  1183. add_param_list (to, from, param)
  1184. ParameterList    *to, *from;
  1185. Parameter    *param;
  1186. {
  1187.     Parameter    *p;
  1188.  
  1189.     p = (Parameter *)malloc(sizeof(Parameter));
  1190.     *p = *param;
  1191.  
  1192.     to->first = from->first;
  1193.     from->last->next = p;
  1194.     to->last = p;
  1195.     p->next = NULL;
  1196. }
  1197.  
  1198. /* Free storage used by the elements in the function parameter list.
  1199.  */
  1200. void
  1201. free_param_list (param_list)
  1202. ParameterList    *param_list;
  1203. {
  1204.     Parameter    *p, *next;
  1205.  
  1206.     p = param_list->first;
  1207.     while (p != NULL) {
  1208.     next = p->next;
  1209.     free_parameter(p);
  1210.     free((char *)p);
  1211.     p = next;
  1212.     }
  1213. }
  1214.  
  1215. /* Initialize an empty list of function parameter names.
  1216.  * This is just a list of function parameter declarations with
  1217.  * only the name field set.
  1218.  */
  1219. void
  1220. new_ident_list (param_list)
  1221. ParameterList    *param_list;
  1222. {
  1223.     param_list->first = param_list->last = NULL;
  1224. }
  1225.  
  1226. /* Add an item to the list of function parameter declarations but set only
  1227.  * the parameter name field.
  1228.  */
  1229. void
  1230. add_ident_list (to, from, name)
  1231. ParameterList    *to, *from;
  1232. char        *name;
  1233. {
  1234.     Parameter    *p;
  1235.  
  1236.     p = (Parameter *)malloc(sizeof(Parameter));
  1237.     p->decl_spec = NULL;
  1238.     p->declarator = NULL;
  1239.     p->name = strdup(name);
  1240.  
  1241.     to->first = from->first;
  1242.     if (to->first == NULL) {
  1243.     to->first = p;
  1244.     } else {
  1245.     from->last->next = p;
  1246.     }
  1247.     to->last = p;
  1248.     p->next = NULL;
  1249. }
  1250.  
  1251. /* Initialize a declarator.
  1252.  */
  1253. void
  1254. new_declarator (d, name, text)
  1255. Declarator    *d;
  1256. char        *name, *text;
  1257. {
  1258.     d->name = strdup(name);
  1259.     d->text = strdup(text);
  1260.     d->func_def = FUNC_DEF_NONE;
  1261.     d->params.first = d->params.last = NULL;
  1262. }
  1263.  
  1264. /* Free storage used by a declarator.
  1265.  */
  1266. void
  1267. free_declarator (d)
  1268. Declarator    *d;
  1269. {
  1270.     if (d->name != NULL)
  1271.     free(d->name);
  1272.     if (d->text != NULL)
  1273.     free(d->text);
  1274.     free_param_list(&(d->params));
  1275. }
  1276.  
  1277. /* Initialize a declarator list and add the given declarator to it.
  1278.  */
  1279. void
  1280. new_decl_list (decl_list, declarator)
  1281. DeclaratorList    *decl_list;
  1282. Declarator    *declarator;
  1283. {
  1284.     Declarator    *d;
  1285.  
  1286.     d = (Declarator *)malloc(sizeof(Declarator));
  1287.     *d = *declarator;
  1288.  
  1289.     decl_list->first = decl_list->last = d;
  1290.     d->next = NULL;
  1291. }
  1292.  
  1293. /* Add the declarator to the declarator list.
  1294.  */
  1295. void
  1296. add_decl_list (to, from, declarator)
  1297. DeclaratorList    *to, *from;
  1298. Declarator    *declarator;
  1299. {
  1300.     Declarator    *d;
  1301.  
  1302.     d = (Declarator *)malloc(sizeof(Declarator));
  1303.     *d = *declarator;
  1304.  
  1305.     to->first = from->first;
  1306.     from->last->next = d;
  1307.     to->last = d;
  1308.     to->last->next = NULL;
  1309. }
  1310.  
  1311. /* Free storage used by the declarators in the declarator list.
  1312.  */
  1313. void
  1314. free_decl_list (decl_list)
  1315. DeclaratorList    *decl_list;
  1316. {
  1317.     Declarator    *d, *next;
  1318.  
  1319.     d = decl_list->first;
  1320.     while (d != NULL) {
  1321.     next = d->next;
  1322.     free_declarator(d);
  1323.     free((char *)d);
  1324.     d = next;
  1325.     }
  1326. }
  1327.  
  1328. /* Search the list of parameters for a matching parameter name.
  1329.  * Return a pointer to the matching parameter or NULL if not found.
  1330.  */
  1331. static Parameter *
  1332. search_parameter_list (params, name)
  1333. ParameterList    *params;
  1334. char        *name;
  1335. {
  1336.     Parameter    *p;
  1337.  
  1338.     for (p = params->first; p != NULL; p = p->next) {
  1339.     if (strcmp(p->name, name) == 0)
  1340.         return p;
  1341.     }
  1342.     return (Parameter *)NULL;
  1343. }
  1344.  
  1345. /* For each declared variable name in the declarator list,
  1346.  * set the declaration specifier and declarator for the parameter
  1347.  * with the same name.
  1348.  */
  1349. void
  1350. set_param_types (params, decl_spec, declarators)
  1351. ParameterList    *params;
  1352. DeclSpec    *decl_spec;
  1353. DeclaratorList    *declarators;
  1354. {
  1355.     Declarator    *d;
  1356.     Parameter    *p;
  1357.     char    buf[MAX_TEXT_LENGTH];
  1358.  
  1359.     for (d = declarators->first; d != NULL; d = d->next) {
  1360.     /* Search the parameter list for a matching name. */
  1361.     p = search_parameter_list(params, d->name);
  1362.     if (p == NULL) {
  1363.         sprintf(buf, "declared argument \"%s\" is missing", d->name);
  1364.         print_error(buf);
  1365.     } else {
  1366.         p->decl_spec = strdup(decl_spec->text);
  1367.         p->declarator = strdup(delete_string(d->text, "%s"));
  1368.     }
  1369.     }
  1370. }
  1371.  
  1372. /* Output a declaration specifier for an external declaration.
  1373.  */
  1374. static void
  1375. output_decl_spec (decl_spec)
  1376. DeclSpec    *decl_spec;
  1377. {
  1378.     if (extern_out && (decl_spec->flags & DE_STATIC) == 0) {
  1379.     if (strstr(decl_spec->text, "extern") == NULL) {
  1380.         printf("extern ");
  1381.     }
  1382.     }
  1383.     printf("%s ", decl_spec->text);
  1384. }
  1385.  
  1386. /* Output a function parameter type and variable declaration.
  1387.  */
  1388. static void
  1389. output_parameter (p)
  1390. Parameter    *p;
  1391. {
  1392.     char    *s;
  1393.  
  1394.     if (proto_style == 1) {
  1395.     s = strstr(p->declarator, p->name);
  1396.     *s = '\0';
  1397.     printf("%s %s/*%s*/%s", p->decl_spec, p->declarator, p->name,
  1398.            s+strlen(p->name));
  1399.     *s = *(p->name);
  1400.     } else {
  1401.     printf("%s %s", p->decl_spec, p->declarator);
  1402.     }
  1403. }
  1404.  
  1405. /* Output the list of function parameters.
  1406.  */
  1407. static void
  1408. output_parameters (params)
  1409. ParameterList    *params;
  1410. {
  1411.     Parameter    *p;
  1412.  
  1413.     if (proto_style == 0)
  1414.     printf("/*");
  1415.  
  1416.     p = params->first;
  1417.     if (p == NULL) {
  1418.     printf("void");
  1419.     } else {
  1420.     output_parameter(p);
  1421.     p = p->next;
  1422.     while (p != NULL) {
  1423.         printf(", ");
  1424.         output_parameter(p);
  1425.         p = p->next;
  1426.     }
  1427.     }
  1428.  
  1429.     if (proto_style == 0)
  1430.     printf("*/");
  1431. }
  1432.  
  1433. /* Output a declarator.
  1434.  */
  1435. static void
  1436. output_declarator (d)
  1437. Declarator    *d;
  1438. {
  1439.     char    *s;
  1440.  
  1441.     if (d->func_def == FUNC_DEF_NONE) {
  1442.     printf("%s", d->text);
  1443.     } else {
  1444.     if ((s = strstr(d->text, "%s")) != NULL) {
  1445.         *s = '\0';
  1446.         printf("%s", d->text);
  1447.         output_parameters(&(d->params));
  1448.         printf("%s", s+2);
  1449.         *s = '%';
  1450.     }
  1451.     }
  1452. }
  1453.  
  1454. /* Output variable declarations.
  1455.  */
  1456. void
  1457. output_declarations (decl_spec, decl_list)
  1458. DeclSpec    *decl_spec;    /* declaration specifier */
  1459. DeclaratorList    *decl_list;    /* list of declared variables */
  1460. {
  1461.     Declarator    *d;
  1462.  
  1463.     if (variables_out == FALSE)
  1464.     return;
  1465.     if (globals_only && (decl_spec->flags & DE_STATIC))
  1466.     return;
  1467.  
  1468.     for (d = decl_list->first; d != NULL; d = d->next) {
  1469.     if (d->func_def == FUNC_DEF_NONE) {
  1470.         if (strstr(decl_spec->text, "extern") == NULL) {
  1471.         output_decl_spec(decl_spec);
  1472.         output_declarator(d);
  1473.         printf(";\n");
  1474.         }
  1475.     }
  1476.     }
  1477. }
  1478.  
  1479. /* Output the prototype for the function definition.
  1480.  */
  1481. void
  1482. output_prototype (decl_spec, declarator)
  1483. DeclSpec    *decl_spec;
  1484. Declarator    *declarator;
  1485. {
  1486.     Parameter    *p;
  1487.  
  1488.     if (globals_only && (decl_spec->flags & DE_STATIC))
  1489.     return;
  1490.  
  1491.     /* Check for function parameters for which no type has been specified.
  1492.      * This happens when a parameter name appears in the function
  1493.      * declaration but does not appear in the parameter declaration part.
  1494.      * The default type in this cause is "int".
  1495.      */
  1496.     for (p = declarator->params.first; p != NULL; p = p->next) {
  1497.     if (p->decl_spec == NULL) {
  1498.         p->decl_spec = strdup("int");
  1499.         p->declarator = strdup(p->name);
  1500.     }
  1501.     }
  1502.  
  1503.     output_decl_spec(decl_spec);
  1504.     output_declarator(declarator);
  1505.     printf(";\n");
  1506. }
  1507. @//E*O*F semantics.c//
  1508. chmod u=rw,g=r,o=r semantics.c
  1509.  
  1510. echo x - string.c
  1511. sed 's/^@//' > "string.c" <<'@//E*O*F string.c//'
  1512. /*
  1513.  * $Header: string.c,v 1.1 89/03/14 20:59:24 cthuang Exp $
  1514.  *
  1515.  * Some are string handling routines
  1516.  */
  1517. #include <stdio.h>
  1518. #include <strings.h>
  1519.  
  1520. extern char    *malloc();
  1521.  
  1522. /* Copy the string into an allocated memory block.
  1523.  * Return a pointer to the copy.
  1524.  */
  1525. char *
  1526. strdup (s)
  1527. char    *s;
  1528. {
  1529.     char    *dest;
  1530.  
  1531.     if ((dest = malloc((unsigned)(strlen(s)+1))) != NULL)
  1532.     strcpy(dest, s);
  1533.     return dest;
  1534. }
  1535.  
  1536. /* Return a pointer to the first occurence of the substring 
  1537.  * within the string, or NULL if not found.
  1538.  */
  1539. char *
  1540. strstr (src, key)
  1541. char    *src, *key;
  1542. {
  1543.     char    *s;
  1544.     int        keylen;
  1545.  
  1546.     keylen = strlen(key);
  1547.     s = index(src, *key);
  1548.     while (s != NULL) {
  1549.     if (strncmp(s, key, keylen) == 0)
  1550.         return s;
  1551.     s = index(s+1, *key);
  1552.     }
  1553.     return NULL;
  1554. }
  1555. @//E*O*F string.c//
  1556. chmod u=rw,g=r,o=r string.c
  1557.  
  1558. echo x - symbol.c
  1559. sed 's/^@//' > "symbol.c" <<'@//E*O*F symbol.c//'
  1560. /*
  1561.  * $Header: symbol.c,v 1.1 89/03/14 20:59:26 cthuang Exp $
  1562.  *
  1563.  * Symbol table maintenance. Implements an abstract data type called
  1564.  * the symbol table.
  1565.  */
  1566. #include <stdio.h>
  1567. #include <strings.h>
  1568. #include "symbol.h"
  1569.  
  1570. extern char *malloc();
  1571.  
  1572. /* Create a symbol table.
  1573.  * Return a pointer to the symbol table or NULL if an error occurs.
  1574.  */
  1575. SymbolTable *
  1576. create_symbol_table ()
  1577. {
  1578.     SymbolTable *symtab;
  1579.     int i;
  1580.  
  1581.     if ((symtab = (SymbolTable *)malloc(sizeof(SymbolTable))) != NULL) {
  1582.     for (i = 0; i < SYM_MAX_HASH; ++i)
  1583.         symtab->bucket[i] = NULL;
  1584.     }
  1585.     return symtab;
  1586. }
  1587.  
  1588.  
  1589. /* This is a simple hash function mapping a symbol name to a hash bucket. */
  1590.  
  1591. static int
  1592. hash (name)
  1593. char *name;
  1594. {
  1595.     return (name[0] + name[1] + strlen(name)) % SYM_MAX_HASH;
  1596. }
  1597.  
  1598.  
  1599. /* Search the list of symbols <list> for the symbol <name>.
  1600.  * Return a pointer to the symbol or NULL if not found.
  1601.  */
  1602. static Symbol *
  1603. search_symbol_list (list, name)
  1604. Symbol *list;
  1605. char *name;
  1606. {
  1607.     Symbol *sym;
  1608.  
  1609.     for (sym = list; sym != NULL; sym = sym->next) {
  1610.     if (strncmp(sym->name, name, SYM_MAX_LENGTH-1) == 0)
  1611.         return sym;
  1612.     }
  1613.     return NULL;
  1614. }
  1615.  
  1616.  
  1617. /* Look for symbol <name> in symbol table <symtab>.
  1618.  * Return a pointer to the symbol or NULL if not found.
  1619.  */
  1620. Symbol *
  1621. find_symbol (symtab, name)
  1622. SymbolTable *symtab;
  1623. char *name;
  1624. {
  1625.     return search_symbol_list(symtab->bucket[hash(name)], name);
  1626. }
  1627.  
  1628.  
  1629. /* If the symbol <name> does not already exist in symbol table <symtab>,
  1630.  * then add the symbol to the symbol table.
  1631.  * Return a pointer to the symbol or NULL on an error.
  1632.  */
  1633. Symbol *
  1634. new_symbol (symtab, name)
  1635. SymbolTable *symtab;    /* symbol table */
  1636. char *name;        /* symbol name */
  1637. {
  1638.     Symbol    *sym;
  1639.     int        i;
  1640.  
  1641.     if ((sym = find_symbol(symtab, name)) == NULL) {
  1642.     if ((sym = (Symbol *)malloc(sizeof(Symbol))) != NULL) {
  1643.         strncpy(sym->name, name, SYM_MAX_LENGTH-1);
  1644.         sym->name[SYM_MAX_LENGTH-1] = '\0';
  1645.  
  1646.         i = hash(name);
  1647.         sym->next = symtab->bucket[i];
  1648.         symtab->bucket[i] = sym;
  1649.     }
  1650.     }
  1651.     return sym;
  1652. }
  1653. @//E*O*F symbol.c//
  1654. chmod u=rw,g=r,o= symbol.c
  1655.  
  1656. echo Inspecting for damage in transit...
  1657. temp=/tmp/shar$$; dtemp=/tmp/.shar$$
  1658. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  1659. cat > $temp <<\!!!
  1660.        9      50     344 README
  1661.       43     110     826 Makefile
  1662.      105     402    2247 cproto.1
  1663.       20      32     264 cproto.sh
  1664.      432     939    7877 grammar.y
  1665.      103     263    1946 lex.l
  1666.       86     373    2616 cproto.h
  1667.        1       3      21 patchlevel.h
  1668.       32      75     707 semantics.h
  1669.       28      98     673 symbol.h
  1670.       88     272    1827 cproto1.c
  1671.      466    1296    9642 semantics.c
  1672.       43     124     759 string.c
  1673.       93     308    2014 symbol.c
  1674.     1549    4345   31763 total
  1675. !!!
  1676. wc  README Makefile cproto.1 cproto.sh grammar.y lex.l cproto.h patchlevel.h semantics.h symbol.h cproto1.c semantics.c string.c symbol.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  1677. if [ -s $dtemp ]
  1678. then echo "Ouch [diff of wc output]:" ; cat $dtemp
  1679. else echo "No problems found."
  1680. fi
  1681. exit 0
  1682. --
  1683. cthuang@watdragon.uwaterloo.ca
  1684. cthuang@watdragon.waterloo.edu
  1685. cthuang@watdragon.waterloo.cdn
  1686. {uunet,utzoo}!watmath!watdragon!cthuang
  1687.  
  1688. -- 
  1689. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  1690. Use a domain-based address or give alternate paths, or you may lose out.
  1691.