home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cproto.zip
/
cproto46
/
semantic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-18
|
31KB
|
1,226 lines
/* $Id: semantic.c,v 4.5 1998/01/19 00:49:26 cthuang Exp $
*
* Semantic actions executed by the parser of the
* C function prototype generator.
*/
#include <stdio.h>
#include "cproto.h"
#include "semantic.h"
#if OPT_LINTLIBRARY
static int put_parameter ARGS((FILE *outf, Parameter *p, int name_only, int count, int commented));
#define putParameter(fp,p,f,n,c) put_parameter(fp, p, f, n, c)
#else
static int put_parameter ARGS((FILE *outf, Parameter *p, int commented));
#define putParameter(fp,p,f,n,c) put_parameter(fp, p, c)
#endif
static char * concat_string ARGS((char *a, char *b));
#if OPT_LINTLIBRARY
static char * glue_strings ARGS((char *a, char *b));
#endif
static boolean is_void_parameter ARGS((Parameter *p));
static Parameter * search_parameter_list ARGS((ParameterList *params, char *name));
static void put_param_list ARGS((FILE *outf, Declarator *declarator, int commented));
static void put_parameters ARGS((FILE *outf, Declarator *declarator, int commented));
static void put_func_declarator ARGS((FILE *outf, Declarator *declarator, int commented));
static void put_declarator ARGS((FILE *outf, Declarator *declarator, int commented));
static void put_decl_spec ARGS((FILE *outf, DeclSpec *decl_spec));
#if OPT_LINTLIBRARY
static void put_llib_params ARGS((Declarator *d, int c));
#endif
static int uses_varargs ARGS((Declarator *declarator));
static void check_void_param ARGS((Declarator *declarator));
static void set_param_decl_spec ARGS((Declarator *declarator));
static void put_param_decl ARGS((Declarator *declarator, int commented));
/* Head function declarator in a prototype or function definition */
static Declarator *func_declarator;
/* Role of the function declarator
* FUNC_PROTO if it is the declarator in a function prototype.
* FUNC_DEF if it is the declarator in a function definition.
*/
static int where;
/* Output format to use */
static int format;
/* Function-parameter level, used to simplify logic that comments/suppresses
* function parameters in the output.
*/
static int nestedParams;
/* Initialize a new declaration specifier part.
*/
void
new_decl_spec (decl_spec, text, offset, flags)
DeclSpec *decl_spec;
char *text;
long offset;
int flags;
{
#if OPT_LINTLIBRARY
if (lintLibrary()) {
if (!strcmp(text, "register"))
text = "";
}
#endif
decl_spec->text = xstrdup(text);
decl_spec->begin = offset;
decl_spec->flags = flags;
}
/* Free storage used by a declaration specifier part.
*/
void
free_decl_spec (decl_spec)
DeclSpec *decl_spec;
{
free(decl_spec->text);
}
/* Create a new string by joining two strings with a space between them.
* Return a pointer to the resultant string.
* If out of memory, output an error message and exit.
*/
static char *
concat_string (a, b)
char *a, *b;
{
char *result;
result = xmalloc(strlen(a) + strlen(b) + 2);
strcpy(result, a);
strcat(result, " ");
strcat(result, b);
return result;
}
#if OPT_LINTLIBRARY
static char *
glue_strings (a, b) /* concatenate w/o embedded blank */
char *a, *b;
{
char *result;
result = xmalloc(strlen(a) + strlen(b) + 2);
strcpy(result, a);
strcat(result, b);
return result;
}
#endif
/* 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;
result->begin = a->begin;
}
/* Output an error message if the declaration specifier is an untagged
* struct, union or enum.
*/
void
check_untagged (decl_spec)
DeclSpec *decl_spec;
{
if (strstr(decl_spec->text, "struct {}") != NULL) {
put_error();
fputs("untagged struct declaration\n", stderr);
} else if (strstr(decl_spec->text, "union {}") != NULL) {
put_error();
fputs("untagged union declaration\n", stderr);
} else if (strstr(decl_spec->text, "enum {}") != NULL) {
put_error();
fputs("untagged enum declaration\n", stderr);
}
}
/* Allocate and initialize a declarator.
*/
Declarator *
new_declarator (text, name, offset)
char *text, *name;
long offset;
{
Declarator *d;
d = NEW(Declarator);
d->text = xstrdup(text);
d->name = xstrdup(name);
d->begin = offset;
d->begin_comment = d->end_comment = 0;
d->func_def = FUNC_NONE;
new_ident_list(&d->params);
d->head = d;
d->func_stack = NULL;
d->pointer = FALSE;
return d;
}
/* Free storage used by a declarator.
*/
void
free_declarator (d)
Declarator *d;
{
free(d->text);
free(d->name);
free_param_list(&d->params);
if (d->func_stack != NULL)
free_declarator(d->func_stack);
free(d);
}
/* Initialize a declarator list and add the given declarator to it.
*/
void
new_decl_list (decl_list, declarator)
DeclaratorList *decl_list;
Declarator *declarator;
{
decl_list->first = decl_list->last = declarator;
declarator->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);
d = next;
}
}
/* Add the declarator to the declarator list.
*/
void
add_decl_list (to, from, declarator)
DeclaratorList *to, *from;
Declarator *declarator;
{
to->first = from->first;
from->last->next = declarator;
to->last = declarator;
to->last->next = NULL;
}
/* Create a new parameter structure.
*/
Parameter *
new_parameter (decl_spec, declarator)
DeclSpec *decl_spec;
Declarator *declarator;
{
Parameter *param;
param = NEW(Parameter);
if (decl_spec == NULL) {
new_decl_spec(¶m->decl_spec, "", 0L, DS_NONE);
} else {
param->decl_spec = *decl_spec;
}
if (declarator == NULL) {
declarator = new_declarator("", "", 0L);
}
param->declarator = declarator;
param->comment = NULL;
return param;
}
/* Free the storage used by the parameter.
*/
void
free_parameter (param)
Parameter *param;
{
free_decl_spec(¶m->decl_spec);
free_declarator(param->declarator);
if (param->comment != NULL)
free(param->comment);
free(param);
}
/* Return TRUE if the parameter is void.
*/
static boolean
is_void_parameter (p)
Parameter *p;
{
return p == NULL || (strcmp(p->decl_spec.text, "void") == 0 &&
p->declarator->text[0] == '\0');
}
/* Initialize a list of function parameters.
*/
void
new_param_list (param_list, param)
ParameterList *param_list;
Parameter *param;
{
param_list->first = param_list->last = param;
param->next = NULL;
param_list->begin_comment = param_list->end_comment = 0;
param_list->comment = 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);
p = next;
}
if (param_list->comment != NULL)
free(param_list->comment);
}
/* Add the parameter to the function parameter list.
*/
void
add_param_list (to, from, param)
ParameterList *to, *from;
Parameter *param;
{
to->first = from->first;
from->last->next = param;
to->last = param;
param->next = NULL;
}
/* Initialize an empty list of function parameter names.
*/
void
new_ident_list (param_list)
ParameterList *param_list;
{
param_list->first = param_list->last = NULL;
param_list->begin_comment = param_list->end_comment = 0;
param_list->comment = 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;
declarator = new_declarator(name, name, 0L);
p = new_parameter((DeclSpec *)0, declarator);
to->first = from->first;
if (to->first == NULL) {
to->first = p;
} else {
from->last->next = p;
}
to->last = p;
p->next = NULL;
}
/* 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;
}
/* For each name in the declarator list <declarators>, set the declaration
* specifier part of the parameter in <params> having the same name.
* This is also where we promote formal parameters. Parameters of type
* "char", "unsigned char", "short", or "unsigned short" are 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;
for (d = declarators->first; d != NULL; d = d->next) {
/* Search the parameter list for a matching name. */
if ((p = search_parameter_list(params, d->name)) == NULL) {
put_error();
fprintf(stderr, "declared argument \"%s\" is missing\n", d->name);
} else {
decl_spec_text = decl_spec->text;
if (promote_param && strcmp(d->text, d->name) == 0) {
if (decl_spec->flags & (DS_CHAR | DS_SHORT))
decl_spec_text = "int";
else if (decl_spec->flags & DS_FLOAT)
decl_spec_text = "double";
}
free(p->decl_spec.text);
p->decl_spec.text = xstrdup(decl_spec_text);
free_declarator(p->declarator);
p->declarator = d;
}
}
}
/* Output a function parameter.
*/
static int
put_parameter (outf, p,
#if OPT_LINTLIBRARY
name_only, count,
#endif
commented)
FILE *outf;
Parameter *p;
#if OPT_LINTLIBRARY
int name_only; /* nonzero if we only show the parameter name */
int count; /* index in parameter list if we haven't names */
#endif
int commented; /* comment-delimiters already from higher level */
{
char *s;
char gap = ' ';
#if OPT_LINTLIBRARY
if (name_only) {
s = p->declarator->name;
if (lintLibrary()) {
while (*s == '*')
s++;
if (*s == '\0' && !is_void_parameter(p))
s = supply_parm(count);
}
put_string(outf, s); /* ... remainder of p->declarator.name */
return (TRUE);
}
#endif
s = p->decl_spec.text;
#if OPT_LINTLIBRARY
if (lintLibrary()) {
if (is_void_parameter(p))
return (FALSE);
indent(outf);
if (knrLintLibrary() && !*s)
s = "int";
if (strlen(s) < 8)
gap = '\t';
}
#endif
put_string(outf, s);
#if OPT_LINTLIBRARY
if (lintLibrary()) {
char *t, *u;
s = p->declarator->text;
while (*s == '*')
s++;
if (*s == '\0') {
u = p->declarator->text;
p->declarator->text = glue_strings(u, supply_parm(count));
free(u);
} else if (p->declarator->name[0] == '\0') {
if ((t = strstr(s, "%s")) != 0) {
int parenthesized = FALSE;
Declarator *q;
free(p->declarator->name);
p->declarator->name = xstrdup(supply_parm(count));
for (q = p->declarator; q != 0; q = q->func_stack) {
if (q->func_def == FUNC_NONE) {
if (!strcmp(q->text, "(*)")) {
char temp[20];
sprintf(temp, "(*%s)", p->declarator->name);
free(q->text);
q->text = xstrdup(temp);
parenthesized = TRUE;
} else {
free(q->text);
q->text = xstrdup(p->declarator->name);
}
break;
}
}
if (!parenthesized) {
if ((u = strchr(t, PAREN_L)) != 0) { /* e.g., "*%s()" */
t = p->declarator->text;
u = xmalloc(strlen(t) + 3);
(void)sprintf(u, "(%s)", t);
p->declarator->text = u;
free(t);
}
}
} else { /* e.g., s is "[20]" for "char [20]" parameter */
/* ...or something like "* const *" */
while (*s != '\0' && *s != SQUARE_L)
s++;
u = xstrdup(s); /* the "[20]" */
*s = '\0';
if (s != p->declarator->text) {
s = glue_strings(p->declarator->text, supply_parm(count));
} else {
s = xstrdup(supply_parm(count));
}
p->declarator->text = glue_strings(s, u);
free(u);
free(s);
}
}
}
#endif
if (p->declarator->text[0] != '\0') {
if (strcmp(p->declarator->text, ELLIPSIS) == 0) {
put_string(outf, ELLIPSIS);
} else {
if (proto_style != PROTO_ABSTRACT || proto_comments
|| where != FUNC_PROTO
|| strcmp(p->declarator->text, p->declarator->name) != 0)
put_char(outf, gap);
put_declarator(outf, p->declarator, commented);
}
}
return (TRUE);
}
/* Output a parameter list.
*/
static void
put_param_list (outf, declarator, commented)
FILE *outf;
Declarator *declarator;
int commented;
{
#if OPT_LINTLIBRARY
int count = 0;
#endif
Parameter *p;
int f;
int hide_it = (where == FUNC_PROTO) && (proto_style == PROTO_TRADITIONAL);
int do_cmt = proto_comments && hide_it;
p = declarator->params.first;
if (hide_it && !do_cmt) {
;
} else if (is_void_parameter(p)) {
if (do_cmt) {
if (!commented)
put_string(outf, COMMENT_BEGIN);
put_string(outf, "void");
if (!commented)
put_string(outf, COMMENT_END);
} else if (!hide_it)
#if OPT_LINTLIBRARY
if (!knrLintLibrary())
#endif
put_string(outf, "void");
} else {
f = (declarator == func_declarator) ? format : FMT_OTHER;
#if OPT_LINTLIBRARY
if (where == FUNC_PROTO
&& knrLintLibrary()
&& (func_declarator != declarator)) {
do_cmt = TRUE; /* patch: shouldn't have gotten here at all */
}
#endif
if (where == FUNC_DEF && declarator->params.comment != NULL)
put_string(outf, declarator->params.comment);
else if (do_cmt && !commented)
put_string(outf, COMMENT_BEGIN);
put_string(outf, fmt[f].first_param_prefix);
(void)putParameter(outf, p, knrLintLibrary(), ++count, commented);
while (p->next != NULL) {
#if OPT_LINTLIBRARY
if (lint_ellipsis(p->next))
break;
#endif
put_char(outf, ',');
if (where == FUNC_DEF && p->comment != NULL)
put_string(outf, p->comment);
p = p->next;
put_string(outf, fmt[f].middle_param_prefix);
(void)putParameter(outf, p, knrLintLibrary(), ++count, commented);
}
if (where == FUNC_DEF && p->comment != NULL)
put_string(outf, p->comment);
else if (do_cmt && !commented)
put_string(outf, COMMENT_END);
put_string(outf, fmt[f].last_param_suffix);
}
}
/* Output function parameters.
*/
static void
put_parameters (outf, declarator, commented)
FILE *outf;
Declarator *declarator;
int commented;
{
Parameter *p;
nestedParams++;
if (where == FUNC_DEF && func_style == FUNC_TRADITIONAL) {
/* Output parameter name list for traditional function definition. */
p = declarator->params.first;
/* Output parameter name list only for head function declarator. */
if (!is_void_parameter(p) && declarator == func_declarator) {
put_string(outf, fmt[format].first_param_prefix);
put_string(outf, p->declarator->name);
p = p->next;
while (p != NULL && strcmp(p->declarator->text, ELLIPSIS) != 0) {
put_char(outf, ',');
put_string(outf, fmt[format].middle_param_prefix);
put_string(outf, p->declarator->name);
p = p->next;
}
put_string(outf, fmt[format].last_param_suffix);
}
} else {
/* Output parameter type list. */
if (where == FUNC_PROTO && proto_style == PROTO_TRADITIONAL &&
declarator == func_declarator) {
if (proto_comments) {
put_string(outf, COMMENT_BEGIN);
put_param_list(outf, declarator, TRUE);
put_string(outf, COMMENT_END);
}
} else if (func_style != FUNC_NONE || proto_style != PROTO_NONE) {
#if OPT_LINTLIBRARY
if (!knrLintLibrary() || nestedParams <= 1)
#endif
put_param_list(outf, declarator, commented);
}
}
nestedParams--;
}
/* Output a function declarator.
*/
static void
put_func_declarator (outf, declarator, commented)
FILE *outf;
Declarator *declarator;
int commented;
{
char *s, *t, *decl_text;
int f;
int saveNest = nestedParams;
/* Output declarator text before function declarator place holder. */
if ((s = strstr(declarator->text, "%s")) == NULL)
return;
*s = '\0';
put_string(outf, declarator->text);
/* Substitute place holder with function declarator. */
if (declarator->func_stack->func_def == FUNC_NONE) {
decl_text = declarator->func_stack->text;
if (declarator->name[0] == '\0') {
put_string(outf, decl_text);
} else {
int star;
/* Output the declarator text before the declarator name. */
if ((t = strstr(decl_text, declarator->name)) == NULL)
return;
*t = '\0';
star = ((t != decl_text) && (t[-1] == '*'));
put_string(outf, decl_text);
*t = declarator->name[0];
/* Output the declarator prefix before the name. */
f = (declarator == func_declarator) ? format : FMT_OTHER;
if (strcmp(fmt[f].declarator_prefix, " ") != 0)
put_string(outf, fmt[f].declarator_prefix);
/* Output the declarator name. */
if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
declarator != func_declarator) {
if (proto_comments) {
if (star) put_char(outf, ' ');
put_string(outf, COMMENT_BEGIN);
put_string(outf, declarator->name);
put_string(outf, COMMENT_END);
}
} else {
put_string(outf, declarator->name);
}
/* Output the remaining declarator text. */
put_string(outf, t + strlen(declarator->name));
/* Output the declarator suffix. */
put_string(outf, fmt[f].declarator_suffix);
}
} else {
put_func_declarator(outf, declarator->func_stack, commented);
nestedParams = 2; /* e.g., "void (*signal(p1, p2))()" */
}
*s = '%';
s += 2;
/* Output declarator text up to but before parameters place holder. */
if ((t = strstr(s, "()")) == NULL)
return;
*t = '\0';
put_string(outf, s);
if (where == FUNC_PROTO
&& (func_declarator == declarator
|| func_declarator == declarator->head)
&& proto_macro) {
fprintf(outf, " %s(", macro_name);
}
/* Substitute place holder with function parameters. */
put_char(outf, *t++ = PAREN_L);
put_parameters(outf, declarator, commented);
put_string(outf, t);
if (where == FUNC_PROTO
&& (func_declarator == declarator
|| func_declarator == declarator->head)
&& proto_macro) {
put_char(outf, PAREN_R);
}
nestedParams = saveNest;
}
/* Output a declarator.
*/
static void
put_declarator (outf, declarator, commented)
FILE *outf;
Declarator *declarator;
int commented;
{
char *s;
if (declarator->func_def == FUNC_NONE) {
if (where == FUNC_PROTO && proto_style == PROTO_ABSTRACT &&
declarator->name[0] != '\0') {
if ((s = strstr(declarator->text, declarator->name)) == NULL)
return;
*s = '\0';
if (proto_comments) {
fprintf(outf, "%s%s%s%s%s", declarator->text,
COMMENT_BEGIN, declarator->name, COMMENT_END,
s + strlen(declarator->name));
} else {
fprintf(outf, "%s%s", declarator->text,
s + strlen(declarator->name));
}
*s = declarator->name[0];
} else {
put_string(outf, declarator->text);
}
} else {
put_func_declarator(outf, declarator, commented);
}
}
/* Output a declaration specifier for an external declaration.
*/
static void
put_decl_spec (outf, decl_spec)
FILE *outf;
DeclSpec *decl_spec;
{
/* An "extern func()" is legal, but we want to be explicit for lint libs */
#if OPT_LINTLIBRARY
if (decl_spec->text[0] == '\0') {
free(decl_spec->text);
decl_spec->text = xstrdup("int");
}
#endif
if (extern_out && !(decl_spec->flags & DS_STATIC) &&
strkey(decl_spec->text, "extern") == NULL)
put_padded(outf, "extern");
put_padded(outf, decl_spec->text);
}
/* Output the list of parameters in K&R style, for lint-library
*/
#if OPT_LINTLIBRARY
static void
put_llib_params(declarator, commented)
Declarator *declarator;
int commented;
{
Parameter *p;
int count = 0;
nestedParams++;
p = (declarator->func_stack->func_def != FUNC_NONE)
? declarator->func_stack->params.first
: declarator->params.first;
while (p != 0) {
if (lint_ellipsis(p))
break;
if (putParameter(stdout, p, FALSE, ++count, commented))
putchar(';');
p = p->next;
}
nestedParams--;
}
#endif
/* Generate variable declarations.
*/
void
gen_declarations (decl_spec, decl_list)
DeclSpec *decl_spec; /* declaration specifier */
DeclaratorList *decl_list; /* list of declared variables */
{
Declarator *d;
int commented = FALSE;
int saveNest = nestedParams;
#if OPT_LINTLIBRARY
boolean defines = (strchr(decl_spec->text, CURL_L) != 0);
int is_func;
/* special treatment for -l, -T options */
if ((!variables_out && types_out && defines) || (decl_list == 0)) {
strcut(decl_spec->text, "static");
strcut(decl_spec->text, "extern");
fmt_library((decl_list == 0) ? 1 : 2);
if (decl_spec->text[0] != '\0') {
put_string(stdout, decl_spec->text);
put_string(stdout, ";\n");
}
return;
}
#endif
if (!variables_out || (decl_spec->flags & (DS_EXTERN|DS_JUNK))) {
#if OPT_LINTLIBRARY
if (in_include >= extern_in) /* -x option not set? */
#endif
return;
#if OPT_LINTLIBRARY
strcut(decl_spec->text, "extern");
#endif
}
if (scope_out == SCOPE_EXTERN && (decl_spec->flags & DS_STATIC))
return;
if (scope_out == SCOPE_STATIC && !(decl_spec->flags & DS_STATIC))
return;
check_untagged(decl_spec);
func_declarator = NULL;
where = FUNC_OTHER;
format = FMT_OTHER;
nestedParams = 0;
for (d = decl_list->first; d != NULL; d = d->next) {
if (d->func_def == FUNC_NONE
|| d->head->func_stack->pointer
#if OPT_LINTLIBRARY
|| (in_include < extern_in)
#endif
) {
#if OPT_LINTLIBRARY
if (already_declared(d->name)) {
flush_varargs();
continue;
}
/*
* Try to distinguish function declarations from function pointer
* declarations, so that we don't unintentionally emit lint-library
* arguments for function pointers.
*/
is_func = is_actual_func(d);
if (is_func) {
ellipsis_varargs(d);
} else {
nestedParams = 2; /* disable params altogether */
if (types_out)
fmt_library(2);
}
if (lint_shadowed && lintLibrary())
printf("#undef %s\n", d->name);
#endif
put_string(stdout, fmt[FMT_PROTO].decl_spec_prefix);
put_decl_spec(stdout, decl_spec);
put_declarator(stdout, d, commented);
#if OPT_LINTLIBRARY
if (knrLintLibrary() && is_func)
put_llib_params(d, commented);
#endif
put_body(stdout, decl_spec, d);
nestedParams = saveNest;
}
#if OPT_LINTLIBRARY
flush_varargs();
#endif
}
exitlike_func = FALSE;
}
/* Return TRUE if the function uses varargs.
*/
static int
uses_varargs (declarator)
Declarator *declarator;
{
Parameter *p;
return (p = declarator->params.first) != NULL
&& (p->next == NULL)
&& (!strcmp(p->declarator->name, "va_alist"));
}
/* If the parameter list is empty, then replace it with "void".
*/
static void
check_void_param (declarator)
Declarator *declarator;
{
DeclSpec decl_spec;
Parameter *p;
if (declarator->params.first == NULL) {
new_decl_spec(&decl_spec, "void", 0L, DS_NONE);
p = new_parameter(&decl_spec, (Declarator *)0);
new_param_list(&declarator->params, p);
}
}
/* If a parameter name appears in the parameter list of a traditional style
* function definition but is not declared in the parameter declarations,
* then assign it the default type "int".
*/
static void
set_param_decl_spec (declarator)
Declarator *declarator;
{
Parameter *p;
for (p = declarator->params.first; p != NULL; p = p->next) {
if (p->decl_spec.text[0] == '\0' &&
strcmp(p->declarator->text, ELLIPSIS) != 0) {
free(p->decl_spec.text);
p->decl_spec.text = xstrdup("int");
}
}
}
/* Generate a function prototype.
*/
void
gen_prototype (decl_spec, declarator)
DeclSpec *decl_spec;
Declarator *declarator;
{
Parameter *p;
int commented = FALSE;
if (proto_style == PROTO_NONE || (decl_spec->flags & DS_JUNK))
return;
if (scope_out == SCOPE_EXTERN && (decl_spec->flags & DS_STATIC))
return;
if (scope_out == SCOPE_STATIC && !(decl_spec->flags & DS_STATIC))
return;
/*
* Trim pathological keywords (which are legal, but unnecessary) from the
* function and its parameters.
*/
strcut(decl_spec->text, "extern");
for (p = declarator->params.first; p != NULL; p = p->next) {
strcut(p->decl_spec.text, "extern");
strcut(p->decl_spec.text, "auto");
}
#if OPT_LINTLIBRARY
if (lintLibrary())
ellipsis_varargs(declarator);
else if (types_out)
fmt_library(0);
#endif
func_declarator = declarator->head;
if (uses_varargs(func_declarator)) {
/* Generate a prototype for a function that uses varargs by replacing
* the "va_alist" parameter with an empty parameter list.
*/
free_param_list(&func_declarator->params);
func_declarator->params.first = NULL;
}
check_void_param(func_declarator);
set_param_decl_spec(func_declarator);
where = FUNC_PROTO;
format = FMT_PROTO;
nestedParams = 0;
#if OPT_LINTLIBRARY
if (lint_shadowed && lintLibrary())
printf("#undef %s\n", declarator->name);
#endif
put_string(stdout, fmt[format].decl_spec_prefix);
put_decl_spec(stdout, decl_spec);
put_func_declarator(stdout, declarator, commented);
#if OPT_LINTLIBRARY
if (knrLintLibrary())
put_llib_params(declarator, commented);
#endif
put_body(stdout, decl_spec, declarator);
}
/* Generate a declarator for a function pointer declarator or prototype.
*/
void
gen_func_declarator (declarator)
Declarator *declarator;
{
/* Go to the beginning of the function declarator in the temporary
* file and overwrite it with the converted declarator.
*/
fseek(cur_tmp_file(), declarator->begin, 0);
func_declarator = NULL;
where = FUNC_DEF;
format = FMT_FUNC;
nestedParams = 0;
put_func_declarator(cur_tmp_file(), declarator, FALSE);
cur_file_changed();
}
/* Output parameter declarations for old style function definition.
*/
static void
put_param_decl (declarator, commented)
Declarator *declarator;
int commented;
{
#if OPT_LINTLIBRARY
int count = 0;
#endif
Parameter *p;
p = declarator->params.first;
if (!is_void_parameter(p)) {
fputc('\n', cur_tmp_file());
(void)putParameter(cur_tmp_file(), p, knrLintLibrary(), ++count, commented);
fputc(';', cur_tmp_file());
if (p->comment != 0)
fputs(p->comment, cur_tmp_file());
p = p->next;
while (p != NULL && strcmp(p->declarator->text, ELLIPSIS) != 0) {
fputc('\n', cur_tmp_file());
(void)putParameter(cur_tmp_file(), p, knrLintLibrary(), ++count, commented);
fputc(';', cur_tmp_file());
if (p->comment != 0)
fputs(p->comment, cur_tmp_file());
p = p->next;
}
}
}
/* Generate a function definition head.
*/
void
gen_func_definition (decl_spec, declarator)
DeclSpec *decl_spec;
Declarator *declarator;
{
Parameter *p;
ParameterList *params;
char *comment = 0;
int n;
unsigned comment_len;
long diff;
/* Do nothing if the function is already defined in the desired style
* or if the function uses varargs.
*/
func_declarator = declarator->head;
if (func_declarator->func_def == func_style ||
uses_varargs(func_declarator))
return;
/* Save the text between the function head and the function body.
* Read the temporary file from after the last ) or ; to the
* end of the file.
*/
if ((diff = (ftell(cur_tmp_file()) - cur_begin_comment())) > 0) {
comment_len = (unsigned)diff;
*(comment = xmalloc(comment_len)) = '\0';
fseek(cur_tmp_file(), cur_begin_comment(), 0);
fread(comment, sizeof(char), comment_len, cur_tmp_file());
} else {
comment_len = 0;
}
format = FMT_FUNC;
nestedParams = 0;
if (func_declarator->func_def == FUNC_TRADITIONAL
|| func_declarator->func_def == FUNC_BOTH) {
/* Save the text before the parameter declarations. */
params = &func_declarator->params;
n = (int)(params->end_comment - params->begin_comment);
if (n > 0) {
*(params->comment = xmalloc((unsigned)(n+1))) = '\0';
fseek(cur_tmp_file(), params->begin_comment, 0);
fread(params->comment, sizeof(char), (size_t)n, cur_tmp_file());
params->comment[n] = '\0';
format = FMT_FUNC_COMMENT;
}
/* Get the parameter comments. */
for (p = func_declarator->params.first; p != NULL; p = p->next) {
n = (int)(p->declarator->end_comment - p->declarator->begin_comment);
if (n > 0) {
*(p->comment = xmalloc((unsigned)n+1)) = '\0';
fseek(cur_tmp_file(), p->declarator->begin_comment, 0);
fread(p->comment, sizeof(char), (size_t)n, cur_tmp_file());
p->comment[n] = '\0';
format = FMT_FUNC_COMMENT;
}
}
}
check_void_param(func_declarator);
set_param_decl_spec(func_declarator);
/* Go to the beginning of the function head in the temporary file
* and overwrite it with the converted function head.
*/
where = FUNC_DEF;
fseek(cur_tmp_file(), decl_spec->begin, 0);
if (func_style == FUNC_BOTH) {
char *cur_func;
unsigned func_len;
/* Save the current function definition head. */
if ((diff = (cur_begin_comment() - decl_spec->begin)) > 0) {
func_len = (unsigned)diff;
cur_func = xmalloc(func_len);
fread(cur_func, sizeof(char), func_len, cur_tmp_file());
} else {
cur_func = 0;
func_len = 0;
}
fseek(cur_tmp_file(), decl_spec->begin, 0);
fprintf(cur_tmp_file(), "%s\n\n", func_directive);
/* Output new style function definition head. */
if (func_declarator->func_def == FUNC_ANSI) {
if (cur_func != 0)
fwrite(cur_func, sizeof(char), func_len, cur_tmp_file());
} else {
fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
fputs(decl_spec->text, cur_tmp_file());
fputc(' ', cur_tmp_file());
func_style = FUNC_ANSI;
put_func_declarator(cur_tmp_file(), declarator, FALSE);
}
fputs("\n#else\n\n", cur_tmp_file());
/* Output old style function definition head. */
if (func_declarator->func_def == FUNC_TRADITIONAL
|| func_declarator->func_def == FUNC_BOTH) {
if (cur_func != 0)
fwrite(cur_func, sizeof(char), func_len, cur_tmp_file());
} else {
fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
fputs(decl_spec->text, cur_tmp_file());
fputc(' ', cur_tmp_file());
format = FMT_FUNC;
func_style = FUNC_TRADITIONAL;
put_func_declarator(cur_tmp_file(), declarator, FALSE);
put_param_decl(func_declarator, FALSE);
}
fputs("\n#endif", cur_tmp_file());
if (*comment != '\n')
fputc('\n', cur_tmp_file());
func_style = FUNC_BOTH;
if (cur_func != 0)
free(cur_func);
} else {
/* Output declarator specifiers. */
fputs(fmt[format].decl_spec_prefix, cur_tmp_file());
fputs(decl_spec->text, cur_tmp_file());
fputc(' ', cur_tmp_file());
/* Output function declarator. */
put_func_declarator(cur_tmp_file(), declarator, FALSE);
if (func_style == FUNC_TRADITIONAL)
put_param_decl(func_declarator, FALSE);
}
/* Output text between function head and body. */
if (comment != 0) {
fwrite(comment, sizeof(char), comment_len, cur_tmp_file());
free(comment);
}
cur_file_changed();
}