home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume20 / cproto next >
Encoding:
Internet Message Format  |  1989-10-18  |  35.0 KB

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