home *** CD-ROM | disk | FTP | other *** search
- /* $Id: cproto.c 2.1 91/03/25 11:40:34 cthuang Exp $
- *
- * C prototype generator
- * Reads C source code and outputs ANSI C function prototypes.
- */
- #ifndef lint
- static char *rcsid = "$Id: cproto.c 2.1 91/03/25 11:40:34 cthuang Exp $";
- #endif
- #include <stdio.h>
- #include <ctype.h>
- #include "cproto.h"
- #include "patchlev.h"
-
- /* C preprocessor */
- #ifndef CPP
- #define CPP "/lib/cpp"
- #endif
-
- /* getopt declarations */
- extern int getopt();
- extern char *optarg;
- extern int optind;
-
- /* lex declarations */
- extern FILE *yyin; /* lex input stream */
-
- /* Name of the program */
- static char *progname = "cproto";
-
- /* Program options */
-
- /* TRUE if "extern" should appear on external declarations. */
- boolean extern_out = FALSE;
-
- /* TRUE if static declarations are also output. */
- boolean static_out = FALSE;
-
- /* TRUE if variable declarations are output. */
- boolean variables_out = FALSE;
-
- /* TRUE if formal parameter promotion is enabled. */
- boolean promote_param = TRUE;
-
- /* Style of function prototype generated */
- int proto_style = PROTO_ANSI;
-
- /* Name of macro to guard prototypes */
- char *macro_name = "P_";
-
- /* TRUE if prototype macro definition is output. */
- boolean define_macro = TRUE;
-
- /* String output before prototype declaration specifiers */
- char *decl_spec_prefix = "";
-
- /* String output before prototype declarator */
- char *declarator_prefix = " ";
-
- /* String output after prototype declarator */
- char *declarator_suffix = "";
-
- /* String output before the first parameter in a function prototype */
- char *first_param_prefix = "";
-
- /* String output before each subsequent parameter in a function prototype */
- char *middle_param_prefix = " ";
-
- /* String output after the last parameter in a function prototype */
- char *last_param_suffix = "";
-
- /* Include file directories */
- #ifdef MSDOS
- int num_inc_dir = 1;
- char *inc_dir[MAX_INC_DIR] = { ".\\" };
- #else
- int num_inc_dir = 2;
- char *inc_dir[MAX_INC_DIR] = { "./", "/usr/include/" };
- #endif
-
- /* Output an error message along with the current line number in the
- * source file.
- */
- void
- output_error ()
- {
- fprintf(stderr, "\"%s\", line %d: ", cur_file, line_num);
- }
-
- /* Replace any character escape sequences in a string with the actual
- * characters. Return a pointer to malloc'ed memory containing the result.
- * This function knows only a few escape sequences.
- */
- static char *
- escape_string (src)
- char *src;
- {
- char *result, *get, *put;
-
- result = strdup(src);
- put = result;
- get = src;
- while (*get != '\0') {
- if (*get == '\\') {
- switch (*(++get)) {
- case 'n':
- *put++ = '\n';
- ++get;
- break;
- case 't':
- *put++ = '\t';
- ++get;
- break;
- default:
- if (*get != '\0')
- *put++ = *get++;
- }
- } else {
- *put++ = *get++;
- }
- }
- *put = *get;
- return result;
- }
-
- /* Append a path name separator to the end of the string if it doesn't
- * end with one already. Allocate storage for the result and return
- * a pointer to it.
- */
- static char *
- add_path_sep (s)
- char *s;
- {
- char *result, ch;
- int n;
-
- n = strlen(s);
- result = malloc(n+2);
- strcpy(result, s);
- ch = result[n-1];
- if (ch != '/' && ch != '\\') {
- result[n] = '/';
- result[n+1] = '\0';
- }
- return result;
- }
-
- /* Output usage message and exit.
- */
- static void
- usage ()
- {
- fprintf(stderr,
- "usage: %s [ option ... ] [ file ... ]\n", progname);
- fputs(" -e output \"extern\" keyword before global declarations\n",
- stderr);
- fputs(" -f n select function prototype style (0 to 4)\n", stderr);
- fputs(" -p disable prototype promotion\n", stderr);
- fputs(" -s output static declarations\n", stderr);
- fputs(" -v output variable declarations\n", stderr);
- fputs(" -m nam set name of macro guarding prototypes\n", stderr);
- fputs(" -d omit prototype macro definition\n", stderr);
- fputs(" -D name[=value]\n", stderr);
- fputs(" -U name\n", stderr);
- fputs(" -I directory\n", stderr);
- fputs(" C preprocessor options\n", stderr);
- fputs(
- " -F fmt set prototype template in the form \"int main (a, b)\"\n",
- stderr);
- fputs(" -V print version information\n", stderr);
- exit(1);
- }
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- int i, c, n;
- char *s, *cpp_cmd, tmp[MAX_TEXT_LENGTH];
- #ifndef MSDOS
- char *cmd;
- #endif
-
- /* Allocate buffer for C preprocessor command line. */
- n = strlen(CPP) + 1;
- for (i = 0; i < argc; ++i) {
- n += strlen(argv[i]) + 1;
- }
- cpp_cmd = malloc(n);
- strcpy(cpp_cmd, CPP);
- #ifndef MSDOS
- cmd = malloc(n);
- #endif
-
- /* Scan command line options. */
- while ((c = getopt(argc, argv, "D:deF:f:I:m:psU:Vv")) != EOF) {
- switch (c) {
- case 'I':
- if (num_inc_dir < MAX_INC_DIR) {
- inc_dir[num_inc_dir++] = add_path_sep(optarg);
- } else {
- fprintf(stderr, "%s: too many include directories\n",
- progname);
- }
- case 'D':
- case 'U':
- sprintf(tmp, " -%c%s", c, optarg);
- strcat(cpp_cmd, tmp);
- break;
- case 'd':
- define_macro = FALSE;
- break;
- case 'e':
- extern_out = TRUE;
- break;
- case 'F':
- s = escape_string(optarg);
-
- decl_spec_prefix = s;
- while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
- if (*s == '\0') usage();
- *s++ = '\0';
- while (*s != '\0' && isascii(*s) && isalnum(*s)) ++s;
- if (*s == '\0') usage();
-
- declarator_prefix = s;
- while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
- if (*s == '\0') usage();
- *s++ = '\0';
- while (*s != '\0' && isascii(*s) && isalnum(*s)) ++s;
- if (*s == '\0') usage();
-
- declarator_suffix = s;
- while (*s != '\0' && *s != '(') ++s;
- if (*s == '\0') usage();
- *s++ = '\0';
-
- first_param_prefix = s;
- while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
- if (*s == '\0') usage();
- *s++ = '\0';
- while (*s != '\0' && *s != ',') ++s;
- if (*s == '\0') usage();
-
- middle_param_prefix = ++s;
- while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
- if (*s == '\0') usage();
- *s++ = '\0';
- while (*s != '\0' && isascii(*s) && isalnum(*s)) ++s;
- if (*s == '\0') usage();
-
- last_param_suffix = s;
- while (*s != '\0' && *s != ')') ++s;
- *s = '\0';
-
- break;
- case 'f':
- proto_style = atoi(optarg);
- if (proto_style < 0 || proto_style > PROTO_MACRO)
- proto_style = PROTO_ANSI;
- break;
- case 'm':
- macro_name = optarg;
- break;
- case 'p':
- promote_param = FALSE;
- break;
- case 's':
- static_out = TRUE;
- break;
- case 'V':
- fprintf(stderr, "%s patchlevel %d\n", rcsid, PATCHLEVEL);
- break;
- case 'v':
- variables_out = TRUE;
- break;
- case '?':
- default:
- usage();
- }
- }
-
- if (proto_style == PROTO_MACRO && define_macro) {
- printf("#if defined(__STDC__) || defined(__cplusplus)\n");
- printf("# define %s(s) s\n", macro_name);
- printf("#else\n");
- printf("# define %s(s) ()\n", macro_name);
- printf("#endif\n\n");
- }
-
- if (optind == argc) {
- printf("/* stdin */\n");
- parse_file();
- } else {
- for (i = optind; i < argc; ++i) {
- #ifdef MSDOS
- if (freopen(argv[i], "r", yyin) == NULL) {
- fprintf(stderr, "%s: cannot open file %s\n", progname, argv[i]);
- continue;
- }
- #else
- sprintf(cmd, "%s %s", cpp_cmd, argv[i]);
- if ((yyin = popen(cmd, "r")) == NULL) {
- fprintf(stderr, "%s: error running cpp\n", progname);
- continue;
- }
- #endif
- strcpy(cur_file, argv[i]);
- line_num = 1;
- printf("/* %s */\n", cur_file);
- parse_file();
- #ifdef MSDOS
- fclose(yyin);
- #else
- pclose(yyin);
- #endif
- }
- }
-
- if (proto_style == PROTO_MACRO && define_macro) {
- printf("\n#undef %s\n", macro_name);
- }
-
- return 0;
- }
-