home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / cpp114.zoo / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-31  |  9.3 KB  |  427 lines

  1. /*---------------------------------------------------------------------*\
  2. |                                    |
  3. | CPP -- a stand-alone C preprocessor                    |
  4. | Copyright (c) 1993-95 Hacker Ltd.        Author: Scott Bigham    |
  5. |                                    |
  6. | Permission is granted to anyone to use this software for any purpose    |
  7. | on any computer system, and to redistribute it freely, with the    |
  8. | following restrictions:                        |
  9. | - No charge may be made other than reasonable charges for repro-    |
  10. |     duction.                                |
  11. | - Modified versions must be clearly marked as such.            |
  12. | - The author is not responsible for any harmful consequences of    |
  13. |     using this software, even if they result from defects therein.    |
  14. |                                    |
  15. | main.c -- kick it all off                        |
  16. \*---------------------------------------------------------------------*/
  17.  
  18. #include <stdio.h>
  19. #include <stddef.h>
  20. #include <stdlib.h>
  21. #include <signal.h>
  22. #include <time.h>
  23. #include <unistd.h>
  24. #include "global.h"
  25. #include "ztype.h"
  26. #include "patchlev.h"
  27.  
  28. #define DEFAULT_CONFIG_NAME "cpp_defs.h"
  29.  
  30. FILE *outf = stdout;
  31. FILE *inf = NULL;
  32. char *argv0;
  33. char **I_list;
  34. char date_string[12], time_string[9];
  35. int nerrs;
  36.  
  37. int sl_style = SL_NORMAL,
  38.     keep_comments = 0,
  39.     do_trigraphs = 0,
  40.     ansi = 0,
  41.     w_bad_chars = 1,
  42.     w_nest_cmts = 0,
  43.     f_cpp_cmts = 0,
  44.     w_bad_concat = 1,
  45.     w_pragma = 0,
  46.     pedantic = 0,
  47.     gcc_strings = 0;
  48. static int verbose = 0;
  49.  
  50. int in_config_file = 0;
  51. static char *config_file_name = NULL;
  52. static char stdin_name[] = STDIN_NAME;
  53.  
  54. int fluff_mode = 0;
  55.  
  56. static void usage()
  57. {
  58.   fprintf(stderr, "usage: %s [-Dname[=value]...] [-Uname] "
  59.       "[ infile [ outfile ] ]\n", argv0
  60.   );
  61.   exit(1);
  62. }
  63.  
  64. static void dammit(sig)
  65.   int sig;
  66. {
  67.   fatal("received signal %d", sig);
  68. }
  69.  
  70. static void setup_signals()
  71. {
  72.   (void)signal(SIGHUP, dammit);
  73.   (void)signal(SIGINT, dammit);
  74.   (void)signal(SIGQUIT, dammit);
  75.   (void)signal(SIGILL, dammit);
  76.   (void)signal(SIGTRAP, dammit);
  77.   (void)signal(SIGABRT, dammit);
  78. #ifdef SIGEMT
  79.   (void)signal(SIGEMT, dammit);
  80. #endif
  81.   (void)signal(SIGFPE, dammit);
  82.   (void)signal(SIGBUS, dammit);
  83.   (void)signal(SIGSEGV, dammit);
  84. #ifdef SIGSYS
  85.   (void)signal(SIGSYS, dammit);
  86. #endif
  87.   (void)signal(SIGPIPE, dammit);
  88.   (void)signal(SIGALRM, dammit);
  89.   (void)signal(SIGTERM, dammit);
  90. }
  91.  
  92. /* add_include() -- adds |path| to the list of include directories */
  93. static void add_include(path)
  94.   char *path;
  95. {
  96.   static char **cur_I = NULL;
  97.   static int n_I;
  98.   ptrdiff_t dp;
  99.  
  100.   if (!cur_I)
  101.     cur_I = I_list = (char **)mallok((n_I = 3) * sizeof (char *));
  102.  
  103.   if (cur_I - I_list == n_I) {
  104.     dp = cur_I - I_list;
  105.     I_list = reallok(I_list, (n_I *= 2) * sizeof (char *));
  106.  
  107.     cur_I = I_list + dp;
  108.   }
  109.   *cur_I++ = path;
  110.   if (verbose && path) {
  111.     fprintf(stderr, "Adding include path \"%s\"\n", path);
  112.   }
  113. }
  114.  
  115. /* long_option() -- parses long option |s| */
  116. static void long_option(s)
  117.   char *s;
  118. {
  119.   int yesno = 1;
  120.   char *t;
  121.  
  122.   if (*s == 'W' || *s == 'f') {
  123.     if (s[1] == 'n' && s[2] == 'o' && s[3] == '-') {
  124.       yesno = 0;
  125.       t = s + 4;
  126.     } else
  127.       t = s + 1;
  128.     if (*s == 'W') {        /* warnings */
  129.       if (streq(t, "bad-chars"))
  130.     w_bad_chars = yesno;
  131.       else if (streq(t, "nested-comments"))
  132.     w_nest_cmts = yesno;
  133.       else if (streq(t, "bad-concat-tokens"))
  134.     w_bad_concat = yesno;
  135.       else if (streq(t, "unknown-pragma"))
  136.     w_pragma = yesno;
  137.       else {
  138.     error("unknown -W option:  %s", t);
  139.     usage();
  140.       }
  141.     } else {            /* actions */
  142.       if (streq(t, "c++-comments"))
  143.     f_cpp_cmts = yesno;
  144.       else if (streq(t, "implicit-newlines"))
  145.     gcc_strings = yesno;
  146.       else {
  147.     error("unknown -f option:  %s", t);
  148.     usage();
  149.       }
  150.     }
  151.   } else if (*s == 'X') {
  152.     if (streq(s + 1, "fluff"))
  153.       fluff_mode = 1;
  154.     else {
  155.       error("unknown -X option:  %s", s + 1);
  156.       usage();
  157.     }
  158.   } else if (streq(s, "ansi")) {
  159.     ansi = 1;
  160.     do_trigraphs ^= 1;
  161.   } else if (streq(s, "pedantic")) {
  162.     pedantic = 1;
  163.   } else {
  164.     error("unrecognized option -%s", s);
  165.     usage();
  166.   }
  167. }
  168.  
  169. /*
  170.    opt_define() -- handle -Dfred.  |s| points to the beginning of the token
  171.    to #define.
  172. */
  173. static void opt_define(s)
  174.   char *s;
  175. {
  176.   Macro *M, *M1;
  177.   char *t;
  178.   unsigned int hv;
  179.   int hmm = 0;
  180.   static char one[] = "1";
  181.  
  182.   hv = hash_id(s, &t);
  183.   if (*t && *t != '=') {
  184.     error("malformed -D option \"%s\"", s);
  185.     return;
  186.   }
  187.   if (*t)
  188.     *t++ = '\0';
  189.   else
  190.     t = one;
  191.   M1 = mk_Macro();
  192.   M1->m_text = tokenize_string(t);
  193.   if ((M = lookup(s, hv))) {
  194.  
  195.     /*
  196.        guard against re-#definition of magic tokens or previously -U'd tokens
  197.     */
  198.     if (M->flags & (UNDEF | MAGIC))
  199.       hmm = 1;
  200.     if (hmm || !macro_eq(M1, M)) {
  201.       if (!hmm)
  202.     error("non-identical redefinition of \"%s\"", s);
  203.     }
  204.     free_Macro(M1);
  205.     return;
  206.   }
  207.   hash_add(s, hv, M1);
  208. }
  209.  
  210. /*
  211.    opt_undefine() -- handle -Ufred.  |s| points to the beginning of the token
  212.    to #undef.
  213. */
  214. static void opt_undefine(s)
  215.   char *s;
  216. {
  217.   Macro *M;
  218.   int was_there = 0;
  219.   unsigned int hv;
  220.  
  221.   hv = hash_id(s, NULL);
  222.   if ((M = lookup(s, hv))) {
  223.     if (M->flags & MAGIC)
  224.       return;
  225.     if (M->m_text)
  226.       free_tlist(M->m_text);
  227.     was_there = 1;
  228.   } else {
  229.     M = mk_Macro();
  230.   }
  231.   M->m_text = NULL;
  232.   M->flags |= UNDEF;
  233.   if (!was_there)
  234.     hash_add(s, hv, M);
  235. }
  236.  
  237. /* do_cmdline_arg() -- process the command-line argument |s| */
  238. void do_cmdline_arg(arg)
  239.   register char *arg;
  240. {
  241.   switch (arg[1]) {
  242.   case 'P':
  243.     switch (arg[2]) {
  244.     case '0':
  245.     case '\0':
  246.       sl_style = SL_NONE;
  247.       break;
  248.     case '1':
  249.       sl_style = SL_NORMAL;
  250.       break;
  251.     case '2':
  252.       sl_style = SL_LINE;
  253.       break;
  254.     default:
  255.       error("bad argument '%c' to -P option", arg[2]);
  256.     }
  257.     break;
  258.   case 'C':
  259.     keep_comments = 1;
  260.     break;
  261.   case 'T':
  262.     do_trigraphs ^= 1;
  263.     break;
  264.   case 'I':
  265.     add_include(copy_filename(arg + 2, 0));
  266.     break;
  267.   case 'D':
  268.     opt_define(arg + 2);
  269.     break;
  270.   case 'U':
  271.     opt_undefine(arg + 2);
  272.     break;
  273.   case 'V':
  274.     verbose = 1;
  275.     fprintf(stderr, "CPP -- C preprocessor v%d.%d.%d\n"
  276.         "(c) 1993-95 Hacker Ltd., all rights reserved\n",
  277.         CPP_VERSION, CPP_RELEASE, CPP_PATCHLEVEL);
  278.     break;
  279.   case 'S':            /* already handled elsewhere */
  280.     break;
  281.   default:
  282.     long_option(arg + 1);
  283.   }
  284. }
  285.  
  286. /* do_all_cmdline_args() -- process all command_line arguments */
  287. static int Argc = 0;
  288. static char **Argv = 0;
  289. int Argc_end = 0;
  290.  
  291. void do_all_cmdline_args()
  292. {
  293.   int i;
  294.  
  295.   for (i = 1; i < Argc && *Argv[i] == '-' && Argv[i][1] != '\0'; i++)
  296.     do_cmdline_arg(Argv[i]);
  297.   hash_clean_undef();
  298.   Argc_end = i;
  299. }
  300.   
  301. /* do_config_file() -- read standard #define's from config file */
  302. static void do_config_file()
  303. {
  304.   char buf[128];
  305.   register const char *s;
  306.   register int len;
  307.  
  308.   if (!config_file_name) {    /* default config file */
  309.     if (!(s = getenv("LIB")))
  310.       s = ".";
  311.     while (*s) {
  312.       len = strcspn(s, ",;");
  313.       strncpy(buf, s, len);
  314.       buf[len] = PATH_SEP;
  315.       strcpy(buf + len + 1, DEFAULT_CONFIG_NAME);
  316.       if (access(buf, R_OK) == 0) {
  317.     in_config_file = 1;
  318.     process_file(buf);
  319.     in_config_file = 0;
  320.     return;
  321.       }
  322.       s += len;
  323.       if (*s)
  324.     s++;
  325.     }
  326.   } else {            /* user-specified config file */
  327.     if (!*config_file_name)
  328.       return;
  329.     if (access(config_file_name, R_OK) != 0) {
  330.       warning("cannot open user-specified config file \"%s\"",
  331.           config_file_name);
  332.     } else {
  333.       in_config_file = 1;
  334.       process_file(config_file_name);
  335.       in_config_file = 0;
  336.     }
  337.   }
  338. }
  339.  
  340. /* include_path_list() -- extract individual include-file paths from the
  341.    path list |incdir|.  Handles both TOS-style ["u:\include,d:\include"]
  342.    and POSIX-style ["/include:/d/include"] lists. */
  343. static void include_path_list(incdir)
  344.   char *incdir;
  345. {
  346.   register char *s = incdir;
  347.   size_t len;
  348.   const char *sep = ":";
  349.  
  350.   /* ',' or ';' list separators indicate a TOS-style list */
  351.   if (strpbrk(s, ",;"))
  352.     sep = ",;";
  353.  
  354.   while (*s) {
  355.     len = strcspn(s, sep);
  356.     add_include(copy_filename(s, len));
  357.     s += len;
  358.     if (*s)
  359.       s++;
  360.   }
  361. }
  362.  
  363. /* main() -- guess... */
  364. int main(argc, argv)
  365.   int argc;
  366.   char **argv;
  367. {
  368.   register int i;
  369.   char *infnam;
  370.   register char **cur_I, *incdir;
  371.   time_t t;
  372.   struct tm *T;
  373.  
  374.   argv0 = argv[0];
  375.   Z_type_init();
  376.   hash_setup();
  377.   cond_setup();
  378.   setup_signals();
  379.   time(&t);
  380.   T = localtime(&t);
  381.   strftime(date_string, 12, "%b %d %Y", T);
  382.   strftime(time_string, 9, "%H:%M:%S", T);
  383.   add_include((char *)0);
  384.   /* first check for user-specified config file */
  385.   for (i = 1; i < argc && *argv[i] == '-' && argv[i][1] != '\0'; i++)
  386.     if (*argv[i] == '-' && argv[i][1] == 'S')
  387.       config_file_name = argv[i] + 2;
  388.   Argc = argc;
  389.   Argv = argv;
  390.   do_config_file();
  391.   if (Argc_end == 0)
  392.     do_all_cmdline_args();
  393. #ifndef UNIXHOST
  394.   if ((incdir = getenv("INCLUDE")))
  395. #else
  396.   if ((incdir = getenv("INCLUDE")) || (incdir = getenv("C68INC")))
  397. #endif
  398.     include_path_list(incdir);
  399.   add_include((char *)0);
  400.   if (argc - i > 2) {
  401.     error("too many arguments");
  402.     usage();
  403.   }
  404.   if (i < argc && !streq(argv[i], "-"))
  405.     infnam = copy_filename(argv[i], 0);
  406.   else
  407.     infnam = stdin_name;
  408.   if (i + 1 < argc && (streq(argv[i + 1], "-") || !(outf = xfopen(argv[i + 1], "w"))))
  409.     fatal("%s: cannot open output file %s", argv0, argv[i + 1]);
  410.   process_file(infnam);
  411.   free(infnam);
  412.   for (cur_I = I_list + 1; *cur_I; cur_I++)
  413.     if (*cur_I)
  414.       free(*cur_I);
  415.   free(I_list);
  416.   fclose(outf);
  417.   hash_free();
  418.   cond_shutdown();
  419.   tok_shutdown();
  420.   free_cmt_buf();
  421.   if (nerrs > 0) {
  422.     fprintf(stderr, "%d errors\n", nerrs);
  423.     return 1;
  424.   }
  425.   return 0;
  426. }
  427.