home *** CD-ROM | disk | FTP | other *** search
- /* $Id: semantic.c 2.1 91/03/25 11:40:31 cthuang Exp $
- *
- * C prototype generator
- * These routines implement the semantic actions executed by the yacc parser.
- */
- #include <stdio.h>
- #include "cproto.h"
- #include "semantic.h"
-
- /* Output a string to standard output. */
- #define put_string(s) fputs(s, stdout)
-
- /* Create a new string by joining two strings with a space between them.
- * Return a pointer to the resultant string or NULL if an error occurred.
- */
- static char *
- concat_string (a, b)
- char *a, *b;
- {
- char *result;
-
- if ((result = malloc((unsigned)(strlen(a) + strlen(b) + 2))) != NULL) {
- strcpy(result, a);
- strcat(result, " ");
- strcat(result, b);
- }
- return result;
- }
-
- /* Return TRUE if the given identifier is really a typedef name.
- * Search the symbol table for the identifier.
- */
- boolean
- is_typedef_name (name)
- char *name;
- {
- return (boolean)(find_symbol(typedef_names, name) != NULL);
- }
-
- /* Initialize a new declaration specifier part.
- */
- void
- new_decl_spec (decl_spec, text, flags)
- DeclSpec *decl_spec;
- char *text;
- unsigned short flags;
- {
- decl_spec->text = strdup(text);
- decl_spec->flags = flags;
- }
-
- /* Append two declaration specifier parts together.
- */
- void
- join_decl_specs (result, a, b)
- DeclSpec *result, *a, *b;
- {
- result->text = concat_string(a->text, b->text);
- result->flags = a->flags | b->flags;
- free(a->text);
- free(b->text);
- }
-
- /* Free storage used by a declaration specifier part.
- */
- void
- free_decl_spec (decl_spec)
- DeclSpec *decl_spec;
- {
- free(decl_spec->text);
- }
-
- /* Initialize the parameter structure.
- */
- void
- new_parameter (param, decl_spec, declarator)
- Parameter *param; /* pointer to structure to be initialized */
- DeclSpec *decl_spec; /* declaration specifier structure */
- Declarator *declarator; /* declarator structure */
- {
- if (decl_spec == NULL) {
- new_decl_spec(&(param->decl_spec), "", DE_JUNK);
- } else {
- param->decl_spec = *decl_spec;
- }
-
- if (declarator == NULL) {
- new_declarator(&(param->declarator), "", "");
- } else {
- param->declarator = *declarator;
- }
- }
-
- /* Free the storage used by the parameter.
- */
- void
- free_parameter (param)
- Parameter *param;
- {
- free_decl_spec(&(param->decl_spec));
- free_declarator(&(param->declarator));
- }
-
- /* Initialize a list of function parameters.
- */
- void
- new_param_list (param_list, param)
- ParameterList *param_list;
- Parameter *param;
- {
- Parameter *p;
-
- p = (Parameter *)malloc((unsigned)sizeof(Parameter));
- *p = *param;
-
- param_list->first = param_list->last = p;
- p->next = NULL;
- }
-
- /* Add the function parameter declaration to the list.
- */
- void
- add_param_list (to, from, param)
- ParameterList *to, *from;
- Parameter *param;
- {
- Parameter *p;
-
- p = (Parameter *)malloc((unsigned)sizeof(Parameter));
- *p = *param;
-
- to->first = from->first;
- from->last->next = p;
- to->last = p;
- p->next = NULL;
- }
-
- /* Free storage used by the elements in the function parameter list.
- */
- void
- free_param_list (param_list)
- ParameterList *param_list;
- {
- Parameter *p, *next;
-
- p = param_list->first;
- while (p != NULL) {
- next = p->next;
- free_parameter(p);
- free(p);
- p = next;
- }
- }
-
- /* Initialize an empty list of function parameter names.
- */
- void
- new_ident_list (param_list)
- ParameterList *param_list;
- {
- param_list->first = param_list->last = NULL;
- }
-
- /* Add an item to the list of function parameter declarations but set only
- * the parameter name field.
- */
- void
- add_ident_list (to, from, name)
- ParameterList *to, *from;
- char *name;
- {
- Parameter *p;
- Declarator declarator;
-
- p = (Parameter *)malloc((unsigned)sizeof(Parameter));
- new_declarator(&declarator, name, name);
- new_parameter(p, NULL, &declarator);
-
- to->first = from->first;
- if (to->first == NULL) {
- to->first = p;
- } else {
- from->last->next = p;
- }
- to->last = p;
- p->next = NULL;
- }
-
- /* Initialize a declarator.
- */
- void
- new_declarator (d, name, text)
- Declarator *d;
- char *name, *text;
- {
- d->name = strdup(name);
- d->text = strdup(text);
- d->func_def = FUNC_NONE;
- d->params.first = d->params.last = NULL;
- }
-
- /* Free storage used by a declarator.
- */
- void
- free_declarator (d)
- Declarator *d;
- {
- free(d->name);
- free(d->text);
- free_param_list(&(d->params));
- }
-
- /* Initialize a declarator list and add the given declarator to it.
- */
- void
- new_decl_list (decl_list, declarator)
- DeclaratorList *decl_list;
- Declarator *declarator;
- {
- Declarator *d;
-
- d = (Declarator *)malloc((unsigned)sizeof(Declarator));
- *d = *declarator;
-
- decl_list->first = decl_list->last = d;
- d->next = NULL;
- }
-
- /* Add the declarator to the declarator list.
- */
- void
- add_decl_list (to, from, declarator)
- DeclaratorList *to, *from;
- Declarator *declarator;
- {
- Declarator *d;
-
- d = (Declarator *)malloc((unsigned)sizeof(Declarator));
- *d = *declarator;
-
- to->first = from->first;
- from->last->next = d;
- to->last = d;
- to->last->next = NULL;
- }
-
- /* Free storage used by the declarators in the declarator list.
- */
- void
- free_decl_list (decl_list)
- DeclaratorList *decl_list;
- {
- Declarator *d, *next;
-
- d = decl_list->first;
- while (d != NULL) {
- next = d->next;
- free_declarator(d);
- free((char *)d);
- d = next;
- }
- }
-
- /* Search the list of parameters for a matching parameter name.
- * Return a pointer to the matching parameter or NULL if not found.
- */
- static Parameter *
- search_parameter_list (params, name)
- ParameterList *params;
- char *name;
- {
- Parameter *p;
-
- for (p = params->first; p != NULL; p = p->next) {
- if (strcmp(p->declarator.name, name) == 0)
- return p;
- }
- return (Parameter *)NULL;
- }
-
- /* This routine is called to generate function prototypes from traditional
- * style function definitions. For each parameter name in the declarator
- * list, find the matching parameter name in the parameter list and set
- * that parameter's declaration specifier.
- * This is also where we promote formal parameters. Parameters of type
- * "char", "unsigned char", "short", or "unsigned short" get promoted to
- * "int". Parameters of type "float" are promoted to "double".
- */
- void
- set_param_types (params, decl_spec, declarators)
- ParameterList *params;
- DeclSpec *decl_spec;
- DeclaratorList *declarators;
- {
- Declarator *d;
- Parameter *p;
- char *decl_spec_text, *s;
-
- for (d = declarators->first; d != NULL; d = d->next) {
- /* Search the parameter list for a matching name. */
- p = search_parameter_list(params, d->name);
- if (p == NULL) {
- output_error();
- fprintf(stderr, "declared argument \"%s\" is missing\n", d->name);
- } else {
- p->declarator.text = strdup(d->text);
- decl_spec_text = decl_spec->text;
- if (promote_param && strcmp(d->text, d->name) == 0) {
- s = rindex(decl_spec_text, ' ');
- s = (s != NULL) ? s+1 : decl_spec_text;
- if (strcmp(s, "char") == 0 || strcmp(s, "short") == 0)
- decl_spec_text = "int";
- else if (strcmp(s, "float") == 0)
- decl_spec_text = "double";
- }
- p->decl_spec.text = strdup(decl_spec_text);
- }
- }
- }
-
- /* Output a declaration specifier for an external declaration.
- */
- static void
- output_decl_spec (decl_spec)
- DeclSpec *decl_spec;
- {
- if (extern_out && (decl_spec->flags & DE_STATIC) == 0) {
- if (strstr(decl_spec->text, "extern") == NULL) {
- put_string("extern ");
- }
- }
- put_string(decl_spec->text);
- }
-
- static void output_parameters();
-
- /* Output a declarator.
- */
- static void
- output_declarator (d)
- Declarator *d;
- {
- char *s;
-
- if (d->func_def == FUNC_NONE) {
- put_string(d->text);
- } else {
- if ((s = strstr(d->text, "()")) != NULL) {
- *s = '\0';
- put_string(d->text);
- put_string(declarator_suffix);
- if (proto_style == PROTO_MACRO)
- printf(" %s(", macro_name);
- fputc(*s++ = '(', stdout);
- output_parameters(&(d->params));
- fputc(*s++, stdout);
- if (proto_style == PROTO_MACRO)
- putchar(')');
- put_string(s);
- }
- }
- }
-
- /* Output a function parameter.
- */
- static void
- output_parameter (p)
- Parameter *p;
- {
- char *s;
-
- put_string(p->decl_spec.text);
- if (proto_style == PROTO_ABSTRACT && strlen(p->declarator.name) > 0) {
- s = strstr(p->declarator.text, p->declarator.name);
- *s = '\0';
- printf(" %s/*%s*/%s", p->declarator.text, p->declarator.name,
- s + strlen(p->declarator.name));
- *s = *(p->declarator.name);
- } else {
- if (strlen(p->declarator.text) > 0) {
- putchar(' ');
- output_declarator(&(p->declarator));
- }
- }
- }
-
- /* Output the list of function parameters.
- */
- static void
- output_parameters (params)
- ParameterList *params;
- {
- Parameter *p;
-
- if (proto_style == PROTO_TRADITIONAL)
- put_string("/*");
-
- p = params->first;
- if (p == NULL ||
- (strcmp(p->decl_spec.text, "void") == 0 &&
- strlen(p->declarator.text) == 0)) {
- put_string("void");
- } else {
- put_string(first_param_prefix);
- output_parameter(p);
- p = p->next;
- while (p != NULL) {
- putchar(',');
- put_string(middle_param_prefix);
- output_parameter(p);
- p = p->next;
- }
- put_string(last_param_suffix);
- }
-
- if (proto_style == PROTO_TRADITIONAL)
- put_string("*/");
- }
-
- /* Output variable declarations.
- */
- void
- output_declarations (decl_spec, decl_list)
- DeclSpec *decl_spec; /* declaration specifier */
- DeclaratorList *decl_list; /* list of declared variables */
- {
- Declarator *d;
-
- if (!variables_out || (decl_spec->flags & DE_JUNK))
- return;
- if (!static_out && (decl_spec->flags & DE_STATIC))
- return;
-
- for (d = decl_list->first; d != NULL; d = d->next) {
- if (d->func_def == FUNC_NONE) {
- put_string(decl_spec_prefix);
- output_decl_spec(decl_spec);
- putchar(' ');
- output_declarator(d);
- put_string(";\n");
- }
- }
- }
-
- /* Output a function prototype.
- */
- void
- output_prototype (decl_spec, declarator)
- DeclSpec *decl_spec;
- Declarator *declarator;
- {
- Parameter *p;
-
- if (proto_style == PROTO_NONE)
- return;
- if (decl_spec->flags & DE_JUNK)
- return;
- if (!static_out && (decl_spec->flags & DE_STATIC))
- return;
-
- /* Check for parameter names with no declaration specifiers. This
- * happens when a parameter name appears in the identifier list of a
- * function definition but does not appear in the parameter declaration
- * part. The default type in this cause is "int".
- */
- for (p = declarator->params.first; p != NULL; p = p->next) {
- if (strlen(p->decl_spec.text) == 0) {
- free(p->decl_spec.text);
- p->decl_spec.text = strdup("int");
- }
- }
-
- put_string(decl_spec_prefix);
- output_decl_spec(decl_spec);
- put_string(declarator_prefix);
- output_declarator(declarator);
- put_string(";\n");
- }
-