home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / cproto / part02 / semantic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-25  |  10.4 KB  |  479 lines

  1. /* $Id: semantic.c 2.1 91/03/25 11:40:31 cthuang Exp $
  2.  *
  3.  * C prototype generator
  4.  * These routines implement the semantic actions executed by the yacc parser.
  5.  */
  6. #include <stdio.h>
  7. #include "cproto.h"
  8. #include "semantic.h"
  9.  
  10. /* Output a string to standard output. */
  11. #define put_string(s) fputs(s, stdout)
  12.  
  13. /* Create a new string by joining two strings with a space between them.
  14.  * Return a pointer to the resultant string or NULL if an error occurred.
  15.  */
  16. static char *
  17. concat_string (a, b)
  18. char *a, *b;
  19. {
  20.     char *result;
  21.  
  22.     if ((result = malloc((unsigned)(strlen(a) + strlen(b) + 2))) != NULL) {
  23.     strcpy(result, a);
  24.     strcat(result, " ");
  25.     strcat(result, b);
  26.     }
  27.     return result;
  28. }
  29.  
  30. /* Return TRUE if the given identifier is really a typedef name.
  31.  * Search the symbol table for the identifier.
  32.  */
  33. boolean
  34. is_typedef_name (name)
  35. char *name;
  36. {
  37.     return (boolean)(find_symbol(typedef_names, name) != NULL);
  38. }
  39.  
  40. /* Initialize a new declaration specifier part.
  41.  */
  42. void
  43. new_decl_spec (decl_spec, text, flags)
  44. DeclSpec *decl_spec;
  45. char *text;
  46. unsigned short flags;
  47. {
  48.     decl_spec->text = strdup(text);
  49.     decl_spec->flags = flags;
  50. }
  51.  
  52. /* Append two declaration specifier parts together.
  53.  */
  54. void
  55. join_decl_specs (result, a, b)
  56. DeclSpec *result, *a, *b;
  57. {
  58.     result->text = concat_string(a->text, b->text);
  59.     result->flags = a->flags | b->flags;
  60.     free(a->text);
  61.     free(b->text);
  62. }
  63.  
  64. /* Free storage used by a declaration specifier part.
  65.  */
  66. void
  67. free_decl_spec (decl_spec)
  68. DeclSpec *decl_spec;
  69. {
  70.     free(decl_spec->text);
  71. }
  72.  
  73. /* Initialize the parameter structure.
  74.  */
  75. void
  76. new_parameter (param, decl_spec, declarator)
  77. Parameter *param;        /* pointer to structure to be initialized */
  78. DeclSpec *decl_spec;        /* declaration specifier structure */
  79. Declarator *declarator;        /* declarator structure */
  80. {
  81.     if (decl_spec == NULL) {
  82.     new_decl_spec(&(param->decl_spec), "", DE_JUNK);
  83.     } else {
  84.     param->decl_spec = *decl_spec;
  85.     }
  86.  
  87.     if (declarator == NULL) {
  88.     new_declarator(&(param->declarator), "", "");
  89.     } else {
  90.     param->declarator = *declarator;
  91.     }
  92. }
  93.  
  94. /* Free the storage used by the parameter.
  95.  */
  96. void
  97. free_parameter (param)
  98. Parameter *param;
  99. {
  100.     free_decl_spec(&(param->decl_spec));
  101.     free_declarator(&(param->declarator));
  102. }
  103.  
  104. /* Initialize a list of function parameters.
  105.  */
  106. void
  107. new_param_list (param_list, param)
  108. ParameterList *param_list;
  109. Parameter *param;
  110. {
  111.     Parameter *p;
  112.  
  113.     p = (Parameter *)malloc((unsigned)sizeof(Parameter));
  114.     *p = *param;
  115.     
  116.     param_list->first = param_list->last = p;
  117.     p->next = NULL;
  118. }
  119.  
  120. /* Add the function parameter declaration to the list.
  121.  */
  122. void
  123. add_param_list (to, from, param)
  124. ParameterList *to, *from;
  125. Parameter *param;
  126. {
  127.     Parameter *p;
  128.  
  129.     p = (Parameter *)malloc((unsigned)sizeof(Parameter));
  130.     *p = *param;
  131.  
  132.     to->first = from->first;
  133.     from->last->next = p;
  134.     to->last = p;
  135.     p->next = NULL;
  136. }
  137.  
  138. /* Free storage used by the elements in the function parameter list.
  139.  */
  140. void
  141. free_param_list (param_list)
  142. ParameterList *param_list;
  143. {
  144.     Parameter *p, *next;
  145.  
  146.     p = param_list->first;
  147.     while (p != NULL) {
  148.     next = p->next;
  149.     free_parameter(p);
  150.     free(p);
  151.     p = next;
  152.     }
  153. }
  154.  
  155. /* Initialize an empty list of function parameter names.
  156.  */
  157. void
  158. new_ident_list (param_list)
  159. ParameterList *param_list;
  160. {
  161.     param_list->first = param_list->last = NULL;
  162. }
  163.  
  164. /* Add an item to the list of function parameter declarations but set only
  165.  * the parameter name field.
  166.  */
  167. void
  168. add_ident_list (to, from, name)
  169. ParameterList *to, *from;
  170. char *name;
  171. {
  172.     Parameter *p;
  173.     Declarator declarator;
  174.  
  175.     p = (Parameter *)malloc((unsigned)sizeof(Parameter));
  176.     new_declarator(&declarator, name, name);
  177.     new_parameter(p, NULL, &declarator);
  178.  
  179.     to->first = from->first;
  180.     if (to->first == NULL) {
  181.     to->first = p;
  182.     } else {
  183.     from->last->next = p;
  184.     }
  185.     to->last = p;
  186.     p->next = NULL;
  187. }
  188.  
  189. /* Initialize a declarator.
  190.  */
  191. void
  192. new_declarator (d, name, text)
  193. Declarator *d;
  194. char *name, *text;
  195. {
  196.     d->name = strdup(name);
  197.     d->text = strdup(text);
  198.     d->func_def = FUNC_NONE;
  199.     d->params.first = d->params.last = NULL;
  200. }
  201.  
  202. /* Free storage used by a declarator.
  203.  */
  204. void
  205. free_declarator (d)
  206. Declarator *d;
  207. {
  208.     free(d->name);
  209.     free(d->text);
  210.     free_param_list(&(d->params));
  211. }
  212.  
  213. /* Initialize a declarator list and add the given declarator to it.
  214.  */
  215. void
  216. new_decl_list (decl_list, declarator)
  217. DeclaratorList *decl_list;
  218. Declarator *declarator;
  219. {
  220.     Declarator *d;
  221.  
  222.     d = (Declarator *)malloc((unsigned)sizeof(Declarator));
  223.     *d = *declarator;
  224.  
  225.     decl_list->first = decl_list->last = d;
  226.     d->next = NULL;
  227. }
  228.  
  229. /* Add the declarator to the declarator list.
  230.  */
  231. void
  232. add_decl_list (to, from, declarator)
  233. DeclaratorList *to, *from;
  234. Declarator *declarator;
  235. {
  236.     Declarator *d;
  237.  
  238.     d = (Declarator *)malloc((unsigned)sizeof(Declarator));
  239.     *d = *declarator;
  240.  
  241.     to->first = from->first;
  242.     from->last->next = d;
  243.     to->last = d;
  244.     to->last->next = NULL;
  245. }
  246.  
  247. /* Free storage used by the declarators in the declarator list.
  248.  */
  249. void
  250. free_decl_list (decl_list)
  251. DeclaratorList *decl_list;
  252. {
  253.     Declarator *d, *next;
  254.  
  255.     d = decl_list->first;
  256.     while (d != NULL) {
  257.     next = d->next;
  258.     free_declarator(d);
  259.     free((char *)d);
  260.     d = next;
  261.     }
  262. }
  263.  
  264. /* Search the list of parameters for a matching parameter name.
  265.  * Return a pointer to the matching parameter or NULL if not found.
  266.  */
  267. static Parameter *
  268. search_parameter_list (params, name)
  269. ParameterList *params;
  270. char *name;
  271. {
  272.     Parameter *p;
  273.  
  274.     for (p = params->first; p != NULL; p = p->next) {
  275.     if (strcmp(p->declarator.name, name) == 0)
  276.         return p;
  277.     }
  278.     return (Parameter *)NULL;
  279. }
  280.  
  281. /* This routine is called to generate function prototypes from traditional
  282.  * style function definitions.  For each parameter name in the declarator
  283.  * list, find the matching parameter name in the parameter list and set
  284.  * that parameter's declaration specifier.
  285.  * This is also where we promote formal parameters.  Parameters of type
  286.  * "char", "unsigned char", "short", or "unsigned short" get promoted to
  287.  * "int".  Parameters of type "float" are promoted to "double".
  288.  */
  289. void
  290. set_param_types (params, decl_spec, declarators)
  291. ParameterList *params;
  292. DeclSpec *decl_spec;
  293. DeclaratorList *declarators;
  294. {
  295.     Declarator *d;
  296.     Parameter *p;
  297.     char *decl_spec_text, *s;
  298.  
  299.     for (d = declarators->first; d != NULL; d = d->next) {
  300.     /* Search the parameter list for a matching name. */
  301.     p = search_parameter_list(params, d->name);
  302.     if (p == NULL) {
  303.         output_error();
  304.         fprintf(stderr, "declared argument \"%s\" is missing\n", d->name);
  305.     } else {
  306.         p->declarator.text = strdup(d->text);
  307.         decl_spec_text = decl_spec->text;
  308.         if (promote_param && strcmp(d->text, d->name) == 0) {
  309.             s = rindex(decl_spec_text, ' ');
  310.         s = (s != NULL) ? s+1 : decl_spec_text;
  311.         if (strcmp(s, "char") == 0 || strcmp(s, "short") == 0)
  312.             decl_spec_text = "int";
  313.         else if (strcmp(s, "float") == 0)
  314.             decl_spec_text = "double";
  315.         }
  316.         p->decl_spec.text = strdup(decl_spec_text);
  317.     }
  318.     }
  319. }
  320.  
  321. /* Output a declaration specifier for an external declaration.
  322.  */
  323. static void
  324. output_decl_spec (decl_spec)
  325. DeclSpec *decl_spec;
  326. {
  327.     if (extern_out && (decl_spec->flags & DE_STATIC) == 0) {
  328.     if (strstr(decl_spec->text, "extern") == NULL) {
  329.         put_string("extern ");
  330.     }
  331.     }
  332.     put_string(decl_spec->text);
  333. }
  334.  
  335. static void output_parameters();
  336.  
  337. /* Output a declarator.
  338.  */
  339. static void
  340. output_declarator (d)
  341. Declarator *d;
  342. {
  343.     char *s;
  344.  
  345.     if (d->func_def == FUNC_NONE) {
  346.     put_string(d->text);
  347.     } else {
  348.     if ((s = strstr(d->text, "()")) != NULL) {
  349.         *s = '\0';
  350.         put_string(d->text);
  351.         put_string(declarator_suffix);
  352.         if (proto_style == PROTO_MACRO)
  353.         printf(" %s(", macro_name);
  354.         fputc(*s++ = '(', stdout);
  355.         output_parameters(&(d->params));
  356.         fputc(*s++, stdout);
  357.         if (proto_style == PROTO_MACRO)
  358.         putchar(')');
  359.         put_string(s);
  360.     }
  361.     }
  362. }
  363.  
  364. /* Output a function parameter.
  365.  */
  366. static void
  367. output_parameter (p)
  368. Parameter *p;
  369. {
  370.     char *s;
  371.  
  372.     put_string(p->decl_spec.text);
  373.     if (proto_style == PROTO_ABSTRACT && strlen(p->declarator.name) > 0) {
  374.     s = strstr(p->declarator.text, p->declarator.name);
  375.     *s = '\0';
  376.     printf(" %s/*%s*/%s", p->declarator.text, p->declarator.name,
  377.         s + strlen(p->declarator.name));
  378.     *s = *(p->declarator.name);
  379.     } else {
  380.     if (strlen(p->declarator.text) > 0) {
  381.         putchar(' ');
  382.         output_declarator(&(p->declarator));
  383.     }
  384.     }
  385. }
  386.  
  387. /* Output the list of function parameters.
  388.  */
  389. static void
  390. output_parameters (params)
  391. ParameterList *params;
  392. {
  393.     Parameter *p;
  394.  
  395.     if (proto_style == PROTO_TRADITIONAL)
  396.     put_string("/*");
  397.  
  398.     p = params->first;
  399.     if (p == NULL ||
  400.         (strcmp(p->decl_spec.text, "void") == 0 &&
  401.      strlen(p->declarator.text) == 0)) {
  402.     put_string("void");
  403.     } else {
  404.     put_string(first_param_prefix);
  405.     output_parameter(p);
  406.     p = p->next;
  407.     while (p != NULL) {
  408.         putchar(',');
  409.         put_string(middle_param_prefix);
  410.         output_parameter(p);
  411.         p = p->next;
  412.     }
  413.     put_string(last_param_suffix);
  414.     }
  415.  
  416.     if (proto_style == PROTO_TRADITIONAL)
  417.     put_string("*/");
  418. }
  419.  
  420. /* Output variable declarations.
  421.  */
  422. void
  423. output_declarations (decl_spec, decl_list)
  424. DeclSpec *decl_spec;        /* declaration specifier */
  425. DeclaratorList *decl_list;    /* list of declared variables */
  426. {
  427.     Declarator *d;
  428.  
  429.     if (!variables_out || (decl_spec->flags & DE_JUNK))
  430.     return;
  431.     if (!static_out && (decl_spec->flags & DE_STATIC))
  432.     return;
  433.  
  434.     for (d = decl_list->first; d != NULL; d = d->next) {
  435.     if (d->func_def == FUNC_NONE) {
  436.         put_string(decl_spec_prefix);
  437.         output_decl_spec(decl_spec);
  438.         putchar(' ');
  439.         output_declarator(d);
  440.         put_string(";\n");
  441.     }
  442.     }
  443. }
  444.  
  445. /* Output a function prototype.
  446.  */
  447. void
  448. output_prototype (decl_spec, declarator)
  449. DeclSpec *decl_spec;
  450. Declarator *declarator;
  451. {
  452.     Parameter *p;
  453.  
  454.     if (proto_style == PROTO_NONE)
  455.     return;
  456.     if (decl_spec->flags & DE_JUNK)
  457.     return;
  458.     if (!static_out && (decl_spec->flags & DE_STATIC))
  459.     return;
  460.  
  461.     /* Check for parameter names with no declaration specifiers.  This
  462.      * happens when a parameter name appears in the identifier list of a
  463.      * function definition but does not appear in the parameter declaration
  464.      * part.  The default type in this cause is "int".
  465.      */
  466.     for (p = declarator->params.first; p != NULL; p = p->next) {
  467.     if (strlen(p->decl_spec.text) == 0) {
  468.         free(p->decl_spec.text);
  469.         p->decl_spec.text = strdup("int");
  470.     }
  471.     }
  472.  
  473.     put_string(decl_spec_prefix);
  474.     output_decl_spec(decl_spec);
  475.     put_string(declarator_prefix);
  476.     output_declarator(declarator);
  477.     put_string(";\n");
  478. }
  479.