tblcmp.c 23 KB

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