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

  1. /* $Id: cproto.c 2.1 91/03/25 11:40:34 cthuang Exp $
  2.  *
  3.  * C prototype generator
  4.  * Reads C source code and outputs ANSI C function prototypes.
  5.  */
  6. #ifndef lint
  7. static char *rcsid = "$Id: cproto.c 2.1 91/03/25 11:40:34 cthuang Exp $";
  8. #endif
  9. #include <stdio.h>
  10. #include <ctype.h>
  11. #include "cproto.h"
  12. #include "patchlev.h"
  13.  
  14. /* C preprocessor */
  15. #ifndef CPP
  16. #define CPP "/lib/cpp"
  17. #endif
  18.  
  19. /* getopt declarations */
  20. extern int getopt();
  21. extern char *optarg;
  22. extern int optind;
  23.  
  24. /* lex declarations */
  25. extern FILE *yyin;    /* lex input stream */
  26.  
  27. /* Name of the program */
  28. static char *progname = "cproto";
  29.  
  30. /* Program options */
  31.  
  32. /* TRUE if "extern" should appear on external declarations. */
  33. boolean extern_out = FALSE;
  34.  
  35. /* TRUE if static declarations are also output. */
  36. boolean static_out = FALSE;
  37.  
  38. /* TRUE if variable declarations are output. */
  39. boolean variables_out = FALSE;
  40.  
  41. /* TRUE if formal parameter promotion is enabled. */
  42. boolean promote_param = TRUE;
  43.  
  44. /* Style of function prototype generated */
  45. int proto_style = PROTO_ANSI;
  46.  
  47. /* Name of macro to guard prototypes */
  48. char *macro_name = "P_";
  49.  
  50. /* TRUE if prototype macro definition is output. */
  51. boolean define_macro = TRUE;
  52.  
  53. /* String output before prototype declaration specifiers */
  54. char *decl_spec_prefix = "";
  55.  
  56. /* String output before prototype declarator */
  57. char *declarator_prefix = " ";
  58.  
  59. /* String output after prototype declarator */
  60. char *declarator_suffix = "";
  61.  
  62. /* String output before the first parameter in a function prototype */
  63. char *first_param_prefix = "";
  64.  
  65. /* String output before each subsequent parameter in a function prototype */
  66. char *middle_param_prefix = " ";
  67.  
  68. /* String output after the last parameter in a function prototype */
  69. char *last_param_suffix = "";
  70.  
  71. /* Include file directories */
  72. #ifdef MSDOS
  73. int num_inc_dir = 1;
  74. char *inc_dir[MAX_INC_DIR] = { ".\\" };
  75. #else
  76. int num_inc_dir = 2;
  77. char *inc_dir[MAX_INC_DIR] = { "./", "/usr/include/" };
  78. #endif
  79.  
  80. /* Output an error message along with the current line number in the
  81.  * source file.
  82.  */
  83. void
  84. output_error ()
  85. {
  86.     fprintf(stderr, "\"%s\", line %d: ", cur_file, line_num);
  87. }
  88.  
  89. /* Replace any character escape sequences in a string with the actual
  90.  * characters.  Return a pointer to malloc'ed memory containing the result.
  91.  * This function knows only a few escape sequences.
  92.  */
  93. static char *
  94. escape_string (src)
  95. char *src;
  96. {
  97.     char *result, *get, *put;
  98.  
  99.     result = strdup(src);
  100.     put = result;
  101.     get = src;
  102.     while (*get != '\0') {
  103.     if (*get == '\\') {
  104.         switch (*(++get)) {
  105.         case 'n':
  106.         *put++ = '\n';
  107.         ++get;
  108.         break;
  109.         case 't':
  110.         *put++ = '\t';
  111.         ++get;
  112.         break;
  113.         default:
  114.         if (*get != '\0')
  115.             *put++ = *get++;
  116.         }
  117.     } else {
  118.         *put++ = *get++;
  119.     }
  120.     }
  121.     *put = *get;
  122.     return result;
  123. }
  124.  
  125. /* Append a path name separator to the end of the string if it doesn't
  126.  * end with one already.  Allocate storage for the result and return
  127.  * a pointer to it.
  128.  */
  129. static char *
  130. add_path_sep (s)
  131. char *s;
  132. {
  133.     char *result, ch;
  134.     int n;
  135.  
  136.     n = strlen(s);
  137.     result = malloc(n+2);
  138.     strcpy(result, s);
  139.     ch = result[n-1];
  140.     if (ch != '/' && ch != '\\') {
  141.     result[n] = '/';
  142.     result[n+1] = '\0';
  143.     }
  144.     return result;
  145. }
  146.  
  147. /* Output usage message and exit.
  148.  */
  149. static void
  150. usage ()
  151. {
  152.     fprintf(stderr,
  153.     "usage: %s [ option ... ] [ file ... ]\n", progname);
  154.     fputs("  -e      output \"extern\" keyword before global declarations\n",
  155.     stderr);
  156.     fputs("  -f n    select function prototype style (0 to 4)\n", stderr);
  157.     fputs("  -p      disable prototype promotion\n", stderr);
  158.     fputs("  -s      output static declarations\n", stderr);
  159.     fputs("  -v      output variable declarations\n", stderr);
  160.     fputs("  -m nam  set name of macro guarding prototypes\n", stderr);
  161.     fputs("  -d      omit prototype macro definition\n", stderr);
  162.     fputs("  -D name[=value]\n", stderr);
  163.     fputs("  -U name\n", stderr);
  164.     fputs("  -I directory\n", stderr);
  165.     fputs("          C preprocessor options\n", stderr);
  166.     fputs(
  167.     "  -F fmt  set prototype template in the form \"int main (a, b)\"\n",
  168.     stderr);
  169.     fputs("  -V      print version information\n", stderr);
  170.     exit(1);
  171. }
  172.  
  173. main (argc, argv)
  174. int argc;
  175. char **argv;
  176. {
  177.     int i, c, n;
  178.     char *s, *cpp_cmd, tmp[MAX_TEXT_LENGTH];
  179. #ifndef MSDOS
  180.     char *cmd;
  181. #endif
  182.  
  183.     /* Allocate buffer for C preprocessor command line. */
  184.     n = strlen(CPP) + 1;
  185.     for (i = 0; i < argc; ++i) {
  186.     n += strlen(argv[i]) + 1;
  187.     }
  188.     cpp_cmd = malloc(n);
  189.     strcpy(cpp_cmd, CPP);
  190. #ifndef MSDOS
  191.     cmd = malloc(n);
  192. #endif
  193.  
  194.     /* Scan command line options. */
  195.     while ((c = getopt(argc, argv, "D:deF:f:I:m:psU:Vv")) != EOF) {
  196.     switch (c) {
  197.     case 'I':
  198.         if (num_inc_dir < MAX_INC_DIR) {
  199.         inc_dir[num_inc_dir++] = add_path_sep(optarg);
  200.         } else {
  201.         fprintf(stderr, "%s: too many include directories\n",
  202.             progname);
  203.         }
  204.     case 'D':
  205.     case 'U':
  206.         sprintf(tmp, " -%c%s", c, optarg);
  207.         strcat(cpp_cmd, tmp);
  208.         break;
  209.     case 'd':
  210.         define_macro = FALSE;
  211.         break;
  212.     case 'e':
  213.         extern_out = TRUE;
  214.         break;
  215.     case 'F':
  216.         s = escape_string(optarg);
  217.  
  218.         decl_spec_prefix = s;
  219.         while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
  220.         if (*s == '\0') usage();
  221.         *s++ = '\0';
  222.         while (*s != '\0' && isascii(*s) && isalnum(*s)) ++s;
  223.         if (*s == '\0') usage();
  224.  
  225.         declarator_prefix = s;
  226.         while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
  227.         if (*s == '\0') usage();
  228.         *s++ = '\0';
  229.         while (*s != '\0' && isascii(*s) && isalnum(*s)) ++s;
  230.         if (*s == '\0') usage();
  231.  
  232.         declarator_suffix = s;
  233.         while (*s != '\0' && *s != '(') ++s;
  234.         if (*s == '\0') usage();
  235.         *s++ = '\0';
  236.  
  237.         first_param_prefix = s;
  238.         while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
  239.         if (*s == '\0') usage();
  240.         *s++ = '\0';
  241.         while (*s != '\0' && *s != ',') ++s;
  242.         if (*s == '\0') usage();
  243.  
  244.         middle_param_prefix = ++s;
  245.         while (*s != '\0' && isascii(*s) && !isalnum(*s)) ++s;
  246.         if (*s == '\0') usage();
  247.         *s++ = '\0';
  248.         while (*s != '\0' && isascii(*s) && isalnum(*s)) ++s;
  249.         if (*s == '\0') usage();
  250.  
  251.         last_param_suffix = s;
  252.         while (*s != '\0' && *s != ')') ++s;
  253.         *s = '\0';
  254.  
  255.         break;
  256.     case 'f':
  257.         proto_style = atoi(optarg);
  258.         if (proto_style < 0 || proto_style > PROTO_MACRO)
  259.         proto_style = PROTO_ANSI;
  260.         break;
  261.     case 'm':
  262.         macro_name = optarg;
  263.         break;
  264.     case 'p':
  265.         promote_param = FALSE;
  266.         break;
  267.     case 's':
  268.         static_out = TRUE;
  269.         break;
  270.     case 'V':
  271.         fprintf(stderr, "%s patchlevel %d\n", rcsid, PATCHLEVEL);
  272.         break;
  273.     case 'v':
  274.         variables_out = TRUE;
  275.         break;
  276.     case '?':
  277.     default:
  278.         usage();
  279.     }
  280.     }
  281.  
  282.     if (proto_style == PROTO_MACRO && define_macro) {
  283.     printf("#if defined(__STDC__) || defined(__cplusplus)\n");
  284.     printf("# define %s(s) s\n", macro_name);
  285.     printf("#else\n");
  286.     printf("# define %s(s) ()\n", macro_name);
  287.     printf("#endif\n\n");
  288.     }
  289.  
  290.     if (optind == argc) {
  291.     printf("/* stdin */\n");
  292.     parse_file();
  293.     } else {
  294.     for (i = optind; i < argc; ++i) {
  295. #ifdef MSDOS
  296.         if (freopen(argv[i], "r", yyin) == NULL) {
  297.         fprintf(stderr, "%s: cannot open file %s\n", progname, argv[i]);
  298.         continue;
  299.         }
  300. #else
  301.         sprintf(cmd, "%s %s", cpp_cmd, argv[i]);
  302.         if ((yyin = popen(cmd, "r")) == NULL) {
  303.         fprintf(stderr, "%s: error running cpp\n", progname);
  304.         continue;
  305.         }
  306. #endif
  307.         strcpy(cur_file, argv[i]);
  308.         line_num = 1;
  309.         printf("/* %s */\n", cur_file);
  310.         parse_file();
  311. #ifdef MSDOS
  312.         fclose(yyin);
  313. #else
  314.         pclose(yyin);
  315. #endif
  316.     }
  317.     }
  318.  
  319.     if (proto_style == PROTO_MACRO && define_macro) {
  320.     printf("\n#undef %s\n", macro_name);
  321.     }
  322.  
  323.     return 0;
  324. }
  325.