home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / cproto / part02 / semantic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-15  |  17.8 KB  |  747 lines

  1. /* $Id: semantic.c 3.3 92/03/14 11:58:17 cthuang Exp $
  2.  *
  3.  * Semantic actions executed by the parser of the
  4.  * C function prototype generator.
  5.  */
  6. #include <stdio.h>
  7. #include "cproto.h"
  8. #include "semantic.h"
  9.  
  10. /* Head function declarator in a prototype or function definition */
  11. static Declarator *func_declarator;
  12.  
  13. /* Where the declarator appears */
  14. static int where;
  15.  
  16. /* Output format to use */
  17. static int format;
  18.  
  19. /* Initialize a new declaration specifier part.
  20.  */
  21. void
  22. new_decl_spec (decl_spec, text, offset, flags)
  23. DeclSpec *decl_spec;
  24. char *text;
  25. long offset;
  26. int flags;
  27. {
  28.     decl_spec->text = xstrdup(text);
  29.     decl_spec->begin = offset;
  30.     decl_spec->flags = flags;
  31. }
  32.  
  33. /* Free storage used by a declaration specifier part.
  34.  */
  35. void
  36. free_decl_spec (decl_spec)
  37. DeclSpec *decl_spec;
  38. {
  39.     free(decl_spec->text);
  40. }
  41.  
  42. /* Create a new string by joining two strings with a space between them.
  43.  * Return a pointer to the resultant string.
  44.  * If out of memory, output an error message and exit.
  45.  */
  46. static char *
  47. concat_string (a, b)
  48. char *a, *b;
  49. {
  50.     char *result;
  51.  
  52.     result = xmalloc(strlen(a) + strlen(b) + 2);
  53.     strcpy(result, a);
  54.     strcat(result, " ");
  55.     strcat(result, b);
  56.     return result;
  57. }
  58.  
  59. /* Append two declaration specifier parts together.
  60.  */
  61. void
  62. join_decl_specs (result, a, b)
  63. DeclSpec *result, *a, *b;
  64. {
  65.     result->text = concat_string(a->text, b->text);
  66.     result->flags = a->flags | b->flags;
  67.     result->begin = a->begin;
  68. }
  69.  
  70. /* Output an error message if the declaration specifier is an untagged
  71.  * struct, union or enum.
  72.  */
  73. void
  74. check_untagged (decl_spec)
  75. DeclSpec *decl_spec;
  76. {
  77.     if (strstr(decl_spec->text, "struct {}") != NULL) {
  78.     put_error();
  79.     fputs("untagged struct declaration\n", stderr);
  80.     } else if (strstr(decl_spec->text, "union {}") != NULL) {
  81.     put_error();
  82.     fputs("untagged union declaration\n", stderr);
  83.     } else if (strstr(decl_spec->text, "enum {}") != NULL) {
  84.     put_error();
  85.     fputs("untagged enum declaration\n", stderr);
  86.     }
  87. }
  88.  
  89. /* Allocate and initialize a declarator.
  90.  */
  91. Declarator *
  92. new_declarator (text, name, offset)
  93. char *text, *name;
  94. long offset;
  95. {
  96.     Declarator *d;
  97.  
  98.     d = (Declarator *)xmalloc(sizeof(Declarator));
  99.     d->text = xstrdup(text);
  100.     d->name = xstrdup(name);
  101.     d->begin = offset;
  102.     d->begin_comment = d->end_comment = 0;
  103.     d->func_def = FUNC_NONE;
  104.     new_ident_list(&d->params);
  105.     d->head = d;
  106.     d->func_stack = NULL;
  107.     return d;
  108. }
  109.  
  110. /* Free storage used by a declarator.
  111.  */
  112. void
  113. free_declarator (d)
  114. Declarator *d;
  115. {
  116.     free(d->text);
  117.     free(d->name);
  118.     free_param_list(&(d->params));
  119.     if (d->func_stack != NULL)
  120.     free_declarator(d->func_stack);
  121.     free(d);
  122. }
  123.  
  124. /* Initialize a declarator list and add the given declarator to it.
  125.  */
  126. void
  127. new_decl_list (decl_list, declarator)
  128. DeclaratorList *decl_list;
  129. Declarator *declarator;
  130. {
  131.     decl_list->first = decl_list->last = declarator;
  132.     declarator->next = NULL;
  133. }
  134.  
  135. /* Free storage used by the declarators in the declarator list.
  136.  */
  137. void
  138. free_decl_list (decl_list)
  139. DeclaratorList *decl_list;
  140. {
  141.     Declarator *d, *next;
  142.  
  143.     d = decl_list->first;
  144.     while (d != NULL) {
  145.     next = d->next;
  146.     free_declarator(d);
  147.     d = next;
  148.     }
  149. }
  150.  
  151. /* Add the declarator to the declarator list.
  152.  */
  153. void
  154. add_decl_list (to, from, declarator)
  155. DeclaratorList *to, *from;
  156. Declarator *declarator;
  157. {
  158.     to->first = from->first;
  159.     from->last->next = declarator;
  160.     to->last = declarator;
  161.     to->last->next = NULL;
  162. }
  163.  
  164. /* Initialize the parameter structure.
  165.  */
  166. void
  167. new_parameter (param, decl_spec, declarator)
  168. Parameter *param;        /* parameter to be initialized */
  169. DeclSpec *decl_spec;
  170. Declarator *declarator;
  171. {
  172.     if (decl_spec == NULL) {
  173.     new_decl_spec(&(param->decl_spec), "", 0L, DS_JUNK);
  174.     } else {
  175.     param->decl_spec = *decl_spec;
  176.     }
  177.  
  178.     if (declarator == NULL) {
  179.     declarator = new_declarator("", "", 0L);
  180.     }
  181.     param->declarator = declarator;
  182.  
  183.     param->comment = NULL;
  184. }
  185.  
  186. /* Free the storage used by the parameter.
  187.  */
  188. void
  189. free_parameter (param)
  190. Parameter *param;
  191. {
  192.     free_decl_spec(&(param->decl_spec));
  193.     free_declarator(param->declarator);
  194.     if (param->comment != NULL)
  195.     free(param->comment);
  196. }
  197.  
  198. /* Return TRUE if the parameter is void.
  199.  */
  200. boolean
  201. is_void_parameter (p)
  202. Parameter *p;
  203. {
  204.     return p == NULL || (strcmp(p->decl_spec.text, "void") == 0 &&
  205.     strlen(p->declarator->text) == 0);
  206. }
  207.  
  208. /* Initialize a list of function parameters.
  209.  */
  210. void
  211. new_param_list (param_list, param)
  212. ParameterList *param_list;
  213. Parameter *param;
  214. {
  215.     Parameter *p;
  216.  
  217.     p = (Parameter *)xmalloc(sizeof(Parameter));
  218.     *p = *param;
  219.     
  220.     param_list->first = param_list->last = p;
  221.     p->next = NULL;
  222.  
  223.     param_list->begin_comment = param_list->end_comment = 0;
  224.     param_list->comment = NULL;
  225. }
  226.  
  227. /* Free storage used by the elements in the function parameter list.
  228.  */
  229. void
  230. free_param_list (param_list)
  231. ParameterList *param_list;
  232. {
  233.     Parameter *p, *next;
  234.  
  235.     p = param_list->first;
  236.     while (p != NULL) {
  237.     next = p->next;
  238.     free_parameter(p);
  239.     free(p);
  240.     p = next;
  241.     }
  242.  
  243.     if (param_list->comment != NULL)
  244.     free(param_list->comment);
  245. }
  246.  
  247. /* Add the function parameter declaration to the list.
  248.  */
  249. void
  250. add_param_list (to, from, param)
  251. ParameterList *to, *from;
  252. Parameter *param;
  253. {
  254.     Parameter *p;
  255.  
  256.     p = (Parameter *)xmalloc(sizeof(Parameter));
  257.     *p = *param;
  258.  
  259.     to->first = from->first;
  260.     from->last->next = p;
  261.     to->last = p;
  262.     p->next = NULL;
  263. }
  264.  
  265. /* Initialize an empty list of function parameter names.
  266.  */
  267. void
  268. new_ident_list (param_list)
  269. ParameterList *param_list;
  270. {
  271.     param_list->first = param_list->last = NULL;
  272.     param_list->begin_comment = param_list->end_comment = 0;
  273.     param_list->comment = NULL;
  274. }
  275.  
  276. /* Add an item to the list of function parameter declarations but set only
  277.  * the parameter name field.
  278.  */
  279. void
  280. add_ident_list (to, from, name)
  281. ParameterList *to, *from;
  282. char *name;
  283. {
  284.     Parameter *p;
  285.     Declarator *declarator;
  286.  
  287.     p = (Parameter *)xmalloc(sizeof(Parameter));
  288.     declarator = new_declarator(name, name, 0L);
  289.     new_parameter(p, NULL, declarator);
  290.  
  291.     to->first = from->first;
  292.     if (to->first == NULL) {
  293.     to->first = p;
  294.     } else {
  295.     from->last->next = p;
  296.     }
  297.     to->last = p;
  298.     p->next = NULL;
  299. }
  300.  
  301. /* Search the list of parameters for a matching parameter name.
  302.  * Return a pointer to the matching parameter or NULL if not found.
  303.  */
  304. static Parameter *
  305. search_parameter_list (params, name)
  306. ParameterList *params;
  307. char *name;
  308. {
  309.     Parameter *p;
  310.  
  311.     for (p = params->first; p != NULL; p = p->next) {
  312.     if (strcmp(p->declarator->name, name) == 0)
  313.         return p;
  314.     }
  315.     return (Parameter *)NULL;
  316. }
  317.  
  318. /* For each name in the declarator list <declarators>, set the declaration
  319.  * specifier part of the parameter in <params> having the same name.
  320.  * This is also where we promote formal parameters.  Parameters of type
  321.  * "char", "unsigned char", "short", or "unsigned short" are promoted to
  322.  * "int".  Parameters of type "float" are promoted to "double".
  323.  */
  324. void
  325. set_param_types (params, decl_spec, declarators)
  326. ParameterList *params;
  327. DeclSpec *decl_spec;
  328. DeclaratorList *declarators;
  329. {
  330.     Declarator *d;
  331.     Parameter *p;
  332.     char *decl_spec_text;
  333.  
  334.     for (d = declarators->first; d != NULL; d = d->next) {
  335.     /* Search the parameter list for a matching name. */
  336.     p = search_parameter_list(params, d->name);
  337.     if (p == NULL) {
  338.         put_error();
  339.         fprintf(stderr, "declared argument \"%s\" is missing\n", d->name);
  340.     } else {
  341.         decl_spec_text = decl_spec->text;
  342.         if (promote_param && strcmp(d->text, d->name) == 0) {
  343.         if (decl_spec->flags & (DS_CHAR | DS_SHORT))
  344.             decl_spec_text = "int";
  345.         else if (decl_spec->flags & DS_FLOAT)
  346.             decl_spec_text = "double";
  347.         }
  348.         free(p->decl_spec.text);
  349.         p->decl_spec.text = xstrdup(decl_spec_text);
  350.  
  351.         free_declarator(p->declarator);
  352.         p->declarator = d;
  353.     }
  354.     }
  355. }
  356.  
  357. static void put_declarator();
  358.  
  359. /* Output a function parameter.
  360.  */
  361. static void
  362. put_parameter (outf, p)
  363. FILE *outf;
  364. Parameter *p;
  365. {
  366.     fputs(p->decl_spec.text, outf);
  367.     if (strlen(p->declarator->text) > 0) {
  368.     if (strcmp(p->declarator->text, "...") != 0)
  369.         fputc(' ', outf);
  370.     put_declarator(outf, p->declarator);
  371.     }
  372. }
  373.  
  374. /* Output parameter type list. */
  375.  
  376. static void
  377. put_parameters (outf, declarator)
  378. FILE *outf;
  379. Declarator *declarator;
  380. {
  381.     Parameter *p;
  382.     int f;
  383.  
  384.     if (where == FUNC_DEF && func_style == FUNC_TRADITIONAL) {
  385.  
  386.     /* Output traditional style parameter name list. */
  387.     p = declarator->params.first;
  388.  
  389.     /* Output paramter name list only for head function declarator. */
  390.     if (!is_void_parameter(p) && declarator == func_declarator) {
  391.         fputs(fmt[format].first_param_prefix, outf);
  392.         fputs(p->declarator->name, outf);
  393.         p = p->next;
  394.         while (p != NULL && strcmp(p->declarator->text, "...") != 0) {
  395.         fputc(',', outf);
  396.         fputs(fmt[format].middle_param_prefix, outf);
  397.         fputs(p->declarator->name, outf);
  398.         p = p->next;
  399.         }
  400.         fputs(fmt[format].last_param_suffix, outf);
  401.     }
  402.     } else {
  403.  
  404.     /* Output parameter type list. */
  405.     if (where == FUNC_PROTO && proto_style == PROTO_TRADITIONAL &&
  406.         declarator == func_declarator)
  407.         fputs("/*", outf);
  408.  
  409.     p = declarator->params.first;
  410.     if (is_void_parameter(p)) {
  411.         if (p != NULL || ((where == FUNC_PROTO || where == FUNC_DEF) &&
  412.         declarator == func_declarator))
  413.         fputs("void", outf);
  414.     } else {
  415.         f = (declarator == func_declarator) ? format : FMT_OTHER;
  416.  
  417.         if (where == FUNC_DEF && declarator->params.comment != NULL)
  418.         fputs(declarator->params.comment, outf);
  419.         
  420.         fputs(fmt[f].first_param_prefix, outf);
  421.         put_parameter(outf, p);
  422.  
  423.         while (p->next != NULL) {
  424.         fputc(',', outf);
  425.         if (where == FUNC_DEF && p->comment != NULL)
  426.             fputs(p->comment, outf);
  427.  
  428.         p = p->next;
  429.         fputs(fmt[f].middle_param_prefix, outf);
  430.         put_parameter(outf, p);
  431.         }
  432.         if (where == FUNC_DEF && p->comment != NULL)
  433.         fputs(p->comment, outf);
  434.  
  435.         fputs(fmt[f].last_param_suffix, outf);
  436.     }
  437.  
  438.     if (where == FUNC_PROTO && proto_style == PROTO_TRADITIONAL &&
  439.         declarator == func_declarator)
  440.         fputs("*/", outf);
  441.     }
  442. }
  443.  
  444. /* Output a function declarator.
  445.  */
  446. static void
  447. put_func_declarator (outf, declarator)
  448. FILE *outf;
  449. Declarator *declarator;
  450. {
  451.     char *s, *t, *decl_text;
  452.     int f;
  453.  
  454.     /* Output declarator text before function declarator place holder. */
  455.     if ((s = strstr(declarator->text, "%s")) == NULL)
  456.     return;
  457.     *s = '\0';
  458.     fputs(declarator->text, outf);
  459.  
  460.     /* Substitute place holder with function declarator. */
  461.     if (declarator->func_stack->func_def == FUNC_NONE) {
  462.  
  463.     decl_text = declarator->func_stack->text;
  464.     if (strlen(declarator->name) == 0) {
  465.         fputs(decl_text, outf);
  466.     } else {
  467.  
  468.         /* Output the declarator text before the declarator name. */
  469.         if ((t = strstr(decl_text, declarator->name)) == NULL)
  470.         return;
  471.         *t = '\0';
  472.         fputs(decl_text, outf);
  473.         *t = declarator->name[0];
  474.  
  475.         /* Output the declarator prefix before the name. */
  476.         f = (declarator == func_declarator) ? format : FMT_OTHER;
  477.         if (strcmp(fmt[f].declarator_prefix, " ") != 0)
  478.         fputs(fmt[f].declarator_prefix, outf);
  479.  
  480.         if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
  481.         declarator != func_declarator)
  482.         fputs("/*", outf);
  483.  
  484.         /* Output the declarator name. */
  485.         fputs(declarator->name, outf);
  486.  
  487.         if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
  488.         declarator != func_declarator)
  489.         fputs("*/", outf);
  490.  
  491.         /* Output the remaining declarator text. */
  492.         fputs(t + strlen(declarator->name), outf);
  493.  
  494.         /* Output the declarator suffix. */
  495.         fputs(fmt[f].declarator_suffix, outf);
  496.     }
  497.     } else {
  498.     put_func_declarator(outf, declarator->func_stack);
  499.     }
  500.     *s = '%';
  501.     s += 2;
  502.  
  503.     /* Output declarator text up to but before parameters place holder. */
  504.     if ((t = strstr(s, "()")) == NULL)
  505.     return;
  506.     *t = '\0';
  507.     fputs(s, outf);
  508.  
  509.     if (where == FUNC_PROTO && proto_style == PROTO_MACRO &&
  510.     declarator == func_declarator) {
  511.     fprintf(outf, " %s(", macro_name);
  512.     }
  513.  
  514.     /* Substitute place holder with function parameters. */
  515.     fputc(*t++ = '(', outf);
  516.     put_parameters(outf, declarator);
  517.     fputs(t, outf);
  518.  
  519.     if (where == FUNC_PROTO && proto_style == PROTO_MACRO &&
  520.     declarator == func_declarator) {
  521.     fputc(')', outf);
  522.     }
  523. }
  524.  
  525. /* Output a declarator.
  526.  */
  527. static void
  528. put_declarator (outf, declarator)
  529. FILE *outf;
  530. Declarator *declarator;
  531. {
  532.     char *s;
  533.  
  534.     if (declarator->func_def == FUNC_NONE) {
  535.     if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
  536.         strlen(declarator->name) > 0) {
  537.         if ((s = strstr(declarator->text, declarator->name)) == NULL)
  538.         return;
  539.         *s = '\0';
  540.         fprintf(outf, "%s/*%s*/%s", declarator->text,
  541.         declarator->name, s + strlen(declarator->name));
  542.         *s = declarator->name[0];
  543.     } else {
  544.         fputs(declarator->text, outf);
  545.     }
  546.     } else {
  547.     put_func_declarator(outf, declarator);
  548.     }
  549. }
  550.  
  551. /* Output a declaration specifier for an external declaration.
  552.  */
  553. static void
  554. put_decl_spec (outf, decl_spec)
  555. FILE *outf;
  556. DeclSpec *decl_spec;
  557. {
  558.     if (extern_out && (decl_spec->flags & DS_STATIC) == 0) {
  559.     if (strstr(decl_spec->text, "extern") == NULL) {
  560.         fputs("extern ", outf);
  561.     }
  562.     }
  563.     fputs(decl_spec->text, outf);
  564.     fputc(' ', outf);
  565. }
  566.  
  567. /* Generate variable declarations.
  568.  */
  569. void
  570. gen_declarations (decl_spec, decl_list)
  571. DeclSpec *decl_spec;        /* declaration specifier */
  572. DeclaratorList *decl_list;    /* list of declared variables */
  573. {
  574.     Declarator *d;
  575.  
  576.     if (!variables_out || (decl_spec->flags & DS_JUNK))
  577.     return;
  578.     if (!static_out && (decl_spec->flags & DS_STATIC))
  579.     return;
  580.  
  581.     func_declarator = NULL;
  582.     where = FUNC_OTHER;
  583.     format = FMT_OTHER;
  584.     for (d = decl_list->first; d != NULL; d = d->next) {
  585.     if (d->func_def == FUNC_NONE) {
  586.         fputs(fmt[FMT_PROTO].decl_spec_prefix, stdout);
  587.         put_decl_spec(stdout, decl_spec);
  588.         put_declarator(stdout, d);
  589.         fputs(";\n", stdout);
  590.     }
  591.     }
  592. }
  593.  
  594. /* If a parameter name appears in the parameter list of a traditional style
  595.  * function definition but is not declared in the parameter declarations,
  596.  * then assign it the default type "int".
  597.  */
  598. static void
  599. set_param_decl_spec (declarator)
  600. Declarator *declarator;
  601. {
  602.     Parameter *p;
  603.  
  604.     for (p = declarator->params.first; p != NULL; p = p->next) {
  605.     if (strlen(p->decl_spec.text) == 0 &&
  606.         strcmp(p->declarator->text, "...") != 0) {
  607.         free(p->decl_spec.text);
  608.         p->decl_spec.text = xstrdup("int");
  609.     }
  610.     }
  611. }
  612.  
  613. /* Generate a function prototype.
  614.  */
  615. void
  616. gen_prototype (decl_spec, declarator)
  617. DeclSpec *decl_spec;
  618. Declarator *declarator;
  619. {
  620.     if (proto_style == PROTO_NONE)
  621.     return;
  622.     if (decl_spec->flags & DS_JUNK)
  623.     return;
  624.     if (!static_out && (decl_spec->flags & DS_STATIC))
  625.     return;
  626.  
  627.     func_declarator = declarator->head;
  628.     set_param_decl_spec(func_declarator);
  629.  
  630.     where = FUNC_PROTO;
  631.     format = FMT_PROTO;
  632.     fputs(fmt[format].decl_spec_prefix, stdout);
  633.     put_decl_spec(stdout, decl_spec);
  634.     put_func_declarator(stdout, declarator);
  635.     fputs(";\n", stdout);
  636. }
  637.  
  638. /* Generate a declarator for a function pointer declarator or prototype.
  639.  */
  640. void
  641. gen_func_declarator (declarator)
  642. Declarator *declarator;
  643. {
  644.     /* Go to the beginning of the function declarator in the temporary
  645.      * file and overwrite it with the converted declarator.
  646.      */
  647.     fseek(cur_tmp_file(), declarator->begin, 0);
  648.     func_declarator = NULL;
  649.     where = FUNC_DEF;
  650.     format = FMT_FUNC;
  651.     put_func_declarator(cur_tmp_file(), declarator);
  652.     cur_file_changed();
  653. }
  654.  
  655. /* Generate a function definition head.
  656.  */
  657. void
  658. gen_func_definition (decl_spec, declarator)
  659. DeclSpec *decl_spec;
  660. Declarator *declarator;
  661. {
  662.     Parameter *p;
  663.     ParameterList *params;
  664.     char *comment;
  665.     int comment_len, n;
  666.  
  667.     /* Return if the function is already defined in the desired style. */
  668.     if (declarator->func_def == func_style)
  669.     return;
  670.  
  671.     /* Save the text between the function head and the function body.
  672.      * Read the temporary file from after the last ) or ; to the
  673.      * end of the file.
  674.      */
  675.     comment_len = (int)(ftell(cur_tmp_file()) - begin_comment);
  676.     comment = xmalloc(comment_len);
  677.     fseek(cur_tmp_file(), begin_comment, 0);
  678.     fread(comment, sizeof(char), comment_len, cur_tmp_file());
  679.  
  680.     func_declarator = declarator->head;
  681.     format = FMT_FUNC;
  682.  
  683.     /* Save the text before the parameter declarations. */
  684.     if (func_style == FUNC_ANSI) {
  685.     params = &func_declarator->params;
  686.     n = (int)(params->end_comment - params->begin_comment);
  687.     if (n > 0) {
  688.         params->comment = xmalloc(n+1);
  689.         fseek(cur_tmp_file(), params->begin_comment, 0);
  690.         fread(params->comment, sizeof(char), n, cur_tmp_file());
  691.         params->comment[n] = '\0';
  692.         format = FMT_FUNC_COMMENT;
  693.     }
  694.     }
  695.  
  696.     /* Get the parameter comments. */
  697.     for (p = func_declarator->params.first; p != NULL; p = p->next) {
  698.     n = (int)(p->declarator->end_comment - p->declarator->begin_comment);
  699.     if (n > 0) {
  700.         p->comment = xmalloc(n+1);
  701.         fseek(cur_tmp_file(), p->declarator->begin_comment, 0);
  702.         fread(p->comment, sizeof(char), n, cur_tmp_file());
  703.         p->comment[n] = '\0';
  704.         format = FMT_FUNC_COMMENT;
  705.     }
  706.     }
  707.  
  708.     set_param_decl_spec(func_declarator);
  709.  
  710.     /* Go to the beginning of the function head in the temporary file
  711.      * and overwrite it with the converted function head.
  712.      */
  713.     fseek(cur_tmp_file(), decl_spec->begin, 0);
  714.  
  715.     /* Output declarator specifiers. */
  716.     fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
  717.     fputs(decl_spec->text, cur_tmp_file());
  718.     fputc(' ', cur_tmp_file());
  719.  
  720.     /* Output function declarator. */
  721.     where = FUNC_DEF;
  722.     put_func_declarator(cur_tmp_file(), declarator);
  723.  
  724.     if (func_style == FUNC_TRADITIONAL) {
  725.     /* Output traditional style parameter declarations. */
  726.     p = func_declarator->params.first;
  727.     if (!is_void_parameter(p)) {
  728.         fputc('\n', cur_tmp_file());
  729.         put_parameter(cur_tmp_file(), p);
  730.         fputc(';', cur_tmp_file());
  731.         p = p->next;
  732.         while (p != NULL && strcmp(p->declarator->text, "...") != 0) {
  733.         fputc('\n', cur_tmp_file());
  734.         put_parameter(cur_tmp_file(), p);
  735.         fputc(';', cur_tmp_file());
  736.         p = p->next;
  737.         }
  738.     }
  739.     }
  740.  
  741.     /* Output text between function head and body. */
  742.     fwrite(comment, sizeof(char), comment_len, cur_tmp_file());
  743.     free(comment);
  744.  
  745.     cur_file_changed();
  746. }
  747.