Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

925 lines
25 KiB

4 years ago
  1. /* tblcmp - table compression routines */
  2. /*-
  3. * Copyright (c) 1990 The Regents of the University of California.
  4. * All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Vern Paxson.
  8. *
  9. * The United States Government has rights in this work pursuant
  10. * to contract no. DE-AC03-76SF00098 between the United States
  11. * Department of Energy and the University of California.
  12. *
  13. * Redistribution and use in source and binary forms are permitted provided
  14. * that: (1) source distributions retain this entire copyright notice and
  15. * comment, and (2) distributions including binaries display the following
  16. * acknowledgement: ``This product includes software developed by the
  17. * University of California, Berkeley and its contributors'' in the
  18. * documentation or other materials provided with the distribution and in
  19. * all advertising materials mentioning features or use of this software.
  20. * Neither the name of the University nor the names of its contributors may
  21. * be used to endorse or promote products derived from this software without
  22. * specific prior written permission.
  23. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  24. * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  25. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  26. */
  27. #ifndef lint
  28. static char rcsid[] =
  29. "@(#) $Header: /usr/fsys/odin/a/vern/flex/RCS/tblcmp.c,v 2.5 90/06/27 23:48:38 vern Exp $ (LBL)";
  30. #endif
  31. #include "flexdef.h"
  32. /* declarations for functions that have forward references */
  33. void mkentry PROTO((register int*, int, int, int, int));
  34. void mkprot PROTO((int[], int, int));
  35. void mktemplate PROTO((int[], int, int));
  36. void mv2front PROTO((int));
  37. int tbldiff PROTO((int[], int, int[]));
  38. /* bldtbl - build table entries for dfa state
  39. *
  40. * synopsis
  41. * int state[numecs], statenum, totaltrans, comstate, comfreq;
  42. * bldtbl( state, statenum, totaltrans, comstate, comfreq );
  43. *
  44. * State is the statenum'th dfa state. It is indexed by equivalence class and
  45. * gives the number of the state to enter for a given equivalence class.
  46. * totaltrans is the total number of transitions out of the state. Comstate
  47. * is that state which is the destination of the most transitions out of State.
  48. * Comfreq is how many transitions there are out of State to Comstate.
  49. *
  50. * A note on terminology:
  51. * "protos" are transition tables which have a high probability of
  52. * either being redundant (a state processed later will have an identical
  53. * transition table) or nearly redundant (a state processed later will have
  54. * many of the same out-transitions). A "most recently used" queue of
  55. * protos is kept around with the hope that most states will find a proto
  56. * which is similar enough to be usable, and therefore compacting the
  57. * output tables.
  58. * "templates" are a special type of proto. If a transition table is
  59. * homogeneous or nearly homogeneous (all transitions go to the same
  60. * destination) then the odds are good that future states will also go
  61. * to the same destination state on basically the same character set.
  62. * These homogeneous states are so common when dealing with large rule
  63. * sets that they merit special attention. If the transition table were
  64. * simply made into a proto, then (typically) each subsequent, similar
  65. * state will differ from the proto for two out-transitions. One of these
  66. * out-transitions will be that character on which the proto does not go
  67. * to the common destination, and one will be that character on which the
  68. * state does not go to the common destination. Templates, on the other
  69. * hand, go to the common state on EVERY transition character, and therefore
  70. * cost only one difference.
  71. */
  72. void bldtbl( state, statenum, totaltrans, comstate, comfreq )
  73. int state[], statenum, totaltrans, comstate, comfreq;
  74. {
  75. int extptr, extrct[2][CSIZE + 1];
  76. int mindiff, minprot, i, d;
  77. int checkcom;
  78. /* If extptr is 0 then the first array of extrct holds the result of the
  79. * "best difference" to date, which is those transitions which occur in
  80. * "state" but not in the proto which, to date, has the fewest differences
  81. * between itself and "state". If extptr is 1 then the second array of
  82. * extrct hold the best difference. The two arrays are toggled
  83. * between so that the best difference to date can be kept around and
  84. * also a difference just created by checking against a candidate "best"
  85. * proto.
  86. */
  87. extptr = 0;
  88. /* if the state has too few out-transitions, don't bother trying to
  89. * compact its tables
  90. */
  91. if ( (totaltrans * 100) < (numecs * PROTO_SIZE_PERCENTAGE) )
  92. mkentry( state, numecs, statenum, JAMSTATE, totaltrans );
  93. else
  94. {
  95. /* checkcom is true if we should only check "state" against
  96. * protos which have the same "comstate" value
  97. */
  98. checkcom = comfreq * 100 > totaltrans * CHECK_COM_PERCENTAGE;
  99. minprot = firstprot;
  100. mindiff = totaltrans;
  101. if ( checkcom )
  102. {
  103. /* find first proto which has the same "comstate" */
  104. for ( i = firstprot; i != NIL; i = protnext[i] )
  105. if ( protcomst[i] == comstate )
  106. {
  107. minprot = i;
  108. mindiff = tbldiff( state, minprot, extrct[extptr] );
  109. break;
  110. }
  111. }
  112. else
  113. {
  114. /* since we've decided that the most common destination out
  115. * of "state" does not occur with a high enough frequency,
  116. * we set the "comstate" to zero, assuring that if this state
  117. * is entered into the proto list, it will not be considered
  118. * a template.
  119. */
  120. comstate = 0;
  121. if ( firstprot != NIL )
  122. {
  123. minprot = firstprot;
  124. mindiff = tbldiff( state, minprot, extrct[extptr] );
  125. }
  126. }
  127. /* we now have the first interesting proto in "minprot". If
  128. * it matches within the tolerances set for the first proto,
  129. * we don't want to bother scanning the rest of the proto list
  130. * to see if we have any other reasonable matches.
  131. */
  132. if ( mindiff * 100 > totaltrans * FIRST_MATCH_DIFF_PERCENTAGE )
  133. { /* not a good enough match. Scan the rest of the protos */
  134. for ( i = minprot; i != NIL; i = protnext[i] )
  135. {
  136. d = tbldiff( state, i, extrct[1 - extptr] );
  137. if ( d < mindiff )
  138. {
  139. extptr = 1 - extptr;
  140. mindiff = d;
  141. minprot = i;
  142. }
  143. }
  144. }
  145. /* check if the proto we've decided on as our best bet is close
  146. * enough to the state we want to match to be usable
  147. */
  148. if ( mindiff * 100 > totaltrans * ACCEPTABLE_DIFF_PERCENTAGE )
  149. {
  150. /* no good. If the state is homogeneous enough, we make a
  151. * template out of it. Otherwise, we make a proto.
  152. */
  153. if ( comfreq * 100 >= totaltrans * TEMPLATE_SAME_PERCENTAGE )
  154. mktemplate( state, statenum, comstate );
  155. else
  156. {
  157. mkprot( state, statenum, comstate );
  158. mkentry( state, numecs, statenum, JAMSTATE, totaltrans );
  159. }
  160. }
  161. else
  162. { /* use the proto */
  163. mkentry( extrct[extptr], numecs, statenum,
  164. prottbl[minprot], mindiff );
  165. /* if this state was sufficiently different from the proto
  166. * we built it from, make it, too, a proto
  167. */
  168. if ( mindiff * 100 >= totaltrans * NEW_PROTO_DIFF_PERCENTAGE )
  169. mkprot( state, statenum, comstate );
  170. /* since mkprot added a new proto to the proto queue, it's possible
  171. * that "minprot" is no longer on the proto queue (if it happened
  172. * to have been the last entry, it would have been bumped off).
  173. * If it's not there, then the new proto took its physical place
  174. * (though logically the new proto is at the beginning of the
  175. * queue), so in that case the following call will do nothing.
  176. */
  177. mv2front( minprot );
  178. }
  179. }
  180. }
  181. /* cmptmps - compress template table entries
  182. *
  183. * synopsis
  184. * cmptmps();
  185. *
  186. * template tables are compressed by using the 'template equivalence
  187. * classes', which are collections of transition character equivalence
  188. * classes which always appear together in templates - really meta-equivalence
  189. * classes. until this point, the tables for templates have been stored
  190. * up at the top end of the nxt array; they will now be compressed and have
  191. * table entries made for them.
  192. */
  193. void cmptmps()
  194. {
  195. int tmpstorage[CSIZE + 1];
  196. register int *tmp = tmpstorage, i, j;
  197. int totaltrans, trans;
  198. peakpairs = numtemps * numecs + tblend;
  199. if ( usemecs )
  200. {
  201. /* create equivalence classes base on data gathered on template
  202. * transitions
  203. */
  204. nummecs = cre8ecs( tecfwd, tecbck, numecs );
  205. }
  206. else
  207. nummecs = numecs;
  208. if ( lastdfa + numtemps + 1 >= current_max_dfas )
  209. increase_max_dfas();
  210. /* loop through each template */
  211. for ( i = 1; i <= numtemps; ++i )
  212. {
  213. totaltrans = 0; /* number of non-jam transitions out of this template */
  214. for ( j = 1; j <= numecs; ++j )
  215. {
  216. trans = tnxt[numecs * i + j];
  217. if ( usemecs )
  218. {
  219. /* the absolute value of tecbck is the meta-equivalence class
  220. * of a given equivalence class, as set up by cre8ecs
  221. */
  222. if ( tecbck[j] > 0 )
  223. {
  224. tmp[tecbck[j]] = trans;
  225. if ( trans > 0 )
  226. ++totaltrans;
  227. }
  228. }
  229. else
  230. {
  231. tmp[j] = trans;
  232. if ( trans > 0 )
  233. ++totaltrans;
  234. }
  235. }
  236. /* it is assumed (in a rather subtle way) in the skeleton that
  237. * if we're using meta-equivalence classes, the def[] entry for
  238. * all templates is the jam template, i.e., templates never default
  239. * to other non-jam table entries (e.g., another template)
  240. */
  241. /* leave room for the jam-state after the last real state */
  242. mkentry( tmp, nummecs, lastdfa + i + 1, JAMSTATE, totaltrans );
  243. }
  244. }
  245. /* expand_nxt_chk - expand the next check arrays */
  246. void expand_nxt_chk()
  247. {
  248. register int old_max = current_max_xpairs;
  249. current_max_xpairs += MAX_XPAIRS_INCREMENT;
  250. ++num_reallocs;
  251. nxt = reallocate_integer_array( nxt, current_max_xpairs );
  252. chk = reallocate_integer_array( chk, current_max_xpairs );
  253. bzero( (char *) (chk + old_max),
  254. MAX_XPAIRS_INCREMENT * sizeof( int ) / sizeof( char ) );
  255. }
  256. /* find_table_space - finds a space in the table for a state to be placed
  257. *
  258. * synopsis
  259. * int *state, numtrans, block_start;
  260. * int find_table_space();
  261. *
  262. * block_start = find_table_space( state, numtrans );
  263. *
  264. * State is the state to be added to the full speed transition table.
  265. * Numtrans is the number of out-transitions for the state.
  266. *
  267. * find_table_space() returns the position of the start of the first block (in
  268. * chk) able to accommodate the state
  269. *
  270. * In determining if a state will or will not fit, find_table_space() must take
  271. * into account the fact that an end-of-buffer state will be added at [0],
  272. * and an action number will be added in [-1].
  273. */
  274. int find_table_space( state, numtrans )
  275. int *state, numtrans;
  276. {
  277. /* firstfree is the position of the first possible occurrence of two
  278. * consecutive unused records in the chk and nxt arrays
  279. */
  280. register int i;
  281. register int *state_ptr, *chk_ptr;
  282. register int *ptr_to_last_entry_in_state;
  283. /* if there are too many out-transitions, put the state at the end of
  284. * nxt and chk
  285. */
  286. if ( numtrans > MAX_XTIONS_FULL_INTERIOR_FIT )
  287. {
  288. /* if table is empty, return the first available spot in chk/nxt,
  289. * which should be 1
  290. */
  291. if ( tblend < 2 )
  292. return ( 1 );
  293. i = tblend - numecs; /* start searching for table space near the
  294. * end of chk/nxt arrays
  295. */
  296. }
  297. else
  298. i = firstfree; /* start searching for table space from the
  299. * beginning (skipping only the elements
  300. * which will definitely not hold the new
  301. * state)
  302. */
  303. while ( 1 ) /* loops until a space is found */
  304. {
  305. if ( i + numecs > current_max_xpairs )
  306. expand_nxt_chk();
  307. /* loops until space for end-of-buffer and action number are found */
  308. while ( 1 )
  309. {
  310. if ( chk[i - 1] == 0 ) /* check for action number space */
  311. {
  312. if ( chk[i] == 0 ) /* check for end-of-buffer space */
  313. break;
  314. else
  315. i += 2; /* since i != 0, there is no use checking to
  316. * see if (++i) - 1 == 0, because that's the
  317. * same as i == 0, so we skip a space
  318. */
  319. }
  320. else
  321. ++i;
  322. if ( i + numecs > current_max_xpairs )
  323. expand_nxt_chk();
  324. }
  325. /* if we started search from the beginning, store the new firstfree for
  326. * the next call of find_table_space()
  327. */
  328. if ( numtrans <= MAX_XTIONS_FULL_INTERIOR_FIT )
  329. firstfree = i + 1;
  330. /* check to see if all elements in chk (and therefore nxt) that are
  331. * needed for the new state have not yet been taken
  332. */
  333. state_ptr = &state[1];
  334. ptr_to_last_entry_in_state = &chk[i + numecs + 1];
  335. for ( chk_ptr = &chk[i + 1]; chk_ptr != ptr_to_last_entry_in_state;
  336. ++chk_ptr )
  337. if ( *(state_ptr++) != 0 && *chk_ptr != 0 )
  338. break;
  339. if ( chk_ptr == ptr_to_last_entry_in_state )
  340. return ( i );
  341. else
  342. ++i;
  343. }
  344. }
  345. /* inittbl - initialize transition tables
  346. *
  347. * synopsis
  348. * inittbl();
  349. *
  350. * Initializes "firstfree" to be one beyond the end of the table. Initializes
  351. * all "chk" entries to be zero. Note that templates are built in their
  352. * own tbase/tdef tables. They are shifted down to be contiguous
  353. * with the non-template entries during table generation.
  354. */
  355. void inittbl()
  356. {
  357. register int i;
  358. bzero( (char *) chk, current_max_xpairs * sizeof( int ) / sizeof( char ) );
  359. tblend = 0;
  360. firstfree = tblend + 1;
  361. numtemps = 0;
  362. if ( usemecs )
  363. {
  364. /* set up doubly-linked meta-equivalence classes
  365. * these are sets of equivalence classes which all have identical
  366. * transitions out of TEMPLATES
  367. */
  368. tecbck[1] = NIL;
  369. for ( i = 2; i <= numecs; ++i )
  370. {
  371. tecbck[i] = i - 1;
  372. tecfwd[i - 1] = i;
  373. }
  374. tecfwd[numecs] = NIL;
  375. }
  376. }
  377. /* mkdeftbl - make the default, "jam" table entries
  378. *
  379. * synopsis
  380. * mkdeftbl();
  381. */
  382. void mkdeftbl()
  383. {
  384. int i;
  385. jamstate = lastdfa + 1;
  386. ++tblend; /* room for transition on end-of-buffer character */
  387. if ( tblend + numecs > current_max_xpairs )
  388. expand_nxt_chk();
  389. /* add in default end-of-buffer transition */
  390. nxt[tblend] = end_of_buffer_state;
  391. chk[tblend] = jamstate;
  392. for ( i = 1; i <= numecs; ++i )
  393. {
  394. nxt[tblend + i] = 0;
  395. chk[tblend + i] = jamstate;
  396. }
  397. jambase = tblend;
  398. base[jamstate] = jambase;
  399. def[jamstate] = 0;
  400. tblend += numecs;
  401. ++numtemps;
  402. }
  403. /* mkentry - create base/def and nxt/chk entries for transition array
  404. *
  405. * synopsis
  406. * int state[numchars + 1], numchars, statenum, deflink, totaltrans;
  407. * mkentry( state, numchars, statenum, deflink, totaltrans );
  408. *
  409. * "state" is a transition array "numchars" characters in size, "statenum"
  410. * is the offset to be used into the base/def tables, and "deflink" is the
  411. * entry to put in the "def" table entry. If "deflink" is equal to
  412. * "JAMSTATE", then no attempt will be made to fit zero entries of "state"
  413. * (i.e., jam entries) into the table. It is assumed that by linking to
  414. * "JAMSTATE" they will be taken care of. In any case, entries in "state"
  415. * marking transitions to "SAME_TRANS" are treated as though they will be
  416. * taken care of by whereever "deflink" points. "totaltrans" is the total
  417. * number of transitions out of the state. If it is below a certain threshold,
  418. * the tables are searched for an interior spot that will accommodate the
  419. * state array.
  420. */
  421. void mkentry( state, numchars, statenum, deflink, totaltrans )
  422. register int *state;
  423. int numchars, statenum, deflink, totaltrans;
  424. {
  425. register int minec, maxec, i, baseaddr;
  426. int tblbase, tbllast;
  427. if ( totaltrans == 0 )
  428. { /* there are no out-transitions */
  429. if ( deflink == JAMSTATE )
  430. base[statenum] = JAMSTATE;
  431. else
  432. base[statenum] = 0;
  433. def[statenum] = deflink;
  434. return;
  435. }
  436. for ( minec = 1; minec <= numchars; ++minec )
  437. {
  438. if ( state[minec] != SAME_TRANS )
  439. if ( state[minec] != 0 || deflink != JAMSTATE )
  440. break;
  441. }
  442. if ( totaltrans == 1 )
  443. {
  444. /* there's only one out-transition. Save it for later to fill
  445. * in holes in the tables.
  446. */
  447. stack1( statenum, minec, state[minec], deflink );
  448. return;
  449. }
  450. for ( maxec = numchars; maxec > 0; --maxec )
  451. {
  452. if ( state[maxec] != SAME_TRANS )
  453. if ( state[maxec] != 0 || deflink != JAMSTATE )
  454. break;
  455. }
  456. /* Whether we try to fit the state table in the middle of the table
  457. * entries we have already generated, or if we just take the state
  458. * table at the end of the nxt/chk tables, we must make sure that we
  459. * have a valid base address (i.e., non-negative). Note that not only are
  460. * negative base addresses dangerous at run-time (because indexing the
  461. * next array with one and a low-valued character might generate an
  462. * array-out-of-bounds error message), but at compile-time negative
  463. * base addresses denote TEMPLATES.
  464. */
  465. /* find the first transition of state that we need to worry about. */
  466. if ( totaltrans * 100 <= numchars * INTERIOR_FIT_PERCENTAGE )
  467. { /* attempt to squeeze it into the middle of the tabls */
  468. baseaddr = firstfree;
  469. while ( baseaddr < minec )
  470. {
  471. /* using baseaddr would result in a negative base address below
  472. * find the next free slot
  473. */
  474. for ( ++baseaddr; chk[baseaddr] != 0; ++baseaddr )
  475. ;
  476. }
  477. if ( baseaddr + maxec - minec >= current_max_xpairs )
  478. expand_nxt_chk();
  479. for ( i = minec; i <= maxec; ++i )
  480. if ( state[i] != SAME_TRANS )
  481. if ( state[i] != 0 || deflink != JAMSTATE )
  482. if ( chk[baseaddr + i - minec] != 0 )
  483. { /* baseaddr unsuitable - find another */
  484. for ( ++baseaddr;
  485. baseaddr < current_max_xpairs &&
  486. chk[baseaddr] != 0;
  487. ++baseaddr )
  488. ;
  489. if ( baseaddr + maxec - minec >= current_max_xpairs )
  490. expand_nxt_chk();
  491. /* reset the loop counter so we'll start all
  492. * over again next time it's incremented
  493. */
  494. i = minec - 1;
  495. }
  496. }
  497. else
  498. {
  499. /* ensure that the base address we eventually generate is
  500. * non-negative
  501. */
  502. baseaddr = max( tblend + 1, minec );
  503. }
  504. tblbase = baseaddr - minec;
  505. tbllast = tblbase + maxec;
  506. if ( tbllast >= current_max_xpairs )
  507. expand_nxt_chk();
  508. base[statenum] = tblbase;
  509. def[statenum] = deflink;
  510. for ( i = minec; i <= maxec; ++i )
  511. if ( state[i] != SAME_TRANS )
  512. if ( state[i] != 0 || deflink != JAMSTATE )
  513. {
  514. nxt[tblbase + i] = state[i];
  515. chk[tblbase + i] = statenum;
  516. }
  517. if ( baseaddr == firstfree )
  518. /* find next free slot in tables */
  519. for ( ++firstfree; chk[firstfree] != 0; ++firstfree )
  520. ;
  521. tblend = max( tblend, tbllast );
  522. }
  523. /* mk1tbl - create table entries for a state (or state fragment) which
  524. * has only one out-transition
  525. *
  526. * synopsis
  527. * int state, sym, onenxt, onedef;
  528. * mk1tbl( state, sym, onenxt, onedef );
  529. */
  530. void mk1tbl( state, sym, onenxt, onedef )
  531. int state, sym, onenxt, onedef;
  532. {
  533. if ( firstfree < sym )
  534. firstfree = sym;
  535. while ( chk[firstfree] != 0 )
  536. if ( ++firstfree >= current_max_xpairs )
  537. expand_nxt_chk();
  538. base[state] = firstfree - sym;
  539. def[state] = onedef;
  540. chk[firstfree] = state;
  541. nxt[firstfree] = onenxt;
  542. if ( firstfree > tblend )
  543. {
  544. tblend = firstfree++;
  545. if ( firstfree >= current_max_xpairs )
  546. expand_nxt_chk();
  547. }
  548. }
  549. /* mkprot - create new proto entry
  550. *
  551. * synopsis
  552. * int state[], statenum, comstate;
  553. * mkprot( state, statenum, comstate );
  554. */
  555. void mkprot( state, statenum, comstate )
  556. int state[], statenum, comstate;
  557. {
  558. int i, slot, tblbase;
  559. if ( ++numprots >= MSP || numecs * numprots >= PROT_SAVE_SIZE )
  560. {
  561. /* gotta make room for the new proto by dropping last entry in
  562. * the queue
  563. */
  564. slot = lastprot;
  565. lastprot = protprev[lastprot];
  566. protnext[lastprot] = NIL;
  567. }
  568. else
  569. slot = numprots;
  570. protnext[slot] = firstprot;
  571. if ( firstprot != NIL )
  572. protprev[firstprot] = slot;
  573. firstprot = slot;
  574. prottbl[slot] = statenum;
  575. protcomst[slot] = comstate;
  576. /* copy state into save area so it can be compared with rapidly */
  577. tblbase = numecs * (slot - 1);
  578. for ( i = 1; i <= numecs; ++i )
  579. protsave[tblbase + i] = state[i];
  580. }
  581. /* mktemplate - create a template entry based on a state, and connect the state
  582. * to it
  583. *
  584. * synopsis
  585. * int state[], statenum, comstate, totaltrans;
  586. * mktemplate( state, statenum, comstate, totaltrans );
  587. */
  588. void mktemplate( state, statenum, comstate )
  589. int state[], statenum, comstate;
  590. {
  591. int i, numdiff, tmpbase, tmp[CSIZE + 1];
  592. Char transset[CSIZE + 1];
  593. int tsptr;
  594. ++numtemps;
  595. tsptr = 0;
  596. /* calculate where we will temporarily store the transition table
  597. * of the template in the tnxt[] array. The final transition table
  598. * gets created by cmptmps()
  599. */
  600. tmpbase = numtemps * numecs;
  601. if ( tmpbase + numecs >= current_max_template_xpairs )
  602. {
  603. current_max_template_xpairs += MAX_TEMPLATE_XPAIRS_INCREMENT;
  604. ++num_reallocs;
  605. tnxt = reallocate_integer_array( tnxt, current_max_template_xpairs );
  606. }
  607. for ( i = 1; i <= numecs; ++i )
  608. if ( state[i] == 0 )
  609. tnxt[tmpbase + i] = 0;
  610. else
  611. {
  612. transset[tsptr++] = i;
  613. tnxt[tmpbase + i] = comstate;
  614. }
  615. if ( usemecs )
  616. mkeccl( transset, tsptr, tecfwd, tecbck, numecs, 0 );
  617. mkprot( tnxt + tmpbase, -numtemps, comstate );
  618. /* we rely on the fact that mkprot adds things to the beginning
  619. * of the proto queue
  620. */
  621. numdiff = tbldiff( state, firstprot, tmp );
  622. mkentry( tmp, numecs, statenum, -numtemps, numdiff );
  623. }
  624. /* mv2front - move proto queue element to front of queue
  625. *
  626. * synopsis
  627. * int qelm;
  628. * mv2front( qelm );
  629. */
  630. void mv2front( qelm )
  631. int qelm;
  632. {
  633. if ( firstprot != qelm )
  634. {
  635. if ( qelm == lastprot )
  636. lastprot = protprev[lastprot];
  637. protnext[protprev[qelm]] = protnext[qelm];
  638. if ( protnext[qelm] != NIL )
  639. protprev[protnext[qelm]] = protprev[qelm];
  640. protprev[qelm] = NIL;
  641. protnext[qelm] = firstprot;
  642. protprev[firstprot] = qelm;
  643. firstprot = qelm;
  644. }
  645. }
  646. /* place_state - place a state into full speed transition table
  647. *
  648. * synopsis
  649. * int *state, statenum, transnum;
  650. * place_state( state, statenum, transnum );
  651. *
  652. * State is the statenum'th state. It is indexed by equivalence class and
  653. * gives the number of the state to enter for a given equivalence class.
  654. * Transnum is the number of out-transitions for the state.
  655. */
  656. void place_state( state, statenum, transnum )
  657. int *state, statenum, transnum;
  658. {
  659. register int i;
  660. register int *state_ptr;
  661. int position = find_table_space( state, transnum );
  662. /* base is the table of start positions */
  663. base[statenum] = position;
  664. /* put in action number marker; this non-zero number makes sure that
  665. * find_table_space() knows that this position in chk/nxt is taken
  666. * and should not be used for another accepting number in another state
  667. */
  668. chk[position - 1] = 1;
  669. /* put in end-of-buffer marker; this is for the same purposes as above */
  670. chk[position] = 1;
  671. /* place the state into chk and nxt */
  672. state_ptr = &state[1];
  673. for ( i = 1; i <= numecs; ++i, ++state_ptr )
  674. if ( *state_ptr != 0 )
  675. {
  676. chk[position + i] = i;
  677. nxt[position + i] = *state_ptr;
  678. }
  679. if ( position + numecs > tblend )
  680. tblend = position + numecs;
  681. }
  682. /* stack1 - save states with only one out-transition to be processed later
  683. *
  684. * synopsis
  685. * int statenum, sym, nextstate, deflink;
  686. * stack1( statenum, sym, nextstate, deflink );
  687. *
  688. * if there's room for another state one the "one-transition" stack, the
  689. * state is pushed onto it, to be processed later by mk1tbl. If there's
  690. * no room, we process the sucker right now.
  691. */
  692. void stack1( statenum, sym, nextstate, deflink )
  693. int statenum, sym, nextstate, deflink;
  694. {
  695. if ( onesp >= ONE_STACK_SIZE - 1 )
  696. mk1tbl( statenum, sym, nextstate, deflink );
  697. else
  698. {
  699. ++onesp;
  700. onestate[onesp] = statenum;
  701. onesym[onesp] = sym;
  702. onenext[onesp] = nextstate;
  703. onedef[onesp] = deflink;
  704. }
  705. }
  706. /* tbldiff - compute differences between two state tables
  707. *
  708. * synopsis
  709. * int state[], pr, ext[];
  710. * int tbldiff, numdifferences;
  711. * numdifferences = tbldiff( state, pr, ext )
  712. *
  713. * "state" is the state array which is to be extracted from the pr'th
  714. * proto. "pr" is both the number of the proto we are extracting from
  715. * and an index into the save area where we can find the proto's complete
  716. * state table. Each entry in "state" which differs from the corresponding
  717. * entry of "pr" will appear in "ext".
  718. * Entries which are the same in both "state" and "pr" will be marked
  719. * as transitions to "SAME_TRANS" in "ext". The total number of differences
  720. * between "state" and "pr" is returned as function value. Note that this
  721. * number is "numecs" minus the number of "SAME_TRANS" entries in "ext".
  722. */
  723. int tbldiff( state, pr, ext )
  724. int state[], pr, ext[];
  725. {
  726. register int i, *sp = state, *ep = ext, *protp;
  727. register int numdiff = 0;
  728. protp = &protsave[numecs * (pr - 1)];
  729. for ( i = numecs; i > 0; --i )
  730. {
  731. if ( *++protp == *++sp )
  732. *++ep = SAME_TRANS;
  733. else
  734. {
  735. *++ep = *sp;
  736. ++numdiff;
  737. }
  738. }
  739. return ( numdiff );
  740. }