PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/wml_backend/p4_gm4/src/m4.c

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