Bug Summary

File:iface.c
Warning:line 1668, column 86
Potential memory leak

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 iface.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 -pic-is-pie -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/iface.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 <wchar.h>
20#include <stdlib.h>
21#include <string.h>
22#include <limits.h>
23#include <errno(*__errno_location ()).h>
24#include <ctype.h>
25
26#include "foma.h"
27#include "zlib.h"
28
29extern int g_show_flags;
30extern int g_obey_flags;
31extern int g_flag_is_epsilon;
32extern int g_print_space;
33extern int g_print_pairs;
34extern int g_minimal;
35extern int g_name_nets;
36extern int g_print_sigma;
37extern int g_quit_on_fail;
38extern int g_quote_special;
39extern int g_recursive_define;
40extern int g_sort_arcs;
41extern int g_verbose;
42extern int g_minimize_hopcroft;
43extern int g_list_limit;
44extern int g_list_random_limit;
45extern int g_compose_tristate;
46extern int g_med_limit ;
47extern int g_med_cutoff ;
48extern int g_lexc_align ;
49extern char *g_att_epsilon;
50
51extern int foma_net_print(struct fsm *net, gzFile outfile);
52
53static char *sigptr(struct sigma *sigma, int number);
54static int print_dot(struct fsm *net, char *filename);
55static int print_net(struct fsm *net, char *filename);
56static int print_sigma(struct sigma *sigma, FILE *out);
57static int view_net(struct fsm *net);
58
59#define FVAR_BOOL1 1
60#define FVAR_INT2 2
61#define FVAR_STRING3 3
62
63#define LINE_LIMIT8192 8192
64
65struct g_v {
66 void *ptr;
67 char *name;
68 int type;
69} global_vars[] = {
70 {&g_flag_is_epsilon, "flag-is-epsilon", FVAR_BOOL1},
71 {&g_minimal, "minimal", FVAR_BOOL1},
72 {&g_name_nets, "name-nets", FVAR_BOOL1},
73 {&g_obey_flags, "obey-flags", FVAR_BOOL1},
74 {&g_print_pairs, "print-pairs", FVAR_BOOL1},
75 {&g_print_sigma, "print-sigma", FVAR_BOOL1},
76 {&g_print_space, "print-space", FVAR_BOOL1},
77 {&g_quit_on_fail, "quit-on-fail", FVAR_BOOL1},
78 {&g_recursive_define, "recursive-define", FVAR_BOOL1},
79 {&g_quote_special, "quote-special", FVAR_BOOL1},
80 {&g_show_flags, "show-flags", FVAR_BOOL1},
81 {&g_sort_arcs, "sort-arcs", FVAR_BOOL1},
82 {&g_verbose, "verbose", FVAR_BOOL1},
83 {&g_minimize_hopcroft,"hopcroft-min", FVAR_BOOL1},
84 {&g_compose_tristate, "compose-tristate", FVAR_BOOL1},
85 {&g_med_limit, "med-limit", FVAR_INT2},
86 {&g_med_cutoff, "med-cutoff", FVAR_INT2},
87 {&g_lexc_align, "lexc-align", FVAR_BOOL1},
88 {&g_att_epsilon, "att-epsilon", FVAR_STRING3},
89 {NULL((void*)0), NULL((void*)0), 0}
90};
91
92char warranty[] = "\nLicensed under the Apache License, Version 2.0 (the \"License\")\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n";
93
94struct global_help {
95 char *name;
96 char *help;
97 char *longhelp;
98} global_help[] = {
99 {"regex <regex>", "read a regular expression","Enter a regular expression and add result to top of stack.\nShort form: re\nSee `help operator' for operators, or `help precedence' for operator precedence."},
100 {"ambiguous upper","returns the input words which have multiple paths in a transducer","Short form: ambiguous\n"},
101 {"apply up <string>","apply <string> up to the top network on stack","Short form: up <string>\n"},
102 {"apply down <string>","apply <string> down to the top network on stack","Short form: down <string>\n" },
103 {"apply med <string>","find approximate matches to string in top network by minimum edit distance","Short form: med <string>\n" },
104 {"apply up","enter apply up mode (Ctrl-D exits)","Short form: up\n"},
105 {"apply down","enter apply down mode (Ctrl-D exits)","Short form: down\n"},
106 {"apply med","enter apply med mode (Ctrl-D exits)","Short form: med\n"},
107 {"apropos <string>","search help for <string>",""},
108 {"clear stack","clears the stack",""},
109 {"close sigma","removes unknown symbols from FSM","" },
110 {"compact sigma","removes redundant symbols from FSM","" },
111 {"complete net","completes the FSM","" },
112 {"compose net","composes networks on stack",""},
113 {"concatenate","concatenates networks on stack","" },
114 {"crossproduct net","cross-product of top two FSMs on stack","See ×\n" },
115 {"define <name> <r.e.>","define a network","Example: \ndefine A x -> y;\n and\nA = x -> y;\n\nare equivalent\n"},
116 {"define <fname>(<v1,..,vn>) <r.e.>","define function","Example: define Remove(X) [X -> 0].l;"},
117 {"determinize net","determinizes top FSM on stack",""},
118 {"echo <string>","echo a string",""},
119 {"eliminate flag <name>","eliminate flag <name> diacritics from the top network",""},
120 {"eliminate flags","eliminate all flag diacritics from the top network",""},
121 {"export cmatrix (filename)","export the confusion matrix as an AT&T transducer",""},
122 {"extract ambiguous","extracts the ambiguous paths of a transducer","Short form: examb"},
123 {"extract unambiguous","extracts the unambiguous paths of a transducer","Short form: exunamb"},
124 {"help license","prints license",""},
125 {"help warranty","prints warranty information",""},
126 {"ignore net","applies ignore to top two FSMs on stack","See /\n"},
127 {"intersect net","intersects FSMs on stack","See ∩ (or &)\n" },
128 {"invert net","inverts top FSM","See ⁻¹ (or .i)\n"},
129 {"label net","extracts all attested symbol pairs from FSM","See also: sigma net"},
130 {"letter machine","Converts top FSM to a letter machine","See also: _lm(L)"},
131 {"load stack <filename>","Loads networks and pushes them on the stack","Short form: load"},
132 {"load defined <filename>","Restores defined networks from file","Short form: loadd"},
133 {"lower-side net","takes lower projection of top FSM","See ₂ (or .l)\n"},
134 {"minimize net","minimizes top FSM","Minimization can be controlled through the variable minimal: when set to OFF FSMs are never minimized.\nAlso, hopcroft-min can be set to OFF in which case minimization is done by double reversal and determinization (aka Brzozowski's algorithm). It is likely to be much slower.\n"},
135 {"name net <string>","names top FSM",""},
136 {"negate net","complements top FSM","See ¬\n" },
137 {"one-plus net","Kleene plus on top FSM","See +\n" },
138 {"pop stack","remove top FSM from stack","" },
139 {"print cmatrix","prints the confusion matrix associated with the top network in tabular format",""},
140 {"print defined","prints defined symbols and functions",""},
141 {"print dot (>filename)","prints top FSM in Graphviz dot format",""},
142 {"print lower-words","prints words on the lower side of top FSM",""},
143 {"print lower-words > filename","prints words on the lower side of top FSM to file",""},
144 {"print name","prints the name of the top FSM","" },
145 {"print net","prints all information about top FSM","Short form: net\n" },
146 {"print pairs","prints input-output pairs from top FSM","Short form: pairs\n"},
147 {"print pairs > filename","prints input-output pairs from top FSM to file","Short form: pairs\n"},
148 {"print random-lower","prints random words from lower side","Short form: random-lower\n" },
149 {"print random-upper","prints random words from upper side","Short form: random-upper" },
150 {"print random-words","prints random words from top FSM","Short form: random-words\n"},
151 {"print random-pairs","prints random input-output pairs from top FSM","Short form: random-pairs\n"},
152 {"print sigma","prints the alphabet of the top FSM","Short form: sigma\n"},
153 {"print size","prints size information about top FSM","Short form: size\n"},
154 {"print shortest-string","prints the shortest string of the top FSM","Short form: pss\n"},
155 {"print shortest-string-size","prints length of shortest string","Short form: psz\n"},
156 {"print upper-words","prints words on the upper side of top FSM","Short form: upper-words"},
157 {"print upper-words > filename","prints words on the upper side of top FSM to file","Short form:upper-words"},
158 {"print words","prints words of top FSM","Short form: words"},
159 {"print words > filename","prints words of top FSM to file","Short form: words"},
160 {"prune net","makes top network coaccessible",""},
161 {"push (defined) <name>","adds a defined FSM to top of stack",""},
162 {"quit","exit foma",""},
163 {"read att <filename>","read a file in AT&T FSM format and add to top of stack","Short form: ratt"},
164 {"read cmatrix <filename>","read a confusion matrix and associate it with the network on top of the stack",""},
165 {"read prolog <filename>","reads prolog format file",""},
166 {"read lexc <filename>","read and compile lexc format file",""},
167 {"read spaced-text <filename>","compile space-separated words/word-pairs separated by newlines into a FST",""},
168 {"read text <filename>","compile a list of words separated by newlines into an automaton",""},
169 {"reverse net","reverses top FSM","Short form: rev\nSee .r\n"},
170 {"rotate stack","rotates stack",""},
171 {"save defined <filename>","save all defined networks to binary file","Short form: saved" },
172 {"save stack <filename>","save stack to binary file","Short form: ss" },
173 {"set <variable> <ON|OFF>","sets a global variable (see show variables)","" },
174 {"show variables","prints all variable/value pairs",""},
175 {"shuffle net","asynchronous product on top two FSMs on stack","See ∥ (or <>)\n"},
176 {"sigma net","Extracts the alphabet and creates a FSM that accepts all single symbols in it","See also: label net"},
177 {"source <file>","read and compile script file",""},
178 {"sort net","sorts arcs topologically on top FSM",""},
179 {"sort in","sorts input arcs by sigma numbers on top FSM",""},
180 {"sort out","sorts output arcs by sigma number on top FSM",""},
181 {"substitute defined X for Y","substitutes defined network X at all arcs containing Y ",""},
182 {"substitute symbol X for Y","substitutes all occurrences of Y in an arc with X",""},
183 {"system <cmd>","execute a system command","" },
184 {"test unambiguous","test if top FST is unambiguous","Short form: tunam\n"},
185 {"test equivalent","test if the top two FSMs are equivalent","Short form: equ\nNote: equivalence is undecidable for transducers in the general case. The result is reliable only for recognizers.\n"},
186 {"test functional","test if the top FST is functional (single-valued)","Short form: tfu\n"},
187 {"test identity","test if top FST represents identity relations only","Short form: tid\n"},
188 {"test lower-universal","test if lower side is Σ*","Short form: tlu\n"},
189 {"test upper-universal","test if upper side is Σ*","Short form: tuu\n"},
190 {"test non-null","test if top machine is not the empty language","Short form:tnn\n" },
191 {"test null","test if top machine is the empty language (∅)","Short form: tnu\n" },
192 {"test sequential","tests if top machine is sequential","Short form: tseq\n"},
193 {"turn stack","turns stack upside down","" },
194 {"twosided flag-diacritics","changes flags to always be identity pairs","Short form: tfd" },
195 {"undefine <name>","remove <name> from defined networks","See define\n"},
196 {"union net","union of top two FSMs","See ∪ (or |)\n"},
197 {"upper-side net","upper projection of top FSM","See ₁ (or .u)\n"},
198 {"view net","display top network (if supported)",""},
199 {"zero-plus net","Kleene star on top fsm","See *\n"},
200 {"variable compose-tristate","use the tristate composition algorithm","Default value: OFF\n"},
201 {"variable show-flags","show flag diacritics in `apply'","Default value: ON\n"},
202 {"variable obey-flags","obey flag diacritics in `apply'","Default value: ON\n"},
203 {"variable minimal","minimize resulting FSMs","Default value: ON\n"},
204 {"variable print-pairs","always print both sides when applying","Default value: OFF\n"},
205 {"variable print-space","print spaces between symbols","Default value: OFF\n"},
206 {"variable print-sigma","print the alphabet when printing network","Default value: ON\n"},
207 {"quit-on-fail","Abort operations when encountering errors","Default value: ON\n"},
208 {"variable recursive-define","Allow recursive definitions","Default value: OFF\n"},
209 {"variable verbose","Verbosity of interface","Default value: ON\n"},
210 {"variable hopcroft-min","ON = Hopcroft minimization, OFF = Brzozowski minimization","Default value: ON\n"},
211 {"variable med-limit","the limit on number of matches in apply med","Default value: 3\n"},
212 {"variable med-cutoff","the cost limit for terminating a search in apply med","Default value: 3\n"},
213 {"variable att-epsilon","the EPSILON symbol when reading/writing AT&T files","Default value: @0@\n"},
214 {"variable lexc-align","Forces X:0 X:X of 0:X alignment of lexicon entry symbols","Default value: OFF\n"},
215 {"write prolog (> filename)","writes top network to prolog format file/stdout","Short form: wpl"},
216 {"write att (> <filename>)","writes top network to AT&T format file/stdout","Short form: watt"},
217 {"re operator: (∀<var name>)(F)","universal quantification","Example: $.A is equivalent to:\n(∃x)(x ∈ A ∧ (∀y)(¬(y ∈ A ∧ ¬(x = y))))"},
218 {"re operator: (∃<var name>)(F)","existential quantification","Example: $.A is equivalent to:\n(∃x)(x ∈ A ∧ ¬(∃y)(y ∈ A ∧ ¬(x = y)))"},
219 {"logic re operator: ∈","`in' predicate for logical formulae",""},
220 {"logic re operator: S(t1,t2)","successor-of predicate for logical formulae",""},
221 {"logic re operator: ≤","less-than or equal-to","Refers to position of quantified substring\n" },
222 {"logic re operator: ≥","more-than or equal-to","Refers to position of quantified substring\n" },
223 {"logic re operator: ≺","precedes","Refers to position of quantified substring\n"},
224 {"logic re operator: ≻","follows","Refers to position of quantified substring\n"},
225 {"logic re operator: ∧","conjunction","Operationally equivalent to ∩\n"},
226 {"logic re operator: ∨","disjunction","Operationally equivalent to ∪\n"},
227 {"logic re operator: →","implication","A → B is equivalent to ¬A ∨ B "},
228 {"logic re operator: ↔","biconditional","A ↔ B is equivalent to (¬A ∨ B) ∧ (¬B ∨ A)"},
229 {"re operator: ∘ (or .o.) ","compose","A .o. B is the composition of transducers/recognizers A and B\nThe composition algorithm can be controlled with the variable\ncompose-tristate. The default algorithm is a `bistate' composition that eliminates redundant paths but may fail to find the shortest path.\n"},
230 {"re operator: × (or .x.) ","cross-product","A × B (where A and B are recognizers, not transducers\nyields the cross-product of A and B.\n"},
231 {"re operator: .O. ","`lenient' composition","Lenient composition as defined in Karttunen(1998) A .O. B = [A ∘ B] .P. B\n"},
232 {"re operator: ∥ (or <>) ","shuffle (asynchronous product)","A ∥ B yields the asynchronous (or shuffle) product of FSM A and B.\n" },
233 {"re operator: => ","context restriction, e.g. A => B _ C, D _ E","A => B _ C yields the language where every instance of a substring drawn from A is surrounded by B and C. Multiple contexts can be specified if separated by commas, e.g.: A => B _ C, D _ E"},
234 {"re operator: ->, <-, <->, etc.","replacement operators","If LHS is a transducer, no RHS is needed in rule."},
235 {"re operator: @->, @>, etc.","directed replacement operators",""},
236 {"re operator: (->), (@->), etc. ","optional replacements","Optional replacement operators variants. Note that the directional modes leftmost/rightmost/longest/shortest are not affected by optionality, i.e. only replacement is optional, not mode. Hence A (@->) B is not in general equivalent to the parallel rule A @-> B, A -> ... "},
237 {"re operator: ||,\\/,\\\\,// ","replacement direction specifiers","Rewrite rules direction specifier meaning is:\nA -> B || C _ D (replace if C and D match on upper side)\nA -> B // C _ D (replace if C matches of lower side and D matches on upper side)\nA -> B \\\\ C _ D (replace if C matches on upper side and D matches on lower side)\nA -> B \\/ C _ D (replace if C and D match on lower side)\n"},
238 {"re operator: _ ","replacement or restriction context specifier",""},
239 {"re operator: ,,","parallel context replacement operator","Separates parallel rules, e.g.:\nA -> B , C @-> D || E _ F ,, G -> H \\/ I _ J\n"},
240 {"re operator: ,","parallel replacement operator","Separates rules and contexts. Example: A -> B, C <- D || E _ F"},
241 {"re operator: [.<r.e.>.]","single-epsilon control in replacement LHS, e.g. [..] -> x","If the LHS contains the empty string, as does [.a*.] -> x, the rule yields a transducer where the empty string is assumed to occur exactly once between each symbol."},
242 {"re operator: ...","markup replacement control (e.g. A -> B ... C || D _ E)","A -> B ... C yields a replacement transducer where the center A is left untouched and B and C inserted around A." },
243 {"re operator: ","concatenation","Binary operator: A B\nConcatenation is performed implicitly according to its precedence level without overt specification\n"},
244 {"re operator: ∪ (or |) ","union","Binary operator: A|B"},
245 {"re operator: ∩ (or &) ","intersection","Binary operator: A&B" },
246 {"re operator: - ","set minus","Binary operator A-B"},
247 {"re operator: .P.","priority union (upper)","Binary operator A .P. B\nEquivalent to: A .P. B = A ∪ [¬[A₁] ∘ B]\n" },
248 {"re operator: .p.","priority union (lower)","Binary operator A .p. B\nEquivalent to: A .p. B = A ∪ [¬[A₂] ∘ B]" },
249 {"re operator: <","precedes","Binary operator A < B\nYields the language where no instance of A follows an instance of B."},
250 {"re operator: >","follows","Binary operator A > B\nYields the language where no instance of A precedes an instance of B."},
251 {"re operator: /","ignore","Binary operator A/B\nYield the language/transducer where arbitrary sequences of strings/mappings from B are interspersed in A. For single-symbol languages B, A/B = A ∥ B*"},
252 {"re operator: ./.","ignore except at edges","Yields the language where arbitrary sequences from B are interspersed in A, except as the very first and very last symbol."},
253 {"re operator: \\\\\\","left quotient","Binary operator: A\\\\\\B\nInformally: the set of suffixes one can add to A to get strings in B\n"},
254 {"re operator: ///","right quotient","Binary operator A///B\nInformally: the set of prefixes one can add to B to get a string in A\n"},
255 {"re operator: /\\/","interleaving quotient","Binary operator A/\\/B\nInformally: the set of strings you can interdigitate (non-continuously) to B to get strings in A\n"},
256 {"re operator: ¬ (or ~) ","complement","Unary operator ~A, equivalent to Σ* - A\n"},
257 {"re operator: $","contains a factor of","Unary operator $A\nEquivalent to: Σ* A Σ*\n"},
258 {"re operator: $.","contains exactly one factor of","Unary operator $.A\nYields the language that contains exactly one factor from A.\nExample: if A = [a b|b a], $.A contains strings ab, ba, abb, bba, but not abab, baba, aba, bab, etc.\n"},
259 {"re operator: $?","contains maximally one factor of","Unary operator: $?A, yields the language that contains zero or one factors from A. See also $.A."},
260 {"re operator: +","Kleene plus","Unary operator A+\n"},
261 {"re operator: *","Kleene star","Unary operator A*\n" },
262 {"re operator: ^n ^<n ^>n ^{m,n}","m, n-ary concatenations","A^n: A concatenated with itself exactly n times\nA^<n: A concatenated with itself less than n times\nA^>n: A concatenated with itself more than n times\nA^{m,n}: A concatenated with itself between m and n times\n"},
263 {"re operator: ₁ (or .1 or .u)","upper projection","Unary operator A.u\n"},
264 {"re operator: ₂ (or .2 or .l)","lower projection","Unary operator A.l\n"},
265 {"re operator: ⁻¹ (or .i)","inverse of transducer","Unary operator A.i\n"},
266 {"re operator: .f","eliminate all flags","Unary operator A.f: eliminates all flag diacritics in A"},
267 {"re operator: .r","reverse of FSM","Unary operator A.r\n"},
268 {"re operator: :","cross-product","Binary operator A:B, see also A × B\n"},
269 {"re operator: \\","term complement (\\x = [Σ-x])","Unary operator \\A\nSingle symbols not in A. Equivalent to [Σ-A]\n"},
270 {"re operator: `","substitution/homomorphism","Ternary operator `[A,B,C] Replace instances of symbol B with symbol C in language A. Also removes the substituted symbol from the alphabet.\n"},
271 {"re operator: { ... }","concatenate symbols","Single-symbol-concatenation\nExample: {abcd} is equivalent to a b c d\n"},
272 {"re operator: (A)","optionality","Equivalent to A | ε\nNote: parentheses inside logical formulas function as grouping, see ∀,∃\n"},
273 {"re operator: @\"filename\"","read saved network from file","Note: loads networks stored with e.g. \"save stack\" but if file contains more than one network, only the first one is used in the regular expression. See also \"load stack\" and \"load defined\"\n"},
274 {"special symbol: Σ (or ?)","`any' symbol in r.e.",""},
275 {"special symbol: ε (or 0, [])","epsilon symbol in r.e.",""},
276 {"special symbol: ∅","the empty language symbol in r.e.",""},
277 {"special symbol: .#.","word boundary symbol in replacements, restrictions","Signifies both end and beginning of word/string\nExample: A => B _ .#. (allow A only between B and end-of-string)\nExample: A -> B || .#. _ C (replace A with B if it occurs in the beginning of a word and is followed by C)\n"},
278 {"operator precedence: ","see: `help precedence'","\\ `\n:\n+ * ^ ₁ ₂ ⁻¹ .f .r\n¬ $ $. $?\n(concatenation)\n> <\n∪ ∩ - .P. .p.\n=> -> (->) @-> etc.\n∥\n× ∘ .O.\nNote: compatibility variants (i.e. | = ∪ etc.) are not listed."},
279
280 {NULL((void*)0),NULL((void*)0),NULL((void*)0)}
281};
282
283void iface_help() {
284 struct global_help *gh;
285 int i, maxlen;
286
287 for (maxlen = 0, gh = global_help; gh->name != NULL((void*)0); gh++) {
288 maxlen = maxlen < utf8strlen(gh->name) ? utf8strlen(gh->name) : maxlen;
289 }
290 for (gh = global_help; gh->name != NULL((void*)0); gh++) {
291 printf("%s",gh->name);
292 for (i = maxlen - utf8strlen(gh->name); i>=0; i--) {
293 printf("%s"," ");
294 }
295 printf("%s\n",gh->help);
296 }
297}
298
299void iface_ambiguous_upper() {
300 if (iface_stack_check(1))
301 stack_add(fsm_extract_ambiguous_domain(stack_pop()));
302}
303
304void iface_apropos(char *s) {
305 struct global_help *gh;
306 int i, maxlen;
307
308 for (maxlen = 0, gh = global_help; gh->name != NULL((void*)0); gh++) {
309 if (strstr(gh->name,s) != NULL((void*)0) || strstr(gh->help,s) != NULL((void*)0)) {
310 maxlen = maxlen < utf8strlen(gh->name) ? utf8strlen(gh->name) : maxlen;
311 }
312 }
313 for (gh = global_help; gh->name != NULL((void*)0); gh++) {
314 if (strstr(gh->name,s) != NULL((void*)0) || strstr(gh->help,s) != NULL((void*)0)) {
315 printf("%s",gh->name);
316 for (i = maxlen - utf8strlen(gh->name); i>=0; i--) {
317 printf("%s"," ");
318 }
319 printf("%s\n",gh->help);
320 }
321 }
322}
323
324void iface_help_search(char *s) {
325 struct global_help *gh;
326
327 for (gh = global_help; gh->name != NULL((void*)0); gh++) {
328 if (strstr(gh->name,s) != NULL((void*)0) || strstr(gh->help,s) != NULL((void*)0)) {
329 printf("##\n");
330 printf("%-32.32s%s\n%s\n",gh->name,gh->help,gh->longhelp);
331 }
332 }
333}
334
335void iface_print_bool(int value) {
336 printf("%i (1 = TRUE, 0 = FALSE)\n",value);
337}
338
339void iface_warranty() {
340 printf("%s",warranty);
341}
342
343void iface_apply_set_params(struct apply_handle *h) {
344 apply_set_print_space(h, g_print_space);
345 apply_set_print_pairs(h, g_print_pairs);
346 apply_set_show_flags(h, g_show_flags);
347 apply_set_obey_flags(h, g_obey_flags);
348}
349
350void iface_apply_med(char *word) {
351 char *result;
352 struct apply_med_handle *amedh;
353 if (!iface_stack_check(1)) {
354 return;
355 }
356 amedh = stack_get_med_ah();
357
358 apply_med_set_heap_max(amedh,4194304+1);
359 apply_med_set_med_limit(amedh,g_med_limit);
360 apply_med_set_med_cutoff(amedh,g_med_cutoff);
361
362 result = apply_med(amedh, word);
363 if (result == NULL((void*)0)) {
364 printf("???\n");
365 return;
366 } else {
367 printf("%s\n",result);
368 printf("%s\n", apply_med_get_instring(amedh));
369 printf("Cost[f]: %i\n\n", apply_med_get_cost(amedh));
370 }
371 while ((result = apply_med(amedh,NULL((void*)0))) != NULL((void*)0)) {
372 printf("%s\n",result);
373 printf("%s\n", apply_med_get_instring(amedh));
374 printf("Cost[f]: %i\n\n", apply_med_get_cost(amedh));
375 }
376}
377
378int iface_apply_file(char *infilename, char *outfilename, int direction) {
379 char *result, inword[LINE_LIMIT8192];
380 struct apply_handle *ah;
381 FILE *OUTFILE, *INFILE;
382
383 if (direction != AP_D1 && direction != AP_U2) {
384 perror("Invalid direction in iface_apply_file().\n");
385 return 1;
386 }
387 if (!iface_stack_check(1)) { return 0; }
388 INFILE = fopen(infilename, "r");
389 if (INFILE == NULL((void*)0)) {
390 fprintf(stderrstderr, "%s: ", infilename);
391 perror("Error opening file");
392 return 1;
393 }
394
395 if (outfilename == NULL((void*)0)) {
396 OUTFILE = stdoutstdout;
397 } else {
398 OUTFILE = fopen(outfilename, "w");
399 printf("Writing output to file %s.\n", outfilename);
400 if (OUTFILE == NULL((void*)0)) {
401 fprintf(stderrstderr, "%s: ", outfilename);
402 perror("Error opening output file.");
403 return 1;
404 }
405 }
406 ah = stack_get_ah();
407 iface_apply_set_params(ah);
408 while ((fgets(inword,LINE_LIMIT8192,INFILE)) != NULL((void*)0)) {
409 if (inword[strlen(inword)-1] == '\n') {
410 inword[strlen(inword)-1] = '\0';
411 }
412
413 fprintf(OUTFILE,"\n%s\n", inword);
414 if (direction == AP_D1)
415 result = apply_down(ah,inword);
416 else
417 result = apply_up(ah,inword);
418
419 if (result == NULL((void*)0)) {
420 fprintf(OUTFILE,"???\n");
421 continue;
422 } else {
423 fprintf(OUTFILE,"%s\n",result);
424 }
425 for (;;) {
426 if (direction == AP_D1)
427 result = apply_down(ah,NULL((void*)0));
428 if (direction == AP_U2)
429 result = apply_up(ah,NULL((void*)0));
430 if (result == NULL((void*)0))
431 break;
432 fprintf(OUTFILE,"%s\n", result);
433 }
434 }
435 if (outfilename != NULL((void*)0))
436 fclose(OUTFILE);
437 return 0;
438}
439
440void iface_apply_down(char *word) {
441 int i;
442 char *result;
443 struct apply_handle *ah;
444 if (!iface_stack_check(1)) {
445 return;
446 }
447 ah = stack_get_ah();
448 iface_apply_set_params(ah);
449 result = apply_down(ah, word);
450 if (result == NULL((void*)0)) {
451 printf("???\n");
452 return;
453 } else {
454 printf("%s\n",result);
455 }
456 for (i = g_list_limit; i > 0; i--) {
457 result = apply_down(ah, NULL((void*)0));
458 if (result == NULL((void*)0))
459 break;
460 printf("%s\n",result);
461 }
462}
463
464void iface_apply_up(char *word) {
465 int i;
466 char *result;
467 struct apply_handle *ah;
468 if (!iface_stack_check(1)) {
469 return;
470 }
471 ah = stack_get_ah();
472
473 iface_apply_set_params(ah);
474 result = apply_up(ah, word);
475
476 if (result == NULL((void*)0)) {
477 printf("???\n");
478 return;
479 } else {
480 printf("%s\n",result);
481 }
482 for (i = g_list_limit; i > 0; i--) {
483 result = apply_up(ah, NULL((void*)0));
484 if (result == NULL((void*)0))
485 break;
486 printf("%s\n",result);
487 }
488}
489
490void iface_close() {
491 if (iface_stack_check(1)) {
492 stack_add(fsm_topsort(fsm_minimize(fsm_close_sigma(stack_pop(),0))));
493 }
494}
495
496void iface_compact() {
497 if (iface_stack_check(1)) {
498 fsm_compact(stack_find_top()->fsm);
499 sigma_sort(stack_find_top()->fsm);
500 stack_add(fsm_topsort(fsm_minimize(stack_pop())));
501 }
502}
503
504void iface_complete() {
505 if (iface_stack_check(1))
506 stack_add(fsm_complete(stack_pop()));
507}
508
509
510void iface_compose() {
511 struct fsm *one, *two;
512 if (iface_stack_check(2)) {
513 while (stack_size()>1) {
514 one = stack_pop();
515 two = stack_pop();
516 stack_add(fsm_topsort(fsm_minimize(fsm_compose(one,two))));
517 }
518 }
519}
520
521void iface_conc() {
522 struct fsm *one, *two;
523 if (iface_stack_check(2)) {
524 while (stack_size()>1) {
525 printf("dd");
526 one = stack_pop();
527 two = stack_pop();
528 stack_add(fsm_topsort(fsm_minimize(fsm_concat(one,two))));
529 }
530 }
531}
532
533void iface_crossproduct() {
534 struct fsm *one, *two;
535 if (iface_stack_check(2)) {
536 one = stack_pop();
537 two = stack_pop();
538 stack_add(fsm_topsort(fsm_minimize(fsm_cross_product(one,two))));
539 }
540}
541void iface_determinize() {
542 if (iface_stack_check(1))
543 stack_add(fsm_determinize(stack_pop()));
544}
545
546void iface_eliminate_flags() {
547 if (iface_stack_check(1))
548 stack_add(flag_eliminate(stack_pop(), NULL((void*)0)));
549}
550
551void iface_extract_ambiguous() {
552 if (iface_stack_check(1))
553 stack_add(fsm_extract_ambiguous(stack_pop()));
554}
555
556void iface_extract_unambiguous() {
557 if (iface_stack_check(1))
558 stack_add(fsm_extract_unambiguous(stack_pop()));
559}
560
561int iface_extract_number(char *s) {
562 int i;
563 for (i=0; *(s+i) != '\0' && ((unsigned char) *(s+i) < '0' || (unsigned char) *(s+i) > '9'); i++) { }
564 return(atoi(s+i));
565}
566
567void iface_eliminate_flag(char *name) {
568 if (iface_stack_check(1))
569 stack_add(flag_eliminate(stack_pop(), name));
570}
571
572void iface_factorize() {
573 if (iface_stack_check(1))
574 stack_add(fsm_bimachine(stack_pop()));
575}
576
577void iface_sequentialize() {
578 if (iface_stack_check(1))
579 stack_add(fsm_sequentialize(stack_pop()));
580}
581
582void iface_ignore() {
583 struct fsm *one, *two;
584 if (iface_stack_check(2)) {
585 one = stack_pop();
586 two = stack_pop();
587 stack_add(fsm_topsort(fsm_minimize(fsm_ignore(one,two,OP_IGNORE_ALL1))));
588 }
589}
590
591void iface_intersect() {
592 if (iface_stack_check(2)) {
593 while (stack_size()>1)
594 stack_add(fsm_topsort(fsm_minimize(fsm_intersect(stack_pop(),stack_pop()))));
595 }
596}
597
598void iface_invert() {
599 if (iface_stack_check(1))
600 stack_add(fsm_invert(stack_pop()));
601}
602
603void iface_label_net() {
604 if (iface_stack_check(1))
605 stack_add(fsm_sigma_pairs_net(stack_pop()));
606}
607
608void iface_letter_machine() {
609 if (iface_stack_check(1))
610 stack_add(fsm_topsort(fsm_minimize(fsm_letter_machine(stack_pop()))));
611}
612
613void iface_load_defined(char *filename) {
614 load_defined(g_defines, filename);
615}
616
617void iface_load_stack(char *filename) {
618 struct fsm *net;
619 fsm_read_binary_handle fsrh;
620
621 if ((fsrh = fsm_read_binary_file_multiple_init(filename)) == NULL((void*)0)) {
622 fprintf(stderrstderr, "%s: ", filename);
623 perror("File error");
624 return;
625 }
626 while ((net = fsm_read_binary_file_multiple(fsrh)) != NULL((void*)0))
627 stack_add(net);
628 return;
629}
630
631void iface_lower_side() {
632 if (iface_stack_check(1))
633 stack_add(fsm_topsort(fsm_minimize(fsm_lower(stack_pop()))));
634}
635
636void iface_minimize() {
637 int store_minimal_var;
638 if (iface_stack_check(1)) {
639 store_minimal_var = g_minimal;
640 g_minimal = 1;
641 stack_add(fsm_topsort(fsm_minimize(stack_pop())));
642 g_minimal = store_minimal_var;
643 }
644}
645
646void iface_one_plus() {
647 if (iface_stack_check(1))
648 stack_add(fsm_topsort(fsm_minimize(fsm_kleene_plus(stack_pop()))));
649}
650
651void iface_pop() {
652 struct fsm *net;
653 if (stack_size() < 1)
654 printf("Stack is empty.\n");
655 else {
656 net = stack_pop();
657 fsm_destroy(net);
658 }
659}
660
661void iface_lower_words(int limit) {
662 char *result;
663 struct apply_handle *ah;
664 int i;
665 if (!iface_stack_check(1)) {
666 return;
667 }
668 limit = (limit == -1) ? g_list_limit : limit;
669 if (iface_stack_check(1)) {
670 ah = stack_get_ah();
671 iface_apply_set_params(ah);
672 for (i = limit; i > 0; i--) {
673 result = apply_lower_words(ah);
674 if (result == NULL((void*)0))
675 break;
676 printf("%s\n",result);
677 }
678 apply_reset_enumerator(ah);
679 }
680}
681
682void iface_name_net(char *name) {
683 if (iface_stack_check(1)) {
684 strncpy(stack_find_top()->fsm->name, name, 40);
685 iface_print_name();
686 }
687}
688void iface_negate() {
689 if (iface_stack_check(1))
690 stack_add(fsm_topsort(fsm_minimize(fsm_complement(stack_pop()))));
691}
692
693void iface_print_dot(char *filename) {
694 if (iface_stack_check(1)) {
695 if (filename != NULL((void*)0))
696 printf("Writing dot file to %s.\n",filename);
697 print_dot(stack_find_top()->fsm, filename);
698 }
699}
700
701void iface_print_net(char *netname, char *filename) {
702 struct fsm *net;
703 if (netname != NULL((void*)0)) {
704 if ((net = find_defined(g_defines, netname)) == NULL((void*)0)) {
705 if (g_verbose)
706 {
707 fprintf(stderrstderr,"No defined network %s.\n", netname);
708 fflush(stderrstderr);
709 }
710 return;
711 }
712 print_net(net, filename);
713 } else {
714 if (iface_stack_check(1))
715 print_net(stack_find_top()->fsm, filename);
716 }
717}
718
719void iface_print_cmatrix_att(char *filename) {
720 FILE *outfile;
721 if (iface_stack_check(1)) {
722 if (stack_find_top()->fsm->medlookup == NULL((void*)0) || stack_find_top()->fsm->medlookup->confusion_matrix == NULL((void*)0)) {
723 printf("No confusion matrix defined.\n");
724 } else {
725 if (filename == NULL((void*)0)) {
726 outfile = stdoutstdout;
727 } else {
728 outfile = fopen(filename,"w");
729 printf("Writing confusion matrix to file '%s'.\n", filename);
730 }
731 cmatrix_print_att(stack_find_top()->fsm, outfile);
732 }
733 }
734}
735
736void iface_print_cmatrix() {
737 if (iface_stack_check(1)) {
738 if (stack_find_top()->fsm->medlookup == NULL((void*)0) || stack_find_top()->fsm->medlookup->confusion_matrix == NULL((void*)0)) {
739 printf("No confusion matrix defined.\n");
740 } else {
741 cmatrix_print(stack_find_top()->fsm);
742 }
743 }
744}
745
746void iface_print_defined() {
747 struct defined_networks *defined;
748 struct defined_functions *defined_f;
749 if (g_defines == NULL((void*)0)) {
750 printf("No defined symbols.\n");
751 }
752 for (defined = g_defines; defined != NULL((void*)0); defined = defined->next) {
753 if (defined->name != NULL((void*)0)) {
754 printf("%s\t",defined->name);
755 print_stats(defined->net);
756 }
757 }
758 for (defined_f = g_defines_f; defined_f != NULL((void*)0); defined_f = defined_f->next) {
759 if (defined_f->name != NULL((void*)0)) {
760 printf("%s@%i)\t",defined_f->name,defined_f->numargs);
761 printf("%s\n",defined_f->regex);
762 }
763 }
764}
765
766void iface_print_name() {
767 if (iface_stack_check(1))
768 printf("%s\n",stack_find_top()->fsm->name);
769}
770
771void iface_quit() {
772 struct fsm *net;
773 remove_defined(g_defines, NULL((void*)0));
774 while (!(stack_isempty())) {
775 net = stack_pop();
776 fsm_destroy(net);
777 }
778 exit(0);
779}
780
781void iface_random_lower(int limit) {
782 iface_apply_random(&apply_random_lower, limit);
783}
784
785void iface_random_upper(int limit) {
786 iface_apply_random(&apply_random_upper, limit);
787}
788
789void iface_random_words(int limit) {
790 iface_apply_random(&apply_random_words, limit);
791}
792
793void iface_apply_random(char *(*applyer)(struct apply_handle *h), int limit) {
794 char *result;
795 struct apply_handle *ah;
796 int i;
797 struct apply_results {
798 char *string;
799 int count;
800 } *results, *tempresults;
801
802 limit = (limit == -1) ? g_list_random_limit : limit;
803 if (iface_stack_check(1)) {
804 results = calloc(limit, sizeof(struct apply_results));
805 ah = stack_get_ah();
806 iface_apply_set_params(ah);
807 for (i = limit; i > 0; i--) {
808 result = NULL((void*)0);
809 result = applyer(ah);
810 if (result != NULL((void*)0)) {
811 for (tempresults = results; tempresults - results < limit; tempresults++) {
812 if (tempresults->string == NULL((void*)0)) {
813 tempresults->string = strdup(result);
814 tempresults->count = 1;
815 break;
816 }
817 else if (strcmp(tempresults->string, result) == 0) {
818 tempresults->count++;
819 break;
820 }
821 }
822 }
823 }
824 for (tempresults = results; tempresults - results < limit; tempresults++) {
825 if (tempresults->string != NULL((void*)0)) {
826 printf("[%i] %s\n", tempresults->count, tempresults->string);
827 free(tempresults->string);
828 }
829 }
830 free(results);
831 apply_reset_enumerator(ah);
832 }
833}
834
835void iface_print_sigma() {
836 if (iface_stack_check(1))
837 print_sigma(stack_find_top()->fsm->sigma,stdoutstdout);
838}
839void iface_print_stats() {
840 if (iface_stack_check(1))
841 print_stats(stack_find_top()->fsm);
842}
843
844void iface_print_shortest_string() {
845 /* L - ?+ [[L .o. [?:"@TMP@"]*].l .o. "@TMP@":?*].l; */
846 struct fsm *Result, *ResultU, *ResultL, *one, *onel, *oneu;
847 struct apply_handle *ah;
848 char *word;
849 if (iface_stack_check(1)) {
850 one = fsm_copy(stack_find_top()->fsm);
851 /* L - ?+ [[L .o. [?:"@TMP@"]*].l .o. "@TMP@":?*].l; */
852 if (stack_find_top()->fsm->arity == 1) {
853 Result = fsm_minimize(fsm_minus(fsm_copy(one),fsm_concat(fsm_kleene_plus(fsm_identity()),fsm_lower(fsm_compose(fsm_lower(fsm_compose(fsm_copy(one),fsm_kleene_star(fsm_cross_product(fsm_identity(),fsm_symbol("@TMP@"))))),fsm_kleene_star(fsm_cross_product(fsm_symbol("@TMP@"),fsm_identity())))))));
854 ah = apply_init(Result);
855 word = apply_words(ah);
856 if (word != NULL((void*)0)) printf("%s\n",word);
857 apply_clear(ah);
858 fsm_destroy(Result);
859 } else {
860 onel = fsm_lower(fsm_copy(one));
861 oneu = fsm_upper(one);
862 ResultU = fsm_minimize(fsm_minus(fsm_copy(oneu),fsm_concat(fsm_kleene_plus(fsm_identity()),fsm_lower(fsm_compose(fsm_lower(fsm_compose(fsm_copy(oneu),fsm_kleene_star(fsm_cross_product(fsm_identity(),fsm_symbol("@TMP@"))))),fsm_kleene_star(fsm_cross_product(fsm_symbol("@TMP@"),fsm_identity())))))));
863 ResultL = fsm_minimize(fsm_minus(fsm_copy(onel),fsm_concat(fsm_kleene_plus(fsm_identity()),fsm_lower(fsm_compose(fsm_lower(fsm_compose(fsm_copy(onel),fsm_kleene_star(fsm_cross_product(fsm_identity(),fsm_symbol("@TMP@"))))),fsm_kleene_star(fsm_cross_product(fsm_symbol("@TMP@"),fsm_identity())))))));
864 fsm_destroy(oneu);
865 fsm_destroy(onel);
866 ah = apply_init(ResultU);
867 word = apply_words(ah);
868 if (word == NULL((void*)0)) word = "";
869 printf("Upper: %s\n",word);
870 apply_clear(ah);
871 fsm_destroy(ResultU);
872 ah = apply_init(ResultL);
873 word = apply_words(ah);
874 if (word == NULL((void*)0)) word = "";
875 printf("Lower: %s\n",word);
876 apply_clear(ah);
877 fsm_destroy(ResultL);
878 }
879 }
880}
881
882void iface_print_shortest_string_size() {
883 struct fsm *Result, *ResultU, *ResultL, *one, *onel, *oneu;
884 if (iface_stack_check(1)) {
885 one = fsm_copy(stack_find_top()->fsm);
886 /* [L .o. [?:a]*].l; */
887 if (stack_find_top()->fsm->arity == 1) {
888 Result = fsm_minimize(fsm_lower(fsm_compose(one,fsm_kleene_star(fsm_cross_product(fsm_identity(),fsm_symbol("a"))))));
889 printf("Shortest acyclic path length: %i\n",Result->statecount-1);
890
891 } else {
892 onel = fsm_lower(fsm_copy(one));
893 oneu = fsm_upper(one);
894 ResultU = fsm_minimize(fsm_lower(fsm_compose(oneu,fsm_kleene_star(fsm_cross_product(fsm_identity(),fsm_symbol("a"))))));
895 ResultL = fsm_minimize(fsm_lower(fsm_compose(onel,fsm_kleene_star(fsm_cross_product(fsm_identity(),fsm_symbol("a"))))));
896 printf("Shortest acyclic upper path length: %i\n",(ResultU->statecount)-1);
897 printf("Shortest acyclic lower path length: %i\n",(ResultL->statecount)-1);
898 }
899 }
900}
901
902int iface_read_att(char *filename) {
903 struct fsm *tempnet;
904 printf("Reading AT&T file: %s\n",filename);
905 tempnet = read_att(filename);
906 if (tempnet == NULL((void*)0)) {
907 fprintf(stderrstderr, "%s: ", filename);
908 perror("Error opening file");
909 return 1;
910 } else {
911 stack_add(tempnet);
912 return 0;
913 }
914}
915
916int iface_read_prolog(char *filename) {
917 struct fsm *tempnet;
918 printf("Reading prolog: %s\n",filename);
919 tempnet = fsm_read_prolog(filename);
920 if (tempnet == NULL((void*)0)) {
921 fprintf(stderrstderr, "%s: ", filename);
922 perror ("Error opening file");
923 return 1;
924 } else {
925 stack_add(tempnet);
926 return 0;
927 }
928}
929
930int iface_read_spaced_text(char *filename) {
931 struct fsm *net;
932 net = fsm_read_spaced_text_file(filename);
933 if (net == NULL((void*)0)) {
934 fprintf(stderrstderr, "%s: ", filename);
935 perror("File error");
936 return 1;
937 }
938 stack_add(fsm_topsort(fsm_minimize(net)));
939 return 0;
940}
941
942int iface_read_text(char *filename) {
943 struct fsm *net;
944 net = fsm_read_text_file(filename);
945 if (net == NULL((void*)0)) {
946 fprintf(stderrstderr, "%s: ", filename);
947 perror("File error");
948 return 1;
949 }
950 stack_add(fsm_topsort(fsm_minimize(net)));
951 return 0;
952}
953
954int iface_stack_check (int size) {
955 if (stack_size() < size) {
956 printf("Not enough networks on stack. Operation requires at least %i.\n",size);
957 return 0;
958 }
959 return 1;
960}
961
962void iface_substitute_symbol (char *original, char *substitute) {
963 if (iface_stack_check(1)) {
964 dequote_string(original);
965 dequote_string(substitute);
966 stack_add(fsm_topsort(fsm_minimize(fsm_substitute_symbol(stack_pop(), original, substitute))));
967 printf("Substituted '%s' for '%s'.\n", substitute, original);
968 }
969}
970
971void iface_substitute_defined (char *original, char *substitute) {
972 struct fsm *subnet;
973 struct fsm *newnet;
974 if (iface_stack_check(1)) {
975 dequote_string(original);
976 dequote_string(substitute);
977 if ((subnet = find_defined(g_defines, substitute)) == NULL((void*)0)) {
978 printf("No defined network '%s'.\n",substitute);
979 } else {
980 if (fsm_symbol_occurs(stack_find_top()->fsm, original, M_UPPER1 + M_LOWER2) == 0) {
981 printf("Symbol '%s' does not occur.\n", original);
982 } else {
983 newnet = fsm_substitute_label(stack_find_top()->fsm, original, subnet);
984 stack_pop();
985 printf("Substituted network '%s' for '%s'.\n", substitute, original);
986 stack_add(fsm_topsort(fsm_minimize(newnet)));
987 }
988 }
989 }
990}
991
992void iface_upper_words(int limit) {
993 char *result;
994 struct apply_handle *ah;
995 int i;
996 limit = (limit == -1) ? g_list_limit : limit;
997 if (iface_stack_check(1)) {
998 ah = stack_get_ah();
999 iface_apply_set_params(ah);
1000 for (i = limit; i > 0; i--) {
1001 result = apply_upper_words(ah);
1002 if (result == NULL((void*)0))
1003 break;
1004 printf("%s\n",result);
1005 }
1006 apply_reset_enumerator(ah);
1007 }
1008}
1009
1010void iface_prune() {
1011 if (iface_stack_check(1))
1012 stack_add(fsm_topsort(fsm_coaccessible(stack_pop())));
1013}
1014void iface_reverse() {
1015 if (iface_stack_check(1))
1016 stack_add(fsm_topsort(fsm_determinize(fsm_reverse((stack_pop())))));
1017}
1018void iface_rotate() {
1019 if (iface_stack_check(1))
1020 stack_rotate();
1021}
1022void iface_save_defined(char *filename) {
1023 save_defined(g_defines, filename);
1024}
1025
1026void iface_save_stack(char *filename) {
1027 gzFile outfile;
1028 struct stack_entry *stack_ptr;
1029
1030 if (iface_stack_check(1)) {
1031 if ((outfile = gzopen(filename, "wb")) == NULL((void*)0)) {
1032 printf("Error opening file %s for writing.\n", filename);
1033 return;
1034 }
1035 printf("Writing to file %s.\n", filename);
1036 for (stack_ptr = stack_find_bottom(); stack_ptr->next != NULL((void*)0); stack_ptr = stack_ptr->next) {
1037 foma_net_print(stack_ptr->fsm, outfile);
1038 }
1039 gzclose(outfile);
1040 return;
1041 }
1042}
1043
1044void iface_show_variables() {
1045 int i;
1046 for (i=0; global_vars[i].name != NULL((void*)0); i++) {
1047 if (global_vars[i].type == FVAR_BOOL1) {
1048 printf("%-17.17s: %s\n",global_vars[i].name, *((int *)(global_vars[i].ptr)) == 1 ? "ON" : "OFF");
1049 }
1050 if (global_vars[i].type == FVAR_INT2) {
1051 printf("%-17.17s: %i\n",global_vars[i].name, *((int *)(global_vars[i].ptr)));
1052 }
1053 if (global_vars[i].type == FVAR_STRING3) {
1054 printf("%-17.17s: %s\n",global_vars[i].name, *((char **)(global_vars[i].ptr)) );
1055 }
1056 }
1057}
1058void iface_show_variable(char *name) {
1059 int i;
1060 for (i=0; global_vars[i].name != NULL((void*)0); i++) {
1061 if (strncmp(name,global_vars[i].name,8) == 0) {
1062 printf("%s = %s\n",global_vars[i].name, *((int *)(global_vars[i].ptr)) == 1 ? "ON" : "OFF");
1063 return;
1064 }
1065 }
1066 printf("*There is no global variable '%s'.\n",name);
1067}
1068
1069void iface_set_variable(char *name, char *value) {
1070 int i,j;
1071 char *endptr;
1072 for (i=0; global_vars[i].name != NULL((void*)0); i++) {
1073 if (strncmp(name,global_vars[i].name,8) == 0) {
1074 if (global_vars[i].type == FVAR_BOOL1) {
1075 if ((strcmp(value,"ON") == 0) || (strcmp(value, "1") == 0)) {
1076 j = 1;
1077 } else if ((strcmp(value,"OFF") == 0) || (strcmp(value, "0") == 0)) {
1078 j = 0;
1079 } else {
1080 printf("Invalid value '%s' for variable '%s'\n",value, global_vars[i].name);
1081 return;
1082 }
1083 *((int *)(global_vars[i].ptr)) = j;
1084 printf("variable %s = %s\n",global_vars[i].name, *((int *)(global_vars[i].ptr)) == 1 ? "ON" : "OFF");
1085 return;
1086 }
1087 if (global_vars[i].type == FVAR_STRING3) {
1088 *((char **)(global_vars[i].ptr)) = strdup(value);
1089 printf("variable %s = %s\n",global_vars[i].name, value);
1090 return;
1091 }
1092 if (global_vars[i].type == FVAR_INT2) {
1093 errno(*__errno_location ()) = 0;
1094 j = strtol(value, &endptr, 10);
1095 if ((errno(*__errno_location ()) != 0 || endptr == value) || j < 0) {
1096 printf("invalid value %s for variable %s\n", value, global_vars[i].name);
1097 return;
1098 } else {
1099 printf("variable %s = %i\n", global_vars[i].name, j);
1100 *((int *)(global_vars[i].ptr)) = j;
1101 return;
1102 }
1103 }
1104 }
1105 }
1106 printf("*There is no global variable '%s'.\n",name);
1107}
1108
1109void iface_shuffle() {
1110 if (iface_stack_check(2))
1111 while (stack_size()>1)
1112 stack_add(fsm_minimize(fsm_shuffle(stack_pop(),stack_pop())));
1113}
1114
1115void iface_sigma_net() {
1116 if (iface_stack_check(1))
1117 stack_add(fsm_sigma_net(stack_pop()));
1118}
1119
1120void iface_sort_input() {
1121 if (iface_stack_check(1)) {
1122 fsm_sort_arcs(stack_find_top()->fsm,1);
1123 }
1124}
1125
1126void iface_sort_output() {
1127 if (iface_stack_check(1)) {
1128 fsm_sort_arcs(stack_find_top()->fsm,2);
1129 }
1130}
1131
1132void iface_sort() {
1133 if (iface_stack_check(1)) {
1134 sigma_sort(stack_find_top()->fsm);
1135 stack_add(fsm_topsort(stack_pop()));
1136 }
1137}
1138
1139
1140void iface_test_equivalent() {
1141 struct fsm *one, *two;
1142 if (iface_stack_check(2)) {
1143 one = fsm_copy(stack_find_top()->fsm);
1144 two = fsm_copy(stack_find_second()->fsm);
1145 fsm_count(one);
1146 fsm_count(two);
1147
1148 //if (one->arccount != two->arccount || one->statecount != two->statecount || one->finalcount != two->finalcount) {
1149 //iface_print_bool(0);
1150 //} else {
1151 iface_print_bool(fsm_equivalent(one, two));
1152 //iface_print_bool(fsm_isempty(fsm_union(fsm_minus(fsm_copy(one),fsm_copy(two)),fsm_minus(fsm_copy(two),fsm_copy(one)))));
1153 //}
1154 }
1155}
1156
1157void iface_test_functional() {
1158 if (iface_stack_check(1))
1159 iface_print_bool(fsm_isfunctional(stack_find_top()->fsm));
1160}
1161
1162void iface_test_identity() {
1163 if (iface_stack_check(1))
1164 iface_print_bool(fsm_isidentity(stack_find_top()->fsm));
1165}
1166
1167void iface_test_nonnull() {
1168 if (iface_stack_check(1))
1169 iface_print_bool(!fsm_isempty(stack_find_top()->fsm));
1170}
1171
1172void iface_test_null() {
1173 if (iface_stack_check(1))
1174 iface_print_bool(fsm_isempty(stack_find_top()->fsm));
1175}
1176
1177void iface_test_unambiguous() {
1178 if (iface_stack_check(1))
1179 iface_print_bool(fsm_isunambiguous(stack_find_top()->fsm));
1180}
1181
1182void iface_test_lower_universal() {
1183 if (iface_stack_check(1)) {
1184 struct fsm *tmp = fsm_complement(fsm_lower(fsm_copy(stack_find_top()->fsm)));
1185 iface_print_bool(fsm_isempty(tmp));
1186 fsm_destroy(tmp);
1187 }
1188}
1189
1190void iface_test_sequential() {
1191 if (iface_stack_check(1))
1192 iface_print_bool(fsm_issequential(stack_find_top()->fsm));
1193}
1194
1195void iface_test_upper_universal() {
1196 if (iface_stack_check(1)) {
1197 struct fsm *tmp = fsm_complement(fsm_upper(fsm_copy(stack_find_top()->fsm)));
1198 iface_print_bool(fsm_isempty(tmp));
1199 fsm_destroy(tmp);
1200 }
1201}
1202
1203void iface_turn() {
1204 if (iface_stack_check(1))
1205 stack_rotate();
1206}
1207
1208void iface_twosided_flags() {
1209 if (iface_stack_check(1)) {
1210 stack_add(flag_twosided(stack_pop()));
1211 }
1212}
1213
1214void iface_union() {
1215 if (iface_stack_check(2))
1216 while (stack_size()>1)
1217 stack_add(fsm_minimize(fsm_union(stack_pop(),stack_pop())));
1218}
1219void iface_upper_side() {
1220 if (iface_stack_check(1))
1221 stack_add(fsm_topsort(fsm_minimize(fsm_upper(stack_pop()))));
1222}
1223
1224void iface_view() {
1225 if (iface_stack_check(1))
1
Taking true branch
1226 view_net(stack_find_top()->fsm);
2
Calling 'view_net'
1227}
1228
1229void iface_words_file(char *filename, int type) {
1230 /* type 0 (words), 1 (upper-words), 2 (lower-words) */
1231 FILE *outfile;
1232 char *result;
1233 static char *(*applyer)(struct apply_handle *h) = &apply_words;
1234 struct apply_handle *ah;
1235
1236 if (type == 1) {
1237 applyer = &apply_upper_words;
1238 }
1239 if (type == 2) {
1240 applyer = &apply_lower_words;
1241 }
1242 if (iface_stack_check(1)) {
1243 if (stack_find_top()->fsm->pathcount == PATHCOUNT_CYCLIC-1) {
1244 printf("FSM is cyclic: can't write all words to file.\n");
1245 return;
1246 }
1247 printf("Writing to %s.\n",filename);
1248 if ((outfile = fopen(filename, "w")) == NULL((void*)0)) {
1249 perror("Error opening file");
1250 return;
1251 }
1252 ah = stack_get_ah();
1253 iface_apply_set_params(ah);
1254 for (;;) {
1255 result = applyer(ah);
1256 if (result == NULL((void*)0))
1257 break;
1258 fprintf(outfile,"%s\n",result);
1259 }
1260 apply_reset_enumerator(ah);
1261 fclose(outfile);
1262 }
1263}
1264
1265void iface_words(int limit) {
1266 char *result;
1267 struct apply_handle *ah;
1268 int i;
1269 limit = (limit == -1) ? g_list_limit : limit;
1270 if (iface_stack_check(1)) {
1271 ah = stack_get_ah();
1272 iface_apply_set_params(ah);
1273 for (i = limit; i > 0; i--) {
1274 result = apply_words(ah);
1275 if (result == NULL((void*)0))
1276 break;
1277 printf("%s\n",result);
1278 }
1279 apply_reset_enumerator(ah);
1280 }
1281}
1282
1283/* Splits string of upper:lower pairs with space separator into two strings */
1284/* e.g. a:b c:d e 0:g => ace,bdeg */
1285
1286void iface_split_string(char *result, char *string) {
1287 int i;
1288 char space = '\001', epsilon = '\002', separator = '\003';
1289 /* Simulate: SEPARATOR \SPACE+ @-> 0 .o. SPACE|SEPARATOR|EPSILON -> 0 */
1290 /* to extract only upper side of string */
1291 for (i = 0 ; ; ) {
1292 zero:
1293 if (result[i] == '\0') {
1294 break;
1295 } else if (result[i] == space || result[i] == epsilon) {
1296 i++;
1297 goto zero;
1298 } else if (result[i] == separator) {
1299 i++;
1300 goto one;
1301 } else {
1302 strncat(string, result+i, 1);
1303 i++;
1304 goto zero;
1305 }
1306 one:
1307 if (result[i] == '\0') {
1308 break;
1309 } else if (result[i] == space) {
1310 i++;
1311 goto zero;
1312 } else {
1313 i++;
1314 goto one;
1315 }
1316 }
1317}
1318
1319void iface_split_result(char *result, char **upper, char **lower) {
1320 *upper = calloc(strlen(result), sizeof(char));
1321 *lower = calloc(strlen(result), sizeof(char));
1322 /* Split string into upper by filtering input side */
1323 /* and lower by the same filter, but reversed */
1324 iface_split_string(result, *upper);
1325 xstrrev(result);
1326 iface_split_string(result, *lower);
1327 xstrrev(*lower);
1328 xstrrev(result);
1329}
1330
1331
1332void iface_pairs_call(int limit, int random) {
1333 char *result, *upper, *lower;
1334 struct apply_handle *ah;
1335 int i;
1336 limit = (limit == -1) ? g_list_limit : limit;
1337 if (iface_stack_check(1)) {
1338 ah = stack_get_ah();
1339 apply_set_show_flags(ah, g_show_flags);
1340 apply_set_obey_flags(ah, g_obey_flags);
1341 apply_set_space_symbol(ah, "\001");
1342 apply_set_epsilon(ah, "\002");
1343 apply_set_separator(ah, "\003");
1344 for (i = limit; i > 0; i--) {
1345 if (random == 1)
1346 result = apply_random_words(ah);
1347 else
1348 result = apply_words(ah);
1349 if (result == NULL((void*)0))
1350 break;
1351 iface_split_result(result, &upper, &lower);
1352 printf("%s\t%s\n",upper, lower);
1353 free(upper);
1354 free(lower);
1355 }
1356 apply_set_space_symbol(ah, " ");
1357 apply_set_epsilon(ah, "0");
1358 apply_set_separator(ah, ":");
1359 apply_reset_enumerator(ah);
1360 }
1361}
1362
1363void iface_random_pairs(int limit) {
1364 iface_pairs_call(limit, 1);
1365}
1366
1367void iface_pairs(int limit) {
1368 iface_pairs_call(limit, 0);
1369}
1370
1371void iface_pairs_file(char *filename) {
1372 FILE *outfile;
1373 char *result, *upper, *lower;
1374 struct apply_handle *ah;
1375 if (iface_stack_check(1)) {
1376 if (stack_find_top()->fsm->pathcount == PATHCOUNT_CYCLIC-1) {
1377 printf("FSM is cyclic: can't write all pairs to file.\n");
1378 return;
1379 }
1380 printf("Writing to %s.\n",filename);
1381 if ((outfile = fopen(filename, "w")) == NULL((void*)0)) {
1382 perror("Error opening file");
1383 return;
1384 }
1385 ah = stack_get_ah();
1386 apply_set_show_flags(ah, g_show_flags);
1387 apply_set_obey_flags(ah, g_obey_flags);
1388 apply_set_space_symbol(ah, "\001");
1389 apply_set_epsilon(ah, "\002");
1390 apply_set_separator(ah, "\003");
1391 for (;;) {
1392 result = apply_words(ah);
1393 if (result == NULL((void*)0))
1394 break;
1395 iface_split_result(result, &upper, &lower);
1396 fprintf(outfile, "%s\t%s\n", upper, lower);
1397 free(upper);
1398 free(lower);
1399 }
1400 apply_set_space_symbol(ah, " ");
1401 apply_set_epsilon(ah, "0");
1402 apply_set_separator(ah, ":");
1403 apply_reset_enumerator(ah);
1404 fclose(outfile);
1405 }
1406}
1407
1408int iface_write_att(char *filename) {
1409 FILE *outfile;
1410 struct fsm *net;
1411 if (!iface_stack_check(1)) {
1412 return 1;
1413 }
1414 net = stack_find_top()->fsm;
1415 if (filename == NULL((void*)0)) {
1416 outfile = stdoutstdout;
1417 } else {
1418 printf("Writing AT&T file: %s\n",filename);
1419 outfile = fopen(filename, "w");
1420 if(outfile == NULL((void*)0)) {
1421 fprintf(stderrstderr, "%s: ", filename);
1422 perror("File error opening.");
1423 return 1;
1424 }
1425 }
1426 net_print_att(net, outfile);
1427 if (filename != NULL((void*)0))
1428 fclose(outfile);
1429 return 0;
1430}
1431
1432void iface_write_prolog(char *filename) {
1433 if (iface_stack_check(1))
1434 foma_write_prolog(stack_find_top()->fsm, filename);
1435}
1436
1437void iface_zero_plus() {
1438 if (iface_stack_check(1))
1439 stack_add(fsm_topsort(fsm_minimize(fsm_kleene_star(stack_pop()))));
1440}
1441
1442static char *sigptr(struct sigma *sigma, int number) {
1443 char *mystr;
1444 if (number
18.1
'number' is not equal to EPSILON
== EPSILON0)
19
Taking false branch
1445 return "0";
1446 if (number
19.1
'number' is not equal to UNKNOWN
== UNKNOWN1)
20
Taking false branch
1447 return "?";
1448 if (number
20.1
'number' is not equal to IDENTITY
== IDENTITY2)
21
Taking false branch
1449 return "@";
1450
1451 for (; sigma != NULL((void*)0); sigma = sigma->next) {
22
Loop condition is false. Execution continues on line 1464
1452 if (sigma->number == number) {
1453 if (strcmp(sigma->symbol,"0") == 0)
1454 return("\"0\"");
1455 if (strcmp(sigma->symbol,"?") == 0)
1456 return("\"?\"");
1457 if (strcmp(sigma->symbol,"\n") == 0)
1458 return("\\n");
1459 if (strcmp(sigma->symbol,"\r") == 0)
1460 return("\\r");
1461 return (sigma->symbol);
1462 }
1463 }
1464 mystr = malloc(sizeof(char)*40);
23
Memory is allocated
1465 snprintf(mystr, 40, "NONE(%i)",number);
1466 return(mystr);
1467}
1468
1469static int print_net(struct fsm *net, char *filename) {
1470 struct fsm_state *stateptr;
1471 int previous_state = -1, i;
1472 int *finals;
1473 FILE *out;
1474 if (filename == NULL((void*)0)) {
1475 out = stdoutstdout;
1476 } else {
1477 if ((out = fopen(filename, "w")) == NULL((void*)0)) {
1478 printf("Error writing to file %s. Using stdout.\n", filename);
1479 out = stdoutstdout;
1480 }
1481 printf("Writing network to file %s.\n", filename);
1482 }
1483 fsm_count(net);
1484 finals = malloc(sizeof(int)*(net->statecount));
1485 stateptr = net->states;
1486
1487 for (i=0; (stateptr+i)->state_no != -1; i++) {
1488 if ((stateptr+i)->final_state == 1) {
1489 *(finals+((stateptr+i)->state_no)) = 1;
1490 } else {
1491 *(finals+((stateptr+i)->state_no)) = 0;
1492 }
1493 if ((stateptr+i)->in != (stateptr+i)->out) {
1494 net->arity = 2;
1495 }
1496 }
1497 print_sigma(net->sigma, out);
1498 fprintf(out,"Net: %s\n",net->name);
1499 fprintf(out,"Flags: ");
1500 if (net->is_deterministic == YES1) { fprintf(out,"deterministic ");}
1501 if (net->is_pruned == YES1) { fprintf(out,"pruned ");}
1502 if (net->is_minimized == YES1) { fprintf(out,"minimized ");}
1503 if (net->is_epsilon_free == YES1) { fprintf(out,"epsilon_free ");}
1504 if (net->is_loop_free) { fprintf(out,"loop_free "); }
1505 if (net->arcs_sorted_in) { fprintf(out,"arcs_sorted_in "); }
1506 if (net->arcs_sorted_out) { fprintf(out,"arcs_sorted_out "); }
1507 fprintf(out,"\n");
1508 fprintf(out,"Arity: %i\n", net->arity);
1509 for (; stateptr->state_no != -1; stateptr++) {
1510 if (stateptr->state_no != previous_state) {
1511 if (stateptr->start_state) {
1512 fprintf(out,"S");
1513 }
1514 if (stateptr->final_state) {
1515 fprintf(out,"f");
1516 }
1517 if (stateptr->in==-1) {
1518 fprintf(out,"s%i:\t(no arcs).\n",stateptr->state_no);
1519 continue;
1520 } else {
1521 fprintf(out,"s%i:\t",stateptr->state_no);
1522 }
1523 }
1524 previous_state = stateptr->state_no;
1525 if (stateptr->in == stateptr->out) {
1526 if (stateptr->in == IDENTITY2) {
1527 fprintf(out,"@ -> ");
1528 } else if (stateptr->in == UNKNOWN1) {
1529 fprintf(out,"?:? -> ");
1530 } else {
1531 fprintf(out,"%s -> ",sigptr(net->sigma, stateptr->in));
1532 }
1533 } else {
1534 fprintf(out,"<%s:%s> -> ",sigptr(net->sigma, stateptr->in),sigptr(net->sigma, stateptr->out));
1535 }
1536 if (*(finals+(stateptr->target)) == 1) {
1537 fprintf(out,"f");
1538 }
1539 fprintf(out,"s%i",stateptr->target);
1540 if ((stateptr+1)->state_no == stateptr->state_no) {
1541 fprintf(out,", ");
1542 } else {
1543 fprintf(out,".\n");
1544 }
1545
1546 }
1547 if (filename != NULL((void*)0)) {
1548 fclose(out);
1549 }
1550 free(finals);
1551 return 0;
1552}
1553
1554void print_mem_size(struct fsm *net) {
1555 char size[20];
1556 struct sigma *sigma;
1557 unsigned int s;
1558 float sf;
1559 s = 0;
1560 for (sigma = net->sigma; sigma != NULL((void*)0) && sigma->number != -1; sigma = sigma->next) {
1561 s += strlen(sigma->symbol)+1+sizeof(struct sigma);
1562 }
1563 s += sizeof(struct fsm);
1564 s += sizeof(struct fsm_state) * net->linecount;
1565 sf = s;
1566 if (s < 1024) {
1567 sprintf(size, "%i bytes. ", s);
1568 } else if (s >= 1024 && s < 1048576) {
1569 sprintf(size, "%.1f kB. ", sf/1024);
1570 } else if (s >= 1048576 && s < 1073741824) {
1571 sprintf(size, "%.1f MB. ", sf/1048576);
1572 } else if (s >= 1073741824) {
1573 sprintf(size, "%.1f GB. ", sf/1073741824);
1574 }
1575 fprintf(stdoutstdout, "%s", size);
1576 fflush(stdoutstdout);
1577}
1578
1579int print_stats(struct fsm *net) {
1580 print_mem_size(net);
1581 if (net->statecount == 1) { printf("1 state, "); } else { printf("%i states, ",net->statecount); }
1582 if (net->arccount == 1) { printf("1 arc, "); } else { printf("%i arcs, ",net->arccount); }
1583 if (net->pathcount == 1)
1584 printf("1 path");
1585 else if (net->pathcount == -1)
1586 printf("Cyclic");
1587 else if (net->pathcount == -2)
1588 printf("more than %lld paths",LLONG_MAX9223372036854775807LL);
1589 else if (net->pathcount == -3)
1590 printf("unknown number of paths");
1591 else
1592 printf("%lld paths",net->pathcount);
1593 printf(".\n");
1594 return 0;
1595}
1596
1597static int print_sigma(struct sigma *sigma, FILE *out) {
1598 int size;
1599 fprintf (out,"Sigma:");
1600 for (size = 0; sigma != NULL((void*)0); sigma = sigma->next) {
1601 if (sigma->number > 2) {
1602 fprintf(out," %s",(sigma->symbol));
1603 size++;
1604 }
1605 if (sigma->number == IDENTITY2) {
1606 fprintf(out," %s","@");
1607 }
1608 if (sigma->number == UNKNOWN1) {
1609 fprintf(out," %s","?");
1610 }
1611 }
1612 fprintf(out,"\n");
1613 fprintf(out,"Size: %i.\n",size);
1614 return(1);
1615}
1616
1617static int print_dot(struct fsm *net, char *filename) {
1618 struct fsm_state *stateptr;
1619 FILE *dotfile;
1620 int i, j, linelen;
1621 short *finals, *printed;
1622
1623 fsm_count(net);
1624
1625 finals = malloc(sizeof(short)*net->statecount);
1626 stateptr = net->states;
1627
1628 for (i=0; (stateptr+i)->state_no != -1; i++) {
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
8
Assuming the condition is false
9
Loop condition is false. Execution continues on line 1636
1629 if ((stateptr+i)->final_state == 1) {
6
Assuming field 'final_state' is not equal to 1
7
Taking false branch
1630 *(finals+((stateptr+i)->state_no)) = 1;
1631 } else {
1632 *(finals+((stateptr+i)->state_no)) = 0;
1633 }
1634 }
1635
1636 if (filename != NULL((void*)0)) {
10
Assuming 'filename' is not equal to NULL
11
Taking true branch
1637 dotfile = fopen(filename,"w");
1638 } else {
1639 dotfile = stdoutstdout;
1640 }
1641
1642 fprintf(dotfile,"digraph A {\nrankdir = LR;\n");
1643 /* Go through states */
1644 for (i=0; i < net->statecount; i++) {
12
Assuming 'i' is >= field 'statecount'
13
Loop condition is false. Execution continues on line 1652
1645 if (*(finals+i)) {
1646 fprintf(dotfile,"node [shape=doublecircle,style=filled] %i\n",i);
1647 } else {
1648 fprintf(dotfile,"node [shape=circle,style=filled] %i\n",i);
1649 }
1650 }
1651
1652 printed = calloc(net->linecount,sizeof(printed));
1653 /* Go through arcs */
1654 for (i=0; (stateptr+i)->state_no != -1; i++) {
1655 if ((stateptr+i)->target == -1 || printed[i] == 1)
14
Assuming the condition is false
15
Taking false branch
1656 continue;
1657 fprintf(dotfile,"%i -> %i [label=\"", (stateptr+i)->state_no, (stateptr+i)->target);
1658 linelen = 0;
1659 for (j=i; (stateptr+j)->state_no == (stateptr+i)->state_no; j++) {
1660 if (((stateptr+i)->target
15.1
'(stateptr+i)->target' is equal to '(stateptr+j)->target'
== ((stateptr+j)->target)) && printed[j] == 0) {
16
Taking true branch
1661 printed[j] = 1;
1662
1663 if (((stateptr+j)->in == ((stateptr+j)->out)) && (stateptr+j)->out != UNKNOWN1 ) {
17
Assuming field 'in' is not equal to field 'out'
1664 fprintf(dotfile,"%s", escape_string(sigptr(net->sigma, (stateptr+j)->in),'"'));
1665 linelen += strlen((sigptr(net->sigma, (stateptr+j)->in)));
1666 } else {
1667 fprintf(dotfile,"<%s:%s>", escape_string(sigptr(net->sigma, (stateptr+j)->in),'"'), escape_string(sigptr(net->sigma, (stateptr+j)->out),'"'));
1668 linelen += strlen((sigptr(net->sigma, (stateptr+j)->in))) + strlen(sigptr(net->sigma, (stateptr+j)->out)) + 3;
18
Calling 'sigptr'
24
Returned allocated memory
25
Potential memory leak
1669 }
1670 if (linelen > 12) {
1671 fprintf(dotfile, "\\n");
1672 linelen = 0;
1673 } else {
1674 fprintf(dotfile, " ");
1675 }
1676 }
1677 }
1678 fprintf(dotfile,"\"];\n");
1679 }
1680
1681
1682 free(finals);
1683 free(printed);
1684 fprintf(dotfile, "}\n");
1685 if (filename != NULL((void*)0))
1686 fclose(dotfile);
1687 return(1);
1688}
1689
1690static int view_net(struct fsm *net) {
1691
1692 char tmpstr[255];
1693 char *dotname;
1694#ifndef __APPLE__
1695 char *pngname;
1696#endif /* __APPLE__ */
1697
1698 dotname = strncpy(tmpstr,tempnam(NULL((void*)0),"foma"), 250);
1699 strcat(dotname, ".dot");
1700 dotname = strdup(tmpstr);
1701 print_dot(net, dotname);
3
Calling 'print_dot'
1702
1703#ifdef __APPLE__
1704 sprintf(tmpstr,"/usr/bin/open -a Graphviz %s &",dotname);
1705 if (system(tmpstr) == -1)
1706 printf("Error opening viewer.\n");
1707
1708#endif /* __APPLE__ */
1709
1710#ifndef __APPLE__
1711 pngname = strdup(tempnam(NULL((void*)0), "foma"));
1712 sprintf(tmpstr,"dot -Tpng %s > %s ",dotname,pngname);
1713 if (system(tmpstr) == -1)
1714 printf("Error writing tempfile.\n");
1715 sprintf(tmpstr,"/usr/bin/xdg-open %s 2>/dev/null &",pngname);
1716 if (system(tmpstr) == -1)
1717 printf("Error opening viewer.\n");
1718 free(pngname);
1719#endif /* __APPLE__ */
1720
1721 free(dotname);
1722
1723 return(1);
1724}