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 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 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_REMOVE 1 |
| 27 | #define SUBSET_DETERMINIZE 2 |
| 28 | #define SUBSET_TEST_STAR_FREE 3 |
| 29 | |
| 30 | #define NHASH_LOAD_LIMIT 2 /* load limit for nhash table size */ |
| 31 | |
| 32 | static int fsm_linecount, num_states, num_symbols, epsilon_symbol, *single_sigma_array, *double_sigma_array, limit, num_start_states, op; |
| 33 | |
| 34 | static _Bool *finals, deterministic, numss; |
| 35 | |
| 36 | struct e_closure_memo { |
| 37 | int state; |
| 38 | int mark; |
| 39 | struct e_closure_memo *target; |
| 40 | struct e_closure_memo *next; |
| 41 | }; |
| 42 | |
| 43 | static 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 | |
| 45 | static struct e_closure_memo *e_closure_memo; |
| 46 | |
| 47 | int T_last_unmarked, T_limit; |
| 48 | |
| 49 | struct nhash_list { |
| 50 | int setnum; |
| 51 | unsigned int size; |
| 52 | unsigned int set_offset; |
| 53 | struct nhash_list *next; |
| 54 | }; |
| 55 | |
| 56 | struct T_memo { |
| 57 | unsigned char finalstart; |
| 58 | unsigned int size; |
| 59 | unsigned int set_offset; |
| 60 | }; |
| 61 | |
| 62 | struct trans_list { |
| 63 | int inout; |
| 64 | int target; |
| 65 | } *trans_list_determinize; |
| 66 | |
| 67 | struct trans_array { |
| 68 | struct trans_list *transitions; |
| 69 | unsigned int size; |
| 70 | unsigned int tail; |
| 71 | } *trans_array_determinize; |
| 72 | |
| 73 | static struct T_memo *T_ptr; |
| 74 | |
| 75 | static int nhash_tablesize, nhash_load, current_setnum, *e_table, *marktable, *temp_move, mainloop, maxsigma, *set_table, set_table_size, star_free_mark; |
| 76 | static unsigned int set_table_offset; |
| 77 | static struct nhash_list *table; |
| 78 | |
| 79 | extern 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 | |
| 81 | static void init(struct fsm *net); |
| 82 | INLINE static int e_closure(int states); |
| 83 | INLINE static int set_lookup(int *lookup_table, int size); |
| 84 | static int initial_e_closure(struct fsm *network); |
| 85 | static void memoize_e_closure(struct fsm_state *fsm); |
| 86 | static int next_unmarked(void); |
| 87 | static void single_symbol_to_symbol_pair(int symbol, int *symbol_in, int *symbol_out); |
| 88 | static int symbol_pair_to_single_symbol(int in, int out); |
| 89 | static void sigma_to_pairs(struct fsm *net); |
| 90 | static int nhash_find_insert(int *set, int setsize); |
| 91 | INLINE static int hashf(int *set, int setsize); |
| 92 | static int nhash_insert(int hashval, int *set, int setsize); |
| 93 | static void nhash_rebuild_table (); |
| 94 | static void nhash_init (int initial_size); |
| 95 | static void nhash_free(struct nhash_list *nptr, int size); |
| 96 | static void e_closure_free(); |
| 97 | static void init_trans_array(struct fsm *net); |
| 98 | static struct fsm *fsm_subset(struct fsm *net, int operation); |
| 99 | |
| 100 | struct fsm *fsm_epsilon_remove(struct fsm *net) { |
| 101 | return(fsm_subset(net, SUBSET_EPSILON_REMOVE)); |
| 102 | } |
| 103 | |
| 104 | struct fsm *fsm_determinize(struct fsm *net) { |
| 105 | return(fsm_subset(net, SUBSET_DETERMINIZE)); |
| |
| 106 | } |
| 107 | |
| 108 | static struct fsm *fsm_subset(struct fsm *net, int operation) { |
| 109 | |
| 110 | int T, U; |
| 111 | |
| 112 | if (net->is_deterministic == YES && operation != SUBSET_TEST_STAR_FREE) { |
| 2 | | Assuming field 'is_deterministic' is not equal to YES | |
|
| 113 | return(net); |
| 114 | } |
| 115 | |
| 116 | op = operation; |
| 117 | fsm_count(net); |
| 118 | num_states = net->statecount; |
| 119 | deterministic = 1; |
| 120 | init(net); |
| |
| 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 = YES; |
| 129 | net->is_epsilon_free = YES; |
| 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_REMOVE && epsilon_symbol == -1) { |
| 144 | net->is_epsilon_free = YES; |
| 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_FREE) { |
| 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 | |
| 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 | |
| 176 | setsize = (T_ptr+T)->size; |
| 177 | theset = set_table+(T_ptr+T)->set_offset; |
| 178 | minsym = INT_MAX; |
| 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 | |
| 193 | fsm_state_end_state(); |
| 194 | continue; |
| 195 | } |
| 196 | |
| 197 | |
| 198 | |
| 199 | for (next_minsym = INT_MAX; minsym != INT_MAX ; minsym = next_minsym, next_minsym = INT_MAX) { |
| 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_REMOVE) { |
| 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 | |
| 234 | if (transitions->inout < next_minsym) { |
| 235 | next_minsym = transitions->inout; |
| 236 | } |
| 237 | } |
| 238 | if (operation == SUBSET_DETERMINIZE) { |
| 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_FREE) { |
| 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 | |
| 252 | star_free_mark = 0; |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | fsm_state_end_state(); |
| 259 | } while ((T = next_unmarked()) != -1); |
| 260 | |
| 261 | |
| 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 | |
| 279 | static void init(struct fsm *net) { |
| 280 | |
| 281 | |
| 282 | |
| 283 | e_table = calloc(net->statecount,sizeof(int)); |
| 284 | |
| 285 | |
| 286 | |
| 287 | mainloop = 1; |
| 288 | |
| 289 | |
| 290 | |
| 291 | |
| 292 | |
| 293 | temp_move = malloc((net->statecount + 1) *sizeof(int)); |
| 294 | |
| 295 | |
| 296 | |
| 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 | |
| 303 | |
| 304 | |
| 305 | |
| 306 | |
| 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 | |
| 314 | |
| 315 | |
| 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 | |
| 324 | static 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 | |
| 328 | static 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 | |
| 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 | |
| 382 | INLINE static int e_closure(int states) { |
| 383 | |
| 384 | int i, set_size; |
| 385 | struct e_closure_memo *ptr; |
| 386 | |
| 387 | |
| 388 | |
| 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 | |
| 403 | ptr = e_closure_memo + *(temp_move+i); |
| 404 | if (ptr->target == NULL) |
| 405 | continue; |
| 406 | ptr_stack_push(ptr); |
| 407 | |
| 408 | while (!(ptr_stack_isempty())) { |
| 409 | ptr = ptr_stack_pop(); |
| 410 | |
| 411 | if (*(marktable+ptr->state) == mainloop) |
| 412 | continue; |
| 413 | |
| 414 | ptr->mark = mainloop; |
| 415 | *(marktable+ptr->state) = mainloop; |
| 416 | |
| 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) |
| 424 | continue; |
| 425 | |
| 426 | |
| 427 | for (; ptr != NULL ; ptr = ptr->next) { |
| 428 | if (ptr->target->mark != mainloop) { |
| 429 | |
| 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 | |
| 441 | INLINE static int set_lookup (int *lookup_table, int size) { |
| 442 | |
| 443 | |
| 444 | |
| 445 | |
| 446 | return(nhash_find_insert(lookup_table, size)); |
| 447 | |
| 448 | } |
| 449 | |
| 450 | void 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 | |
| 468 | static 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 | |
| 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 | |
| 484 | if ((op == SUBSET_TEST_STAR_FREE) || ((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 | |
| 496 | if (epsilon_symbol != -1) { |
| 497 | memoize_e_closure(fsm); |
| 498 | } |
| 499 | return(e_closure(j)); |
| 500 | } |
| 501 | |
| 502 | static 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 | |
| 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; |
| 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; |
| 535 | ptr = ptr->next; |
| 536 | } |
| 537 | } |
| 538 | } |
| 539 | if (state == -1) { |
| 540 | break; |
| 541 | } |
| 542 | if ((fsm+i)->target == -1) { |
| 543 | continue; |
| 544 | } |
| 545 | |
| 546 | if ((fsm+i)->in == EPSILON && (fsm+i)->out == EPSILON) { |
| 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 | |
| 559 | static 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 | |
| 572 | static 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 | |
| 579 | static int symbol_pair_to_single_symbol(int in, int out) { |
| 580 | return(*(double_sigma_array+maxsigma*in+out)); |
| 581 | } |
| 582 | |
| 583 | static 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< 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 | |
| 604 | |
| 605 | |
| 606 | |
| 607 | |
| 608 | |
| 609 | |
| 610 | |
| 611 | |
| 612 | |
| 613 | |
| 614 | |
| 615 | |
| 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 == UNKNOWN || z == UNKNOWN) |
| 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 == EPSILON && z == EPSILON) { |
| 633 | epsilon_symbol = x; |
| 634 | } |
| 635 | x++; |
| 636 | } |
| 637 | } |
| 638 | num_symbols = x; |
| 639 | } |
| 640 | |
| 641 | |
| 642 | |
| 643 | |
| 644 | |
| 645 | |
| 646 | static 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; tableptr = tableptr->next) { |
| 656 | if ((tableptr)->size != setsize) { |
| 657 | continue; |
| 658 | } else { |
| 659 | |
| 660 | |
| 661 | |
| 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_FREE && found == 1) { |
| 669 | for (j=0, currlist= set_table+tableptr->set_offset; j < setsize; j++) { |
| 670 | if (*(set+j) != *(currlist+j)) { |
| 671 | |
| 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_LIMIT > nhash_tablesize) { |
| 683 | nhash_rebuild_table(); |
| 684 | hashval = hashf(set, setsize); |
| 685 | } |
| 686 | return(nhash_insert(hashval, set, setsize)); |
| 687 | } |
| 688 | } |
| 689 | |
| 690 | INLINE 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 | |
| 703 | static 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 | |
| 717 | static 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 | |
| 750 | static 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; (tableptr = tableptr->next)) { |
| 769 | |
| 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; |
| 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 | |
| 791 | static 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 | } |
| 801 | static 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; eptr != NULL; ) { |
| 808 | eprev = eptr; |
| 809 | eptr = eptr->next; |
| 810 | free(eprev); |
| 811 | } |
| 812 | |
| 813 | } |
| 814 | free(e_closure_memo); |
| 815 | } |
| 816 | |
| 817 | static 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; nptr2 = nnext) { |
| 822 | nnext = nptr2->next; |
| 823 | free(nptr2); |
| 824 | } |
| 825 | } |
| 826 | free(nptr); |
| 827 | } |