home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / m4-1.4-src.tgz / tar.out / fsf / m4 / src / m4.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  12KB  |  494 lines

  1. /* GNU m4 -- A simple macro processor
  2.    Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
  3.   
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.   
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.   
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. #include "m4.h"
  20.  
  21. #include <getopt.h>
  22. #include <sys/signal.h>
  23.  
  24. static void usage _((int));
  25.  
  26. /* Operate interactively (-e).  */
  27. static int interactive = 0;
  28.  
  29. /* Enable sync output for /lib/cpp (-s).  */
  30. int sync_output = 0;
  31.  
  32. /* Debug (-d[flags]).  */
  33. int debug_level = 0;
  34.  
  35. /* Hash table size (should be a prime) (-Hsize).  */
  36. int hash_table_size = HASHMAX;
  37.  
  38. /* Disable GNU extensions (-G).  */
  39. int no_gnu_extensions = 0;
  40.  
  41. /* Prefix all builtin functions by `m4_'.  */
  42. int prefix_all_builtins = 0;
  43.  
  44. /* Max length of arguments in trace output (-lsize).  */
  45. int max_debug_argument_length = 0;
  46.  
  47. /* Suppress warnings about missing arguments.  */
  48. int suppress_warnings = 0;
  49.  
  50. /* If not zero, then value of exit status for warning diagnostics.  */
  51. int warning_status = 0;
  52.  
  53. /* Artificial limit for expansion_level in macro.c.  */
  54. int nesting_limit = 250;
  55.  
  56. #ifdef ENABLE_CHANGEWORD
  57. /* User provided regexp for describing m4 words.  */
  58. const char *user_word_regexp = NULL;
  59. #endif
  60.  
  61. /* Name of frozen file to digest after initialization.  */
  62. const char *frozen_file_to_read = NULL;
  63.  
  64. /* Name of frozen file to produce near completion.  */
  65. const char *frozen_file_to_write = NULL;
  66.  
  67. /* The name this program was run with. */
  68. const char *program_name;
  69.  
  70. /* If non-zero, display usage information and exit.  */
  71. static int show_help = 0;
  72.  
  73. /* If non-zero, print the version on standard output and exit.  */
  74. static int show_version = 0;
  75.  
  76. struct macro_definition
  77. {
  78.   struct macro_definition *next;
  79.   int code;            /* D, U or t */
  80.   const char *macro;
  81. };
  82. typedef struct macro_definition macro_definition;
  83.  
  84. /* Error handling functions.  */
  85.  
  86. /*-------------------------------------------------------------------------.
  87. | Print source and line reference on standard error, as a prefix for error |
  88. | messages.  Flush standard output first.                   |
  89. `-------------------------------------------------------------------------*/
  90.  
  91. void
  92. reference_error (void)
  93. {
  94.   fflush (stdout);
  95.   fprintf (stderr, "%s:%d: ", current_file, current_line);
  96. }
  97.  
  98. #ifdef USE_STACKOVF
  99.  
  100. /*---------------------------------------.
  101. | Tell user stack overflowed and abort.     |
  102. `---------------------------------------*/
  103.  
  104. static void
  105. stackovf_handler (void)
  106. {
  107.   M4ERROR ((EXIT_FAILURE, 0,
  108.         "ERROR: Stack overflow.  (Infinite define recursion?)"));
  109. }
  110.  
  111. #endif /* USE_STACKOV */
  112.  
  113. /* Memory allocation.  */
  114.  
  115. /*------------------------.
  116. | Failsafe free routine.  |
  117. `------------------------*/
  118.  
  119. void
  120. xfree (voidstar p)
  121. {
  122.   if (p != NULL)
  123.     free (p);
  124. }
  125.  
  126.  
  127. /*---------------------------------------------.
  128. | Print a usage message and exit with STATUS.  |
  129. `---------------------------------------------*/
  130.  
  131. static void
  132. usage (int status)
  133. {
  134.   if (status != EXIT_SUCCESS)
  135.     fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
  136.   else
  137.     {
  138.       printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
  139.       fputs ("\
  140. Mandatory or optional arguments to long options are mandatory or optional\n\
  141. for short options too.\n\
  142. \n\
  143. Operation modes:\n\
  144.       --help                   display this help and exit\n\
  145.       --version                output version information and exit\n\
  146.   -e, --interactive            unbuffer output, ignore interrupts\n\
  147.   -E, --fatal-warnings         stop execution after first warning\n\
  148.   -Q, --quiet, --silent        suppress some warnings for builtins\n\
  149.   -P, --prefix-builtins        force a `m4_' prefix to all builtins\n",
  150.          stdout);
  151. #ifdef ENABLE_CHANGEWORD
  152.       fputs ("\
  153.   -W, --word-regexp=REGEXP     use REGEXP for macro name syntax\n",
  154.          stdout);
  155. #endif
  156.       fputs ("\
  157. \n\
  158. Preprocessor features:\n\
  159.   -I, --include=DIRECTORY      search this directory second for includes\n\
  160.   -D, --define=NAME[=VALUE]    enter NAME has having VALUE, or empty\n\
  161.   -U, --undefine=NAME          delete builtin NAME\n\
  162.   -s, --synclines              generate `#line NO \"FILE\"' lines\n",
  163.          stdout);
  164.       fputs ("\
  165. \n\
  166. Limits control:\n\
  167.   -G, --traditional            suppress all GNU extensions\n\
  168.   -H, --hashsize=PRIME         set symbol lookup hash table size\n\
  169.   -L, --nesting-limit=NUMBER   change artificial nesting limit\n",
  170.          stdout);
  171.       fputs ("\
  172. \n\
  173. Frozen state files:\n\
  174.   -F, --freeze-state=FILE      produce a frozen state on FILE at end\n\
  175.   -R, --reload-state=FILE      reload a frozen state from FILE at start\n",
  176.          stdout);
  177.       fputs ("\
  178. \n\
  179. Debugging:\n\
  180.   -d, --debug=[FLAGS]          set debug level (no FLAGS implies `aeq')\n\
  181.   -t, --trace=NAME             trace NAME when it will be defined\n\
  182.   -l, --arglength=NUM          restrict macro tracing size\n\
  183.   -o, --error-output=FILE      redirect debug and trace output\n",
  184.          stdout);
  185.       fputs ("\
  186. \n\
  187. FLAGS is any of:\n\
  188.   t   trace for all macro calls, not only traceon'ed\n\
  189.   a   show actual arguments\n\
  190.   e   show expansion\n\
  191.   q   quote values as necessary, with a or e flag\n\
  192.   c   show before collect, after collect and after call\n\
  193.   x   add a unique macro call id, useful with c flag\n\
  194.   f   say current input file name\n\
  195.   l   say current input line number\n\
  196.   p   show results of path searches\n\
  197.   i   show changes in input files\n\
  198.   V   shorthand for all of the above flags\n",
  199.          stdout);
  200.       fputs ("\
  201. \n\
  202. If no FILE or if FILE is `-', standard input is read.\n",
  203.          stdout);
  204.     }
  205.   exit (status);
  206. }
  207.  
  208. /*--------------------------------------.
  209. | Decode options and launch execution.  |
  210. `--------------------------------------*/
  211.  
  212. static const struct option long_options[] =
  213. {
  214.   {"arglength", required_argument, NULL, 'l'},
  215.   {"debug", optional_argument, NULL, 'd'},
  216.   {"diversions", required_argument, NULL, 'N'},
  217.   {"error-output", required_argument, NULL, 'o'},
  218.   {"fatal-warnings", no_argument, NULL, 'E'},
  219.   {"freeze-state", required_argument, NULL, 'F'},
  220.   {"hashsize", required_argument, NULL, 'H'},
  221.   {"include", required_argument, NULL, 'I'},
  222.   {"interactive", no_argument, NULL, 'e'},
  223.   {"nesting-limit", required_argument, NULL, 'L'},
  224.   {"prefix-builtins", no_argument, NULL, 'P'},
  225.   {"quiet", no_argument, NULL, 'Q'},
  226.   {"reload-state", required_argument, NULL, 'R'},
  227.   {"silent", no_argument, NULL, 'Q'},
  228.   {"synclines", no_argument, NULL, 's'},
  229.   {"traditional", no_argument, NULL, 'G'},
  230.   {"word-regexp", required_argument, NULL, 'W'},
  231.  
  232.   {"help", no_argument, &show_help, 1},
  233.   {"version", no_argument, &show_version, 1},
  234.  
  235.   /* These are somewhat troublesome.  */
  236.   { "define", required_argument, NULL, 'D' },
  237.   { "undefine", required_argument, NULL, 'U' },
  238.   { "trace", required_argument, NULL, 't' },
  239.  
  240.   { 0, 0, 0, 0 },
  241. };
  242.  
  243. #ifdef ENABLE_CHANGEWORD
  244. #define OPTSTRING "B:D:EF:GH:I:L:N:PQR:S:T:U:W:d::el:o:st:"
  245. #else
  246. #define OPTSTRING "B:D:EF:GH:I:L:N:PQR:S:T:U:d::el:o:st:"
  247. #endif
  248.  
  249. int
  250. main (int argc, char *const *argv, char *const *envp)
  251. {
  252.   macro_definition *head;    /* head of deferred argument list */
  253.   macro_definition *tail;
  254.   macro_definition *new;
  255.   int optchar;            /* option character */
  256.  
  257.   macro_definition *defines;
  258.   FILE *fp;
  259.  
  260.   program_name = argv[0];
  261.  
  262.   include_init ();
  263.   debug_init ();
  264. #ifdef USE_STACKOVF
  265.   setup_stackovf_trap (argv, envp, stackovf_handler);
  266. #endif
  267.  
  268.   /* First, we decode the arguments, to size up tables and stuff.  */
  269.  
  270.   head = tail = NULL;
  271.  
  272.   while (optchar = getopt_long (argc, argv, OPTSTRING, long_options, NULL),
  273.      optchar != EOF)
  274.     switch (optchar)
  275.       {
  276.       default:
  277.     usage (EXIT_FAILURE);
  278.  
  279.       case 0:
  280.     break;
  281.  
  282.       case 'B':            /* compatibility junk */
  283.       case 'N':
  284.       case 'S':
  285.       case 'T':
  286.     break;
  287.  
  288.       case 'D':
  289.       case 'U':
  290.       case 't':
  291.  
  292.     /* Arguments that cannot be handled until later are accumulated.  */
  293.  
  294.     new = (macro_definition *) xmalloc (sizeof (macro_definition));
  295.     new->code = optchar;
  296.     new->macro = optarg;
  297.     new->next = NULL;
  298.  
  299.     if (head == NULL)
  300.       head = new;
  301.     else
  302.       tail->next = new;
  303.     tail = new;
  304.  
  305.     break;
  306.  
  307.       case 'E':
  308.     warning_status = EXIT_FAILURE;
  309.     break;
  310.  
  311.       case 'F':
  312.     frozen_file_to_write = optarg;
  313.     break;
  314.  
  315.       case 'G':
  316.     no_gnu_extensions = 1;
  317.     break;
  318.  
  319.       case 'H':
  320.     hash_table_size = atoi (optarg);
  321.     if (hash_table_size <= 0)
  322.       hash_table_size = HASHMAX;
  323.     break;
  324.  
  325.       case 'I':
  326.     add_include_directory (optarg);
  327.     break;
  328.  
  329.       case 'L':
  330.     nesting_limit = atoi (optarg);
  331.     break;
  332.  
  333.       case 'P':
  334.     prefix_all_builtins = 1;
  335.     break;
  336.  
  337.       case 'Q':
  338.     suppress_warnings = 1;
  339.     break;
  340.  
  341.       case 'R':
  342.     frozen_file_to_read = optarg;
  343.     break;
  344.  
  345. #ifdef ENABLE_CHANGEWORD
  346.       case 'W':
  347.     user_word_regexp = optarg;
  348.     break;
  349. #endif
  350.  
  351.       case 'd':
  352.     debug_level = debug_decode (optarg);
  353.     if (debug_level < 0)
  354.       {
  355.         error (0, 0, "bad debug flags: `%s'", optarg);
  356.         debug_level = 0;
  357.       }
  358.     break;
  359.  
  360.       case 'e':
  361.     interactive = 1;
  362.     break;
  363.  
  364.       case 'l':
  365.     max_debug_argument_length = atoi (optarg);
  366.     if (max_debug_argument_length <= 0)
  367.       max_debug_argument_length = 0;
  368.     break;
  369.  
  370.       case 'o':
  371.     if (!debug_set_output (optarg))
  372.       error (0, errno, optarg);
  373.     break;
  374.  
  375.       case 's':
  376.     sync_output = 1;
  377.     break;
  378.       }
  379.  
  380.   if (show_version)
  381.     {
  382.       printf ("GNU %s %s\n", PRODUCT, VERSION);
  383.       exit (EXIT_SUCCESS);
  384.     }
  385.  
  386.   if (show_help)
  387.     usage (EXIT_SUCCESS);
  388.  
  389.   defines = head;
  390.  
  391.   /* Do the basic initialisations.  */
  392.  
  393.   input_init ();
  394.   output_init ();
  395.   symtab_init ();
  396.   include_env_init ();
  397.  
  398.   if (frozen_file_to_read)
  399.     reload_frozen_state (frozen_file_to_read);
  400.   else
  401.     builtin_init ();
  402.  
  403.   /* Handle deferred command line macro definitions.  Must come after
  404.      initialisation of the symbol table.  */
  405.  
  406.   while (defines != NULL)
  407.     {
  408.       macro_definition *next;
  409.       char *macro_value;
  410.       symbol *sym;
  411.  
  412.       switch (defines->code)
  413.     {
  414.     case 'D':
  415.       macro_value = strchr (defines->macro, '=');
  416.       if (macro_value == NULL)
  417.         macro_value = "";
  418.       else
  419.         *macro_value++ = '\0';
  420.       define_user_macro (defines->macro, macro_value, SYMBOL_INSERT);
  421.       break;
  422.  
  423.     case 'U':
  424.       lookup_symbol (defines->macro, SYMBOL_DELETE);
  425.       break;
  426.  
  427.     case 't':
  428.       sym = lookup_symbol (defines->macro, SYMBOL_INSERT);
  429.       SYMBOL_TRACED (sym) = TRUE;
  430.       break;
  431.  
  432.     default:
  433.       M4ERROR ((warning_status, 0,
  434.             "INTERNAL ERROR: Bad code in deferred arguments"));
  435.       abort ();
  436.     }
  437.  
  438.       next = defines->next;
  439.       xfree ((voidstar) defines);
  440.       defines = next;
  441.     }
  442.  
  443.   /* Interactive mode means unbuffered output, and interrupts ignored.  */
  444.  
  445.   if (interactive)
  446.     {
  447.       signal (SIGINT, SIG_IGN);
  448.       setbuf (stdout, (char *) NULL);
  449.     }
  450.  
  451.   /* Handle the various input files.  Each file is pushed on the input,
  452.      and the input read.  Wrapup text is handled separately later.  */
  453.  
  454.   if (optind == argc)
  455.     {
  456.       push_file (stdin, "stdin");
  457.       expand_input ();
  458.     }
  459.   else
  460.     for (; optind < argc; optind++)
  461.       {
  462.     if (strcmp (argv[optind], "-") == 0)
  463.       push_file (stdin, "stdin");
  464.     else
  465.       {
  466.         fp = path_search (argv[optind]);
  467.         if (fp == NULL)
  468.           {
  469.         error (0, errno, argv[optind]);
  470.         continue;
  471.           }
  472.         else
  473.           push_file (fp, argv[optind]);
  474.       }
  475.     expand_input ();
  476.       }
  477. #undef NEXTARG
  478.  
  479.   /* Now handle wrapup text.  */
  480.  
  481.   while (pop_wrapup ())
  482.     expand_input ();
  483.  
  484.   if (frozen_file_to_write)
  485.     produce_frozen_state (frozen_file_to_write);
  486.   else
  487.     {
  488.       make_diversion (0);
  489.       undivert_all ();
  490.     }
  491.  
  492.   exit (EXIT_SUCCESS);
  493. }
  494.