This is Unofficial EPICS BASE Doxygen Site
dfa.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 /* dfa - DFA construction 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 /* declare functions that have forward references */
41 
42 void dump_associated_rules (FILE*, int);
43 void dump_transitions (FILE*, int[]);
44 void sympartition (int[], int, int[], int[]);
45 int symfollowset (int[], int, int, int[]);
46 
47 
48 /* check_for_backtracking - check a DFA state for backtracking
49  *
50  * synopsis
51  * int ds, state[numecs];
52  * check_for_backtracking( ds, state );
53  *
54  * ds is the number of the state to check and state[] is its out-transitions,
55  * indexed by equivalence class, and state_rules[] is the set of rules
56  * associated with this state
57  */
58 
59 void check_for_backtracking(int ds, int state[])
60 {
61  if ( (reject && ! dfaacc[ds].dfaacc_set) || ! dfaacc[ds].dfaacc_state )
62  { /* state is non-accepting */
64 
65  if ( backtrack_report )
66  {
67  fprintf( backtrack_file, "State #%d is non-accepting -\n", ds );
68 
69  /* identify the state */
71 
72  /* now identify it further using the out- and jam-transitions */
74 
75  putc( '\n', backtrack_file );
76  }
77  }
78  }
79 
80 
81 /* check_trailing_context - check to see if NFA state set constitutes
82  * "dangerous" trailing context
83  *
84  * synopsis
85  * int nfa_states[num_states+1], num_states;
86  * int accset[nacc+1], nacc;
87  * check_trailing_context( nfa_states, num_states, accset, nacc );
88  *
89  * NOTES
90  * Trailing context is "dangerous" if both the head and the trailing
91  * part are of variable size \and/ there's a DFA state which contains
92  * both an accepting state for the head part of the rule and NFA states
93  * which occur after the beginning of the trailing context.
94  * When such a rule is matched, it's impossible to tell if having been
95  * in the DFA state indicates the beginning of the trailing context
96  * or further-along scanning of the pattern. In these cases, a warning
97  * message is issued.
98  *
99  * nfa_states[1 .. num_states] is the list of NFA states in the DFA.
100  * accset[1 .. nacc] is the list of accepting numbers for the DFA state.
101  */
102 
103 void check_trailing_context(int *nfa_states, int num_states, int *accset, int nacc)
104 {
105  int i, j;
106 
107  for ( i = 1; i <= num_states; ++i )
108  {
109  int ns = nfa_states[i];
110  int type = state_type[ns];
111  int ar = assoc_rule[ns];
112 
113  if ( type == STATE_NORMAL || rule_type[ar] != RULE_VARIABLE )
114  { /* do nothing */
115  }
116 
117  else if ( type == STATE_TRAILING_CONTEXT )
118  {
119  /* potential trouble. Scan set of accepting numbers for
120  * the one marking the end of the "head". We assume that
121  * this looping will be fairly cheap since it's rare that
122  * an accepting number set is large.
123  */
124  for ( j = 1; j <= nacc; ++j )
125  if ( accset[j] & YY_TRAILING_HEAD_MASK )
126  {
127  fprintf( stderr,
128  "%s: Dangerous trailing context in rule at line %d\n",
129  program_name, rule_linenum[ar] );
130  return;
131  }
132  }
133  }
134  }
135 
136 
137 /* dump_associated_rules - list the rules associated with a DFA state
138  *
139  * synopisis
140  * int ds;
141  * FILE *file;
142  * dump_associated_rules( file, ds );
143  *
144  * goes through the set of NFA states associated with the DFA and
145  * extracts the first MAX_ASSOC_RULES unique rules, sorts them,
146  * and writes a report to the given file
147  */
148 
149 void dump_associated_rules(FILE *file, int ds)
150 {
151  int i, j;
152  int num_associated_rules = 0;
153  int rule_set[MAX_ASSOC_RULES + 1];
154  int *dset = dss[ds];
155  int size = dfasiz[ds];
156 
157  for ( i = 1; i <= size; ++i )
158  {
159  int rule_num = rule_linenum[assoc_rule[dset[i]]];
160 
161  for ( j = 1; j <= num_associated_rules; ++j )
162  if ( rule_num == rule_set[j] )
163  break;
164 
165  if ( j > num_associated_rules )
166  { /* new rule */
167  if ( num_associated_rules < MAX_ASSOC_RULES )
168  rule_set[++num_associated_rules] = rule_num;
169  }
170  }
171 
172  bubble( rule_set, num_associated_rules );
173 
174  fprintf( file, " associated rule line numbers:" );
175 
176  for ( i = 1; i <= num_associated_rules; ++i )
177  {
178  if ( i % 8 == 1 )
179  putc( '\n', file );
180 
181  fprintf( file, "\t%d", rule_set[i] );
182  }
183 
184  putc( '\n', file );
185  }
186 
187 
188 /* dump_transitions - list the transitions associated with a DFA state
189  *
190  * synopisis
191  * int state[numecs];
192  * FILE *file;
193  * dump_transitions( file, state );
194  *
195  * goes through the set of out-transitions and lists them in human-readable
196  * form (i.e., not as equivalence classes); also lists jam transitions
197  * (i.e., all those which are not out-transitions, plus EOF). The dump
198  * is done to the given file.
199  */
200 
201 void dump_transitions(FILE *file, int state[])
202 {
203  int i, ec;
204  int out_char_set[CSIZE];
205 
206  for ( i = 0; i < csize; ++i )
207  {
208  ec = abs( ecgroup[i] );
209  out_char_set[i] = state[ec];
210  }
211 
212  fprintf( file, " out-transitions: " );
213 
214  list_character_set( file, out_char_set );
215 
216  /* now invert the members of the set to get the jam transitions */
217  for ( i = 0; i < csize; ++i )
218  out_char_set[i] = ! out_char_set[i];
219 
220  fprintf( file, "\n jam-transitions: EOF " );
221 
222  list_character_set( file, out_char_set );
223 
224  putc( '\n', file );
225  }
226 
227 
228 /* epsclosure - construct the epsilon closure of a set of ndfa states
229  *
230  * synopsis
231  * int t[current_max_dfa_size], numstates, accset[num_rules + 1], nacc;
232  * int hashval;
233  * int *epsclosure();
234  * t = epsclosure( t, &numstates, accset, &nacc, &hashval );
235  *
236  * NOTES
237  * the epsilon closure is the set of all states reachable by an arbitrary
238  * number of epsilon transitions which themselves do not have epsilon
239  * transitions going out, unioned with the set of states which have non-null
240  * accepting numbers. t is an array of size numstates of nfa state numbers.
241  * Upon return, t holds the epsilon closure and numstates is updated. accset
242  * holds a list of the accepting numbers, and the size of accset is given
243  * by nacc. t may be subjected to reallocation if it is not large enough
244  * to hold the epsilon closure.
245  *
246  * hashval is the hash value for the dfa corresponding to the state set
247  */
248 
249 int *epsclosure(int *t, int *ns_addr, int accset[], int *nacc_addr, int *hv_addr)
250 {
251  int stkpos, ns, tsp;
252  int numstates = *ns_addr, nacc, hashval, transsym, nfaccnum;
253  int stkend, nstate;
254  static int did_stk_init = false, *stk;
255 
256 #define MARK_STATE(state) \
257  trans1[state] = trans1[state] - MARKER_DIFFERENCE;
258 
259 #define IS_MARKED(state) (trans1[state] < 0)
260 
261 #define UNMARK_STATE(state) \
262  trans1[state] = trans1[state] + MARKER_DIFFERENCE;
263 
264 #define CHECK_ACCEPT(state) \
265  { \
266  nfaccnum = accptnum[state]; \
267  if ( nfaccnum != NIL ) \
268  accset[++nacc] = nfaccnum; \
269  }
270 
271 #define DO_REALLOCATION \
272  { \
273  current_max_dfa_size += MAX_DFA_SIZE_INCREMENT; \
274  ++num_reallocs; \
275  t = reallocate_integer_array( t, current_max_dfa_size ); \
276  stk = reallocate_integer_array( stk, current_max_dfa_size ); \
277  } \
278 
279 #define PUT_ON_STACK(state) \
280  { \
281  if ( ++stkend >= current_max_dfa_size ) \
282  DO_REALLOCATION \
283  stk[stkend] = state; \
284  MARK_STATE(state) \
285  }
286 
287 #define ADD_STATE(state) \
288  { \
289  if ( ++numstates >= current_max_dfa_size ) \
290  DO_REALLOCATION \
291  t[numstates] = state; \
292  hashval = hashval + state; \
293  }
294 
295 #define STACK_STATE(state) \
296  { \
297  PUT_ON_STACK(state) \
298  CHECK_ACCEPT(state) \
299  if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \
300  ADD_STATE(state) \
301  }
302 
303  if ( ! did_stk_init )
304  {
306  did_stk_init = true;
307  }
308 
309  nacc = stkend = hashval = 0;
310 
311  for ( nstate = 1; nstate <= numstates; ++nstate )
312  {
313  ns = t[nstate];
314 
315  /* the state could be marked if we've already pushed it onto
316  * the stack
317  */
318  if ( ! IS_MARKED(ns) )
319  PUT_ON_STACK(ns)
320 
321  CHECK_ACCEPT(ns)
322  hashval = hashval + ns;
323  }
324 
325  for ( stkpos = 1; stkpos <= stkend; ++stkpos )
326  {
327  ns = stk[stkpos];
328  transsym = transchar[ns];
329 
330  if ( transsym == SYM_EPSILON )
331  {
332  tsp = trans1[ns] + MARKER_DIFFERENCE;
333 
334  if ( tsp != NO_TRANSITION )
335  {
336  if ( ! IS_MARKED(tsp) )
337  STACK_STATE(tsp)
338 
339  tsp = trans2[ns];
340 
341  if ( tsp != NO_TRANSITION )
342  if ( ! IS_MARKED(tsp) )
343  STACK_STATE(tsp)
344  }
345  }
346  }
347 
348  /* clear out "visit" markers */
349 
350  for ( stkpos = 1; stkpos <= stkend; ++stkpos )
351  {
352  if ( IS_MARKED(stk[stkpos]) )
353  {
354  UNMARK_STATE(stk[stkpos])
355  }
356  else
357  flexfatal( "consistency check failed in epsclosure()" );
358  }
359 
360  *ns_addr = numstates;
361  *hv_addr = hashval;
362  *nacc_addr = nacc;
363 
364  return ( t );
365  }
366 
367 
368 /* increase_max_dfas - increase the maximum number of DFAs */
369 
371 {
373 
374  ++num_reallocs;
375 
383 
384  if ( nultrans )
386  }
387 
388 
389 /* ntod - convert an ndfa to a dfa
390  *
391  * synopsis
392  * ntod();
393  *
394  * creates the dfa corresponding to the ndfa we've constructed. the
395  * dfa starts out in state #1.
396  */
397 
398 void ntod(void)
399 {
400  int *accset, ds, nacc, newds;
401  int sym, hashval, numstates, dsize;
402  int num_full_table_rows = 0; /* used only for -f */
403  int *nset, *dset;
404  int targptr, totaltrans, i, comstate, comfreq, targ;
405  int *epsclosure(int *t, int *ns_addr, int *accset, int *nacc_addr, int *hv_addr);
406  int snstods(int *sns, int numstates, int *accset, int nacc, int hashval, int *newds_addr);
407  int symlist[CSIZE + 1];
408  int num_start_states;
409  int todo_head, todo_next;
410 
411  /* note that the following are indexed by *equivalence classes*
412  * and not by characters. Since equivalence classes are indexed
413  * beginning with 1, even if the scanner accepts NUL's, this
414  * means that (since every character is potentially in its own
415  * equivalence class) these arrays must have room for indices
416  * from 1 to CSIZE, so their size must be CSIZE + 1.
417  */
418  int duplist[CSIZE + 1], state[CSIZE + 1];
419  int targfreq[CSIZE + 1], targstate[CSIZE + 1];
420 
421  /* this is so find_table_space(...) will know where to start looking in
422  * chk/nxt for unused records for space to put in the state
423  */
424  if ( fullspd )
425  firstfree = 0;
426 
427  accset = allocate_integer_array( num_rules + 1 );
429 
430  /* the "todo" queue is represented by the head, which is the DFA
431  * state currently being processed, and the "next", which is the
432  * next DFA state number available (not in use). We depend on the
433  * fact that snstods() returns DFA's \in increasing order/, and thus
434  * need only know the bounds of the dfas to be processed.
435  */
436  todo_head = todo_next = 0;
437 
438  for ( i = 0; i <= csize; ++i )
439  {
440  duplist[i] = NIL;
441  symlist[i] = false;
442  }
443 
444  for ( i = 0; i <= num_rules; ++i )
445  accset[i] = NIL;
446 
447  if ( trace )
448  {
449  dumpnfa( scset[1] );
450  fputs( "\n\nDFA Dump:\n\n", stderr );
451  }
452 
453  inittbl();
454 
455  /* check to see whether we should build a separate table for transitions
456  * on NUL characters. We don't do this for full-speed (-F) scanners,
457  * since for them we don't have a simple state number lying around with
458  * which to index the table. We also don't bother doing it for scanners
459  * unless (1) NUL is in its own equivalence class (indicated by a
460  * positive value of ecgroup[NUL]), (2) NUL's equilvalence class is
461  * the last equivalence class, and (3) the number of equivalence classes
462  * is the same as the number of characters. This latter case comes about
463  * when useecs is false or when its true but every character still
464  * manages to land in its own class (unlikely, but it's cheap to check
465  * for). If all these things are true then the character code needed
466  * to represent NUL's equivalence class for indexing the tables is
467  * going to take one more bit than the number of characters, and therefore
468  * we won't be assured of being able to fit it into a YY_CHAR variable.
469  * This rules out storing the transitions in a compressed table, since
470  * the code for interpreting them uses a YY_CHAR variable (perhaps it
471  * should just use an integer, though; this is worth pondering ... ###).
472  *
473  * Finally, for full tables, we want the number of entries in the
474  * table to be a power of two so the array references go fast (it
475  * will just take a shift to compute the major index). If encoding
476  * NUL's transitions in the table will spoil this, we give it its
477  * own table (note that this will be the case if we're not using
478  * equivalence classes).
479  */
480 
481  /* note that the test for ecgroup[0] == numecs below accomplishes
482  * both (1) and (2) above
483  */
484  if ( ! fullspd && ecgroup[0] == numecs )
485  { /* NUL is alone in its equivalence class, which is the last one */
486  int use_NUL_table = (numecs == csize);
487 
488  if ( fulltbl && ! use_NUL_table )
489  { /* we still may want to use the table if numecs is a power of 2 */
490  int power_of_two;
491 
492  for ( power_of_two = 1; power_of_two <= csize; power_of_two *= 2 )
493  if ( numecs == power_of_two )
494  {
495  use_NUL_table = true;
496  break;
497  }
498  }
499 
500  if ( use_NUL_table )
502  /* from now on, nultrans != nil indicates that we're
503  * saving null transitions for later, separate encoding
504  */
505  }
506 
507 
508  if ( fullspd )
509  {
510  for ( i = 0; i <= numecs; ++i )
511  state[i] = 0;
512  place_state( state, 0, 0 );
513  }
514 
515  else if ( fulltbl )
516  {
517  if ( nultrans )
518  /* we won't be including NUL's transitions in the table,
519  * so build it for entries from 0 .. numecs - 1
520  */
521  num_full_table_rows = numecs;
522 
523  else
524  /* take into account the fact that we'll be including
525  * the NUL entries in the transition table. Build it
526  * from 0 .. numecs.
527  */
528  num_full_table_rows = numecs + 1;
529 
530  /* declare it "short" because it's a real long-shot that that
531  * won't be large enough.
532  */
533  printf( "static short int yy_nxt[][%d] =\n {\n",
534  /* '}' so vi doesn't get too confused */
535  num_full_table_rows );
536 
537  /* generate 0 entries for state #0 */
538  for ( i = 0; i < num_full_table_rows; ++i )
539  mk2data( 0 );
540 
541  /* force ',' and dataflush() next call to mk2data */
543 
544  /* force extra blank line next dataflush() */
546  }
547 
548  /* create the first states */
549 
550  num_start_states = lastsc * 2;
551 
552  for ( i = 1; i <= num_start_states; ++i )
553  {
554  numstates = 1;
555 
556  /* for each start condition, make one state for the case when
557  * we're at the beginning of the line (the '%' operator) and
558  * one for the case when we're not
559  */
560  if ( i % 2 == 1 )
561  nset[numstates] = scset[(i / 2) + 1];
562  else
563  nset[numstates] = mkbranch( scbol[i / 2], scset[i / 2] );
564 
565  nset = epsclosure( nset, &numstates, accset, &nacc, &hashval );
566 
567  if ( snstods( nset, numstates, accset, nacc, hashval, &ds ) )
568  {
569  numas += nacc;
570  totnst += numstates;
571  ++todo_next;
572 
573  if ( variable_trailing_context_rules && nacc > 0 )
574  check_trailing_context( nset, numstates, accset, nacc );
575  }
576  }
577 
578  if ( ! fullspd )
579  {
580  if ( ! snstods( nset, 0, accset, 0, 0, &end_of_buffer_state ) )
581  flexfatal( "could not create unique end-of-buffer state" );
582 
583  ++numas;
584  ++num_start_states;
585  ++todo_next;
586  }
587 
588  while ( todo_head < todo_next )
589  {
590  targptr = 0;
591  totaltrans = 0;
592 
593  for ( i = 1; i <= numecs; ++i )
594  state[i] = 0;
595 
596  ds = ++todo_head;
597 
598  dset = dss[ds];
599  dsize = dfasiz[ds];
600 
601  if ( trace )
602  fprintf( stderr, "state # %d:\n", ds );
603 
604  sympartition( dset, dsize, symlist, duplist );
605 
606  for ( sym = 1; sym <= numecs; ++sym )
607  {
608  if ( symlist[sym] )
609  {
610  symlist[sym] = 0;
611 
612  if ( duplist[sym] == NIL )
613  { /* symbol has unique out-transitions */
614  numstates = symfollowset( dset, dsize, sym, nset );
615  nset = epsclosure( nset, &numstates, accset,
616  &nacc, &hashval );
617 
618  if ( snstods( nset, numstates, accset,
619  nacc, hashval, &newds ) )
620  {
621  totnst = totnst + numstates;
622  ++todo_next;
623  numas += nacc;
624 
625  if ( variable_trailing_context_rules && nacc > 0 )
626  check_trailing_context( nset, numstates,
627  accset, nacc );
628  }
629 
630  state[sym] = newds;
631 
632  if ( trace )
633  fprintf( stderr, "\t%d\t%d\n", sym, newds );
634 
635  targfreq[++targptr] = 1;
636  targstate[targptr] = newds;
637  ++numuniq;
638  }
639 
640  else
641  {
642  /* sym's equivalence class has the same transitions
643  * as duplist(sym)'s equivalence class
644  */
645  targ = state[duplist[sym]];
646  state[sym] = targ;
647 
648  if ( trace )
649  fprintf( stderr, "\t%d\t%d\n", sym, targ );
650 
651  /* update frequency count for destination state */
652 
653  i = 0;
654  while ( targstate[++i] != targ )
655  ;
656 
657  ++targfreq[i];
658  ++numdup;
659  }
660 
661  ++totaltrans;
662  duplist[sym] = NIL;
663  }
664  }
665 
666  numsnpairs = numsnpairs + totaltrans;
667 
668  if ( caseins && ! useecs )
669  {
670  int j;
671 
672  for ( i = 'A', j = 'a'; i <= 'Z'; ++i, ++j )
673  state[i] = state[j];
674  }
675 
676  if ( ds > num_start_states )
677  check_for_backtracking( ds, state );
678 
679  if ( nultrans )
680  {
681  nultrans[ds] = state[NUL_ec];
682  state[NUL_ec] = 0; /* remove transition */
683  }
684 
685  if ( fulltbl )
686  {
687  /* supply array's 0-element */
688  if ( ds == end_of_buffer_state )
690  else
692 
693  for ( i = 1; i < num_full_table_rows; ++i )
694  /* jams are marked by negative of state number */
695  mk2data( state[i] ? state[i] : -ds );
696 
697  /* force ',' and dataflush() next call to mk2data */
699 
700  /* force extra blank line next dataflush() */
702  }
703 
704  else if ( fullspd )
705  place_state( state, ds, totaltrans );
706 
707  else if ( ds == end_of_buffer_state )
708  /* special case this state to make sure it does what it's
709  * supposed to, i.e., jam on end-of-buffer
710  */
711  stack1( ds, 0, 0, JAMSTATE );
712 
713  else /* normal, compressed state */
714  {
715  /* determine which destination state is the most common, and
716  * how many transitions to it there are
717  */
718 
719  comfreq = 0;
720  comstate = 0;
721 
722  for ( i = 1; i <= targptr; ++i )
723  if ( targfreq[i] > comfreq )
724  {
725  comfreq = targfreq[i];
726  comstate = targstate[i];
727  }
728 
729  bldtbl( state, ds, totaltrans, comstate, comfreq );
730  }
731  }
732 
733  if ( fulltbl )
734  dataend();
735 
736  else if ( ! fullspd )
737  {
738  cmptmps(); /* create compressed template entries */
739 
740  /* create tables for all the states with only one out-transition */
741  while ( onesp > 0 )
742  {
743  mk1tbl( onestate[onesp], onesym[onesp], onenext[onesp],
744  onedef[onesp] );
745  --onesp;
746  }
747 
748  mkdeftbl();
749  }
750  }
751 
752 
753 /* snstods - converts a set of ndfa states into a dfa state
754  *
755  * synopsis
756  * int sns[numstates], numstates, newds, accset[num_rules + 1], nacc, hashval;
757  * int snstods();
758  * is_new_state = snstods( sns, numstates, accset, nacc, hashval, &newds );
759  *
760  * on return, the dfa state number is in newds.
761  */
762 
763 int snstods(int sns[], int numstates, int accset[], int nacc, int hashval, int *newds_addr)
764 {
765  int didsort = 0;
766  int i, j;
767  int newds, *oldsns;
768 
769  for ( i = 1; i <= lastdfa; ++i )
770  if ( hashval == dhash[i] )
771  {
772  if ( numstates == dfasiz[i] )
773  {
774  oldsns = dss[i];
775 
776  if ( ! didsort )
777  {
778  /* we sort the states in sns so we can compare it to
779  * oldsns quickly. we use bubble because there probably
780  * aren't very many states
781  */
782  bubble( sns, numstates );
783  didsort = 1;
784  }
785 
786  for ( j = 1; j <= numstates; ++j )
787  if ( sns[j] != oldsns[j] )
788  break;
789 
790  if ( j > numstates )
791  {
792  ++dfaeql;
793  *newds_addr = i;
794  return ( 0 );
795  }
796 
797  ++hshcol;
798  }
799 
800  else
801  ++hshsave;
802  }
803 
804  /* make a new dfa */
805 
806  if ( ++lastdfa >= current_max_dfas )
808 
809  newds = lastdfa;
810 
811  dss[newds] = (int *) malloc( (unsigned) ((numstates + 1) * sizeof( int )) );
812 
813  if ( ! dss[newds] )
814  flexfatal( "dynamic memory failure in snstods()" );
815 
816  /* if we haven't already sorted the states in sns, we do so now, so that
817  * future comparisons with it can be made quickly
818  */
819 
820  if ( ! didsort )
821  bubble( sns, numstates );
822 
823  for ( i = 1; i <= numstates; ++i )
824  dss[newds][i] = sns[i];
825 
826  dfasiz[newds] = numstates;
827  dhash[newds] = hashval;
828 
829  if ( nacc == 0 )
830  {
831  if ( reject )
832  dfaacc[newds].dfaacc_set = (int *) 0;
833  else
834  dfaacc[newds].dfaacc_state = 0;
835 
836  accsiz[newds] = 0;
837  }
838 
839  else if ( reject )
840  {
841  /* we sort the accepting set in increasing order so the disambiguating
842  * rule that the first rule listed is considered match in the event of
843  * ties will work. We use a bubble sort since the list is probably
844  * quite small.
845  */
846 
847  bubble( accset, nacc );
848 
849  dfaacc[newds].dfaacc_set =
850  (int *) malloc( (unsigned) ((nacc + 1) * sizeof( int )) );
851 
852  if ( ! dfaacc[newds].dfaacc_set )
853  flexfatal( "dynamic memory failure in snstods()" );
854 
855  /* save the accepting set for later */
856  for ( i = 1; i <= nacc; ++i )
857  dfaacc[newds].dfaacc_set[i] = accset[i];
858 
859  accsiz[newds] = nacc;
860  }
861 
862  else
863  { /* find lowest numbered rule so the disambiguating rule will work */
864  j = num_rules + 1;
865 
866  for ( i = 1; i <= nacc; ++i )
867  if ( accset[i] < j )
868  j = accset[i];
869 
870  dfaacc[newds].dfaacc_state = j;
871  }
872 
873  *newds_addr = newds;
874 
875  return ( 1 );
876  }
877 
878 
879 /* symfollowset - follow the symbol transitions one step
880  *
881  * synopsis
882  * int ds[current_max_dfa_size], dsize, transsym;
883  * int nset[current_max_dfa_size], numstates;
884  * numstates = symfollowset( ds, dsize, transsym, nset );
885  */
886 
887 int symfollowset(int ds[], int dsize, int transsym, int nset[])
888 {
889  int ns, tsp, sym, i, j, lenccl, ch, numstates;
890  int ccllist;
891 
892  numstates = 0;
893 
894  for ( i = 1; i <= dsize; ++i )
895  { /* for each nfa state ns in the state set of ds */
896  ns = ds[i];
897  sym = transchar[ns];
898  tsp = trans1[ns];
899 
900  if ( sym < 0 )
901  { /* it's a character class */
902  sym = -sym;
903  ccllist = cclmap[sym];
904  lenccl = ccllen[sym];
905 
906  if ( cclng[sym] )
907  {
908  for ( j = 0; j < lenccl; ++j )
909  { /* loop through negated character class */
910  ch = ccltbl[ccllist + j];
911 
912  if ( ch == 0 )
913  ch = NUL_ec;
914 
915  if ( ch > transsym )
916  break; /* transsym isn't in negated ccl */
917 
918  else if ( ch == transsym )
919  /* next 2 */ goto bottom;
920  }
921 
922  /* didn't find transsym in ccl */
923  nset[++numstates] = tsp;
924  }
925 
926  else
927  for ( j = 0; j < lenccl; ++j )
928  {
929  ch = ccltbl[ccllist + j];
930 
931  if ( ch == 0 )
932  ch = NUL_ec;
933 
934  if ( ch > transsym )
935  break;
936 
937  else if ( ch == transsym )
938  {
939  nset[++numstates] = tsp;
940  break;
941  }
942  }
943  }
944 
945  else if ( sym >= 'A' && sym <= 'Z' && caseins )
946  flexfatal( "consistency check failed in symfollowset" );
947 
948  else if ( sym == SYM_EPSILON )
949  { /* do nothing */
950  }
951 
952  else if ( abs( ecgroup[sym] ) == transsym )
953  nset[++numstates] = tsp;
954 
955 bottom:
956  ;
957  }
958 
959  return ( numstates );
960  }
961 
962 
963 /* sympartition - partition characters with same out-transitions
964  *
965  * synopsis
966  * integer ds[current_max_dfa_size], numstates, duplist[numecs];
967  * symlist[numecs];
968  * sympartition( ds, numstates, symlist, duplist );
969  */
970 
971 void sympartition(int ds[], int numstates, int symlist[], int duplist[])
972 {
973  int tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich;
974 
975  /* partitioning is done by creating equivalence classes for those
976  * characters which have out-transitions from the given state. Thus
977  * we are really creating equivalence classes of equivalence classes.
978  */
979 
980  for ( i = 1; i <= numecs; ++i )
981  { /* initialize equivalence class list */
982  duplist[i] = i - 1;
983  dupfwd[i] = i + 1;
984  }
985 
986  duplist[1] = NIL;
987  dupfwd[numecs] = NIL;
988 
989  for ( i = 1; i <= numstates; ++i )
990  {
991  ns = ds[i];
992  tch = transchar[ns];
993 
994  if ( tch != SYM_EPSILON )
995  {
996  if ( tch < -lastccl || tch > csize )
997  {
998  if ( tch > csize && tch <= CSIZE )
999  flexerror( "scanner requires -8 flag" );
1000 
1001  else
1002  flexfatal(
1003  "bad transition character detected in sympartition()" );
1004  }
1005 
1006  if ( tch >= 0 )
1007  { /* character transition */
1008  /* abs() needed for fake %t ec's */
1009  int ec = abs( ecgroup[tch] );
1010 
1011  mkechar( ec, dupfwd, duplist );
1012  symlist[ec] = 1;
1013  }
1014 
1015  else
1016  { /* character class */
1017  tch = -tch;
1018 
1019  lenccl = ccllen[tch];
1020  cclp = cclmap[tch];
1021  mkeccl( ccltbl + cclp, lenccl, dupfwd, duplist, numecs,
1022  NUL_ec );
1023 
1024  if ( cclng[tch] )
1025  {
1026  j = 0;
1027 
1028  for ( k = 0; k < lenccl; ++k )
1029  {
1030  ich = ccltbl[cclp + k];
1031 
1032  if ( ich == 0 )
1033  ich = NUL_ec;
1034 
1035  for ( ++j; j < ich; ++j )
1036  symlist[j] = 1;
1037  }
1038 
1039  for ( ++j; j <= numecs; ++j )
1040  symlist[j] = 1;
1041  }
1042 
1043  else
1044  for ( k = 0; k < lenccl; ++k )
1045  {
1046  ich = ccltbl[cclp + k];
1047 
1048  if ( ich == 0 )
1049  ich = NUL_ec;
1050 
1051  symlist[ich] = 1;
1052  }
1053  }
1054  }
1055  }
1056  }
#define MAX_ASSOC_RULES
Definition: flexdef.h:263
#define IS_MARKED(state)
int ** dss
Definition: flex.c:92
#define RULE_VARIABLE
Definition: flexdef.h:422
#define MAX_DFAS_INCREMENT
Definition: flexdef.h:174
int * rule_type
Definition: flex.c:78
void stack1(int, int, int, int)
Definition: tblcmp.c:851
int ecgroup[CSIZE+1]
Definition: flex.c:83
int i
Definition: scan.c:967
int fullspd
Definition: flex.c:68
int variable_trailing_context_rules
Definition: flex.c:80
#define YY_TRAILING_HEAD_MASK
Definition: flexdef.h:144
int numuniq
Definition: flex.c:101
void mk1tbl(int, int, int, int)
Definition: tblcmp.c:647
int symfollowset(int[], int, int, int[])
Definition: dfa.c:887
int hshcol
Definition: flex.c:100
#define SYM_EPSILON
Definition: flexdef.h:192
int num_reallocs
Definition: flex.c:100
#define printf
Definition: epicsStdio.h:41
int * cclng
Definition: flex.c:96
int numsnpairs
Definition: flex.c:95
pvd::StructureConstPtr type
void sympartition(int[], int, int[], int[])
Definition: dfa.c:971
#define NIL
Definition: flexdef.h:153
union dfaacc_union * dfaacc
Definition: flex.c:93
void cmptmps(void)
Definition: tblcmp.c:228
void inittbl(void)
Definition: tblcmp.c:430
#define STATE_TRAILING_CONTEXT
Definition: flexdef.h:414
int * dfaacc_set
Definition: flexdef.h:527
#define UNMARK_STATE(state)
int * rule_linenum
Definition: flex.c:78
struct dset dset
#define NUMDATALINES
Definition: flexdef.h:104
void check_trailing_context(int *nfa_states, int num_states, int *accset, int nacc)
Definition: dfa.c:103
#define STACK_STATE(state)
int onestate[ONE_STACK_SIZE]
Definition: flex.c:74
int csize
Definition: flex.c:68
FILE * backtrack_file
Definition: flex.c:104
#define PUT_ON_STACK(state)
int * accsiz
Definition: flex.c:94
int caseins
Definition: flex.c:67
int dfaeql
Definition: flex.c:100
int num_rules
Definition: flex.c:76
#define allocate_integer_array(size)
Definition: flexdef.h:581
int useecs
Definition: flex.c:67
int * dfasiz
Definition: flex.c:92
void dump_transitions(FILE *, int[])
Definition: dfa.c:201
void check_for_backtracking(int ds, int state[])
Definition: dfa.c:59
void list_character_set(FILE *file, int cset[])
Definition: ccl.c:140
int firstfree
Definition: flex.c:92
Definition: devSup.h:140
int lastdfa
Definition: flex.c:91
void dataend(void)
Definition: misc.c:292
int onesp
Definition: flex.c:75
int * scset
Definition: flex.c:87
int numdup
Definition: flex.c:101
int * scbol
Definition: flex.c:87
void flexerror(char[]) NORETURN
int current_max_dfa_size
Definition: flex.c:89
void bubble(int[], int)
Definition: misc.c:152
int NUL_ec
Definition: flex.c:92
int onesym[ONE_STACK_SIZE]
Definition: flex.c:74
int * state_type
Definition: flex.c:78
int end_of_buffer_state
Definition: flex.c:105
int datapos
Definition: flex.c:71
#define NUMDATAITEMS
Definition: flexdef.h:99
void ntod(void)
Definition: dfa.c:398
#define MARKER_DIFFERENCE
Definition: flexdef.h:181
int * epsclosure(int *t, int *ns_addr, int accset[], int *nacc_addr, int *hv_addr)
Definition: dfa.c:249
#define reallocate_int_ptr_array(array, size)
Definition: flexdef.h:597
#define reallocate_integer_array(array, size)
Definition: flexdef.h:584
int onedef[ONE_STACK_SIZE]
Definition: flex.c:75
int * assoc_rule
Definition: flex.c:78
char * program_name
Definition: flex.c:108
int reject
Definition: flex.c:69
int hshsave
Definition: flex.c:101
int onenext[ONE_STACK_SIZE]
Definition: flex.c:75
void flexfatal(char[])
int * trans2
Definition: flex.c:77
int trace
Definition: flex.c:66
int lastsc
Definition: flex.c:87
int * trans1
Definition: flex.c:77
int * ccllen
Definition: flex.c:96
int * cclmap
Definition: flex.c:96
int * nultrans
Definition: flex.c:92
#define NO_TRANSITION
Definition: flexdef.h:156
#define STATE_NORMAL
Definition: flexdef.h:413
int current_max_dfas
Definition: flex.c:90
int mkbranch(int, int)
Definition: nfa.c:358
int snstods(int sns[], int numstates, int accset[], int nacc, int hashval, int *newds_addr)
Definition: dfa.c:763
int num_backtracking
Definition: flex.c:102
int totnst
Definition: flex.c:101
void increase_max_dfas(void)
Definition: dfa.c:370
int * base
Definition: flex.c:92
void dump_associated_rules(FILE *, int)
Definition: dfa.c:149
int * def
Definition: flex.c:92
int dataline
Definition: flex.c:71
#define JAMSTATE
Definition: flexdef.h:176
void bldtbl(int[], int, int, int, int)
#define reallocate_dfaacc_union(array, size)
Definition: flexdef.h:603
#define stderr
Definition: epicsStdio.h:32
Char * ccltbl
Definition: flex.c:98
int dfaacc_state
Definition: flexdef.h:528
int numecs
Definition: flex.c:83
int fulltbl
Definition: flex.c:67
int * transchar
Definition: flex.c:77
void dumpnfa(int)
Definition: nfa.c:106
#define CHECK_ACCEPT(state)
#define CSIZE
Definition: flexdef.h:58
int backtrack_report
Definition: flex.c:68
void mkeccl(unsigned char ccls[], int lenccl, int fwd[], int bck[], int llsiz, int NUL_mapping)
Definition: ecs.c:232
void mkdeftbl(void)
Definition: tblcmp.c:467
int numas
Definition: flex.c:94
int * dhash
Definition: flex.c:94
void mkechar(int tch, int fwd[], int bck[])
Definition: ecs.c:328
void mk2data(int)
Definition: misc.c:494
void place_state(int *, int, int)
Definition: tblcmp.c:807