Category : C Source Code
Archive   : C-PROTO.ZIP
Filename : PROTO.C

 
Output of file : PROTO.C contained in archive : C-PROTO.ZIP
/* This program parses a K&R C program and produces a list of */
/* function prototypes for every function defined in the source. */
/* It does not handle function arguments which are pointers. */
/* No function prototype will be produced for any function which has */
/* a pointer as an argument. */

/* Nor does it produce function prototypes for functions defined */
/* using the ANSI standard for defining function definitions. */

/* Also note that the input to this program is not a C source */
/* program but is instead, the output from the C preprocessor. */

/* Converted to ANSI C (Microsoft QuickC version 2.5) */
/* Also removed the string "vlARGS" from the output by commenting */
/* the original statement and replacing it with one that did not */
/* include the string. */
/* January 20, 1991 - Gordon Torrie */

#include
#include
#include
#include

#define MAX_VARS 20
#define MAX_CHARS 80

void next_statement ( void );
int getword ( void );
void try_proc ( void );
void match_variable (char *compare);
void error (char *s);

char inname[MAX_CHARS];
char word[MAX_CHARS];
char var[MAX_CHARS];
char type[MAX_CHARS];
char proc_name[MAX_CHARS];
char vars[MAX_VARS][MAX_CHARS];
char types[MAX_VARS][MAX_CHARS];

int braces = 0, parens = 0, brackets = 0, line_count = 1;
int bslash = 0, squote = 0, dquote = 0;
int num_var, num_matches;

static FILE *infile, *statics, *externs;

#define IS_IDENT(c) \
(isalnum ((c)) || ((c) == '$') || ((c) == '_') || ((c) == '*') || \
((c) == '[') || ((c) == ']') || ((c) == '+'))

static FILE *open_file(char *name, char *ext, char *mode)
{
char fname[80];
FILE *f;

sprintf (fname, "%s.%s", name, ext);
if ((f = fopen (fname, mode)) == NULL) {
perror (fname);
exit (1);
} /* if */

return (f);
} /* static FILE *open_file */

void main(int argc, char *argv[])
{
if (argc != 2) {
fprintf (stderr, "Usage: %s module\n", argv[0]);
fprintf (stderr, "Reads for cpp output module.i.\n");
fprintf (stderr, "Writes external prototypes to module.ext.\n");
fprintf (stderr, "Writes static prototypes to module.sta.\n");
exit (1);
} /* if */

sprintf (inname, "%s.i", argv[1]);
infile = open_file (argv[1], "i", "r");
externs = open_file (argv[1], "ext", "w");
statics = open_file (argv[1], "sta", "w");

while (getword () != EOF) {
if ((strcmp (word, "extern") == 0) ||
(strcmp (word, "{") == 0) ||
(strcmp (word, ";") == 0) ||
(strcmp (word, ",") == 0) ||
(strcmp (word, "pragma") == 0) ||
(strcmp (word, "typedef") == 0))
next_statement ();
else if (IS_IDENT (word[0]))
try_proc ();
else
error ("Unexpected token");
} /* while */
} /* main */

void next_statement( void )
{
while ((braces != 0) ||
((strcmp (word, ";") != 0) && (strcmp (word, "}") != 0)))
getword ();
} /* next_statement */

int getword ( void )
{
int c, i, done, x;

i = 0;
done = 0;
while (!done) {
c = getc (infile);

if (c == EOF) {

/* Print error message if there are any open */
/* braces, parenthesis or brackets at EOF */
if (braces || parens || brackets)
fprintf (stderr, "%s: %d: {}=%d, ()=%d, []=%d\n",
inname, line_count, braces, parens, brackets);
fclose (infile);
fclose (statics);
fclose (externs);
exit (0);
} /* if */

/* Add the character to the current word unless we are */
/* within a quoted string. */
else if (IS_IDENT (c) && !dquote && !squote) {
word[i] = c;
i++;
} /* if */

else if (isspace (c) || (c == '\f') && !dquote && !squote) {
/* Increment line_count if current character is a newline */
if (c == '\n') line_count++;
if (i > 0) {
word[i] = 0;
c = 0;
done = 1;
} /* if */
} /* else if */

else if ((c == '#') && !dquote && !squote) {
if ((fgets (word, MAX_CHARS - 1, infile) == NULL) ||
((sscanf (word, " %d \"%s\"", &line_count, inname) != 2) &&
(sscanf (word, "line %d \"%s\"", &line_count, inname) != 2)))
{
x = strlen (word) - 1;
if ((x >= 0) && (word[x] == '\n'))
word[x] = '\0';
error ("Unknown # directive");
line_count++;
}

else {
x = strlen (inname) - 1;
if ((x >= 0) && (inname[x] == '"'))
inname[x] = '\0';
}
} /* else if */

else {
if (i == 0) {
switch (c) {
case '{': if (!dquote && !squote) braces++; break;
case '}': if (!dquote && !squote) braces--; break;
case '(': if (!dquote && !squote) parens++; break;
case ')': if (!dquote && !squote) parens--; break;
case '[': if (!dquote && !squote) brackets++; break;
case ']': if (!dquote && !squote) brackets--; break;
case '"': if (!bslash && !squote) dquote = !dquote; break;
case 39: if (!bslash && !dquote) squote = !squote; break;
case '\\': bslash = !bslash; break;

} /* switch */
if (c != '\\')
bslash = 0;
word[0] = c;
word[1] = '\0';
if (!dquote && !squote)
done = 1;
} /* if */
else {
ungetc (c, infile);
word[i] = 0;
c = 0;
done = 1;
} /* else */
} /* else if */
} /* while */
return (c);
} /* getword */

