home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume29 / cproto / part02 / semantic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-06  |  18.2 KB  |  767 lines

  1. /* $Id: semantic.c 3.4 92/04/04 13:59:28 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.         if (where != FUNC_PROTO || proto_comments)
  370.         fputc(' ', outf);
  371.     put_declarator(outf, p->declarator);
  372.     }
  373. }
  374.  
  375. /* Output a parameter list.
  376.  */
  377. static void
  378. put_param_list (outf, declarator)
  379. FILE *outf;
  380. Declarator *declarator;
  381. {
  382.     Parameter *p;
  383.     int f;
  384.  
  385.     p = declarator->params.first;
  386.     if (is_void_parameter(p)) {
  387.     if (p != NULL || ((where == FUNC_PROTO || where == FUNC_DEF) &&
  388.      declarator == func_declarator))
  389.         fputs("void", outf);
  390.     } else {
  391.     f = (declarator == func_declarator) ? format : FMT_OTHER;
  392.  
  393.     if (where == FUNC_DEF && declarator->params.comment != NULL)
  394.         fputs(declarator->params.comment, outf);
  395.         
  396.     fputs(fmt[f].first_param_prefix, outf);
  397.     put_parameter(outf, p);
  398.  
  399.     while (p->next != NULL) {
  400.         fputc(',', outf);
  401.         if (where == FUNC_DEF && p->comment != NULL)
  402.         fputs(p->comment, outf);
  403.  
  404.         p = p->next;
  405.         fputs(fmt[f].middle_param_prefix, outf);
  406.         put_parameter(outf, p);
  407.     }
  408.     if (where == FUNC_DEF && p->comment != NULL)
  409.         fputs(p->comment, outf);
  410.  
  411.     fputs(fmt[f].last_param_suffix, outf);
  412.     }
  413. }
  414.  
  415. /* Output function parameters.
  416.  */
  417. static void
  418. put_parameters (outf, declarator)
  419. FILE *outf;
  420. Declarator *declarator;
  421. {
  422.     Parameter *p;
  423.  
  424.     if (where == FUNC_DEF && func_style == FUNC_TRADITIONAL) {
  425.  
  426.     /* Output parameter name list for traditional function definition. */
  427.     p = declarator->params.first;
  428.  
  429.     /* Output paramter name list only for head function declarator. */
  430.     if (!is_void_parameter(p) && declarator == func_declarator) {
  431.         fputs(fmt[format].first_param_prefix, outf);
  432.         fputs(p->declarator->name, outf);
  433.         p = p->next;
  434.         while (p != NULL && strcmp(p->declarator->text, "...") != 0) {
  435.         fputc(',', outf);
  436.         fputs(fmt[format].middle_param_prefix, outf);
  437.         fputs(p->declarator->name, outf);
  438.         p = p->next;
  439.         }
  440.         fputs(fmt[format].last_param_suffix, outf);
  441.     }
  442.     } else {
  443.  
  444.     /* Output parameter type list. */
  445.     if (where == FUNC_PROTO && proto_style == PROTO_TRADITIONAL &&
  446.      declarator == func_declarator) {
  447.         if (proto_comments) {
  448.         fputs("/*", outf);
  449.         put_param_list(outf, declarator);
  450.         fputs("*/", outf);
  451.         }
  452.     } else {
  453.         put_param_list(outf, declarator);
  454.     }
  455.     }
  456. }
  457.  
  458. /* Output a function declarator.
  459.  */
  460. static void
  461. put_func_declarator (outf, declarator)
  462. FILE *outf;
  463. Declarator *declarator;
  464. {
  465.     char *s, *t, *decl_text;
  466.     int f;
  467.  
  468.     /* Output declarator text before function declarator place holder. */
  469.     if ((s = strstr(declarator->text, "%s")) == NULL)
  470.     return;
  471.     *s = '\0';
  472.     fputs(declarator->text, outf);
  473.  
  474.     /* Substitute place holder with function declarator. */
  475.     if (declarator->func_stack->func_def == FUNC_NONE) {
  476.  
  477.     decl_text = declarator->func_stack->text;
  478.     if (strlen(declarator->name) == 0) {
  479.         fputs(decl_text, outf);
  480.     } else {
  481.  
  482.         /* Output the declarator text before the declarator name. */
  483.         if ((t = strstr(decl_text, declarator->name)) == NULL)
  484.         return;
  485.         *t = '\0';
  486.         fputs(decl_text, outf);
  487.         *t = declarator->name[0];
  488.  
  489.         /* Output the declarator prefix before the name. */
  490.         f = (declarator == func_declarator) ? format : FMT_OTHER;
  491.         if (strcmp(fmt[f].declarator_prefix, " ") != 0)
  492.         fputs(fmt[f].declarator_prefix, outf);
  493.  
  494.         /* Output the declarator name. */
  495.         if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
  496.          declarator != func_declarator) {
  497.         if (proto_comments) {
  498.             fputs("/*", outf);
  499.             fputs(declarator->name, outf);
  500.             fputs("*/", outf);
  501.         }
  502.         } else {
  503.         fputs(declarator->name, outf);
  504.         }
  505.  
  506.         /* Output the remaining declarator text. */
  507.         fputs(t + strlen(declarator->name), outf);
  508.  
  509.         /* Output the declarator suffix. */
  510.         fputs(fmt[f].declarator_suffix, outf);
  511.     }
  512.     } else {
  513.     put_func_declarator(outf, declarator->func_stack);
  514.     }
  515.     *s = '%';
  516.     s += 2;
  517.  
  518.     /* Output declarator text up to but before parameters place holder. */
  519.     if ((t = strstr(s, "()")) == NULL)
  520.     return;
  521.     *t = '\0';
  522.     fputs(s, outf);
  523.  
  524.     if (where == FUNC_PROTO && proto_style == PROTO_MACRO &&
  525.      declarator == func_declarator) {
  526.     fprintf(outf, " %s(", macro_name);
  527.     }
  528.  
  529.     /* Substitute place holder with function parameters. */
  530.     fputc(*t++ = '(', outf);
  531.     put_parameters(outf, declarator);
  532.     fputs(t, outf);
  533.  
  534.     if (where == FUNC_PROTO && proto_style == PROTO_MACRO &&
  535.      declarator == func_declarator) {
  536.     fputc(')', outf);
  537.     }
  538. }
  539.  
  540. /* Output a declarator.
  541.  */
  542. static void
  543. put_declarator (outf, declarator)
  544. FILE *outf;
  545. Declarator *declarator;
  546. {
  547.     char *s;
  548.  
  549.     if (declarator->func_def == FUNC_NONE) {
  550.     if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
  551.      strlen(declarator->name) > 0) {
  552.         if ((s = strstr(declarator->text, declarator->name)) == NULL)
  553.         return;
  554.         *s = '\0';
  555.         if (proto_comments) {
  556.         fprintf(outf, "%s/*%s*/%s", declarator->text, declarator->name,
  557.          s + strlen(declarator->name));
  558.         } else {
  559.         fprintf(outf, "%s%s", declarator->text,
  560.          s + strlen(declarator->name));
  561.         }
  562.         *s = declarator->name[0];
  563.     } else {
  564.         fputs(declarator->text, outf);
  565.     }
  566.     } else {
  567.     put_func_declarator(outf, declarator);
  568.     }
  569. }
  570.  
  571. /* Output a declaration specifier for an external declaration.
  572.  */
  573. static void
  574. put_decl_spec (outf, decl_spec)
  575. FILE *outf;
  576. DeclSpec *decl_spec;
  577. {
  578.     if (extern_out && (decl_spec->flags & DS_STATIC) == 0) {
  579.     if (strstr(decl_spec->text, "extern") == NULL) {
  580.         fputs("extern ", outf);
  581.     }
  582.     }
  583.     fputs(decl_spec->text, outf);
  584.     fputc(' ', outf);
  585. }
  586.  
  587. /* Generate variable declarations.
  588.  */
  589. void
  590. gen_declarations (decl_spec, decl_list)
  591. DeclSpec *decl_spec;        /* declaration specifier */
  592. DeclaratorList *decl_list;    /* list of declared variables */
  593. {
  594.     Declarator *d;
  595.  
  596.     if (!variables_out || (decl_spec->flags & DS_JUNK))
  597.     return;
  598.     if (!static_out && (decl_spec->flags & DS_STATIC))
  599.     return;
  600.  
  601.     func_declarator = NULL;
  602.     where = FUNC_OTHER;
  603.     format = FMT_OTHER;
  604.     for (d = decl_list->first; d != NULL; d = d->next) {
  605.     if (d->func_def == FUNC_NONE) {
  606.         fputs(fmt[FMT_PROTO].decl_spec_prefix, stdout);
  607.         put_decl_spec(stdout, decl_spec);
  608.         put_declarator(stdout, d);
  609.         fputs(";\n", stdout);
  610.     }
  611.     }
  612. }
  613.  
  614. /* If a parameter name appears in the parameter list of a traditional style
  615.  * function definition but is not declared in the parameter declarations,
  616.  * then assign it the default type "int".
  617.  */
  618. static void
  619. set_param_decl_spec (declarator)
  620. Declarator *declarator;
  621. {
  622.     Parameter *p;
  623.  
  624.     for (p = declarator->params.first; p != NULL; p = p->next) {
  625.     if (strlen(p->decl_spec.text) == 0 &&
  626.         strcmp(p->declarator->text, "...") != 0) {
  627.         free(p->decl_spec.text);
  628.         p->decl_spec.text = xstrdup("int");
  629.     }
  630.     }
  631. }
  632.  
  633. /* Generate a function prototype.
  634.  */
  635. void
  636. gen_prototype (decl_spec, declarator)
  637. DeclSpec *decl_spec;
  638. Declarator *declarator;
  639. {
  640.     if (proto_style == PROTO_NONE)
  641.     return;
  642.     if (decl_spec->flags & DS_JUNK)
  643.     return;
  644.     if (!static_out && (decl_spec->flags & DS_STATIC))
  645.     return;
  646.  
  647.     func_declarator = declarator->head;
  648.     set_param_decl_spec(func_declarator);
  649.  
  650.     where = FUNC_PROTO;
  651.     format = FMT_PROTO;
  652.     fputs(fmt[format].decl_spec_prefix, stdout);
  653.     put_decl_spec(stdout, decl_spec);
  654.     put_func_declarator(stdout, declarator);
  655.     fputs(";\n", stdout);
  656. }
  657.  
  658. /* Generate a declarator for a function pointer declarator or prototype.
  659.  */
  660. void
  661. gen_func_declarator (declarator)
  662. Declarator *declarator;
  663. {
  664.     /* Go to the beginning of the function declarator in the temporary
  665.      * file and overwrite it with the converted declarator.
  666.      */
  667.     fseek(cur_tmp_file(), declarator->begin, 0);
  668.     func_declarator = NULL;
  669.     where = FUNC_DEF;
  670.     format = FMT_FUNC;
  671.     put_func_declarator(cur_tmp_file(), declarator);
  672.     cur_file_changed();
  673. }
  674.  
  675. /* Generate a function definition head.
  676.  */
  677. void
  678. gen_func_definition (decl_spec, declarator)
  679. DeclSpec *decl_spec;
  680. Declarator *declarator;
  681. {
  682.     Parameter *p;
  683.     ParameterList *params;
  684.     char *comment;
  685.     int comment_len, n;
  686.  
  687.     /* Return if the function is already defined in the desired style. */
  688.     if (declarator->func_def == func_style)
  689.     return;
  690.  
  691.     /* Save the text between the function head and the function body.
  692.      * Read the temporary file from after the last ) or ; to the
  693.      * end of the file.
  694.      */
  695.     comment_len = (int)(ftell(cur_tmp_file()) - cur_begin_comment());
  696.     comment = xmalloc(comment_len);
  697.     fseek(cur_tmp_file(), cur_begin_comment(), 0);
  698.     fread(comment, sizeof(char), comment_len, cur_tmp_file());
  699.  
  700.     func_declarator = declarator->head;
  701.     format = FMT_FUNC;
  702.  
  703.     /* Save the text before the parameter declarations. */
  704.     if (func_style == FUNC_ANSI) {
  705.     params = &func_declarator->params;
  706.     n = (int)(params->end_comment - params->begin_comment);
  707.     if (n > 0) {
  708.         params->comment = xmalloc(n+1);
  709.         fseek(cur_tmp_file(), params->begin_comment, 0);
  710.         fread(params->comment, sizeof(char), n, cur_tmp_file());
  711.         params->comment[n] = '\0';
  712.         format = FMT_FUNC_COMMENT;
  713.     }
  714.     }
  715.  
  716.     /* Get the parameter comments. */
  717.     for (p = func_declarator->params.first; p != NULL; p = p->next) {
  718.     n = (int)(p->declarator->end_comment - p->declarator->begin_comment);
  719.     if (n > 0) {
  720.         p->comment = xmalloc(n+1);
  721.         fseek(cur_tmp_file(), p->declarator->begin_comment, 0);
  722.         fread(p->comment, sizeof(char), n, cur_tmp_file());
  723.         p->comment[n] = '\0';
  724.         format = FMT_FUNC_COMMENT;
  725.     }
  726.     }
  727.  
  728.     set_param_decl_spec(func_declarator);
  729.  
  730.     /* Go to the beginning of the function head in the temporary file
  731.      * and overwrite it with the converted function head.
  732.      */
  733.     fseek(cur_tmp_file(), decl_spec->begin, 0);
  734.  
  735.     /* Output declarator specifiers. */
  736.     fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
  737.     fputs(decl_spec->text, cur_tmp_file());
  738.     fputc(' ', cur_tmp_file());
  739.  
  740.     /* Output function declarator. */
  741.     where = FUNC_DEF;
  742.     put_func_declarator(cur_tmp_file(), declarator);
  743.  
  744.     if (func_style == FUNC_TRADITIONAL) {
  745.     /* Output traditional style parameter declarations. */
  746.     p = func_declarator->params.first;
  747.     if (!is_void_parameter(p)) {
  748.         fputc('\n', cur_tmp_file());
  749.         put_parameter(cur_tmp_file(), p);
  750.         fputc(';', cur_tmp_file());
  751.         p = p->next;
  752.         while (p != NULL && strcmp(p->declarator->text, "...") != 0) {
  753.         fputc('\n', cur_tmp_file());
  754.         put_parameter(cur_tmp_file(), p);
  755.         fputc(';', cur_tmp_file());
  756.         p = p->next;
  757.         }
  758.     }
  759.     }
  760.  
  761.     /* Output text between function head and body. */
  762.     fwrite(comment, sizeof(char), comment_len, cur_tmp_file());
  763.     free(comment);
  764.  
  765.     cur_file_changed();
  766. }
  767.