main.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
  2. * For full copyright and restrictions on use see the file COPYING in the top
  3. * level of the LLgen tree.
  4. */
  5. /*
  6. * L L G E N
  7. *
  8. * An Extended LL(1) Parser Generator
  9. *
  10. * Author : Ceriel J.H. Jacobs
  11. */
  12. /*
  13. * main.c
  14. * Contains main program, and some error message routines
  15. */
  16. #include "types.h"
  17. #include "io.h"
  18. #include "extern.h"
  19. #include "sets.h"
  20. #include "assert.h"
  21. #include "LLgen.h"
  22. #include <missing_proto.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <unistd.h>
  26. int main(int argc, char *argv[])
  27. {
  28. string arg;
  29. string libpath();
  30. char *beg_sbrk = 0;
  31. /* Initialize */
  32. assval = 0400;
  33. /* read options */
  34. while (argc >= 2 && (arg = argv[1], *arg == '-')) {
  35. while (*++arg) {
  36. switch(*arg) {
  37. case 'j':
  38. case 'J':
  39. jmptable_option = 1;
  40. if (*++arg)
  41. min_cases_for_jmptable = atoi(arg);
  42. break;
  43. case 'w':
  44. case 'W':
  45. wflag = 1;
  46. continue;
  47. case 'v':
  48. case 'V':
  49. verbose++;
  50. continue;
  51. case 'l':
  52. case 'L':
  53. low_percentage = atoi(++arg);
  54. break;
  55. case 'h':
  56. case 'H':
  57. high_percentage = atoi(++arg);
  58. break;
  59. # ifndef NDEBUG
  60. case 'd':
  61. case 'D':
  62. debug++;
  63. continue;
  64. case 'r':
  65. case 'R':
  66. if (rec_file) {
  67. fprintf(stderr,"duplicate -r flag\n");
  68. exit(1);
  69. }
  70. rec_file = ++arg;
  71. break;
  72. case 'i':
  73. case 'I':
  74. if (incl_file) {
  75. fprintf(stderr,"duplicate -i flag\n");
  76. exit(1);
  77. }
  78. incl_file = ++arg;
  79. break;
  80. #endif /* not NDEBUG */
  81. case 'x':
  82. case 'X':
  83. ntneeded = 1;
  84. ntprint = 1;
  85. continue;
  86. case 'a':
  87. case 'A':
  88. ansi_c = 1;
  89. continue;
  90. #ifdef NON_CORRECTING
  91. case 'n':
  92. case 'N':
  93. non_corr = 1;
  94. continue;
  95. case 's':
  96. case 'S':
  97. subpars_sim = 1;
  98. continue;
  99. #endif
  100. case 'g':
  101. case 'G':
  102. strip_grammar = 1;
  103. continue;
  104. default:
  105. fprintf(stderr,"illegal option : %c\n",*arg);
  106. exit(1);
  107. }
  108. break;
  109. }
  110. argv++;
  111. argc--;
  112. }
  113. if (verbose) beg_sbrk = (char *)sbrk(0);
  114. #ifdef NON_CORRECTING
  115. if ((subpars_sim) && (!non_corr)) {
  116. fprintf(stderr,"option -s illegal without -n, turned off\n");
  117. subpars_sim = 0;
  118. }
  119. #endif
  120. /*
  121. * Now check wether the sets should include nonterminals
  122. */
  123. if (verbose == 2) ntneeded = 1;
  124. /*
  125. * Initialise
  126. */
  127. # ifndef NDEBUG
  128. if (!rec_file) {
  129. # endif
  130. rec_file = libpath("rec");
  131. # ifndef NDEBUG
  132. }
  133. if (!incl_file) {
  134. # endif
  135. incl_file = libpath("incl");
  136. # ifndef NDEBUG
  137. }
  138. # endif
  139. #ifdef NON_CORRECTING
  140. if (non_corr) {
  141. nc_incl_file = libpath("nc_incl");
  142. nc_rec_file = libpath ("nc_rec");
  143. }
  144. #endif
  145. mktemp(f_temp);
  146. mktemp(f_pars);
  147. if ((fact = fopen(f_temp,"w")) == NULL) {
  148. fputs("Cannot create temporary\n",stderr);
  149. exit(1);
  150. }
  151. name_init();
  152. readgrammar(argc,argv);
  153. sprintf(f_out, OUTFILE, prefix ? prefix : "LL");
  154. /* for the following two filenames only one L is used; historical
  155. reasons ...
  156. */
  157. sprintf(f_include, HFILE, prefix ? prefix : "L");
  158. sprintf(f_rec, RFILE, prefix ? prefix : "L");
  159. #ifdef NON_CORRECTING
  160. if (non_corr)
  161. sprintf(f_nc, NCFILE, prefix ? prefix : "L");
  162. #endif
  163. setinit(ntneeded);
  164. maxnt = &nonterms[nnonterms];
  165. maxt = &tokens[ntokens];
  166. /*
  167. * Now, the grammar is read. Do some computations
  168. */
  169. co_reach(); /* Check for undefined and unreachable */
  170. if (nerrors) comfatal();
  171. do_compute();
  172. conflchecks();
  173. if (nerrors) comfatal();
  174. fclose(fact);
  175. if (argc-- == 1) {
  176. fputs("No code generation for input from standard input\n",
  177. stderr);
  178. }
  179. else gencode(argc);
  180. UNLINK(f_temp);
  181. UNLINK(f_pars);
  182. if (verbose) {
  183. fprintf(stderr, "number of nonterminals: %d\n", nnonterms);
  184. fprintf(stderr, "number of tokens: %d\n", ntokens);
  185. fprintf(stderr, "number of term structures: %d\n", nterms);
  186. fprintf(stderr, "number of alternation structures: %d\n", nalts);
  187. fprintf(stderr, "total memory used: %ld\n", (long)((long)sbrk(0) - (long)beg_sbrk));
  188. }
  189. exit(0);
  190. }
  191. STATIC void readgrammar(int argc, char *argv[]) {
  192. /*
  193. * Do just what the name suggests : read the grammar
  194. */
  195. register p_file p;
  196. p_mem alloc();
  197. linecount = 0;
  198. f_input = "no filename";
  199. /*
  200. * Build the file structure
  201. */
  202. files = p = (p_file) alloc((unsigned) (argc+1) * sizeof(t_file));
  203. if (argc-- == 1) {
  204. finput = stdin;
  205. f_input = "standard input";
  206. doparse(p++);
  207. } else {
  208. while (argc--) {
  209. if ((finput = fopen(f_input=argv[1],"r")) == NULL) {
  210. fatal(0, e_noopen, f_input, NULL);
  211. }
  212. doparse(p++);
  213. argv++;
  214. fclose(finput);
  215. }
  216. }
  217. maxfiles = p;
  218. if (! lexical) lexical = "yylex";
  219. /*
  220. * There must be a start symbol!
  221. */
  222. if (! nerrors && start == 0) {
  223. fatal(linecount, "Missing %%start", NULL, NULL);
  224. }
  225. if (nerrors) comfatal();
  226. }
  227. STATIC void doparse(p_file p) {
  228. linecount = 0;
  229. p->f_name = f_input;
  230. p->f_firsts = 0;
  231. pfile = p;
  232. torder = -1;
  233. norder = -1;
  234. LLparse();
  235. p->f_nonterminals = norder;
  236. p->f_terminals = torder;
  237. }
  238. /* VARARGS1 */
  239. void error(int lineno, char *s, char *t, char *u) {
  240. /*
  241. * Just an error message
  242. */
  243. ++nerrors;
  244. if (!lineno) lineno = 1;
  245. fprintf(stderr,"\"%s\", line %d: ",f_input, lineno);
  246. fprintf(stderr,s,t,u);
  247. fputs("\n",stderr);
  248. }
  249. /* VARARGS1 */
  250. void warning(int lineno, char *s, char *t, char *u) {
  251. /*
  252. * Just a warning
  253. */
  254. if (wflag) return;
  255. if (!lineno) lineno = 1;
  256. fprintf(stderr,"\"%s\", line %d: (Warning) ",f_input, lineno);
  257. fprintf(stderr,s,t,u);
  258. fputs("\n",stderr);
  259. }
  260. /* VARARGS1 */
  261. void fatal(int lineno, char *s, char *t, char *u) {
  262. /*
  263. * Fatal error
  264. */
  265. error(lineno,s,t,u);
  266. comfatal();
  267. }
  268. void comfatal(void) {
  269. /*
  270. * Some common code for exit on errors
  271. */
  272. if (fact != NULL) {
  273. fclose(fact);
  274. UNLINK(f_temp);
  275. }
  276. if (fpars != NULL) fclose(fpars);
  277. UNLINK(f_pars);
  278. exit(1);
  279. }
  280. void copyfile(char *file) {
  281. /*
  282. * Copies a file indicated by the parameter to filedescriptor fpars.
  283. */
  284. register int c;
  285. register FILE *f;
  286. if ((f = fopen(file,"r")) == NULL) {
  287. fatal(0,"Cannot open library file %s, call an expert",file, NULL);
  288. }
  289. while ((c = getc(f)) != EOF) putc(c,fpars);
  290. fclose(f);
  291. }
  292. void install(char *target, char *source) {
  293. /*
  294. * Copy the temporary file generated from source to target
  295. * if allowed (which means that the target must be generated
  296. * by LLgen from the source, or that the target is not present
  297. */
  298. register int c1, c2;
  299. register FILE *f1, *f2;
  300. int cnt;
  301. /*
  302. * First open temporary, generated for source
  303. */
  304. if ((f1 = fopen(f_pars,"r")) == NULL) {
  305. fatal(0,e_noopen,f_pars, NULL);
  306. }
  307. /*
  308. * Now open target for reading
  309. */
  310. if ((f2 = fopen(target,"r")) == NULL) {
  311. fclose(f1);
  312. RENAME(f_pars, target);
  313. return;
  314. }
  315. /*
  316. * Compute length of LLgen identification string. The target must
  317. * start with that!
  318. */
  319. cnt = strlen(LLgenid) + strlen(source) - 2;
  320. /*
  321. * Now compare the target with the temporary
  322. */
  323. do {
  324. c1 = getc(f1);
  325. c2 = getc(f2);
  326. if (cnt >= 0) cnt--;
  327. } while (c1 == c2 && c1 != EOF);
  328. fclose(f1);
  329. fclose(f2);
  330. /*
  331. * Here, if c1 != c2 the target must be recreated
  332. */
  333. if (c1 != c2) {
  334. if (cnt >= 0) {
  335. fatal(0,"%s : not a file generated by LLgen",target, NULL);
  336. }
  337. RENAME(f_pars,target);
  338. }
  339. }