home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume19 / flex2 / part03 < prev    next >
Text File  |  1989-06-21  |  37KB  |  1,433 lines

  1. Subject:  v19i057:  Flex, a fast LEX replacement, Part03/07
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Vern Paxson <vern@csam.lbl.gov>
  7. Posting-number: Volume 19, Issue 57
  8. Archive-name: flex2/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 7)."
  17. # Contents:  flex/main.c flex/nfa.c
  18. # Wrapped by rsalz@prune.bbn.com on Thu Jun 22 19:01:46 1989
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'flex/main.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'flex/main.c'\"
  22. else
  23. echo shar: Extracting \"'flex/main.c'\" \(16556 characters\)
  24. sed "s/^X//" >'flex/main.c' <<'END_OF_FILE'
  25. X/* flex - tool to generate fast lexical analyzers
  26. X *
  27. X *
  28. X * Copyright (c) 1989 The Regents of the University of California.
  29. X * All rights reserved.
  30. X *
  31. X * This code is derived from software contributed to Berkeley by
  32. X * Vern Paxson.
  33. X * 
  34. X * The United States Government has rights in this work pursuant to
  35. X * contract no. DE-AC03-76SF00098 between the United States Department of
  36. X * Energy and the University of California.
  37. X *
  38. X * Redistribution and use in source and binary forms are permitted
  39. X * provided that the above copyright notice and this paragraph are
  40. X * duplicated in all such forms and that any documentation,
  41. X * advertising materials, and other materials related to such
  42. X * distribution and use acknowledge that the software was developed
  43. X * by the University of California, Berkeley.  The name of the
  44. X * University may not be used to endorse or promote products derived
  45. X * from this software without specific prior written permission.
  46. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  47. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  48. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  49. X *
  50. X */
  51. X
  52. X#ifndef lint
  53. X
  54. Xstatic char copyright[] =
  55. X    "@(#) Copyright (c) 1989 The Regents of the University of California.\n";
  56. Xstatic char CR_continuation[] = "@(#) All rights reserved.\n";
  57. X
  58. Xstatic char rcsid[] =
  59. X    "@(#) $Header: main.c,v 2.2 89/06/20 16:36:26 vern Exp $ (LBL)";
  60. X
  61. X#endif
  62. X
  63. X
  64. X#include "flexdef.h"
  65. X
  66. Xstatic char flex_version[] = "2.1 (beta)";
  67. X
  68. X
  69. X/* these globals are all defined and commented in flexdef.h */
  70. Xint printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
  71. Xint interactive, caseins, useecs, fulltbl, usemecs;
  72. Xint fullspd, gen_line_dirs, performance_report, backtrack_report;
  73. Xint yymore_used, reject, real_reject, continued_action;
  74. Xint yymore_really_used, reject_really_used;
  75. Xint datapos, dataline, linenum;
  76. XFILE *skelfile = NULL;
  77. Xchar *infilename = NULL;
  78. Xint onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
  79. Xint onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
  80. Xint current_mns, num_rules, current_max_rules, lastnfa;
  81. Xint *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
  82. Xint *accptnum, *assoc_rule, *state_type, *rule_type, *rule_linenum;
  83. Xint current_state_type;
  84. Xint variable_trailing_context_rules;
  85. Xint numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
  86. Xint protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
  87. Xint numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
  88. Xint tecbck[CSIZE + 1];
  89. Xint lastsc, current_max_scs, *scset, *scbol, *scxclu, *sceof, *actvsc;
  90. Xchar **scname;
  91. Xint current_max_dfa_size, current_max_xpairs;
  92. Xint current_max_template_xpairs, current_max_dfas;
  93. Xint lastdfa, *nxt, *chk, *tnxt;
  94. Xint *base, *def, tblend, firstfree, **dss, *dfasiz;
  95. Xunion dfaacc_union *dfaacc;
  96. Xint *accsiz, *dhash, numas;
  97. Xint numsnpairs, jambase, jamstate;
  98. Xint lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
  99. Xint current_max_ccl_tbl_size;
  100. Xchar *ccltbl;
  101. Xchar *starttime, *endtime, nmstr[MAXLINE];
  102. Xint sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
  103. Xint tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
  104. Xint num_backtracking, bol_needed;
  105. XFILE *temp_action_file;
  106. XFILE *backtrack_file;
  107. Xint end_of_buffer_state;
  108. X#ifndef SHORT_FILE_NAMES
  109. Xchar action_file_name[] = "/tmp/flexXXXXXX";
  110. X#else
  111. Xchar action_file_name[] = "flexXXXXXX.tmp";
  112. X#endif
  113. X
  114. X#ifndef SHORT_FILE_NAMES
  115. Xstatic char outfile[] = "lex.yy.c";
  116. X#else
  117. Xstatic char outfile[] = "lexyy.c";
  118. X#endif
  119. Xstatic int outfile_created = 0;
  120. X
  121. X
  122. X/* flex - main program
  123. X *
  124. X * synopsis (from the shell)
  125. X *    flex [-v] [file ...]
  126. X */
  127. X
  128. Xmain( argc, argv )
  129. Xint argc;
  130. Xchar **argv;
  131. X
  132. X    {
  133. X    flexinit( argc, argv );
  134. X
  135. X    readin();
  136. X
  137. X    if ( syntaxerror )
  138. X    flexend( 1 );
  139. X
  140. X    if ( yymore_really_used == REALLY_USED )
  141. X    yymore_used = true;
  142. X    else if ( yymore_really_used == REALLY_NOT_USED )
  143. X    yymore_used = false;
  144. X
  145. X    if ( reject_really_used == REALLY_USED )
  146. X    reject = true;
  147. X    else if ( reject_really_used == REALLY_NOT_USED )
  148. X    reject = false;
  149. X
  150. X    if ( performance_report )
  151. X    {
  152. X    if ( yymore_used )
  153. X        fprintf( stderr,
  154. X             "yymore() entails a minor performance penalty\n" );
  155. X
  156. X    if ( interactive )
  157. X        fprintf( stderr,
  158. X         "-I (interactive) entails a minor performance penalty\n" );
  159. X
  160. X    if ( reject )
  161. X        fprintf( stderr,
  162. X             "REJECT entails a large performance penalty\n" );
  163. X
  164. X    if ( variable_trailing_context_rules )
  165. X        fprintf( stderr,
  166. X"Variable trailing context rules entail a large performance penalty\n" );
  167. X    }
  168. X
  169. X    if ( reject )
  170. X    real_reject = true;
  171. X
  172. X    if ( variable_trailing_context_rules )
  173. X    reject = true;
  174. X
  175. X    if ( (fulltbl || fullspd) && reject )
  176. X    {
  177. X    if ( real_reject )
  178. X        flexerror( "REJECT cannot be used with -f or -F" );
  179. X    else
  180. X        flexerror(
  181. X    "variable trailing context rules cannot be used with -f or -F" );
  182. X    }
  183. X
  184. X    /* convert the ndfa to a dfa */
  185. X    ntod();
  186. X
  187. X    /* generate the C state transition tables from the DFA */
  188. X    make_tables();
  189. X
  190. X    /* note, flexend does not return.  It exits with its argument as status. */
  191. X
  192. X    flexend( 0 );
  193. X
  194. X    /*NOTREACHED*/
  195. X    }
  196. X
  197. X
  198. X/* flexend - terminate flex
  199. X *
  200. X * synopsis
  201. X *    int status;
  202. X *    flexend( status );
  203. X *
  204. X *    status is exit status.
  205. X *
  206. X * note
  207. X *    This routine does not return.
  208. X */
  209. X
  210. Xflexend( status )
  211. Xint status;
  212. X
  213. X    {
  214. X    int tblsiz;
  215. X    char *flex_gettime();
  216. X
  217. X    if ( skelfile != NULL )
  218. X    (void) fclose( skelfile );
  219. X
  220. X    if ( temp_action_file )
  221. X    {
  222. X    (void) fclose( temp_action_file );
  223. X    (void) unlink( action_file_name );
  224. X    }
  225. X
  226. X    if ( status != 0 && outfile_created )
  227. X    {
  228. X    (void) fclose( stdout );
  229. X    (void) unlink( outfile );
  230. X    }
  231. X
  232. X    if ( backtrack_report )
  233. X    {
  234. X    if ( num_backtracking == 0 )
  235. X        fprintf( backtrack_file, "No backtracking.\n" );
  236. X    else if ( fullspd || fulltbl )
  237. X        fprintf( backtrack_file,
  238. X             "%d backtracking (non-accepting) states.\n",
  239. X             num_backtracking );
  240. X    else
  241. X        fprintf( backtrack_file, "Compressed tables always backtrack.\n" );
  242. X
  243. X    (void) fclose( backtrack_file );
  244. X    }
  245. X
  246. X    if ( printstats )
  247. X    {
  248. X    endtime = flex_gettime();
  249. X
  250. X    fprintf( stderr, "flex version %s usage statistics:\n", flex_version );
  251. X    fprintf( stderr, "  started at %s, finished at %s\n",
  252. X         starttime, endtime );
  253. X
  254. X    fprintf( stderr, "  %d/%d NFA states\n", lastnfa, current_mns );
  255. X    fprintf( stderr, "  %d/%d DFA states (%d words)\n", lastdfa,
  256. X             current_max_dfas, totnst );
  257. X    fprintf( stderr, "  %d rules\n", num_rules - 1 /* - 1 for def. rule */ );
  258. X
  259. X    if ( num_backtracking == 0 )
  260. X        fprintf( stderr, "  No backtracking\n" );
  261. X    else if ( fullspd || fulltbl )
  262. X        fprintf( stderr, "  %d backtracking (non-accepting) states\n",
  263. X             num_backtracking );
  264. X    else
  265. X        fprintf( stderr, "  compressed tables always backtrack\n" );
  266. X
  267. X    if ( bol_needed )
  268. X        fprintf( stderr, "  Beginning-of-line patterns used\n" );
  269. X
  270. X    fprintf( stderr, "  %d/%d start conditions\n", lastsc,
  271. X             current_max_scs );
  272. X    fprintf( stderr, "  %d epsilon states, %d double epsilon states\n",
  273. X         numeps, eps2 );
  274. X
  275. X    if ( lastccl == 0 )
  276. X        fprintf( stderr, "  no character classes\n" );
  277. X    else
  278. X        fprintf( stderr,
  279. X    "  %d/%d character classes needed %d/%d words of storage, %d reused\n",
  280. X             lastccl, current_maxccls,
  281. X             cclmap[lastccl] + ccllen[lastccl],
  282. X             current_max_ccl_tbl_size, cclreuse );
  283. X
  284. X    fprintf( stderr, "  %d state/nextstate pairs created\n", numsnpairs );
  285. X    fprintf( stderr, "  %d/%d unique/duplicate transitions\n",
  286. X         numuniq, numdup );
  287. X
  288. X    if ( fulltbl )
  289. X        {
  290. X        tblsiz = lastdfa * numecs;
  291. X        fprintf( stderr, "  %d table entries\n", tblsiz );
  292. X        }
  293. X
  294. X    else
  295. X        {
  296. X        tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
  297. X
  298. X        fprintf( stderr, "  %d/%d base-def entries created\n",
  299. X             lastdfa + numtemps, current_max_dfas );
  300. X        fprintf( stderr, "  %d/%d (peak %d) nxt-chk entries created\n",
  301. X             tblend, current_max_xpairs, peakpairs );
  302. X        fprintf( stderr,
  303. X             "  %d/%d (peak %d) template nxt-chk entries created\n",
  304. X             numtemps * nummecs, current_max_template_xpairs,
  305. X             numtemps * numecs );
  306. X        fprintf( stderr, "  %d empty table entries\n", nummt );
  307. X        fprintf( stderr, "  %d protos created\n", numprots );
  308. X        fprintf( stderr, "  %d templates created, %d uses\n",
  309. X             numtemps, tmpuses );
  310. X        }
  311. X
  312. X    if ( useecs )
  313. X        {
  314. X        tblsiz = tblsiz + CSIZE;
  315. X        fprintf( stderr, "  %d/%d equivalence classes created\n",
  316. X             numecs, CSIZE );
  317. X        }
  318. X
  319. X    if ( usemecs )
  320. X        {
  321. X        tblsiz = tblsiz + numecs;
  322. X        fprintf( stderr, "  %d/%d meta-equivalence classes created\n",
  323. X             nummecs, CSIZE );
  324. X        }
  325. X
  326. X    fprintf( stderr, "  %d (%d saved) hash collisions, %d DFAs equal\n",
  327. X         hshcol, hshsave, dfaeql );
  328. X    fprintf( stderr, "  %d sets of reallocations needed\n", num_reallocs );
  329. X    fprintf( stderr, "  %d total table entries needed\n", tblsiz );
  330. X    }
  331. X
  332. X#ifndef VMS
  333. X    exit( status );
  334. X#else
  335. X    exit( status + 1 );
  336. X#endif
  337. X    }
  338. X
  339. X
  340. X/* flexinit - initialize flex
  341. X *
  342. X * synopsis
  343. X *    int argc;
  344. X *    char **argv;
  345. X *    flexinit( argc, argv );
  346. X */
  347. X
  348. Xflexinit( argc, argv )
  349. Xint argc;
  350. Xchar **argv;
  351. X
  352. X    {
  353. X    int i, sawcmpflag, use_stdout;
  354. X    char *arg, *skelname = NULL, *flex_gettime(), clower(), *mktemp();
  355. X
  356. X    printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
  357. X    backtrack_report = performance_report = ddebug = fulltbl = fullspd = false;
  358. X    yymore_used = continued_action = reject = false;
  359. X    yymore_really_used = reject_really_used = false;
  360. X    gen_line_dirs = usemecs = useecs = true;
  361. X
  362. X    sawcmpflag = false;
  363. X    use_stdout = false;
  364. X
  365. X    /* read flags */
  366. X    for ( --argc, ++argv; argc ; --argc, ++argv )
  367. X    {
  368. X    if ( argv[0][0] != '-' || argv[0][1] == '\0' )
  369. X        break;
  370. X
  371. X    arg = argv[0];
  372. X
  373. X    for ( i = 1; arg[i] != '\0'; ++i )
  374. X        switch ( arg[i] )
  375. X        {
  376. X        case 'b':
  377. X            backtrack_report = true;
  378. X            break;
  379. X
  380. X        case 'c':
  381. X            if ( i != 1 )
  382. X            flexerror( "-c flag must be given separately" );
  383. X
  384. X            if ( ! sawcmpflag )
  385. X            {
  386. X            useecs = false;
  387. X            usemecs = false;
  388. X            fulltbl = false;
  389. X            sawcmpflag = true;
  390. X            }
  391. X
  392. X            for ( ++i; arg[i] != '\0'; ++i )
  393. X            switch ( clower( arg[i] ) )
  394. X                {
  395. X                case 'e':
  396. X                useecs = true;
  397. X                break;
  398. X
  399. X                case 'F':
  400. X                fullspd = true;
  401. X                break;
  402. X
  403. X                case 'f':
  404. X                fulltbl = true;
  405. X                break;
  406. X
  407. X                case 'm':
  408. X                usemecs = true;
  409. X                break;
  410. X
  411. X                default:
  412. X                lerrif( "unknown -c option %c",
  413. X                    (int) arg[i] );
  414. X                break;
  415. X                }
  416. X            
  417. X            goto get_next_arg;
  418. X
  419. X        case 'd':
  420. X            ddebug = true;
  421. X            break;
  422. X
  423. X        case 'f':
  424. X            useecs = usemecs = false;
  425. X            fulltbl = true;
  426. X            break;
  427. X
  428. X        case 'F':
  429. X            useecs = usemecs = false;
  430. X            fullspd = true;
  431. X            break;
  432. X
  433. X        case 'I':
  434. X            interactive = true;
  435. X            break;
  436. X
  437. X        case 'i':
  438. X            caseins = true;
  439. X            break;
  440. X
  441. X        case 'L':
  442. X            gen_line_dirs = false;
  443. X            break;
  444. X
  445. X        case 'p':
  446. X            performance_report = true;
  447. X            break;
  448. X
  449. X        case 'S':
  450. X            if ( i != 1 )
  451. X            flexerror( "-S flag must be given separately" );
  452. X
  453. X            skelname = arg + i + 1;
  454. X            goto get_next_arg;
  455. X
  456. X        case 's':
  457. X            spprdflt = true;
  458. X            break;
  459. X
  460. X        case 't':
  461. X            use_stdout = true;
  462. X            break;
  463. X
  464. X        case 'T':
  465. X            trace = true;
  466. X            break;
  467. X
  468. X        case 'v':
  469. X            printstats = true;
  470. X            break;
  471. X
  472. X        default:
  473. X            lerrif( "unknown flag %c", (int) arg[i] );
  474. X            break;
  475. X        }
  476. X
  477. Xget_next_arg: /* used by -c and -S flags in lieu of a "continue 2" control */
  478. X    ;
  479. X    }
  480. X
  481. X    if ( (fulltbl || fullspd) && usemecs )
  482. X    flexerror( "full table and -cm don't make sense together" );
  483. X
  484. X    if ( (fulltbl || fullspd) && interactive )
  485. X    flexerror( "full table and -I are (currently) incompatible" );
  486. X
  487. X    if ( fulltbl && fullspd )
  488. X    flexerror( "full table and -F are mutually exclusive" );
  489. X
  490. X    if ( ! skelname )
  491. X    {
  492. X    static char skeleton_name_storage[400];
  493. X
  494. X    skelname = skeleton_name_storage;
  495. X    (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
  496. X    }
  497. X
  498. X    if ( ! use_stdout )
  499. X    {
  500. X    FILE *prev_stdout = freopen( outfile, "w", stdout );
  501. X
  502. X    if ( prev_stdout == NULL )
  503. X        flexerror( "could not create lex.yy.c" );
  504. X
  505. X    outfile_created = 1;
  506. X    }
  507. X
  508. X    if ( argc )
  509. X    {
  510. X    if ( argc > 1 )
  511. X        flexerror( "extraneous argument(s) given" );
  512. X
  513. X    yyin = fopen( infilename = argv[0], "r" );
  514. X
  515. X    if ( yyin == NULL )
  516. X        lerrsf( "can't open %s", argv[0] );
  517. X    }
  518. X
  519. X    else
  520. X    yyin = stdin;
  521. X
  522. X    if ( backtrack_report )
  523. X    {
  524. X#ifndef SHORT_FILE_NAMES
  525. X    backtrack_file = fopen( "lex.backtrack", "w" );
  526. X#else
  527. X    backtrack_file = fopen( "lex.bck", "w" );
  528. X#endif
  529. X
  530. X    if ( backtrack_file == NULL )
  531. X        flexerror( "could not create lex.backtrack" );
  532. X    }
  533. X
  534. X    else
  535. X    backtrack_file = NULL;
  536. X
  537. X
  538. X    lastccl = 0;
  539. X    lastsc = 0;
  540. X
  541. X    /* initialize the statistics */
  542. X    starttime = flex_gettime();
  543. X
  544. X    if ( (skelfile = fopen( skelname, "r" )) == NULL )
  545. X    lerrsf( "can't open skeleton file %s", skelname );
  546. X
  547. X    (void) mktemp( action_file_name );
  548. X
  549. X    if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
  550. X    lerrsf( "can't open temporary action file %s", action_file_name );
  551. X
  552. X    lastdfa = lastnfa = num_rules = numas = numsnpairs = tmpuses = 0;
  553. X    numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
  554. X    numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
  555. X    num_backtracking = onesp = numprots = 0;
  556. X    variable_trailing_context_rules = bol_needed = false;
  557. X
  558. X    linenum = sectnum = 1;
  559. X    firstprot = NIL;
  560. X
  561. X    /* used in mkprot() so that the first proto goes in slot 1
  562. X     * of the proto queue
  563. X     */
  564. X    lastprot = 1;
  565. X
  566. X    if ( useecs )
  567. X    {
  568. X    /* set up doubly-linked equivalence classes */
  569. X    ecgroup[1] = NIL;
  570. X
  571. X    for ( i = 2; i <= CSIZE; ++i )
  572. X        {
  573. X        ecgroup[i] = i - 1;
  574. X        nextecm[i - 1] = i;
  575. X        }
  576. X
  577. X    nextecm[CSIZE] = NIL;
  578. X    }
  579. X
  580. X    else
  581. X    { /* put everything in its own equivalence class */
  582. X    for ( i = 1; i <= CSIZE; ++i )
  583. X        {
  584. X        ecgroup[i] = i;
  585. X        nextecm[i] = BAD_SUBSCRIPT;    /* to catch errors */
  586. X        }
  587. X    }
  588. X
  589. X    set_up_initial_allocations();
  590. X    }
  591. X
  592. X
  593. X/* readin - read in the rules section of the input file(s)
  594. X *
  595. X * synopsis
  596. X *    readin();
  597. X */
  598. X
  599. Xreadin()
  600. X
  601. X    {
  602. X    if ( ddebug )
  603. X    puts( "#define FLEX_DEBUG" );
  604. X
  605. X    if ( fulltbl )
  606. X    puts( "#define FLEX_FULL_TABLE" );
  607. X    else if ( fullspd )
  608. X    puts( "#define FLEX_FAST_COMPRESSED" );
  609. X    else
  610. X    puts( "#define FLEX_COMPRESSED" );
  611. X
  612. X    skelout();
  613. X
  614. X    line_directive_out( stdout );
  615. X
  616. X    if ( yyparse() )
  617. X    lerrif( "fatal parse error at line %d", linenum );
  618. X
  619. X    if ( useecs )
  620. X    {
  621. X    numecs = cre8ecs( nextecm, ecgroup, CSIZE );
  622. X    ccl2ecl();
  623. X    }
  624. X
  625. X    else
  626. X    numecs = CSIZE;
  627. X
  628. X    }
  629. X
  630. X
  631. X
  632. X/* set_up_initial_allocations - allocate memory for internal tables */
  633. X
  634. Xset_up_initial_allocations()
  635. X
  636. X    {
  637. X    current_mns = INITIAL_MNS;
  638. X    firstst = allocate_integer_array( current_mns );
  639. X    lastst = allocate_integer_array( current_mns );
  640. X    finalst = allocate_integer_array( current_mns );
  641. X    transchar = allocate_integer_array( current_mns );
  642. X    trans1 = allocate_integer_array( current_mns );
  643. X    trans2 = allocate_integer_array( current_mns );
  644. X    accptnum = allocate_integer_array( current_mns );
  645. X    assoc_rule = allocate_integer_array( current_mns );
  646. X    state_type = allocate_integer_array( current_mns );
  647. X
  648. X    current_max_rules = INITIAL_MAX_RULES;
  649. X    rule_type = allocate_integer_array( current_max_rules );
  650. X    rule_linenum = allocate_integer_array( current_max_rules );
  651. X
  652. X    current_max_scs = INITIAL_MAX_SCS;
  653. X    scset = allocate_integer_array( current_max_scs );
  654. X    scbol = allocate_integer_array( current_max_scs );
  655. X    scxclu = allocate_integer_array( current_max_scs );
  656. X    sceof = allocate_integer_array( current_max_scs );
  657. X    scname = allocate_char_ptr_array( current_max_scs );
  658. X    actvsc = allocate_integer_array( current_max_scs );
  659. X
  660. X    current_maxccls = INITIAL_MAX_CCLS;
  661. X    cclmap = allocate_integer_array( current_maxccls );
  662. X    ccllen = allocate_integer_array( current_maxccls );
  663. X    cclng = allocate_integer_array( current_maxccls );
  664. X
  665. X    current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
  666. X    ccltbl = allocate_character_array( current_max_ccl_tbl_size );
  667. X
  668. X    current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
  669. X
  670. X    current_max_xpairs = INITIAL_MAX_XPAIRS;
  671. X    nxt = allocate_integer_array( current_max_xpairs );
  672. X    chk = allocate_integer_array( current_max_xpairs );
  673. X
  674. X    current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
  675. X    tnxt = allocate_integer_array( current_max_template_xpairs );
  676. X
  677. X    current_max_dfas = INITIAL_MAX_DFAS;
  678. X    base = allocate_integer_array( current_max_dfas );
  679. X    def = allocate_integer_array( current_max_dfas );
  680. X    dfasiz = allocate_integer_array( current_max_dfas );
  681. X    accsiz = allocate_integer_array( current_max_dfas );
  682. X    dhash = allocate_integer_array( current_max_dfas );
  683. X    dss = allocate_int_ptr_array( current_max_dfas );
  684. X    dfaacc = allocate_dfaacc_union( current_max_dfas );
  685. X    }
  686. END_OF_FILE
  687. if test 16556 -ne `wc -c <'flex/main.c'`; then
  688.     echo shar: \"'flex/main.c'\" unpacked with wrong size!
  689. fi
  690. # end of 'flex/main.c'
  691. fi
  692. if test -f 'flex/nfa.c' -a "${1}" != "-c" ; then 
  693.   echo shar: Will not clobber existing file \"'flex/nfa.c'\"
  694. else
  695. echo shar: Extracting \"'flex/nfa.c'\" \(17293 characters\)
  696. sed "s/^X//" >'flex/nfa.c' <<'END_OF_FILE'
  697. X/* nfa - NFA construction routines */
  698. X
  699. X/*
  700. X * Copyright (c) 1989 The Regents of the University of California.
  701. X * All rights reserved.
  702. X *
  703. X * This code is derived from software contributed to Berkeley by
  704. X * Vern Paxson.
  705. X * 
  706. X * The United States Government has rights in this work pursuant to
  707. X * contract no. DE-AC03-76SF00098 between the United States Department of
  708. X * Energy and the University of California.
  709. X *
  710. X * Redistribution and use in source and binary forms are permitted
  711. X * provided that the above copyright notice and this paragraph are
  712. X * duplicated in all such forms and that any documentation,
  713. X * advertising materials, and other materials related to such
  714. X * distribution and use acknowledge that the software was developed
  715. X * by the University of California, Berkeley.  The name of the
  716. X * University may not be used to endorse or promote products derived
  717. X * from this software without specific prior written permission.
  718. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  719. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  720. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  721. X */
  722. X
  723. X#ifndef lint
  724. X
  725. Xstatic char copyright[] =
  726. X    "@(#) Copyright (c) 1989 The Regents of the University of California.\n";
  727. Xstatic char CR_continuation[] = "@(#) All rights reserved.\n";
  728. X
  729. Xstatic char rcsid[] =
  730. X    "@(#) $Header: nfa.c,v 2.0 89/06/20 15:50:05 vern Locked $ (LBL)";
  731. X
  732. X#endif
  733. X
  734. X#include "flexdef.h"
  735. X
  736. X/* add_accept - add an accepting state to a machine
  737. X *
  738. X * synopsis
  739. X *
  740. X *   add_accept( mach, accepting_number );
  741. X *
  742. X * accepting_number becomes mach's accepting number.
  743. X */
  744. X
  745. Xadd_accept( mach, accepting_number )
  746. Xint mach;
  747. X
  748. X    {
  749. X    /* hang the accepting number off an epsilon state.  if it is associated
  750. X     * with a state that has a non-epsilon out-transition, then the state
  751. X     * will accept BEFORE it makes that transition, i.e., one character
  752. X     * too soon
  753. X     */
  754. X
  755. X    if ( transchar[finalst[mach]] == SYM_EPSILON )
  756. X    accptnum[finalst[mach]] = accepting_number;
  757. X
  758. X    else
  759. X    {
  760. X    int astate = mkstate( SYM_EPSILON );
  761. X    accptnum[astate] = accepting_number;
  762. X    mach = link_machines( mach, astate );
  763. X    }
  764. X    }
  765. X
  766. X
  767. X/* copysingl - make a given number of copies of a singleton machine
  768. X *
  769. X * synopsis
  770. X *
  771. X *   newsng = copysingl( singl, num );
  772. X *
  773. X *     newsng - a new singleton composed of num copies of singl
  774. X *     singl  - a singleton machine
  775. X *     num    - the number of copies of singl to be present in newsng
  776. X */
  777. X
  778. Xint copysingl( singl, num )
  779. Xint singl, num;
  780. X
  781. X    {
  782. X    int copy, i;
  783. X
  784. X    copy = mkstate( SYM_EPSILON );
  785. X
  786. X    for ( i = 1; i <= num; ++i )
  787. X    copy = link_machines( copy, dupmachine( singl ) );
  788. X
  789. X    return ( copy );
  790. X    }
  791. X
  792. X
  793. X/* dumpnfa - debugging routine to write out an nfa
  794. X *
  795. X * synopsis
  796. X *    int state1;
  797. X *    dumpnfa( state1 );
  798. X */
  799. X
  800. Xdumpnfa( state1 )
  801. Xint state1;
  802. X
  803. X    {
  804. X    int sym, tsp1, tsp2, anum, ns;
  805. X
  806. X    fprintf( stderr, "\n\n********** beginning dump of nfa with start state %d\n",
  807. X         state1 );
  808. X
  809. X    /* we probably should loop starting at firstst[state1] and going to
  810. X     * lastst[state1], but they're not maintained properly when we "or"
  811. X     * all of the rules together.  So we use our knowledge that the machine
  812. X     * starts at state 1 and ends at lastnfa.
  813. X     */
  814. X
  815. X    /* for ( ns = firstst[state1]; ns <= lastst[state1]; ++ns ) */
  816. X    for ( ns = 1; ns <= lastnfa; ++ns )
  817. X    {
  818. X    fprintf( stderr, "state # %4d\t", ns );
  819. X
  820. X    sym = transchar[ns];
  821. X    tsp1 = trans1[ns];
  822. X    tsp2 = trans2[ns];
  823. X    anum = accptnum[ns];
  824. X
  825. X    fprintf( stderr, "%3d:  %4d, %4d", sym, tsp1, tsp2 );
  826. X
  827. X    if ( anum != NIL )
  828. X        fprintf( stderr, "  [%d]", anum );
  829. X
  830. X    fprintf( stderr, "\n" );
  831. X    }
  832. X
  833. X    fprintf( stderr, "********** end of dump\n" );
  834. X    }
  835. X
  836. X
  837. X/* dupmachine - make a duplicate of a given machine
  838. X *
  839. X * synopsis
  840. X *
  841. X *   copy = dupmachine( mach );
  842. X *
  843. X *     copy - holds duplicate of mach
  844. X *     mach - machine to be duplicated
  845. X *
  846. X * note that the copy of mach is NOT an exact duplicate; rather, all the
  847. X * transition states values are adjusted so that the copy is self-contained,
  848. X * as the original should have been.
  849. X *
  850. X * also note that the original MUST be contiguous, with its low and high
  851. X * states accessible by the arrays firstst and lastst
  852. X */
  853. X
  854. Xint dupmachine( mach )
  855. Xint mach;
  856. X
  857. X    {
  858. X    int i, init, state_offset;
  859. X    int state = 0;
  860. X    int last = lastst[mach];
  861. X
  862. X    for ( i = firstst[mach]; i <= last; ++i )
  863. X    {
  864. X    state = mkstate( transchar[i] );
  865. X
  866. X    if ( trans1[i] != NO_TRANSITION )
  867. X        {
  868. X        mkxtion( finalst[state], trans1[i] + state - i );
  869. X
  870. X        if ( transchar[i] == SYM_EPSILON && trans2[i] != NO_TRANSITION )
  871. X        mkxtion( finalst[state], trans2[i] + state - i );
  872. X        }
  873. X
  874. X    accptnum[state] = accptnum[i];
  875. X    }
  876. X
  877. X    if ( state == 0 )
  878. X    flexfatal( "empty machine in dupmachine()" );
  879. X
  880. X    state_offset = state - i + 1;
  881. X
  882. X    init = mach + state_offset;
  883. X    firstst[init] = firstst[mach] + state_offset;
  884. X    finalst[init] = finalst[mach] + state_offset;
  885. X    lastst[init] = lastst[mach] + state_offset;
  886. X
  887. X    return ( init );
  888. X    }
  889. X
  890. X/* finish_rule - finish up the processing for a rule
  891. X *
  892. X * synopsis
  893. X *
  894. X *   finish_rule( mach, variable_trail_rule, headcnt, trailcnt );
  895. X *
  896. X * An accepting number is added to the given machine.  If variable_trail_rule
  897. X * is true then the rule has trailing context and both the head and trail
  898. X * are variable size.  Otherwise if headcnt or trailcnt is non-zero then
  899. X * the machine recognizes a pattern with trailing context and headcnt is
  900. X * the number of characters in the matched part of the pattern, or zero
  901. X * if the matched part has variable length.  trailcnt is the number of
  902. X * trailing context characters in the pattern, or zero if the trailing
  903. X * context has variable length.
  904. X */
  905. X
  906. Xfinish_rule( mach, variable_trail_rule, headcnt, trailcnt )
  907. Xint mach, variable_trail_rule, headcnt, trailcnt;
  908. X
  909. X    {
  910. X    add_accept( mach, num_rules );
  911. X
  912. X    /* we did this in new_rule(), but it often gets the wrong
  913. X     * number because we do it before we start parsing the current rule
  914. X     */
  915. X    rule_linenum[num_rules] = linenum;
  916. X
  917. X    fprintf( temp_action_file, "case %d:\n", num_rules );
  918. X
  919. X    if ( variable_trail_rule )
  920. X    {
  921. X    rule_type[num_rules] = RULE_VARIABLE;
  922. X
  923. X    if ( performance_report )
  924. X        fprintf( stderr, "Variable trailing context rule at line %d\n",
  925. X             rule_linenum[num_rules] );
  926. X
  927. X    variable_trailing_context_rules = true;
  928. X    }
  929. X
  930. X    else
  931. X    {
  932. X    rule_type[num_rules] = RULE_NORMAL;
  933. X
  934. X    if ( headcnt > 0 || trailcnt > 0 )
  935. X        {
  936. X        /* do trailing context magic to not match the trailing characters */
  937. X        char *scanner_cp = "yy_c_buf_p = yy_cp";
  938. X        char *scanner_bp = "yy_bp";
  939. X
  940. X        fprintf( temp_action_file,
  941. X    "*yy_cp = yy_hold_char; /* undo effects of setting up yytext */\n" );
  942. X
  943. X        if ( headcnt > 0 )
  944. X        {
  945. X        if ( headcnt > 0 )
  946. X            fprintf( temp_action_file, "%s = %s + %d;\n",
  947. X                 scanner_cp, scanner_bp, headcnt );
  948. X
  949. X        else
  950. X            fprintf( temp_action_file, "%s = %s;\n",
  951. X                 scanner_cp, scanner_bp );
  952. X        }
  953. X
  954. X        else
  955. X        fprintf( temp_action_file,
  956. X             "%s -= %d;\n", scanner_cp, trailcnt );
  957. X    
  958. X        fprintf( temp_action_file,
  959. X             "YY_DO_BEFORE_ACTION; /* set up yytext again */\n" );
  960. X        }
  961. X    }
  962. X
  963. X    line_directive_out( temp_action_file );
  964. X    }
  965. X
  966. X
  967. X/* link_machines - connect two machines together
  968. X *
  969. X * synopsis
  970. X *
  971. X *   new = link_machines( first, last );
  972. X *
  973. X *     new    - a machine constructed by connecting first to last
  974. X *     first  - the machine whose successor is to be last
  975. X *     last   - the machine whose predecessor is to be first
  976. X *
  977. X * note: this routine concatenates the machine first with the machine
  978. X *  last to produce a machine new which will pattern-match first first
  979. X *  and then last, and will fail if either of the sub-patterns fails.
  980. X *  FIRST is set to new by the operation.  last is unmolested.
  981. X */
  982. X
  983. Xint link_machines( first, last )
  984. Xint first, last;
  985. X
  986. X    {
  987. X    if ( first == NIL )
  988. X    return ( last );
  989. X
  990. X    else if ( last == NIL )
  991. X    return ( first );
  992. X
  993. X    else
  994. X    {
  995. X    mkxtion( finalst[first], last );
  996. X    finalst[first] = finalst[last];
  997. X    lastst[first] = max( lastst[first], lastst[last] );
  998. X    firstst[first] = min( firstst[first], firstst[last] );
  999. X
  1000. X    return ( first );
  1001. X    }
  1002. X    }
  1003. X
  1004. X
  1005. X/* mark_beginning_as_normal - mark each "beginning" state in a machine
  1006. X *                            as being a "normal" (i.e., not trailing context-
  1007. X *                            associated) states
  1008. X *
  1009. X * synopsis
  1010. X *
  1011. X *   mark_beginning_as_normal( mach )
  1012. X *
  1013. X *     mach - machine to mark
  1014. X *
  1015. X * The "beginning" states are the epsilon closure of the first state
  1016. X */
  1017. X
  1018. Xmark_beginning_as_normal( mach )
  1019. Xregister int mach;
  1020. X
  1021. X    {
  1022. X    switch ( state_type[mach] )
  1023. X    {
  1024. X    case STATE_NORMAL:
  1025. X        /* oh, we've already visited here */
  1026. X        return;
  1027. X
  1028. X    case STATE_TRAILING_CONTEXT:
  1029. X        state_type[mach] = STATE_NORMAL;
  1030. X
  1031. X        if ( transchar[mach] == SYM_EPSILON )
  1032. X        {
  1033. X        if ( trans1[mach] != NO_TRANSITION )
  1034. X            mark_beginning_as_normal( trans1[mach] );
  1035. X
  1036. X        if ( trans2[mach] != NO_TRANSITION )
  1037. X            mark_beginning_as_normal( trans2[mach] );
  1038. X        }
  1039. X        break;
  1040. X
  1041. X    default:
  1042. X        flexerror( "bad state type in mark_beginning_as_normal()" );
  1043. X        break;
  1044. X    }
  1045. X    }
  1046. X
  1047. X
  1048. X/* mkbranch - make a machine that branches to two machines
  1049. X *
  1050. X * synopsis
  1051. X *
  1052. X *   branch = mkbranch( first, second );
  1053. X *
  1054. X *     branch - a machine which matches either first's pattern or second's
  1055. X *     first, second - machines whose patterns are to be or'ed (the | operator)
  1056. X *
  1057. X * note that first and second are NEITHER destroyed by the operation.  Also,
  1058. X * the resulting machine CANNOT be used with any other "mk" operation except
  1059. X * more mkbranch's.  Compare with mkor()
  1060. X */
  1061. X
  1062. Xint mkbranch( first, second )
  1063. Xint first, second;
  1064. X
  1065. X    {
  1066. X    int eps;
  1067. X
  1068. X    if ( first == NO_TRANSITION )
  1069. X    return ( second );
  1070. X
  1071. X    else if ( second == NO_TRANSITION )
  1072. X    return ( first );
  1073. X
  1074. X    eps = mkstate( SYM_EPSILON );
  1075. X
  1076. X    mkxtion( eps, first );
  1077. X    mkxtion( eps, second );
  1078. X
  1079. X    return ( eps );
  1080. X    }
  1081. X
  1082. X
  1083. X/* mkclos - convert a machine into a closure
  1084. X *
  1085. X * synopsis
  1086. X *   new = mkclos( state );
  1087. X *
  1088. X *     new - a new state which matches the closure of "state"
  1089. X */
  1090. X
  1091. Xint mkclos( state )
  1092. Xint state;
  1093. X
  1094. X    {
  1095. X    return ( mkopt( mkposcl( state ) ) );
  1096. X    }
  1097. X
  1098. X
  1099. X/* mkopt - make a machine optional
  1100. X *
  1101. X * synopsis
  1102. X *
  1103. X *   new = mkopt( mach );
  1104. X *
  1105. X *     new  - a machine which optionally matches whatever mach matched
  1106. X *     mach - the machine to make optional
  1107. X *
  1108. X * notes:
  1109. X *     1. mach must be the last machine created
  1110. X *     2. mach is destroyed by the call
  1111. X */
  1112. X
  1113. Xint mkopt( mach )
  1114. Xint mach;
  1115. X
  1116. X    {
  1117. X    int eps;
  1118. X
  1119. X    if ( ! SUPER_FREE_EPSILON(finalst[mach]) )
  1120. X    {
  1121. X    eps = mkstate( SYM_EPSILON );
  1122. X    mach = link_machines( mach, eps );
  1123. X    }
  1124. X
  1125. X    /* can't skimp on the following if FREE_EPSILON(mach) is true because
  1126. X     * some state interior to "mach" might point back to the beginning
  1127. X     * for a closure
  1128. X     */
  1129. X    eps = mkstate( SYM_EPSILON );
  1130. X    mach = link_machines( eps, mach );
  1131. X
  1132. X    mkxtion( mach, finalst[mach] );
  1133. X
  1134. X    return ( mach );
  1135. X    }
  1136. X
  1137. X
  1138. X/* mkor - make a machine that matches either one of two machines
  1139. X *
  1140. X * synopsis
  1141. X *
  1142. X *   new = mkor( first, second );
  1143. X *
  1144. X *     new - a machine which matches either first's pattern or second's
  1145. X *     first, second - machines whose patterns are to be or'ed (the | operator)
  1146. X *
  1147. X * note that first and second are both destroyed by the operation
  1148. X * the code is rather convoluted because an attempt is made to minimize
  1149. X * the number of epsilon states needed
  1150. X */
  1151. X
  1152. Xint mkor( first, second )
  1153. Xint first, second;
  1154. X
  1155. X    {
  1156. X    int eps, orend;
  1157. X
  1158. X    if ( first == NIL )
  1159. X    return ( second );
  1160. X
  1161. X    else if ( second == NIL )
  1162. X    return ( first );
  1163. X
  1164. X    else
  1165. X    {
  1166. X    /* see comment in mkopt() about why we can't use the first state
  1167. X     * of "first" or "second" if they satisfy "FREE_EPSILON"
  1168. X     */
  1169. X    eps = mkstate( SYM_EPSILON );
  1170. X
  1171. X    first = link_machines( eps, first );
  1172. X
  1173. X    mkxtion( first, second );
  1174. X
  1175. X    if ( SUPER_FREE_EPSILON(finalst[first]) &&
  1176. X         accptnum[finalst[first]] == NIL )
  1177. X        {
  1178. X        orend = finalst[first];
  1179. X        mkxtion( finalst[second], orend );
  1180. X        }
  1181. X
  1182. X    else if ( SUPER_FREE_EPSILON(finalst[second]) &&
  1183. X          accptnum[finalst[second]] == NIL )
  1184. X        {
  1185. X        orend = finalst[second];
  1186. X        mkxtion( finalst[first], orend );
  1187. X        }
  1188. X
  1189. X    else
  1190. X        {
  1191. X        eps = mkstate( SYM_EPSILON );
  1192. X
  1193. X        first = link_machines( first, eps );
  1194. X        orend = finalst[first];
  1195. X
  1196. X        mkxtion( finalst[second], orend );
  1197. X        }
  1198. X    }
  1199. X
  1200. X    finalst[first] = orend;
  1201. X    return ( first );
  1202. X    }
  1203. X
  1204. X
  1205. X/* mkposcl - convert a machine into a positive closure
  1206. X *
  1207. X * synopsis
  1208. X *   new = mkposcl( state );
  1209. X *
  1210. X *    new - a machine matching the positive closure of "state"
  1211. X */
  1212. X
  1213. Xint mkposcl( state )
  1214. Xint state;
  1215. X
  1216. X    {
  1217. X    int eps;
  1218. X
  1219. X    if ( SUPER_FREE_EPSILON(finalst[state]) )
  1220. X    {
  1221. X    mkxtion( finalst[state], state );
  1222. X    return ( state );
  1223. X    }
  1224. X
  1225. X    else
  1226. X    {
  1227. X    eps = mkstate( SYM_EPSILON );
  1228. X    mkxtion( eps, state );
  1229. X    return ( link_machines( state, eps ) );
  1230. X    }
  1231. X    }
  1232. X
  1233. X
  1234. X/* mkrep - make a replicated machine
  1235. X *
  1236. X * synopsis
  1237. X *   new = mkrep( mach, lb, ub );
  1238. X *
  1239. X *    new - a machine that matches whatever "mach" matched from "lb"
  1240. X *          number of times to "ub" number of times
  1241. X *
  1242. X * note
  1243. X *   if "ub" is INFINITY then "new" matches "lb" or more occurrences of "mach"
  1244. X */
  1245. X
  1246. Xint mkrep( mach, lb, ub )
  1247. Xint mach, lb, ub;
  1248. X
  1249. X    {
  1250. X    int base_mach, tail, copy, i;
  1251. X
  1252. X    base_mach = copysingl( mach, lb - 1 );
  1253. X
  1254. X    if ( ub == INFINITY )
  1255. X    {
  1256. X    copy = dupmachine( mach );
  1257. X    mach = link_machines( mach,
  1258. X                  link_machines( base_mach, mkclos( copy ) ) );
  1259. X    }
  1260. X
  1261. X    else
  1262. X    {
  1263. X    tail = mkstate( SYM_EPSILON );
  1264. X
  1265. X    for ( i = lb; i < ub; ++i )
  1266. X        {
  1267. X        copy = dupmachine( mach );
  1268. X        tail = mkopt( link_machines( copy, tail ) );
  1269. X        }
  1270. X
  1271. X    mach = link_machines( mach, link_machines( base_mach, tail ) );
  1272. X    }
  1273. X
  1274. X    return ( mach );
  1275. X    }
  1276. X
  1277. X
  1278. X/* mkstate - create a state with a transition on a given symbol
  1279. X *
  1280. X * synopsis
  1281. X *
  1282. X *   state = mkstate( sym );
  1283. X *
  1284. X *     state - a new state matching sym
  1285. X *     sym   - the symbol the new state is to have an out-transition on
  1286. X *
  1287. X * note that this routine makes new states in ascending order through the
  1288. X * state array (and increments LASTNFA accordingly).  The routine DUPMACHINE
  1289. X * relies on machines being made in ascending order and that they are
  1290. X * CONTIGUOUS.  Change it and you will have to rewrite DUPMACHINE (kludge
  1291. X * that it admittedly is)
  1292. X */
  1293. X
  1294. Xint mkstate( sym )
  1295. Xint sym;
  1296. X
  1297. X    {
  1298. X    if ( ++lastnfa >= current_mns )
  1299. X    {
  1300. X    if ( (current_mns += MNS_INCREMENT) >= MAXIMUM_MNS )
  1301. X        lerrif( "input rules are too complicated (>= %d NFA states)",
  1302. X            current_mns );
  1303. X    
  1304. X    ++num_reallocs;
  1305. X
  1306. X    firstst = reallocate_integer_array( firstst, current_mns );
  1307. X    lastst = reallocate_integer_array( lastst, current_mns );
  1308. X    finalst = reallocate_integer_array( finalst, current_mns );
  1309. X    transchar = reallocate_integer_array( transchar, current_mns );
  1310. X    trans1 = reallocate_integer_array( trans1, current_mns );
  1311. X    trans2 = reallocate_integer_array( trans2, current_mns );
  1312. X    accptnum = reallocate_integer_array( accptnum, current_mns );
  1313. X    assoc_rule = reallocate_integer_array( assoc_rule, current_mns );
  1314. X    state_type = reallocate_integer_array( state_type, current_mns );
  1315. X    }
  1316. X
  1317. X    firstst[lastnfa] = lastnfa;
  1318. X    finalst[lastnfa] = lastnfa;
  1319. X    lastst[lastnfa] = lastnfa;
  1320. X    transchar[lastnfa] = sym;
  1321. X    trans1[lastnfa] = NO_TRANSITION;
  1322. X    trans2[lastnfa] = NO_TRANSITION;
  1323. X    accptnum[lastnfa] = NIL;
  1324. X    assoc_rule[lastnfa] = num_rules;
  1325. X    state_type[lastnfa] = current_state_type;
  1326. X
  1327. X    /* fix up equivalence classes base on this transition.  Note that any
  1328. X     * character which has its own transition gets its own equivalence class.
  1329. X     * Thus only characters which are only in character classes have a chance
  1330. X     * at being in the same equivalence class.  E.g. "a|b" puts 'a' and 'b'
  1331. X     * into two different equivalence classes.  "[ab]" puts them in the same
  1332. X     * equivalence class (barring other differences elsewhere in the input).
  1333. X     */
  1334. X
  1335. X    if ( sym < 0 )
  1336. X    {
  1337. X    /* we don't have to update the equivalence classes since that was
  1338. X     * already done when the ccl was created for the first time
  1339. X     */
  1340. X    }
  1341. X
  1342. X    else if ( sym == SYM_EPSILON )
  1343. X    ++numeps;
  1344. X
  1345. X    else
  1346. X    {
  1347. X    if ( useecs )
  1348. X        mkechar( sym, nextecm, ecgroup );
  1349. X    }
  1350. X
  1351. X    return ( lastnfa );
  1352. X    }
  1353. X
  1354. X
  1355. X/* mkxtion - make a transition from one state to another
  1356. X *
  1357. X * synopsis
  1358. X *
  1359. X *   mkxtion( statefrom, stateto );
  1360. X *
  1361. X *     statefrom - the state from which the transition is to be made
  1362. X *     stateto   - the state to which the transition is to be made
  1363. X */
  1364. X
  1365. Xmkxtion( statefrom, stateto )
  1366. Xint statefrom, stateto;
  1367. X
  1368. X    {
  1369. X    if ( trans1[statefrom] == NO_TRANSITION )
  1370. X    trans1[statefrom] = stateto;
  1371. X
  1372. X    else if ( (transchar[statefrom] != SYM_EPSILON) ||
  1373. X          (trans2[statefrom] != NO_TRANSITION) )
  1374. X    flexfatal( "found too many transitions in mkxtion()" );
  1375. X
  1376. X    else
  1377. X    { /* second out-transition for an epsilon state */
  1378. X    ++eps2;
  1379. X    trans2[statefrom] = stateto;
  1380. X    }
  1381. X    }
  1382. X
  1383. X/* new_rule - initialize for a new rule
  1384. X *
  1385. X * synopsis
  1386. X *
  1387. X *   new_rule();
  1388. X *
  1389. X * the global num_rules is incremented and the any corresponding dynamic
  1390. X * arrays (such as rule_type[]) are grown as needed.
  1391. X */
  1392. X
  1393. Xnew_rule()
  1394. X
  1395. X    {
  1396. X    if ( ++num_rules >= current_max_rules )
  1397. X    {
  1398. X    ++num_reallocs;
  1399. X    current_max_rules += MAX_RULES_INCREMENT;
  1400. X    rule_type = reallocate_integer_array( rule_type, current_max_rules );
  1401. X    rule_linenum =
  1402. X        reallocate_integer_array( rule_linenum, current_max_rules );
  1403. X    }
  1404. X
  1405. X    if ( num_rules > MAX_RULE )
  1406. X    lerrif( "too many rules (> %d)!", MAX_RULE );
  1407. X
  1408. X    rule_linenum[num_rules] = linenum;
  1409. X    }
  1410. END_OF_FILE
  1411. if test 17293 -ne `wc -c <'flex/nfa.c'`; then
  1412.     echo shar: \"'flex/nfa.c'\" unpacked with wrong size!
  1413. fi
  1414. # end of 'flex/nfa.c'
  1415. fi
  1416. echo shar: End of archive 3 \(of 7\).
  1417. cp /dev/null ark3isdone
  1418. MISSING=""
  1419. for I in 1 2 3 4 5 6 7 ; do
  1420.     if test ! -f ark${I}isdone ; then
  1421.     MISSING="${MISSING} ${I}"
  1422.     fi
  1423. done
  1424. if test "${MISSING}" = "" ; then
  1425.     echo You have unpacked all 7 archives.
  1426.     rm -f ark[1-9]isdone
  1427. else
  1428.     echo You still need to unpack the following archives:
  1429.     echo "        " ${MISSING}
  1430. fi
  1431. ##  End of shell archive.
  1432. exit 0
  1433.