Bug Summary

File:structures.c
Warning:line 796, column 5
Potential leak of memory pointed to by 'newstring'

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 structures.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 -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/structures.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 <string.h>
20#include <stdlib.h>
21#include "foma.h"
22
23static struct defined_quantifiers *quantifiers;
24struct _fsm_options fsm_options;
25
26char *fsm_get_library_version_string() {
27 static char s[20];
28 sprintf(s,"%i.%i.%i%s",MAJOR_VERSION0,MINOR_VERSION10,BUILD_VERSION0,STATUS_VERSION"alpha");
29 return(s);
30}
31
32_Bool fsm_set_option(unsigned long long option, void *value) {
33 switch (option) {
34 case FSMO_SKIP_WORD_BOUNDARY_MARKER:
35 fsm_options.skip_word_boundary_marker = *((_Bool*)value);
36 return 1;
37 }
38 return 0;
39}
40
41void *fsm_get_option(unsigned long long option) {
42 switch (option) {
43 case FSMO_SKIP_WORD_BOUNDARY_MARKER:
44 return &fsm_options.skip_word_boundary_marker;
45 }
46 return NULL((void*)0);
47}
48
49int linesortcompin(struct fsm_state *a, struct fsm_state *b) {
50 return (a->in - b->in);
51}
52
53int linesortcompout(struct fsm_state *a, struct fsm_state *b) {
54 return (a->out - b->out);
55}
56
57void fsm_sort_arcs(struct fsm *net, int direction) {
58 /* direction 1 = in, direction = 2, out */
59 struct fsm_state *fsm;
60 int i, lasthead, numlines;
61 int(*scin)() = linesortcompin;
62 int(*scout)() = linesortcompout;
63 fsm = net->states;
64 for (i=0, numlines = 0, lasthead = 0 ; (fsm+i)->state_no != -1; i++) {
65 if ((fsm+i)->state_no != (fsm+i+1)->state_no || (fsm+i)->target == -1) {
66 numlines++;
67 if ((fsm+i)->target == -1) {
68 numlines--;
69 }
70 if (numlines > 1) {
71 /* Sort, set numlines = 0 */
72 if (direction == 1)
73 qsort(fsm+lasthead, numlines, sizeof(struct fsm_state), scin);
74 else
75 qsort(fsm+lasthead, numlines, sizeof(struct fsm_state), scout);
76 }
77 numlines = 0;
78 lasthead = i + 1;
79 continue;
80 }
81 numlines++;
82 }
83 if (net->arity == 1) {
84 net->arcs_sorted_in = 1;
85 net->arcs_sorted_out = 1;
86 return;
87 }
88 if (direction == 1) {
89 net->arcs_sorted_in = 1;
90 net->arcs_sorted_out = 0;
91 }
92 if (direction == 2) {
93 net->arcs_sorted_out = 1;
94 net->arcs_sorted_in = 0;
95 }
96}
97
98struct state_array *map_firstlines(struct fsm *net) {
99 struct fsm_state *fsm;
100 struct state_array *sa;
101 int i, sold;
102 sold = -1;
103 sa = malloc(sizeof(struct state_array)*((net->statecount)+1));
104 fsm = net->states;
105 for (i=0; (fsm+i)->state_no != -1; i++) {
106 if ((fsm+i)->state_no != sold) {
107 (sa+((fsm+i)->state_no))->transitions = fsm+i;
108 sold = (fsm+i)->state_no;
109 }
110 }
111 return(sa);
112}
113
114struct fsm *fsm_boolean(int value) {
115 if (value == 0)
116 return (fsm_empty_set());
117 else
118 return(fsm_empty_string());
119}
120
121struct fsm *fsm_sigma_net(struct fsm *net) {
122 /* Extract sigma and create net with one arc */
123 /* from state 0 to state 1 with each (state 1 is final) */
124 struct sigma *sig;
125 int pathcount;
126
127 if (sigma_size(net->sigma) == 0) {
128 fsm_destroy(net);
129 return(fsm_empty_set());
130 }
131
132 fsm_state_init(sigma_max(net->sigma));
133 fsm_state_set_current_state(0, 0, 1);
134 pathcount = 0;
135 for (sig = net->sigma; sig != NULL((void*)0); sig = sig->next) {
136 if (sig->number >=3 || sig->number == IDENTITY2) {
137 pathcount++;
138 fsm_state_add_arc(0,sig->number, sig->number, 1, 0, 1);
139 }
140 }
141 fsm_state_end_state();
142 fsm_state_set_current_state(1, 1, 0);
143 fsm_state_end_state();
144 free(net->states);
145 fsm_state_close(net);
146 net->is_minimized = YES1;
147 net->is_loop_free = YES1;
148 net->pathcount = pathcount;
149 sigma_cleanup(net, 1);
150 return(net);
151}
152
153struct fsm *fsm_sigma_pairs_net(struct fsm *net) {
154 /* Create FSM of attested pairs */
155 struct fsm_state *fsm;
156 char *pairs;
157 short int in, out;
158 int i, pathcount, smax;
159
160 smax = sigma_max(net->sigma)+1;
161 pairs = calloc(smax*smax, sizeof(char));
162
163 fsm_state_init(sigma_max(net->sigma));
164 fsm_state_set_current_state(0, 0, 1);
165 pathcount = 0;
166 for (fsm = net->states, i=0; (fsm+i)->state_no != -1; i++) {
167 if ((fsm+i)->target == -1)
168 continue;
169 in = (fsm+i)->in;
170 out = (fsm+i)->out;
171 if (*(pairs+smax*in+out) == 0) {
172 fsm_state_add_arc(0,in,out, 1, 0, 1);
173 *(pairs+smax*in+out) = 1;
174 pathcount++;
175 }
176 }
177 fsm_state_end_state();
178 fsm_state_set_current_state(1, 1, 0);
179 fsm_state_end_state();
180
181 free(pairs);
182 free(net->states);
183
184 fsm_state_close(net);
185 if (pathcount == 0) {
186 fsm_destroy(net);
187 return(fsm_empty_set());
188 }
189 net->is_minimized = YES1;
190 net->is_loop_free = YES1;
191 net->pathcount = pathcount;
192 sigma_cleanup(net, 1);
193 return(net);
194}
195
196int fsm_sigma_destroy(struct sigma *sigma) {
197 struct sigma *sig, *sigp;
198 for (sig = sigma, sigp = NULL((void*)0); sig != NULL((void*)0); sig = sigp) {
199 sigp = sig->next;
200 if (sig->symbol != NULL((void*)0)) {
201 free(sig->symbol);
202 sig->symbol = NULL((void*)0);
203 }
204 free(sig);
205 }
206 return 1;
207}
208
209int fsm_destroy(struct fsm *net) {
210 if (net == NULL((void*)0)) {
211 return 0;
212 }
213 if (net->medlookup != NULL((void*)0) && net->medlookup->confusion_matrix != NULL((void*)0)) {
214 free(net->medlookup->confusion_matrix);
215 net->medlookup->confusion_matrix = NULL((void*)0);
216 }
217 if (net->medlookup != NULL((void*)0)) {
218 free(net->medlookup);
219 net->medlookup = NULL((void*)0);
220 }
221 fsm_sigma_destroy(net->sigma);
222 net->sigma = NULL((void*)0);
223 if (net->states != NULL((void*)0)) {
224 free(net->states);
225 net->states = NULL((void*)0);
226 }
227 free(net);
228 return(1);
229}
230
231struct fsm *fsm_create (char *name) {
232 if (strlen(name) > FSM_NAME_LEN40) {
233 printf("Network name '%s' should consist of at most %d characters.\n", name, FSM_NAME_LEN40);
234 }
235 struct fsm *fsm;
236 fsm = malloc(sizeof(struct fsm));
237 strncpy(fsm->name, name, FSM_NAME_LEN40);
238 fsm->arity = 1;
239 fsm->arccount = 0;
240 fsm->is_deterministic = NO0;
241 fsm->is_pruned = NO0;
242 fsm->is_minimized = NO0;
243 fsm->is_epsilon_free = NO0;
244 fsm->is_loop_free = NO0;
245 fsm->arcs_sorted_in = NO0;
246 fsm->arcs_sorted_out = NO0;
247 fsm->sigma = sigma_create();
248 fsm->states = NULL((void*)0);
249 fsm->medlookup = NULL((void*)0);
250 return(fsm);
251}
252
253struct fsm *fsm_empty_string() {
254 struct fsm *net;
255 net = fsm_create("");
256 net->states = malloc(sizeof(struct fsm_state)*2);
257 add_fsm_arc(net->states, 0, 0, -1, -1, -1, 1, 1);
258 add_fsm_arc(net->states, 1, -1, -1, -1, -1, -1, -1);
259 fsm_update_flags(net,YES1,YES1,YES1,YES1,YES1,NO0);
260 net->statecount = 1;
261 net->finalcount = 1;
262 net->arccount = 0;
263 net->linecount = 2;
264 net->pathcount = 1;
265 return(net);
266}
267
268struct fsm *fsm_identity() {
269 struct fsm *net;
270 struct sigma *sigma;
271 net = fsm_create("");
272 free(net->sigma);
273 net->states = malloc(sizeof(struct fsm_state)*3);
274 add_fsm_arc(net->states, 0, 0, 2, 2, 1, 0, 1);
275 add_fsm_arc(net->states, 1, 1, -1, -1, -1, 1, 0);
276 add_fsm_arc(net->states, 2, -1, -1, -1, -1, -1, -1);
277 sigma = malloc(sizeof(struct sigma));
278 sigma->number = IDENTITY2;
279 sigma->symbol = strdup("@_IDENTITY_SYMBOL_@");
280 sigma->next = NULL((void*)0);
281 net->sigma = sigma;
282 fsm_update_flags(net,YES1,YES1,YES1,YES1,YES1,NO0);
283 net->statecount = 2;
284 net->finalcount = 1;
285 net->arccount = 1;
286 net->linecount = 3;
287 net->pathcount = 1;
288 return(net);
289}
290
291struct fsm *fsm_empty_set() {
292 struct fsm *net;
293 net = fsm_create("");
294 net->states = fsm_empty();
295 fsm_update_flags(net,YES1,YES1,YES1,YES1,YES1,NO0);
296 net->statecount = 1;
297 net->finalcount = 0;
298 net->arccount = 0;
299 net->linecount = 2;
300 net->pathcount = 0;
301 return(net);
302}
303
304struct fsm_state *fsm_empty() {
305 struct fsm_state *new_fsm;
306 new_fsm = malloc(sizeof(struct fsm_state)*2);
307 add_fsm_arc(new_fsm, 0, 0, -1, -1, -1, 0, 1);
308 add_fsm_arc(new_fsm, 1, -1, -1, -1, -1, -1, -1);
309 return(new_fsm);
310}
311
312int fsm_isuniversal(struct fsm *net) {
313 struct fsm_state *fsm;
314 net = fsm_minimize(net);
315 fsm_compact(net);
316 fsm = net->states;
317 if ((fsm->target == 0 && fsm->final_state == 1 && (fsm+1)->state_no == 0) &&
318 (fsm->in == IDENTITY2 && fsm->out == IDENTITY2) &&
319 ((fsm+1)->state_no == -1) &&
320 (sigma_max(net->sigma)<3) ) {
321 return 1;
322 } else {
323 return 0;
324 }
325}
326
327int fsm_isempty(struct fsm *net) {
328 int result;
329 struct fsm *minimal = fsm_minimize(fsm_copy(net));
330 struct fsm_state *fsm = minimal->states;
331 if (fsm->target == -1 && fsm->final_state == 0 && (fsm+1)->state_no == -1)
332 result = 1;
333 else
334 result = 0;
335 fsm_destroy(minimal);
336 return result;
337}
338
339int fsm_issequential(struct fsm *net) {
340 int i, *sigtable, sequential, seentrans, epstrans, laststate, insym;
341 struct fsm_state *fsm;
342 sigtable = calloc(sigma_max(net->sigma)+1,sizeof(int));
343 for (i = 0 ; i < sigma_max(net->sigma)+1; i++) {
344 sigtable[i] = -2;
345 }
346 fsm = net->states;
347 seentrans = epstrans = 0;
348 laststate = -1;
349 for (sequential = 1, i = 0; (fsm+i)->state_no != -1 ; i++) {
350 insym = (fsm+i)->in;
351 if (insym < 0) {
352 continue;
353 }
354 if ((fsm+i)->state_no != laststate) {
355 laststate = (fsm+i)->state_no;
356 epstrans = 0;
357 seentrans = 0;
358 }
359 if (*(sigtable+insym) == laststate || epstrans == 1) {
360 sequential = 0;
361 break;
362 }
363 if (insym == EPSILON0) {
364 if (epstrans == 1 || seentrans == 1) {
365 sequential = 0;
366 break;
367 }
368 epstrans = 1;
369 }
370 *(sigtable+insym) = laststate;
371 seentrans = 1;
372 }
373 free(sigtable);
374 if (!sequential)
375 printf("fails at state %i\n",(fsm+i)->state_no);
376 return(sequential);
377}
378
379int fsm_isfunctional(struct fsm *net) {
380 struct fsm *tmp = fsm_minimize(fsm_compose(fsm_invert(fsm_copy(net)),fsm_copy(net)));
381 int result = fsm_isidentity(tmp);
382 fsm_destroy(tmp);
383 return result;
384}
385
386int fsm_isunambiguous(struct fsm *net) {
387 struct fsm *loweruniqnet, *testnet;
388 int ret;
389 loweruniqnet = fsm_lowerdet(fsm_copy(net));
390 testnet = fsm_minimize(fsm_compose(fsm_invert(fsm_copy(loweruniqnet)),fsm_copy(loweruniqnet)));
391 ret = fsm_isidentity(testnet);
392 fsm_destroy(loweruniqnet);
393 fsm_destroy(testnet);
394 return(ret);
395}
396
397struct fsm *fsm_extract_ambiguous_domain(struct fsm *net) {
398 // define AmbiguousDom(T) [_loweruniq(T) .o. _notid(_loweruniq(T).i .o. _loweruniq(T))].u;
399 struct fsm *loweruniqnet, *result;
400 loweruniqnet = fsm_lowerdet(net);
401 result = fsm_topsort(fsm_minimize(fsm_upper(fsm_compose(fsm_copy(loweruniqnet),fsm_extract_nonidentity(fsm_compose(fsm_invert(fsm_copy(loweruniqnet)), fsm_copy(loweruniqnet)))))));
2
Calling 'fsm_extract_nonidentity'
402 fsm_destroy(loweruniqnet);
403 sigma_cleanup(result,1);
404 fsm_compact(result);
405 sigma_sort(result);
406 return(result);
407}
408
409struct fsm *fsm_extract_ambiguous(struct fsm *net) {
410 struct fsm *result;
411 result = fsm_topsort(fsm_minimize(fsm_compose(fsm_extract_ambiguous_domain(fsm_copy(net)), net)));
412 return(result);
413}
414
415struct fsm *fsm_extract_unambiguous(struct fsm *net) {
416 struct fsm *result;
417 result = fsm_topsort(fsm_minimize(fsm_compose(fsm_complement(fsm_extract_ambiguous_domain(fsm_copy(net))), net)));
1
Calling 'fsm_extract_ambiguous_domain'
418 return(result);
419}
420
421int fsm_isidentity(struct fsm *net) {
422
423 /* We check whether a given transducer only produces identity relations */
424 /* By doing a DFS on the graph, and storing, for each state a "discrepancy" */
425 /* string, showing the current "debt" on the upper or lower side. */
426 /* We immediately fail if: */
427 /* a) we encounter an already seen state with a different current */
428 /* discrepancy than what is stored in the state. */
429 /* b) when traversing an arc, we encounter a mismatch between the arc and */
430 /* the current discrepancy. */
431 /* c) we encounter a final state and have a non-null current discrepancy. */
432 /* d) we encounter @ with a non-null discrepancy anywhere. */
433 /* e) we encounter ? anywhere. */
434
435 struct discrepancy {
436 short int *string;
437 short int length;
438 _Bool visited;
439 };
440
441 struct state_array *state_array;
442 struct fsm_state *curr_ptr;
443 int i, j, v, vp, num_states, factor = 0, newlength = 1, startfrom;
444 short int in, out, *newstring = NULL((void*)0);
445 struct discrepancy *discrepancy, *currd, *targetd;
446 struct fsm *tmp;
447
448 tmp = fsm_minimize(fsm_copy(net));
449 fsm_count(tmp);
450
451 num_states = tmp->statecount;
452 discrepancy = calloc(num_states,sizeof(struct discrepancy));
453 state_array = map_firstlines(tmp);
454 ptr_stack_clear();
455 ptr_stack_push(state_array->transitions);
456
457 while(!ptr_stack_isempty()) {
458
459 curr_ptr = ptr_stack_pop();
460
461 nopop:
462 v = curr_ptr->state_no; /* source state number */
463 vp = curr_ptr->target; /* target state number */
464 currd = discrepancy+v;
465 if (v != -1)
466 currd->visited = 1;
467 if (v == -1 || vp == -1)
468 continue;
469 in = curr_ptr->in;
470 out = curr_ptr->out;
471
472 targetd = discrepancy+vp;
473 /* Check arc and conditions e) d) b) */
474 /* e) */
475 if (in == UNKNOWN1 || out == UNKNOWN1)
476 goto fail;
477 /* d) */
478 if (in == IDENTITY2 && currd->length != 0)
479 goto fail;
480 /* b) */
481 if (currd->length != 0) {
482 if (currd->length > 0 && out != EPSILON0 && out != *(currd->string))
483 goto fail;
484 if (currd->length < 0 && in != EPSILON0 && in != *(currd->string))
485 goto fail;
486 }
487 if (currd->length == 0 && in != out && in != EPSILON0 && out != EPSILON0) {
488 goto fail;
489 }
490
491 /* Calculate new discrepancy */
492 if (currd->length != 0) {
493 if (in != EPSILON0 && out != EPSILON0)
494 factor = 0;
495 else if (in == EPSILON0)
496 factor = -1;
497 else if (out == EPSILON0)
498 factor = 1;
499
500 newlength = currd->length + factor;
501 startfrom = (abs(newlength) <= abs(currd->length)) ? 1 : 0;
502
503 } else if (currd->length == 0) {
504 if (in != EPSILON0 && out != EPSILON0) {
505 newlength = 0;
506 } else {
507 newlength = (out == EPSILON0) ? 1 : -1;
508 }
509 startfrom = 0;
510 }
511
512 if (newstring != NULL((void*)0)) {
513 free(newstring);
514 newstring = NULL((void*)0);
515 }
516 newstring = calloc(abs(newlength),sizeof(int));
517
518 for (i = startfrom, j = 0; i < abs(currd->length); i++, j++) {
519 *(newstring+j) = *((currd->string)+i);
520 }
521 if (newlength != 0) {
522 if (currd->length > 0 && newlength >= currd->length) {
523 *(newstring+j) = in;
524 }
525 if (currd->length < 0 && newlength <= currd->length) {
526 *(newstring+j) = out;
527 }
528 if (currd->length == 0 && newlength < currd->length) {
529 *(newstring+j) = out;
530 }
531 if (currd->length == 0 && newlength > currd->length) {
532 *(newstring+j) = in;
533 }
534 }
535
536 /* Check target conditions a) c) */
537 /* a) */
538 if (((state_array+vp)->transitions)->final_state && newlength != 0)
539 goto fail;
540 if (curr_ptr->state_no == (curr_ptr+1)->state_no) {
541 ptr_stack_push(curr_ptr+1);
542 }
543 if ((discrepancy+vp)->visited) {
544 //free(newstring);
545 if (targetd->length != newlength)
546 goto fail;
547 for (i=0 ; i < abs(newlength); i++) {
548 if (*((targetd->string)+i) != *(newstring+i))
549 goto fail;
550 }
551 } else {
552 /* Add discrepancy to target state */
553 targetd->length = newlength;
554 targetd->string = newstring;
555 curr_ptr = (state_array+vp)->transitions;
556 goto nopop;
557 }
558 }
559 free(state_array);
560 free(discrepancy);
561 fsm_destroy(tmp);
562 if (newstring != NULL((void*)0))
563 free(newstring);
564 return 1;
565 fail:
566 free(state_array);
567 free(discrepancy);
568 ptr_stack_clear();
569 fsm_destroy(tmp);
570 if (newstring != NULL((void*)0))
571 free(newstring);
572 return 0;
573}
574
575struct fsm *fsm_markallfinal(struct fsm *net) {
576 struct fsm_state *fsm;
577 int i;
578 fsm = net->states;
579 for (i=0; (fsm+i)->state_no != -1; i++) {
580 (fsm+i)->final_state = YES1;
581 }
582 return net;
583}
584
585struct fsm *fsm_lowerdet(struct fsm *net) {
586 unsigned int newsym; /* Running number for new syms */
587 struct fsm_state *fsm;
588 char repstr[13];
589 int i,j,maxsigma,maxarc;
590 net = fsm_minimize(net);
591 fsm_count(net);
592 newsym = 8723643;
593 fsm = net->states;
594 maxarc = 0;
595 maxsigma = sigma_max(net->sigma);
596
597 for (i=0, j=0; (fsm+i)->state_no != -1; i++) {
598 if ((fsm+i)->target != -1)
599 j++;
600 if ((fsm+i+1)->state_no != (fsm+i)->state_no) {
601 maxarc = maxarc > j ? maxarc : j;
602 j = 0;
603 }
604 }
605 if (maxarc > (maxsigma-2)) {
606 for (i=maxarc; i > (maxsigma-2); i--) {
607 sprintf(repstr,"%012X",newsym++);
608 sigma_add(repstr, net->sigma);
609 }
610 sigma_sort(net);
611 }
612 for (i=0, j=3; (fsm+i)->state_no != -1; i++) {
613 if ((fsm+i)->target != -1) {
614 (fsm+i)->out = j++;
615 (fsm+i)->in = ((fsm+i)->in == IDENTITY2) ? UNKNOWN1 : (fsm+i)->in;
616 }
617 if ((fsm+i+1)->state_no != (fsm+i)->state_no) {
618 j = 3;
619 }
620 }
621 return(net);
622}
623
624struct fsm *fsm_lowerdeteps(struct fsm *net) {
625 unsigned int newsym; /* Running number for new syms */
626 struct fsm_state *fsm;
627 char repstr[13];
628 int i,j,maxsigma,maxarc;
629 net = fsm_minimize(net);
630 fsm_count(net);
631 newsym = 8723643;
632 fsm = net->states;
633 maxarc = 0;
634 maxsigma = sigma_max(net->sigma);
635
636 for (i=0, j=0; (fsm+i)->state_no != -1; i++) {
637 if ((fsm+i)->target != -1)
638 j++;
639 if ((fsm+i+1)->state_no != (fsm+i)->state_no) {
640 maxarc = maxarc > j ? maxarc : j;
641 j = 0;
642 }
643 }
644 if (maxarc > (maxsigma-2)) {
645 for (i=maxarc; i > (maxsigma-2); i--) {
646 sprintf(repstr,"%012X",newsym++);
647 sigma_add(repstr, net->sigma);
648 }
649 sigma_sort(net);
650 }
651 for (i=0, j=3; (fsm+i)->state_no != -1; i++) {
652 if ((fsm+i)->target != -1 && (fsm+i)->out != EPSILON0) {
653 (fsm+i)->out = j++;
654 (fsm+i)->in = ((fsm+i)->in == IDENTITY2) ? UNKNOWN1 : (fsm+i)->in;
655 }
656 if ((fsm+i+1)->state_no != (fsm+i)->state_no) {
657 j = 3;
658 }
659 }
660 return(net);
661}
662
663struct fsm *fsm_extract_nonidentity(struct fsm *net) {
664
665 /* Same algorithm as for test identity, except we mark the arcs that cause nonidentity */
666 /* Experimental. */
667
668 struct discrepancy {
669 short int *string;
670 short int length;
671 _Bool visited;
672 };
673
674 struct state_array *state_array;
675 struct fsm_state *curr_ptr;
676 struct fsm *net2;
677 int i, j, v, vp, num_states, factor = 0, newlength = 1, startfrom, killnum;
678 short int in, out, *newstring;
679 struct discrepancy *discrepancy, *currd, *targetd;
680
681 fsm_minimize(net);
682 fsm_count(net);
683 killnum = sigma_add("@KILL@", net->sigma);
684
685 num_states = net->statecount;
686 discrepancy = calloc(num_states,sizeof(struct discrepancy));
687 state_array = map_firstlines(net);
688 ptr_stack_push(state_array->transitions);
689
690 while(!ptr_stack_isempty()) {
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
32
Execution continues on line 690
33
Assuming the condition is false
34
Loop condition is false. Execution continues on line 796
691
692 curr_ptr = ptr_stack_pop();
693
694 nopop:
695 v = curr_ptr->state_no; /* source state number */
696 vp = curr_ptr->target; /* target state number */
697 currd = discrepancy+v;
698 if (v != -1)
5
Assuming the condition is true
6
Taking true branch
699 currd->visited = 1;
700 if (v == -1 || vp == -1)
7
Assuming the condition is false
8
Taking false branch
701 continue;
702 in = curr_ptr->in;
703 out = curr_ptr->out;
704
705 targetd = discrepancy+vp;
706 /* Check arc and conditions e) d) b) */
707 /* e) */
708 if (in == UNKNOWN1 || out == UNKNOWN1)
9
Assuming 'in' is not equal to UNKNOWN
10
Assuming 'out' is not equal to UNKNOWN
709 goto fail;
710 /* d) */
711 if (in == IDENTITY2 && currd->length != 0)
11
Assuming 'in' is not equal to IDENTITY
712 goto fail;
713 /* b) */
714 if (currd->length != 0) {
12
Assuming field 'length' is equal to 0
715 if (currd->length > 0 && out != EPSILON0 && out != *(currd->string))
716 goto fail;
717 if (currd->length < 0 && in != EPSILON0 && in != *(currd->string))
718 goto fail;
719 }
720 if (currd->length == 0 && in != out && in != EPSILON0 && out != EPSILON0) {
13
Assuming field 'length' is not equal to 0
721 goto fail;
722 }
723
724 /* Calculate new discrepancy */
725 if (currd->length != 0) {
14
Assuming field 'length' is equal to 0
15
Taking false branch
726 if (in != EPSILON0 && out != EPSILON0)
727 factor = 0;
728 else if (in == EPSILON0)
729 factor = -1;
730 else if (out == EPSILON0)
731 factor = 1;
732
733 newlength = currd->length + factor;
734 startfrom = (abs(newlength) <= abs(currd->length)) ? 1 : 0;
735
736 } else if (currd->length == 0) {
16
Assuming field 'length' is equal to 0
737 if (in != EPSILON0 && out != EPSILON0) {
17
Assuming 'in' is not equal to EPSILON
18
Assuming 'out' is not equal to EPSILON
19
Taking true branch
738 newlength = 0;
739 } else {
740 newlength = (out == EPSILON0) ? 1 : -1;
741 }
742 startfrom = 0;
743 }
744
745 newstring = calloc(abs(newlength),sizeof(int));
20
Memory is allocated
746
747 for (i = startfrom, j = 0; i < abs(currd->length); i++, j++) {
21
Assuming the condition is false
22
Loop condition is false. Execution continues on line 750
748 *(newstring+j) = *((currd->string)+i);
749 }
750 if (newlength
22.1
'newlength' is equal to 0
!= 0) {
751 if (currd->length > 0 && newlength >= currd->length) {
752 *(newstring+j) = in;
753 }
754 if (currd->length < 0 && newlength <= currd->length) {
755 *(newstring+j) = out;
756 }
757 if (currd->length == 0 && newlength < currd->length) {
758 *(newstring+j) = out;
759 }
760 if (currd->length == 0 && newlength > currd->length) {
761 *(newstring+j) = in;
762 }
763
764 }
765
766 /* Check target conditions a) c) */
767 /* a) */
768 if (((state_array+vp)->transitions)->final_state && newlength != 0)
23
Assuming field 'final_state' is 0
769 goto fail;
770 if (curr_ptr->state_no == (curr_ptr+1)->state_no) {
24
Assuming 'curr_ptr->state_no' is not equal to '(curr_ptr+1)->state_no'
25
Taking false branch
771 ptr_stack_push(curr_ptr+1);
772 }
773
774 if ((discrepancy+vp)->visited) {
26
Assuming field 'visited' is true
27
Taking true branch
775 //free(newstring);
776 if (targetd->length != newlength)
28
Assuming 'newlength' is equal to field 'length'
29
Taking false branch
777 goto fail;
778 for (i=0 ; i < abs(newlength); i++) {
30
Assuming the condition is false
31
Loop condition is false. Execution continues on line 789
779 if (*((targetd->string)+i) != *(newstring+i))
780 goto fail;
781 }
782 } else {
783 /* Add discrepancy to target state */
784 targetd->length = newlength;
785 targetd->string = newstring;
786 curr_ptr = (state_array+vp)->transitions;
787 goto nopop;
788 }
789 continue;
790 fail:
791 curr_ptr->out = killnum;
792 if (curr_ptr->state_no == (curr_ptr+1)->state_no) {
793 ptr_stack_push(curr_ptr+1);
794 }
795 }
796 ptr_stack_clear();
35
Potential leak of memory pointed to by 'newstring'
797 sigma_sort(net);
798 net2 = fsm_upper(fsm_compose(net,fsm_contains(fsm_symbol("@KILL@"))));
799 sigma_remove("@KILL@",net2->sigma);
800 sigma_sort(net2);
801 free(state_array);
802 free(discrepancy);
803 return(net2);
804}
805
806struct fsm *fsm_copy (struct fsm *net) {
807 struct fsm *net_copy;
808 if (net == NULL((void*)0))
809 return net;
810
811 net_copy = malloc(sizeof(struct fsm));
812 memcpy(net_copy, net, sizeof(struct fsm));
813
814 fsm_count(net);
815 net_copy->sigma = sigma_copy(net->sigma);
816 net_copy->states = fsm_state_copy(net->states, net->linecount);
817 return(net_copy);
818}
819
820struct fsm_state *fsm_state_copy(struct fsm_state *fsm_state, int linecount) {
821 struct fsm_state *new_fsm_state;
822
823 new_fsm_state = malloc(sizeof(struct fsm_state)*(linecount));
824 memcpy(new_fsm_state, fsm_state, linecount*sizeof(struct fsm_state));
825 return(new_fsm_state);
826}
827
828/* TODO: separate linecount and arccount */
829int find_arccount(struct fsm_state *fsm) {
830 int i;
831 for (i=0;(fsm+i)->state_no != -1; i++) {
832 }
833 return i;
834}
835
836void clear_quantifiers() {
837 quantifiers = NULL((void*)0);
838}
839
840int count_quantifiers() {
841 struct defined_quantifiers *q;
842 int i;
843 for (i = 0, q = quantifiers; q != NULL((void*)0); q = q->next) {
844 i++;
845 }
846 return(i);
847}
848
849void add_quantifier (char *string) {
850 struct defined_quantifiers *q;
851 if (quantifiers == NULL((void*)0)) {
852 q = malloc(sizeof(struct defined_quantifiers));
853 quantifiers = q;
854 } else {
855 for (q = quantifiers; q->next != NULL((void*)0); q = q->next) {
856
857 }
858 q->next = malloc(sizeof(struct defined_quantifiers));
859 q = q->next;
860 }
861 q->name = strdup(string);
862 q->next = NULL((void*)0);
863}
864
865struct fsm *union_quantifiers() {
866/* We create a FSM that simply accepts the union of all */
867/* quantifier symbols */
868
869 struct fsm *net;
870 struct defined_quantifiers *q;
871 int i, syms, s, symlo;
872
873 net = fsm_create("");
874 fsm_update_flags(net, YES1, YES1, YES1, YES1, NO0, NO0);
875
876 for (syms = 0, symlo = 0, q = quantifiers; q != NULL((void*)0); q = q->next) {
877 s = sigma_add(q->name, net->sigma);
878 if (symlo == 0) {
879 symlo = s;
880 }
881 syms++;
882 }
883 net->states = malloc(sizeof(struct fsm_state)*(syms+1));
884 for (i = 0; i < syms; i++) {
885 add_fsm_arc(net->states, i, 0, symlo+i, symlo+i, 0, 1, 1);
886 }
887 add_fsm_arc(net->states, i, -1, -1, -1, -1 ,-1 ,-1);
888 net->arccount = syms;
889 net->statecount = net->finalcount = 1;
890 net->linecount = syms;
891 return(net);
892}
893
894char *find_quantifier (char *string) {
895 struct defined_quantifiers *q;
896 for (q = quantifiers; q != NULL((void*)0); q = q->next) {
897 if (strcmp(string,q->name) == 0)
898 return q->name;
899 }
900 return(NULL((void*)0));
901}
902
903void purge_quantifier (char *string) {
904 struct defined_quantifiers *q, *q_prev;
905 for (q = quantifiers, q_prev = NULL((void*)0); q != NULL((void*)0); q_prev = q, q = q->next) {
906 if (strcmp(string, q->name) == 0) {
907 if (q_prev != NULL((void*)0)) {
908 q_prev->next = q->next;
909 } else {
910 quantifiers = q->next;
911 }
912 }
913 }
914}
915
916struct fsm *fsm_quantifier(char *string) {
917
918 /* \x* x \x* x \x* */
919 return(fsm_concat(fsm_kleene_star(fsm_term_negation(fsm_symbol(string))),fsm_concat(fsm_symbol(string),fsm_concat(fsm_kleene_star(fsm_term_negation(fsm_symbol(string))),fsm_concat(fsm_symbol(string),fsm_kleene_star(fsm_term_negation(fsm_symbol(string))))))));
920
921}
922
923struct fsm *fsm_logical_precedence(char *string1, char *string2) {
924 /* x < y = \y* x \y* [x | y Q* x] ?* */
925 /* 1 2 3 4 5 */
926
927 return(fsm_concat(fsm_kleene_star(fsm_term_negation(fsm_symbol(string2))),fsm_concat(fsm_symbol(string1),fsm_concat(fsm_kleene_star(fsm_term_negation(fsm_symbol(string2))),fsm_concat(fsm_union(fsm_symbol(string1),fsm_concat(fsm_symbol(string2),fsm_concat(union_quantifiers(),fsm_symbol(string1)))),fsm_universal())))));
928
929/* 1,3 fsm_kleene_star(fsm_term_negation(fsm_symbol(string2))) */
930/* 2 = fsm_symbol(string1) */
931/* 5 = fsm_universal() */
932/* 4 = fsm_union(fsm_symbol(string1),fsm_concat(fsm_symbol(string2),fsm_concat(union_quantifiers(),fsm_symbol(string1)))) */
933
934}
935
936/** Logical equivalence, i.e. where two variables span the same substring */
937/** x = y = ?* [x y|y x]/Q ?* [x y|y x]/Q ?* */
938struct fsm *fsm_logical_eq(char *string1, char *string2) {
939 return(fsm_concat(fsm_universal(),fsm_concat(fsm_ignore(fsm_union(fsm_concat(fsm_symbol(string1),fsm_symbol(string2)),fsm_concat(fsm_symbol(string2),fsm_symbol(string1))),union_quantifiers(),OP_IGNORE_ALL1),fsm_concat(fsm_universal(),fsm_concat(fsm_ignore(fsm_union(fsm_concat(fsm_symbol(string1),fsm_symbol(string2)),fsm_concat(fsm_symbol(string2),fsm_symbol(string1))),union_quantifiers(),OP_IGNORE_ALL1),fsm_universal())))));
940}
941