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