PageRenderTime 93ms CodeModel.GetById 38ms RepoModel.GetById 9ms app.codeStats 0ms

/src/wml_backend/p2_mp4h/src/mp4h.c

https://bitbucket.org/shlomif/website-meta-language
C | 510 lines | 366 code | 83 blank | 61 comment | 36 complexity | f95e5322bf20e2dfa895c57a7613c288 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, LGPL-2.0
  1. /* mp4h -- A macro processor for HTML documents
  2. Copyright 2000-2002, Denis Barbier
  3. All rights reserved.
  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. This program is a work based on GNU m4 version 1.4n. Below is the
  9. original copyright.
  10. */
  11. /* GNU m4 -- A simple macro processor
  12. Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
  13. This program is free software; you can redistribute it and/or modify
  14. it under the terms of the GNU General Public License as published by
  15. the Free Software Foundation; either version 2, or (at your option)
  16. any later version.
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. GNU General Public License for more details.
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24. */
  25. #include "mp4h.h"
  26. #include <error.h>
  27. #include <getopt.h>
  28. /* Enable sync output for /lib/cpp (-s). */
  29. int sync_output = 0;
  30. /* Debug (-d[flags]). */
  31. int debug_level = 0;
  32. /* Hash table size (should be a prime) (-Hsize). */
  33. int hash_table_size = HASHMAX;
  34. /* Max length of arguments in trace output (-lsize). */
  35. int max_debug_argument_length = 0;
  36. /* Suppress warnings about missing arguments. */
  37. int suppress_warnings = 0;
  38. /* If not zero, then value of exit status for warning diagnostics. */
  39. int warning_status = 0;
  40. /* Artificial limit for expansion_level in macro.c. */
  41. int nesting_limit = 250;
  42. /* Security level */
  43. int safety_level = 0;
  44. /* Document encoding */
  45. encoding_type document_encoding = ENCODING_8BIT;
  46. /* Flags to control how expansion is performed. */
  47. #define DEFAULT_EXPANSION_FLAGS 3114
  48. int exp_flags = DEFAULT_EXPANSION_FLAGS;
  49. /* Name of frozen file to digest after initialization. */
  50. const char *frozen_file_to_read = NULL;
  51. /* Name of frozen file to produce near completion. */
  52. const char *frozen_file_to_write = NULL;
  53. /* True when -F flag is passed. */
  54. int frozen_dump = 0;
  55. /* The name this program was run with (needed by ../lib/error.c). */
  56. const char *program_name = PACKAGE_NAME;
  57. /* If nonzero, display usage information and exit. */
  58. static int show_help = 0;
  59. /* If nonzero, print the version on standard output and exit. */
  60. static int show_version = 0;
  61. struct macro_definition
  62. {
  63. struct macro_definition *next;
  64. int code; /* D, U or t */
  65. const char *macro;
  66. };
  67. typedef struct macro_definition macro_definition;
  68. /*---------------------------------------------.
  69. | Print a usage message and exit with STATUS. |
  70. `---------------------------------------------*/
  71. #define HELP_EXP_FLAGS(n,str) \
  72. do \
  73. { \
  74. printf(" %c %4d %s\n", \
  75. ((exp_flags & n) ? '*' : ' '), n, str); \
  76. } \
  77. while (0)
  78. static void
  79. usage (int status)
  80. {
  81. if (status != EXIT_SUCCESS)
  82. fprintf (stderr, _("Try `%s --help' for more information.\n"),
  83. PACKAGE_NAME);
  84. else
  85. {
  86. printf (_("Usage: %s [OPTION]... [FILE]...\n"), PACKAGE_NAME);
  87. fputs (_("\
  88. Mandatory or optional arguments to long options are mandatory or optional\n\
  89. for short options too.\n\
  90. \n\
  91. Operation modes:\n\
  92. --help display this help and exit\n\
  93. --version output version information and exit\n\
  94. -E, --fatal-warnings stop execution after first warning\n\
  95. -Q, --quiet, --silent suppress some warnings for builtins\n\
  96. -S, --safety-level=NUMBER disable hazardous functions\n"),
  97. stdout);
  98. fputs (_("\
  99. \n\
  100. Preprocessor features:\n\
  101. -I, --include=DIRECTORY search this directory second for includes\n\
  102. -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n\
  103. -U, --undefine=NAME delete builtin NAME\n\
  104. -s, --synclines generate `#line NO \"FILE\"' lines\n"),
  105. stdout);
  106. fputs (_("\
  107. \n\
  108. Parser features:\n\
  109. -c, --caseless=NUMBER set tags (1), variables (2) or entities (4)\n\
  110. case insensitive. Default value is 3, i.e.\n\
  111. only entities are case sensitive\n\
  112. -e, --encoding=NAME specify document encoding\n\
  113. -X, --expansion=NUMBER set parser behaviour according to the bits\n\
  114. of NUMBER, with (star marks current flags)\n\
  115. "), stdout);
  116. HELP_EXP_FLAGS( 1, "do not parse unknown tags");
  117. HELP_EXP_FLAGS( 2, "unknown tags are assumed being simple");
  118. HELP_EXP_FLAGS( 4, "trailing star in tag name do not make this tag simple");
  119. HELP_EXP_FLAGS( 8, "an unmatched end tag closes all previous unmatched begin tags");
  120. HELP_EXP_FLAGS( 16, "interpret backslashes as printf");
  121. HELP_EXP_FLAGS( 32, "remove trailing slash in tag attributes");
  122. HELP_EXP_FLAGS( 64, "do not remove trailing star in tag name");
  123. HELP_EXP_FLAGS( 128, "do not remove leading star in tag name");
  124. HELP_EXP_FLAGS( 256, "do not add a space before trailing slash in tag attributes");
  125. HELP_EXP_FLAGS( 1024, "suppress warnings about bad nested tags");
  126. HELP_EXP_FLAGS( 2048, "suppress warnings about missing trailing slash");
  127. fputs (_("\
  128. \n\
  129. Limits control:\n\
  130. -H, --hashsize=PRIME set symbol lookup hash table size\n\
  131. -L, --nesting-limit=NUMBER change artificial nesting limit\n"),
  132. stdout);
  133. fputs (_("\
  134. \n\
  135. Frozen state files:\n\
  136. -F, --freeze-state=FILE produce a frozen state on FILE at end\n\
  137. -R, --reload-state=FILE reload a frozen state from FILE at start\n"),
  138. stdout);
  139. fputs (_("\
  140. \n\
  141. Debugging:\n\
  142. -d, --debug=[FLAGS] set debug level (no FLAGS implies `ae')\n\
  143. -t, --trace=NAME trace NAME when it will be defined\n\
  144. -l, --arglength=NUM restrict macro tracing size\n\
  145. -o, --error-output=FILE redirect debug and trace output\n"),
  146. stdout);
  147. fputs (_("\
  148. \n\
  149. FLAGS is any of:\n\
  150. t trace for all macro calls, not only debugging-on'ed\n\
  151. a show actual arguments\n\
  152. e show expansion\n\
  153. c show before collect, after collect and after call\n\
  154. x add a unique macro call id, useful with c flag\n\
  155. f say current input file name\n\
  156. l say current input line number\n\
  157. p show results of path searches\n\
  158. m show results of module operations\n\
  159. i show changes in input files\n\
  160. V shorthand for all of the above flags\n"),
  161. stdout);
  162. fputs (_("\
  163. \n\
  164. If no FILE or if FILE is `-', standard input is read.\n"),
  165. stdout);
  166. }
  167. exit (status);
  168. }
  169. /*--------------------------------------.
  170. | Decode options and launch execution. |
  171. `--------------------------------------*/
  172. static const struct option long_options[] =
  173. {
  174. {"arglength", required_argument, NULL, 'l'},
  175. {"debug", optional_argument, NULL, 'd'},
  176. {"error-output", required_argument, NULL, 'o'},
  177. {"expansion", required_argument, NULL, 'X'},
  178. {"fatal-warnings", no_argument, NULL, 'E'},
  179. {"freeze-state", required_argument, NULL, 'F'},
  180. {"hashsize", required_argument, NULL, 'H'},
  181. {"include", required_argument, NULL, 'I'},
  182. {"nesting-limit", required_argument, NULL, 'L'},
  183. {"quiet", no_argument, NULL, 'Q'},
  184. {"reload-state", required_argument, NULL, 'R'},
  185. {"silent", no_argument, NULL, 'Q'},
  186. {"synclines", no_argument, NULL, 's'},
  187. {"safety-level", required_argument, NULL, 'S'},
  188. {"encoding", required_argument, NULL, 'e'},
  189. {"caseless", required_argument, NULL, 'c'},
  190. {"help", no_argument, NULL, 'h'},
  191. {"version", no_argument, NULL, 'V'},
  192. /* These are somewhat troublesome. */
  193. { "define", required_argument, NULL, 'D' },
  194. { "undefine", required_argument, NULL, 'U' },
  195. { "trace", required_argument, NULL, 't' },
  196. { 0, 0, 0, 0 },
  197. };
  198. #define OPTSTRING "c:D:e:EF:H:I:L:QR:U:X:d:hl:o:sS:Ot:V"
  199. int
  200. main (int argc, char *const *argv)
  201. {
  202. macro_definition *head; /* head of deferred argument list */
  203. macro_definition *tail;
  204. macro_definition *new;
  205. int optchar; /* option character */
  206. macro_definition *defines;
  207. FILE *fp;
  208. char *filename;
  209. int caseless = CASELESS_DEFAULT;
  210. debug_init ();
  211. include_init ();
  212. /* First, we decode the arguments, to size up tables and stuff. */
  213. head = tail = NULL;
  214. while (optchar = getopt_long (argc, argv, OPTSTRING, long_options, NULL),
  215. optchar != EOF)
  216. switch (optchar)
  217. {
  218. default:
  219. usage (EXIT_FAILURE);
  220. case 0:
  221. break;
  222. case 'c':
  223. caseless = atoi (optarg);
  224. if (caseless <= 0)
  225. caseless = CASELESS_DEFAULT;
  226. break;
  227. case 'D':
  228. case 'U':
  229. case 't':
  230. /* Arguments that cannot be handled until later are accumulated. */
  231. new = (macro_definition *) xmalloc (sizeof (macro_definition));
  232. new->code = optchar;
  233. new->macro = optarg;
  234. new->next = NULL;
  235. if (head == NULL)
  236. head = new;
  237. else
  238. tail->next = new;
  239. tail = new;
  240. break;
  241. case 'e':
  242. if (strcasecmp(optarg, "8bit") == 0)
  243. document_encoding = ENCODING_8BIT;
  244. else if (strcasecmp(optarg, "utf8") == 0)
  245. document_encoding = ENCODING_UTF8;
  246. else
  247. error (0, 0, _("Bad encoding: `%s'"), optarg);
  248. break;
  249. case 'E':
  250. warning_status = EXIT_FAILURE;
  251. break;
  252. case 'F':
  253. frozen_file_to_write = optarg;
  254. frozen_dump = 1;
  255. break;
  256. case 'H':
  257. hash_table_size = atoi (optarg);
  258. if (hash_table_size <= 0)
  259. hash_table_size = HASHMAX;
  260. break;
  261. case 'I':
  262. add_include_directory (optarg);
  263. break;
  264. case 'L':
  265. nesting_limit = atoi (optarg);
  266. break;
  267. case 'Q':
  268. suppress_warnings = 1;
  269. break;
  270. case 'R':
  271. frozen_file_to_read = optarg;
  272. break;
  273. case 'd':
  274. debug_level = debug_decode (optarg);
  275. if (debug_level < 0)
  276. {
  277. error (0, 0, _("Bad debug flags: `%s'"), optarg);
  278. debug_level = 0;
  279. }
  280. break;
  281. case 'X':
  282. exp_flags = atoi (optarg);
  283. if (exp_flags < 0)
  284. {
  285. error (0, 0, _("Bad expansion flags: `%s'"), optarg);
  286. exp_flags = DEFAULT_EXPANSION_FLAGS;
  287. }
  288. break;
  289. case 'l':
  290. max_debug_argument_length = atoi (optarg);
  291. if (max_debug_argument_length <= 0)
  292. max_debug_argument_length = 0;
  293. break;
  294. case 'o':
  295. if (!debug_set_output (optarg))
  296. error (0, errno, "%s", optarg);
  297. break;
  298. case 's':
  299. sync_output = 1;
  300. break;
  301. case 'S':
  302. safety_level = atoi (optarg);
  303. break;
  304. case 'V':
  305. show_version = 1;
  306. break;
  307. case 'h':
  308. show_help = 1;
  309. break;
  310. }
  311. if (show_version)
  312. {
  313. printf ("%s (%s)\n", PACKAGE_STRING, PACKAGE_DATE);
  314. exit (EXIT_SUCCESS);
  315. }
  316. if (show_help)
  317. usage (EXIT_SUCCESS);
  318. /* Do the basic initialisations. */
  319. input_init ();
  320. output_init ();
  321. include_env_init ();
  322. symtab_init ();
  323. break_init ();
  324. caseless_init (caseless);
  325. #ifdef HAVE_LOCALE_H
  326. locale_init (LC_ALL, NULL);
  327. #endif
  328. #ifdef WITH_MODULES
  329. module_init ();
  330. #endif
  331. pcre_init ();
  332. if (frozen_file_to_read)
  333. reload_frozen_state (frozen_file_to_read);
  334. else
  335. builtin_init ();
  336. /* Handle deferred command line macro definitions. Must come after
  337. initialisation of the symbol table. */
  338. defines = head;
  339. while (defines != NULL)
  340. {
  341. macro_definition *next;
  342. char *macro_value;
  343. symbol *sym;
  344. switch (defines->code)
  345. {
  346. case 'D':
  347. macro_value = strchr (defines->macro, '=');
  348. if (macro_value == NULL)
  349. macro_value = "";
  350. else
  351. *macro_value++ = '\0';
  352. sym = lookup_variable (defines->macro, SYMBOL_INSERT);
  353. initialize_builtin (sym);
  354. SYMBOL_TYPE (sym) = TOKEN_TEXT;
  355. SYMBOL_TEXT (sym) = xstrdup (macro_value);
  356. break;
  357. case 'U':
  358. lookup_symbol (defines->macro, SYMBOL_DELETE);
  359. break;
  360. case 't':
  361. sym = lookup_symbol (defines->macro, SYMBOL_INSERT);
  362. SYMBOL_TRACED (sym) = TRUE;
  363. break;
  364. default:
  365. MP4HERROR ((warning_status, 0,
  366. "INTERNAL ERROR: Bad code in deferred arguments"));
  367. exit (1);
  368. }
  369. next = defines->next;
  370. xfree ((voidstar) defines);
  371. defines = next;
  372. }
  373. /* Handle the various input files. Each file is pushed on the input,
  374. and the input read. Wrapup text is handled separately later. */
  375. if (optind == argc)
  376. {
  377. push_file (stdin, "stdin");
  378. expand_input ();
  379. }
  380. else
  381. for (; optind < argc; optind++)
  382. {
  383. if (strcmp (argv[optind], "-") == 0)
  384. push_file (stdin, "stdin");
  385. else
  386. {
  387. fp = path_search (argv[optind], &filename);
  388. if (fp == NULL)
  389. {
  390. error (0, errno, "%s", argv[optind]);
  391. MP4HERROR ((warning_status, 0,
  392. _("%s: file skipped"), argv[optind]));
  393. continue;
  394. }
  395. else
  396. {
  397. xfree ((voidstar) current_file);
  398. current_file = xstrdup (filename);
  399. push_file (fp, filename);
  400. xfree ((voidstar) filename);
  401. }
  402. }
  403. expand_input ();
  404. }
  405. #undef NEXTARG
  406. /* Now handle wrapup text. */
  407. while (pop_wrapup ())
  408. expand_input ();
  409. if (frozen_file_to_write)
  410. produce_frozen_state (frozen_file_to_write);
  411. /* Free memory */
  412. input_deallocate ();
  413. debug_deallocate ();
  414. include_deallocate ();
  415. output_deallocate ();
  416. symtab_deallocate ();
  417. break_deallocate ();
  418. builtin_deallocate ();
  419. pcre_deallocate ();
  420. xfree ((voidstar) current_file);
  421. exit (EXIT_SUCCESS);
  422. }