void try_proc ( void )
{
int i, end_of_type;
FILE *f;

if (strcmp (word, "static") == 0) {
proc_name[0] = '\0';
f = statics;
} /* if */
else {
strcpy (proc_name, "extern ");
f = externs;
} /* else */

do {
strcat (proc_name, word);
strcat (proc_name, " ");
} while (getword () == 0);

if ((strcmp (word, ";") == 0) || /* variable/type declaration */
(strcmp (word, ",") == 0) || /* multi var/type declaration */
(strcmp (word, "[") == 0) || /* array initializer */
(strcmp (word, "=") == 0) || /* static initializer */
(strcmp (word, "{") == 0) || /* struct/union definition */
(strcmp (word, ":") == 0)) /* label */
{
next_statement ();
return;
} /* if */

if (strcmp (word, "(") != 0) {error ("( expected"); return;}

/* Accumulate variable names */
num_var = 0;
do {
if (getword () != 0) {
if ((num_var == 0) && (strcmp (word, ")") == 0))
break;
error ("expected arg");
return;
}
if (word[0] == '*') { /* Procedure ptr declaration */
next_statement ();
return;
}
strcpy (vars[num_var], word);
strcpy (types[num_var], "int");
num_var++;
} while (getword () == ',');

if (IS_IDENT (word[0]) || /* identifier */
(strcmp (word, "(") == 0)) /* function argument decl */
{
next_statement ();
return;
} /* if */

if (strcmp (word, ")") != 0) {error (") expected"); return;}

if (num_var == 0) {
getword ();

if (strcmp (word, "{") == 0) { /* Proc with no args */

/* Note that the following statement was changed from the original */
/* fprintf (f, "%svlARGS((void));\n", proc_name); */

fprintf (f, "%s( void );\n", proc_name);
next_statement ();
} /* if */

else if ((strcmp (word, ";") == 0) ||
(strcmp (word, ",") == 0))
; /* proc declaration w/o extern */

else
error ("Unexpected termination of procedure declaration");

return;
} /* if */

/* Find argument type declarations */
end_of_type = 9999;
for (num_matches = 0; num_matches < num_var;) {

type[0] = 0;

while (getword () == 0) {
end_of_type = strlen (type) - 1;
strcat (type, word);
strcpy (var, word);
strcat (type, " ");
} /* while */

if (end_of_type < 1) {
error ("Empty declaration");
return;
} /* if */

/* If we hit a ; the first time through, we are looking
at an existing prototyped procedure declaration! Punt!
*/
if ((strcmp (word, ";") == 0) && (end_of_type == 9999))
return;

if ((strcmp (word, ";") != 0) && (strcmp (word, ",") != 0)) {
strcpy (word, proc_name);
error ("arg type not found, declaration supressed");
return;
} /* if */

else {
type[end_of_type] = '\0';
match_variable (var);

while (strcmp (word, ",") == 0) {
getword ();
match_variable (word);
getword ();
} /* while */

if (strcmp (word, ";") != 0) {
error ("Arg decl did not end with ';'");
return;
} /* if */
} /* else */
} /* for */

/* Note that the following statement was changed from the original */
/* fprintf (f, "%svlARGS((", proc_name); */

fprintf (f, "%s( ", proc_name);
for (i = 0; i < num_var - 1; i++)
fprintf (f, "%s, ", types[i]);
fprintf (f, "%s );\n", types[num_var - 1]);

next_statement ();
} /* try_proc */

void match_variable (char *compare)
{
int i;
char prefix[10], suffix[10];

prefix[0] = suffix[0] = '\0';

while (*compare == ' ') compare++;
while (*compare == '*') {
compare++;
strcat (prefix, "*");
} /* while */

while ((strlen (compare) > 2) &&
(strcmp (&compare[strlen (compare) - 2], "[]") == 0))
{
compare[strlen (compare) - 2] = '\0';
strcat (suffix, "[]");
} /* while */

for (i = 0; i < num_var; i++) {
if (strcmp (compare, vars[i]) == 0) {
if (prefix[0] == '\0')
sprintf (types[i], "%s%s", type, suffix);
else
sprintf (types[i], "%s %s%s", type, prefix, suffix);
num_matches++;
return;
} /* if */
} /* for */

sprintf (word, "%s(%s)", proc_name, compare);
error ("Failed to match type");
} /* match_variable */

void error (char *s)
{
fprintf (stderr, "%s: %d: %s: %s\n", inname, line_count, s, word);
next_statement ();
} /* error */


  3 Responses to “Category : C Source Code
Archive   : C-PROTO.ZIP
Filename : PROTO.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/