Bug Summary

File:determinize.c
Warning:line 626, column 44
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name determinize.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/build/foma/foma-0.10.0+g279~a2d32b38 -resource-dir /usr/lib/llvm-16/lib/clang/16 -D _GNU_SOURCE -D foma_shared_EXPORTS -I /tmp/build/foma/foma-0.10.0+g279~a2d32b38 -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-missing-field-initializers -Wno-deprecated -Wno-unused-parameter -std=c18 -fdebug-compilation-dir=/tmp/build/foma/foma-0.10.0+g279~a2d32b38 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/build/foma/scan-build/2024-09-11-155945-2678-1 -x c /tmp/build/foma/foma-0.10.0+g279~a2d32b38/determinize.c
1/* Foma: a finite-state toolkit and library. */
2/* Copyright © 2008-2021 Mans Hulden */
3
4/* This file is part of foma. */
5
6/* Licensed under the Apache License, Version 2.0 (the "License"); */
7/* you may not use this file except in compliance with the License. */
8/* You may obtain a copy of the License at */
9
10/* http://www.apache.org/licenses/LICENSE-2.0 */
11
12/* Unless required by applicable law or agreed to in writing, software */
13/* distributed under the License is distributed on an "AS IS" BASIS, */
14/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
15/* See the License for the specific language governing permissions and */
16/* limitations under the License. */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <assert.h>
21#include <limits.h>
22#include <stdint.h>
23#include <string.h>
24#include "foma.h"
25
26#define SUBSET_EPSILON_REMOVE1 1
27#define SUBSET_DETERMINIZE2 2
28#define SUBSET_TEST_STAR_FREE3 3
29
30#define NHASH_LOAD_LIMIT2 2 /* load limit for nhash table size */
31
32static int fsm_linecount, num_states, num_symbols, epsilon_symbol, *single_sigma_array, *double_sigma_array, limit, num_start_states, op;
33
34static _Bool *finals, deterministic, numss;
35
36struct e_closure_memo {
37 int state;
38 int mark;
39 struct e_closure_memo *target;
40 struct e_closure_memo *next;
41};
42
43static unsigned int primes[26] = {61,127,251,509,1021,2039,4093,8191,16381,32749,65521,131071,262139,524287,1048573,2097143,4194301,8388593,16777213,33554393,67108859,134217689,268435399,536870909,1073741789,2147483647};
44
45static struct e_closure_memo *e_closure_memo;
46
47int T_last_unmarked, T_limit;
48
49struct nhash_list {
50 int setnum;
51 unsigned int size;
52 unsigned int set_offset;
53 struct nhash_list *next;
54};
55
56struct T_memo {
57 unsigned char finalstart;
58 unsigned int size;
59 unsigned int set_offset;
60};
61
62struct trans_list {
63 int inout;
64 int target;
65} *trans_list_determinize;
66
67struct trans_array {
68 struct trans_list *transitions;
69 unsigned int size;
70 unsigned int tail;
71} *trans_array_determinize;
72
73static struct T_memo *T_ptr;
74
75static int nhash_tablesize, nhash_load, current_setnum, *e_table, *marktable, *temp_move, mainloop, maxsigma, *set_table, set_table_size, star_free_mark;
76static unsigned int set_table_offset;
77static struct nhash_list *table;
78
79extern int add_fsm_arc(struct fsm_state *fsm, int offset, int state_no, int in, int out, int target, int final_state, int start_state);
80
81static void init(struct fsm *net);
82INLINEinline static int e_closure(int states);
83INLINEinline static int set_lookup(int *lookup_table, int size);
84static int initial_e_closure(struct fsm *network);
85static void memoize_e_closure(struct fsm_state *fsm);
86static int next_unmarked(void);
87static void single_symbol_to_symbol_pair(int symbol, int *symbol_in, int *symbol_out);
88static int symbol_pair_to_single_symbol(int in, int out);
89static void sigma_to_pairs(struct fsm *net);
90static int nhash_find_insert(int *set, int setsize);
91INLINEinline static int hashf(int *set, int setsize);
92static int nhash_insert(int hashval, int *set, int setsize);
93static void nhash_rebuild_table ();
94static void nhash_init (int initial_size);
95static void nhash_free(struct nhash_list *nptr, int size);
96static void e_closure_free();
97static void init_trans_array(struct fsm *net);
98static struct fsm *fsm_subset(struct fsm *net, int operation);
99
100struct fsm *fsm_epsilon_remove(struct fsm *net) {
101 return(fsm_subset(net, SUBSET_EPSILON_REMOVE1));
102}
103
104struct fsm *fsm_determinize(struct fsm *net) {
105 return(fsm_subset(net, SUBSET_DETERMINIZE2));
1
Calling 'fsm_subset'
106}
107
108static struct fsm *fsm_subset(struct fsm *net, int operation) {
109
110 int T, U;
111
112 if (net->is_deterministic == YES1 && operation != SUBSET_TEST_STAR_FREE3) {
2
Assuming field 'is_deterministic' is not equal to YES
113 return(net);
114 }
115 /* Export this var */
116 op = operation;
117 fsm_count(net);
118 num_states = net->statecount;
119 deterministic = 1;
120 init(net);
3
Calling 'init'
121 nhash_init((num_states < 12) ? 6 : num_states/2);
122
123 T = initial_e_closure(net);
124
125 int_stack_clear();
126
127 if (deterministic == 1 && epsilon_symbol == -1 && num_start_states == 1 && numss == 0) {
128 net->is_deterministic = YES1;
129 net->is_epsilon_free = YES1;
130 nhash_free(table, nhash_tablesize);
131 free(T_ptr);
132 free(e_table);
133 free(trans_list_determinize);
134 free(trans_array_determinize);
135 free(double_sigma_array);
136 free(single_sigma_array);
137 free(finals);
138 free(temp_move);
139 free(set_table);
140 return(net);
141 }
142
143 if (operation == SUBSET_EPSILON_REMOVE1 && epsilon_symbol == -1) {
144 net->is_epsilon_free = YES1;
145 nhash_free(table, nhash_tablesize);
146 free(T_ptr);
147 free(e_table);
148 free(trans_list_determinize);
149 free(trans_array_determinize);
150 free(double_sigma_array);
151 free(single_sigma_array);
152 free(finals);
153 free(temp_move);
154 free(set_table);
155 return(net);
156 }
157
158 if (operation == SUBSET_TEST_STAR_FREE3) {
159 fsm_state_init(sigma_max(net->sigma)+1);
160 star_free_mark = 0;
161 } else {
162 fsm_state_init(sigma_max(net->sigma));
163 free(net->states);
164 }
165
166 /* init */
167
168 do {
169 int i, j, tail, setsize, *theset, stateno, has_trans, minsym, next_minsym, trgt, symbol_in, symbol_out;
170 struct trans_list *transitions;
171 struct trans_array *tptr;
172
173 fsm_state_set_current_state(T, (T_ptr+T)->finalstart, T == 0 ? 1 : 0);
174
175 /* Prepare set */
176 setsize = (T_ptr+T)->size;
177 theset = set_table+(T_ptr+T)->set_offset;
178 minsym = INT_MAX2147483647;
179 has_trans = 0;
180 for (i = 0; i < setsize; i++) {
181 stateno = *(theset+i);
182 tptr = trans_array_determinize+stateno;
183 tptr->tail = 0;
184 if (tptr->size == 0)
185 continue;
186 if ((tptr->transitions)->inout < minsym) {
187 minsym = (tptr->transitions)->inout;
188 has_trans = 1;
189 }
190 }
191 if (!has_trans) {
192 /* close state */
193 fsm_state_end_state();
194 continue;
195 }
196
197 /* While set not empty */
198
199 for (next_minsym = INT_MAX2147483647; minsym != INT_MAX2147483647 ; minsym = next_minsym, next_minsym = INT_MAX2147483647) {
200 theset = set_table+(T_ptr+T)->set_offset;
201
202 for (i = 0, j = 0 ; i < setsize; i++) {
203
204 stateno = *(theset+i);
205 tptr = trans_array_determinize+stateno;
206 tail = tptr->tail;
207 transitions = (tptr->transitions)+tail;
208
209 while (tail < tptr->size && transitions->inout == minsym) {
210 trgt = transitions->target;
211 if (*(e_table+(trgt)) != mainloop) {
212 *(e_table+(trgt)) = mainloop;
213 *(temp_move+j) = trgt;
214 j++;
215
216 if (operation == SUBSET_EPSILON_REMOVE1) {
217 mainloop++;
218 if ((U = e_closure(j)) != -1) {
219 single_symbol_to_symbol_pair(minsym, &symbol_in, &symbol_out);
220 fsm_state_add_arc(T, symbol_in, symbol_out, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0);
221 j = 0;
222 }
223 }
224 }
225 tail++;
226 transitions++;
227 }
228
229 tptr->tail = tail;
230
231 if (tail == tptr->size)
232 continue;
233 /* Check next minsym */
234 if (transitions->inout < next_minsym) {
235 next_minsym = transitions->inout;
236 }
237 }
238 if (operation == SUBSET_DETERMINIZE2) {
239 mainloop++;
240 if ((U = e_closure(j)) != -1) {
241 single_symbol_to_symbol_pair(minsym, &symbol_in, &symbol_out);
242 fsm_state_add_arc(T, symbol_in, symbol_out, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0);
243 }
244 }
245 if (operation == SUBSET_TEST_STAR_FREE3) {
246 mainloop++;
247 if ((U = e_closure(j)) != -1) {
248 single_symbol_to_symbol_pair(minsym, &symbol_in, &symbol_out);
249 fsm_state_add_arc(T, symbol_in, symbol_out, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0);
250 if (star_free_mark == 1) {
251 //fsm_state_add_arc(T, maxsigma, maxsigma, U, (T_ptr+T)->finalstart, T == 0 ? 1 : 0);
252 star_free_mark = 0;
253 }
254 }
255 }
256 }
257 /* end state */
258 fsm_state_end_state();
259 } while ((T = next_unmarked()) != -1);
260
261 /* wrapup() */
262 nhash_free(table, nhash_tablesize);
263 free(set_table);
264 free(T_ptr);
265 free(temp_move);
266 free(e_table);
267 free(trans_list_determinize);
268 free(trans_array_determinize);
269
270 if (epsilon_symbol != -1)
271 e_closure_free();
272 free(double_sigma_array);
273 free(single_sigma_array);
274 free(finals);
275 fsm_state_close(net);
276 return(net);
277}
278
279static void init(struct fsm *net) {
280 /* A temporary table for handling epsilon closure */
281 /* to avoid doubles */
282
283 e_table = calloc(net->statecount,sizeof(int));
284
285 /* Counter for our access tables */
286
287 mainloop = 1;
288
289 /* Temporary table for storing sets and */
290 /* passing to hash function */
291
292 /* Table for listing current results of move & e-closure */
293 temp_move = malloc((net->statecount + 1) *sizeof(int));
294
295 /* We malloc this much memory to begin with for the new fsm */
296 /* Then grow it by the double as needed */
297
298 limit = next_power_of_two(net->linecount);
299 fsm_linecount = 0;
300 sigma_to_pairs(net);
4
Calling 'sigma_to_pairs'
301
302 /* Optimistically malloc T_ptr array */
303 /* We allocate memory for a number of pointers to a set of states */
304 /* To handle fast lookup in array */
305 /* Optimistically, we choose the initial size to be the number of */
306 /* states in the non-deterministic fsm */
307
308 T_last_unmarked = 0;
309 T_limit = next_power_of_two(num_states);
310
311 T_ptr = calloc(T_limit,sizeof(struct T_memo));
312
313 /* Stores all sets consecutively in one table */
314 /* T_ptr->set_offset and size */
315 /* are used to retrieve the set */
316
317 set_table_size = next_power_of_two(num_states);
318 set_table = malloc(set_table_size*sizeof(int));
319 set_table_offset = 0;
320
321 init_trans_array(net);
322}
323
324static int trans_sort_cmp(const void *a, const void *b) {
325 return (((const struct trans_list *)a)->inout - ((const struct trans_list *)b)->inout);
326}
327
328static void init_trans_array(struct fsm *net) {
329 struct trans_list *arrptr;
330 struct fsm_state *fsm;
331 int i, j, laststate, lastsym, inout, size, state;
332
333 arrptr = trans_list_determinize = malloc(net->linecount * sizeof(struct trans_list));
334 trans_array_determinize = calloc(net->statecount, sizeof(struct trans_array));
335
336 laststate = -1;
337 fsm = net->states;
338
339 for (i=0, size = 0; (fsm+i)->state_no != -1; i++) {
340 state = (fsm+i)->state_no;
341 if (state != laststate) {
342 if (laststate != -1) {
343 (trans_array_determinize+laststate)->size = size;
344 }
345 (trans_array_determinize+state)->transitions = arrptr;
346 size = 0;
347 }
348 laststate = state;
349
350 if ((fsm+i)->target == -1)
351 continue;
352 inout = symbol_pair_to_single_symbol((fsm+i)->in, (fsm+i)->out);
353 if (inout == epsilon_symbol)
354 continue;
355
356 arrptr->inout = inout;
357 arrptr->target = (fsm+i)->target;
358 arrptr++;
359 size++;
360 }
361
362 if (laststate != -1) {
363 (trans_array_determinize+laststate)->size = size;
364 }
365
366 for (i=0; i < net->statecount; i++) {
367 arrptr = (trans_array_determinize+i)->transitions;
368 size = (trans_array_determinize+i)->size;
369 if (size > 1) {
370 qsort(arrptr, size, sizeof(struct trans_list), trans_sort_cmp);
371 lastsym = -1;
372 /* Figure out if we're already deterministic */
373 for (j=0; j < size; j++) {
374 if ((arrptr+j)->inout == lastsym)
375 deterministic = 0;
376 lastsym = (arrptr+j)->inout;
377 }
378 }
379 }
380}
381
382INLINEinline static int e_closure(int states) {
383
384 int i, set_size;
385 struct e_closure_memo *ptr;
386
387 /* e_closure extends the list of states which are reachable */
388 /* and appends these to e_table */
389
390 if (epsilon_symbol == -1)
391 return(set_lookup(temp_move, states));
392
393 if (states == 0)
394 return -1;
395
396 mainloop--;
397
398 set_size = states;
399
400 for (i = 0; i < states; i++) {
401
402 /* State number we want to do e-closure on */
403 ptr = e_closure_memo + *(temp_move+i);
404 if (ptr->target == NULL((void*)0))
405 continue;
406 ptr_stack_push(ptr);
407
408 while (!(ptr_stack_isempty())) {
409 ptr = ptr_stack_pop();
410 /* Don't follow if already seen */
411 if (*(marktable+ptr->state) == mainloop)
412 continue;
413
414 ptr->mark = mainloop;
415 *(marktable+ptr->state) = mainloop;
416 /* Add to tail of list */
417 if (*(e_table+(ptr->state)) != mainloop) {
418 *(temp_move+set_size) = ptr->state;
419 *(e_table+(ptr->state)) = mainloop;
420 set_size++;
421 }
422
423 if (ptr->target == NULL((void*)0))
424 continue;
425 /* Traverse chain */
426
427 for (; ptr != NULL((void*)0) ; ptr = ptr->next) {
428 if (ptr->target->mark != mainloop) {
429 /* Push */
430 ptr->target->mark = mainloop;
431 ptr_stack_push(ptr->target);
432 }
433 }
434 }
435 }
436
437 mainloop++;
438 return(set_lookup(temp_move, set_size));
439}
440
441INLINEinline static int set_lookup (int *lookup_table, int size) {
442
443 /* Look up a set and its corresponding state number */
444 /* if it doesn't exist from before, assign a state number */
445
446 return(nhash_find_insert(lookup_table, size));
447
448}
449
450void add_T_ptr(int setnum, int setsize, unsigned int theset, int fs) {
451
452 int i;
453 if (setnum >= T_limit) {
454 T_limit *= 2;
455 T_ptr = realloc(T_ptr, sizeof(struct T_memo)*T_limit);
456 for (i=setnum; i < T_limit; i++) {
457 (T_ptr+i)->size = 0;
458 }
459 }
460
461 (T_ptr + setnum)->size = setsize;
462 (T_ptr + setnum)->set_offset = theset;
463 (T_ptr + setnum)->finalstart = fs;
464 int_stack_push(setnum);
465
466}
467
468static int initial_e_closure(struct fsm *net) {
469
470 struct fsm_state *fsm;
471 int i,j;
472
473 finals = calloc(num_states, sizeof(_Bool));
474
475 num_start_states = 0;
476 fsm = net->states;
477
478 /* Create lookups for each state */
479 for (i=0,j=0; (fsm+i)->state_no != -1; i++) {
480 if ((fsm+i)->final_state) {
481 finals[(fsm+i)->state_no] = 1;
482 }
483 /* Add the start states as the initial set */
484 if ((op == SUBSET_TEST_STAR_FREE3) || ((fsm+i)->start_state)) {
485 if (*(e_table+((fsm+i)->state_no)) != mainloop) {
486 num_start_states++;
487 numss = (fsm+i)->state_no;
488 *(e_table+((fsm+i)->state_no)) = mainloop;
489 *(temp_move+j) = (fsm+i)->state_no;
490 j++;
491 }
492 }
493 }
494 mainloop++;
495 /* Memoize e-closure(u) */
496 if (epsilon_symbol != -1) {
497 memoize_e_closure(fsm);
498 }
499 return(e_closure(j));
500}
501
502static void memoize_e_closure(struct fsm_state *fsm) {
503
504 int i, state, laststate, *redcheck;
505 struct e_closure_memo *ptr;
506
507 e_closure_memo = calloc(num_states,sizeof(struct e_closure_memo));
508 marktable = calloc(num_states,sizeof(int));
509 /* Table for avoiding redundant epsilon arcs in closure */
510 redcheck = malloc(num_states*sizeof(int));
511
512 for (i=0; i < num_states; i++) {
513 ptr = e_closure_memo+i;
514 ptr->state = i;
515 ptr->target = NULL((void*)0);
516 *(redcheck+i) = -1;
517 }
518
519 laststate = -1;
520
521 for (i=0; ;i++) {
522
523 state = (fsm+i)->state_no;
524
525 if (state != laststate) {
526 if (!int_stack_isempty()) {
527 deterministic = 0;
528 ptr = e_closure_memo+laststate;
529 ptr->target = e_closure_memo+int_stack_pop();
530 while (!int_stack_isempty()) {
531 ptr->next = malloc(sizeof(struct e_closure_memo));
532 ptr->next->state = laststate;
533 ptr->next->target = e_closure_memo+int_stack_pop();
534 ptr->next->next = NULL((void*)0);
535 ptr = ptr->next;
536 }
537 }
538 }
539 if (state == -1) {
540 break;
541 }
542 if ((fsm+i)->target == -1) {
543 continue;
544 }
545 /* Check if we have a redundant epsilon arc */
546 if ((fsm+i)->in == EPSILON0 && (fsm+i)->out == EPSILON0) {
547 if (*(redcheck+((fsm+i)->target)) != (fsm+i)->state_no) {
548 if ((fsm+i)->target != (fsm+i)->state_no) {
549 int_stack_push((fsm+i)->target);
550 *(redcheck+((fsm+i)->target)) = (fsm+i)->state_no;
551 }
552 }
553 laststate = state;
554 }
555 }
556 free(redcheck);
557}
558
559static int next_unmarked(void) {
560 if ((int_stack_isempty()))
561 return -1;
562 return(int_stack_pop());
563
564 if ((T_limit <= T_last_unmarked + 1) || (T_ptr+T_last_unmarked+1)->size == 0) {
565 return -1;
566 } else {
567 T_last_unmarked++;
568 return(T_last_unmarked);
569 }
570}
571
572static void single_symbol_to_symbol_pair(int symbol, int *symbol_in, int *symbol_out) {
573
574 *symbol_in = *(single_sigma_array+(symbol*2));
575 *symbol_out = *(single_sigma_array+(symbol*2+1));
576
577}
578
579static int symbol_pair_to_single_symbol(int in, int out) {
580 return(*(double_sigma_array+maxsigma*in+out));
581}
582
583static void sigma_to_pairs(struct fsm *net) {
584
585 int i, j, x, y, z, next_x = 0;
586 struct fsm_state *fsm;
587
588 fsm = net->states;
589
590 epsilon_symbol = -1;
591 maxsigma = sigma_max(net->sigma);
592 maxsigma++;
593
594 single_sigma_array = malloc(2*maxsigma*maxsigma*sizeof(int));
595 double_sigma_array = malloc(maxsigma*maxsigma*sizeof(int));
5
Storing uninitialized value
596
597 for (i=0; i < maxsigma; i++) {
6
Assuming 'i' is < 'maxsigma'
7
Loop condition is true. Entering loop body
11
Loop condition is false. Execution continues on line 617
598 for (j=0; j
7.1
'j' is < 'maxsigma'
< maxsigma
; j++) {
8
Loop condition is true. Entering loop body
9
Assuming 'j' is >= 'maxsigma'
10
Loop condition is false. Execution continues on line 597
599 *(double_sigma_array+maxsigma*i+j) = -1;
600 }
601 }
602
603 /* f(x) -> y,z sigma pair */
604 /* f(y,z) -> x simple entry */
605 /* if exists f(n) <-> EPSILON, EPSILON, save n */
606 /* symbol(x) x>=1 */
607
608 /* Forward mapping: */
609 /* *(double_sigma_array+maxsigma*in+out) */
610
611 /* Backmapping: */
612 /* *(single_sigma_array+(symbol*2) = in(symbol) */
613 /* *(single_sigma_array+(symbol*2+1) = out(symbol) */
614
615 /* Table for checking whether a state is final */
616
617 x = 0;
618 net->arity = 1;
619 for (i=0; (fsm+i)->state_no != -1; i++) {
12
Assuming the condition is true
13
Loop condition is true. Entering loop body
620 y = (fsm+i)->in;
621 z = (fsm+i)->out;
622 if ((y == -1) || (z == -1))
14
Assuming the condition is false
15
Assuming the condition is false
623 continue;
624 if (y != z || y == UNKNOWN1 || z == UNKNOWN1)
16
Assuming 'y' is equal to 'z'
17
Assuming 'y' is equal to UNKNOWN
625 net->arity = 2;
626 if (*(double_sigma_array+maxsigma*y+z) == -1) {
18
The left operand of '==' is a garbage value
627 *(double_sigma_array+maxsigma*y+z) = x;
628 *(single_sigma_array+next_x) = y;
629 next_x++;
630 *(single_sigma_array+next_x) = z;
631 next_x++;
632 if (y == EPSILON0 && z == EPSILON0) {
633 epsilon_symbol = x;
634 }
635 x++;
636 }
637 }
638 num_symbols = x;
639}
640
641
642/* Functions for hashing n integers */
643/* with permutations hashing to the same value */
644/* necessary for subset construction */
645
646static int nhash_find_insert(int *set, int setsize) {
647 int j, found, *currlist;
648 struct nhash_list *tableptr;
649 unsigned int hashval;
650
651 hashval = hashf(set, setsize);
652 if ((table+hashval)->size == 0) {
653 return(nhash_insert(hashval, set, setsize));
654 } else {
655 for (tableptr=(table+hashval); tableptr != NULL((void*)0); tableptr = tableptr->next) {
656 if ((tableptr)->size != setsize) {
657 continue;
658 } else {
659 /* Compare the list at hashval position */
660 /* to the current set by looking at etable */
661 /* entries */
662 for (j=0, found = 1, currlist= set_table+tableptr->set_offset; j < setsize; j++) {
663 if (*(e_table+(*(currlist+j))) != (mainloop-1)) {
664 found = 0;
665 break;
666 }
667 }
668 if (op == SUBSET_TEST_STAR_FREE3 && found == 1) {
669 for (j=0, currlist= set_table+tableptr->set_offset; j < setsize; j++) {
670 if (*(set+j) != *(currlist+j)) {
671 /* Set mark */
672 star_free_mark = 1;
673 }
674 }
675 }
676 if (found == 1) {
677 return(tableptr->setnum);
678 }
679 }
680 }
681
682 if (nhash_load / NHASH_LOAD_LIMIT2 > nhash_tablesize) {
683 nhash_rebuild_table();
684 hashval = hashf(set, setsize);
685 }
686 return(nhash_insert(hashval, set, setsize));
687 }
688}
689
690INLINEinline static int hashf(int *set, int setsize) {
691 int i;
692 unsigned int hashval, sum = 0;
693 hashval = 6703271;
694 for (i = 0; i < setsize; i++) {
695 hashval = (unsigned int) (*(set+i) + 1103 * setsize) * hashval;
696 sum += *(set+i) + i;
697 }
698 hashval = hashval + sum * 31;
699 hashval = (hashval % nhash_tablesize);
700 return hashval;
701}
702
703static unsigned int move_set(int *set, int setsize) {
704 unsigned int old_offset;
705 if (set_table_offset + setsize >= set_table_size) {
706 while (set_table_offset + setsize >= set_table_size) {
707 set_table_size *= 2;
708 }
709 set_table = realloc(set_table, set_table_size * sizeof(int));
710 }
711 memcpy(set_table+set_table_offset, set, setsize * sizeof(int));
712 old_offset = set_table_offset;
713 set_table_offset += setsize;
714 return(old_offset);
715}
716
717static int nhash_insert(int hashval, int *set, int setsize) {
718 struct nhash_list *tableptr;
719 int i, fs = 0;
720
721 current_setnum++;
722 tableptr = table+hashval;
723
724 nhash_load++;
725 for (i = 0; i < setsize; i++) {
726 if (finals[*(set+i)])
727 fs = 1;
728 }
729 if (tableptr->size == 0) {
730
731 tableptr->set_offset = move_set(set, setsize);
732 tableptr->size = setsize;
733 tableptr->setnum = current_setnum;
734
735 add_T_ptr(current_setnum, setsize, tableptr->set_offset, fs);
736 return(current_setnum);
737 }
738
739 tableptr = malloc(sizeof(struct nhash_list));
740 tableptr->next = (table+hashval)->next;
741 (table+hashval)->next = tableptr;
742 tableptr->setnum = current_setnum;
743 tableptr->size = setsize;
744 tableptr->set_offset = move_set(set, setsize);
745
746 add_T_ptr(current_setnum, setsize, tableptr->set_offset, fs);
747 return(current_setnum);
748}
749
750static void nhash_rebuild_table () {
751 int i, oldsize;
752 struct nhash_list *oldtable, *tableptr, *ntableptr, *newptr;
753 unsigned int hashval;
754
755 oldtable = table;
756 oldsize = nhash_tablesize;
757
758 nhash_load = 0;
759 for (i=0; primes[i] < nhash_tablesize; i++) { }
760 nhash_tablesize = primes[(i+1)];
761
762 table = calloc(nhash_tablesize,sizeof(struct nhash_list));
763 for (i=0; i < oldsize;i++) {
764 if ((oldtable+i)->size == 0) {
765 continue;
766 }
767 tableptr = oldtable+i;
768 for ( ; tableptr != NULL((void*)0); (tableptr = tableptr->next)) {
769 /* rehash */
770 hashval = hashf(set_table+tableptr->set_offset,tableptr->size);
771 ntableptr = table+hashval;
772 if (ntableptr->size == 0) {
773 nhash_load++;
774 ntableptr->size = tableptr->size;
775 ntableptr->set_offset = tableptr->set_offset;
776 ntableptr->setnum = tableptr->setnum;
777 ntableptr->next = NULL((void*)0);
778 } else {
779 newptr = malloc(sizeof(struct nhash_list));
780 newptr->next = ntableptr->next;
781 ntableptr->next = newptr;
782 newptr->setnum = tableptr->setnum;
783 newptr->size = tableptr->size;
784 newptr->set_offset = tableptr->set_offset;
785 }
786 }
787 }
788 nhash_free(oldtable, oldsize);
789}
790
791static void nhash_init (int initial_size) {
792
793 int i;
794
795 for (i=0; primes[i] < initial_size; i++) { }
796 nhash_load = 0;
797 nhash_tablesize = primes[i];
798 table = calloc(nhash_tablesize , sizeof(struct nhash_list));
799 current_setnum = -1;
800}
801static void e_closure_free() {
802 int i;
803 struct e_closure_memo *eptr, *eprev;
804 free(marktable);
805 for (i=0;i < num_states; i++) {
806 eptr = (e_closure_memo+i)->next;
807 for (eprev = NULL((void*)0); eptr != NULL((void*)0); ) {
808 eprev = eptr;
809 eptr = eptr->next;
810 free(eprev);
811 }
812
813 }
814 free(e_closure_memo);
815}
816
817static void nhash_free(struct nhash_list *nptr, int size) {
818 struct nhash_list *nptr2, *nnext;
819 int i;
820 for (i=0; i < size; i++) {
821 for (nptr2 = (nptr+i)->next; nptr2 != NULL((void*)0); nptr2 = nnext) {
822 nnext = nptr2->next;
823 free(nptr2);
824 }
825 }
826 free(nptr);
827}