aboutsummaryrefslogtreecommitdiff
path: root/gfsm
diff options
context:
space:
mode:
authorBryan Jurish <mukau@users.sourceforge.net>2008-11-29 23:22:39 +0000
committerBryan Jurish <mukau@users.sourceforge.net>2008-11-29 23:22:39 +0000
commitd13da71edce4b913736c1e752a211ae20c193292 (patch)
tree57b0c3884b5d465259d21906f89e4ec5635da9d3 /gfsm
parent2072ea2ef54b92775efc83c82d9a4b7a8ac4d616 (diff)
+ added local copy of gfsm source tree in gfsm/ subdir (for pd-extended auto-builds)
+ external builds now use static local libgfsm by default (insulates vs. API change, etc.) svn path=/trunk/externals/moocow/; revision=10403
Diffstat (limited to 'gfsm')
-rw-r--r--gfsm/Changes4
-rw-r--r--gfsm/Makefile.am3
-rw-r--r--gfsm/README.pod10
-rw-r--r--gfsm/README.txt10
-rwxr-xr-xgfsm/autogen.sh9
-rw-r--r--gfsm/configure.in57
-rw-r--r--gfsm/gfsm/AUTHORS31
-rw-r--r--gfsm/gfsm/COPYING510
-rw-r--r--gfsm/gfsm/Changes112
-rw-r--r--gfsm/gfsm/INSTALL229
-rw-r--r--gfsm/gfsm/Makefile.am155
-rw-r--r--gfsm/gfsm/README.cvs19
-rw-r--r--gfsm/gfsm/README.html220
-rw-r--r--gfsm/gfsm/README.pod166
-rw-r--r--gfsm/gfsm/README.txt116
-rwxr-xr-xgfsm/gfsm/autogen.sh57
-rw-r--r--gfsm/gfsm/config/.cvsignore23
-rw-r--r--gfsm/gfsm/config/Makefile.am67
-rw-r--r--gfsm/gfsm/configure.ac870
-rwxr-xr-xgfsm/gfsm/configure.gnu2
-rw-r--r--gfsm/gfsm/doc/.cvsignore27
-rw-r--r--gfsm/gfsm/doc/Makefile.am56
-rw-r--r--gfsm/gfsm/doc/libgfsm/.cvsignore32
-rw-r--r--gfsm/gfsm/doc/libgfsm/Makefile.am235
-rwxr-xr-xgfsm/gfsm/doc/libgfsm/doxy-filter.perl145
-rw-r--r--gfsm/gfsm/doc/libgfsm/libgfsm-header.html8
-rw-r--r--gfsm/gfsm/doc/libgfsm/libgfsm.css216
-rw-r--r--gfsm/gfsm/doc/libgfsm/libgfsm.doxy.dev227
-rw-r--r--gfsm/gfsm/doc/libgfsm/libgfsm.doxy.in229
-rw-r--r--gfsm/gfsm/doc/libgfsm/mainpage.dox.in102
-rw-r--r--gfsm/gfsm/doc/programs/.cvsignore41
-rw-r--r--gfsm/gfsm/doc/programs/Makefile.am309
-rw-r--r--gfsm/gfsm/doc/programs/gfsmprogs.css38
-rw-r--r--gfsm/gfsm/doc/programs/gfsmutils.skel90
-rw-r--r--gfsm/gfsm/gfsm.magic17
-rw-r--r--gfsm/gfsm/gfsm.pc.in26
-rw-r--r--gfsm/gfsm/m4/.cvsignore4
-rw-r--r--gfsm/gfsm/m4/alloca.m442
-rw-r--r--gfsm/gfsm/m4/eoverflow.m464
-rw-r--r--gfsm/gfsm/m4/getdelim.m430
-rw-r--r--gfsm/gfsm/m4/gnulib-cache.m428
-rw-r--r--gfsm/gfsm/m4/gnulib-comp.m470
-rw-r--r--gfsm/gfsm/m4/gnulib-tool.m433
-rw-r--r--gfsm/gfsm/m4/intmax_t.m461
-rw-r--r--gfsm/gfsm/m4/inttypes_h.m426
-rw-r--r--gfsm/gfsm/m4/longdouble.m428
-rw-r--r--gfsm/gfsm/m4/longlong.m423
-rw-r--r--gfsm/gfsm/m4/onceonly_2_57.m486
-rw-r--r--gfsm/gfsm/m4/signed.m417
-rw-r--r--gfsm/gfsm/m4/size_max.m459
-rw-r--r--gfsm/gfsm/m4/stdint_h.m426
-rw-r--r--gfsm/gfsm/m4/vasnprintf.m458
-rw-r--r--gfsm/gfsm/m4/vasprintf.m425
-rw-r--r--gfsm/gfsm/m4/wchar_t.m420
-rw-r--r--gfsm/gfsm/m4/wint_t.m420
-rw-r--r--gfsm/gfsm/m4/xsize.m413
-rw-r--r--gfsm/gfsm/src/.cvsignore20
-rw-r--r--gfsm/gfsm/src/Makefile.am69
-rw-r--r--gfsm/gfsm/src/libgfsm/.cvsignore43
-rw-r--r--gfsm/gfsm/src/libgfsm/Makefile.am288
-rw-r--r--gfsm/gfsm/src/libgfsm/config.h1
-rwxr-xr-xgfsm/gfsm/src/libgfsm/dummy-bison.sh6
-rwxr-xr-xgfsm/gfsm/src/libgfsm/dummy-flex.sh3
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsm.c27
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsm.h78
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAlgebra.c1715
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAlgebra.h559
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAlphabet.c1026
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAlphabet.h450
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArc.c192
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArc.h305
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArc.hi262
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcIndex.c498
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcIndex.h360
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcIndex.hi325
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcIter.c78
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcIter.h202
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcIter.hi126
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcList.c226
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcList.h207
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArcList.hi124
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArith.c199
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmArith.h137
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAssert.h51
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAutomaton.c338
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAutomaton.h557
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAutomaton.hi530
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.c897
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.h225
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmBitVector.c80
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmBitVector.h141
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmBitVector.hi133
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmCommon.c42
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmCommon.h88
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmCompound.c154
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmCompound.h266
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmCompound.hi217
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmConfig.h64
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmConfigAuto.h.in185
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmDebug.c35
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmDebug.h46
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmDraw.c293
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmDraw.h113
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmEnum.c39
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmEnum.h129
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmEnum.hi126
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmError.c46
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmError.h63
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIO.c558
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIO.h208
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIndexed.c157
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIndexed.h231
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIndexed.hi294
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIndexedIO.c464
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIndexedIO.h163
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmLookup.c481
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmLookup.h212
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmMem.c36
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmMem.h110
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmMem.hi135
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmPaths.c431
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmPaths.h240
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmRegex.lex.h342
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmRegex.lex.l201
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmRegex.tab.h84
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmRegex.tab.y149
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.c315
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.h223
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmScanner.c246
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmScanner.h262
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmSemiring.c104
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmSemiring.h183
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmSemiring.hi257
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmSet.c143
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmSet.h163
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmSet.hi136
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmState.c30
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmState.h109
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmState.hi144
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmStateSet.c222
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmStateSet.h219
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmStateSet.hi154
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmTrie.c282
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmTrie.h201
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmUtils.c101
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmUtils.h72
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmVersion.c52
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmVersion.h73
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmWeightMap.c54
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmWeightMap.h222
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmWeightMap.hi232
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/.cvsignore13
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/Makefile.am70
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/Makefile.in555
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/alloca_.h52
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/asnprintf.c37
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/asprintf.c37
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/getdelim.c128
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/getdelim.h28
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/printf-args.c118
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/printf-args.h136
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/printf-parse.c536
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/printf-parse.h74
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/size_max.h27
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.c901
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.h77
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/vasprintf.c42
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/vasprintf.h63
-rw-r--r--gfsm/gfsm/src/libgfsm/gnulib/xsize.h108
-rw-r--r--gfsm/gfsm/src/libgfsm/graveyard.c631
-rwxr-xr-xgfsm/gfsm/src/libgfsm/inc2dot.perl48
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/.cvsignore38
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/Makefile116
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/NOTES.lookup26
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/alphachurn.c11
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/arctab-1test.c54
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/arytest.c27
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/arytest2.c63
-rwxr-xr-xgfsm/gfsm/src/libgfsm/tests/asciigen.perl17
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/bvtest.c30
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/calc2test.l56
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/calc2test.y89
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/calctest.l52
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/calctest.y118
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/commatest.c8
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/compre2test.c41
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/comprelex.l297
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/compretest.l199
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/compretest.y185
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/ctest.c18
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/dettest.c21
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/flex2test.l174
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/flex3test.l232
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/flextest.l59
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/ftest.c17
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/gbtest.c27
-rwxr-xr-xgfsm/gfsm/src/libgfsm/tests/gfsm-chop.perl40
-rwxr-xr-xgfsm/gfsm/src/libgfsm/tests/gfsm-out-degrees.perl11
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.c210
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.h121
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/gfsmlabdump.c73
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/gscantest.c51
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/intfloat.c31
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/iotest.c180
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/lab2ary.c62
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/labchurn.c23
-rwxr-xr-xgfsm/gfsm/src/libgfsm/tests/labcount.perl28
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/labprobs.h71
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/lkptest.tfst8
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/macrotest.i11
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/memtest-alphabet.c26
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/memtest-automaton.c20
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/memtest-general.c168
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/memtest.c26
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/module/.cvsignore18
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/module/Makefile39
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/module/mod1a.c5
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/module/mod1b.c5
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/module/mod1test.c52
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/nofinal.tfst1
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/offsettest.c101
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/ortest.c7
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/pathtest.c289
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/pathtest.tfst9
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/priotest.c171
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/prtest.c28
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/prtest.tfst8
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/ptest.c25
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/rudtest.c100
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/rudtest.tfst3
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/rudtest2.tfst5
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/seek2test.c259
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/seek3test.c611
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/seektest.c365
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/seektest.dat9
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/settest.c36
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/sizes.bc70
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/sizetest.c16
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/sltest.c25
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/statetest.tfst8
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/structtest.c14
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/tagh-lo.testus8
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/test-255.lab3
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/test-stateset.c61
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/test.lab10
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/test.txt2
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/test2.lab2
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/test2.txt1
-rw-r--r--gfsm/gfsm/src/libgfsm/tests/testme.lab5
-rw-r--r--gfsm/gfsm/src/programs/.cvsignore79
-rw-r--r--gfsm/gfsm/src/programs/Makefile.am613
-rw-r--r--gfsm/gfsm/src/programs/arith.tfst9
-rw-r--r--gfsm/gfsm/src/programs/c1.tfst5
-rw-r--r--gfsm/gfsm/src/programs/c2.lab11
-rw-r--r--gfsm/gfsm/src/programs/c2.tfst4
-rw-r--r--gfsm/gfsm/src/programs/c2a.tfst10
-rw-r--r--gfsm/gfsm/src/programs/c2b.tfst22
-rw-r--r--gfsm/gfsm/src/programs/c3a.tfst8
-rw-r--r--gfsm/gfsm/src/programs/c3b.tfst26
-rw-r--r--gfsm/gfsm/src/programs/c3filt.tfst20
-rw-r--r--gfsm/gfsm/src/programs/cat1.tfst3
-rw-r--r--gfsm/gfsm/src/programs/cat2.tfst4
-rw-r--r--gfsm/gfsm/src/programs/comp1a.tfst4
-rw-r--r--gfsm/gfsm/src/programs/comp1b.tfst4
-rw-r--r--gfsm/gfsm/src/programs/comp2.tfst6
-rw-r--r--gfsm/gfsm/src/programs/comp2a.tfst2
-rw-r--r--gfsm/gfsm/src/programs/comp2b.tfst3
-rw-r--r--gfsm/gfsm/src/programs/complement-in.tfst4
-rw-r--r--gfsm/gfsm/src/programs/compose-mohri-1.tfst5
-rw-r--r--gfsm/gfsm/src/programs/compose-mohri-2.tfst4
-rw-r--r--gfsm/gfsm/src/programs/config.h13
-rw-r--r--gfsm/gfsm/src/programs/connect-in.tfst7
-rw-r--r--gfsm/gfsm/src/programs/ctest.tfst7
-rw-r--r--gfsm/gfsm/src/programs/ctest2.tfst6
-rw-r--r--gfsm/gfsm/src/programs/det.tfst5
-rw-r--r--gfsm/gfsm/src/programs/determinize-in.tfst7
-rw-r--r--gfsm/gfsm/src/programs/elookup.tfst2
-rw-r--r--gfsm/gfsm/src/programs/gfsmarcsort.gog107
-rw-r--r--gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.c595
-rw-r--r--gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.h77
-rw-r--r--gfsm/gfsm/src/programs/gfsmarcsort_main.c102
-rw-r--r--gfsm/gfsm/src/programs/gfsmarith.gog132
-rw-r--r--gfsm/gfsm/src/programs/gfsmarith_cmdparser.c773
-rw-r--r--gfsm/gfsm/src/programs/gfsmarith_cmdparser.h93
-rw-r--r--gfsm/gfsm/src/programs/gfsmarith_main.c132
-rw-r--r--gfsm/gfsm/src/programs/gfsmclosure.gog79
-rw-r--r--gfsm/gfsm/src/programs/gfsmclosure_cmdparser.c495
-rw-r--r--gfsm/gfsm/src/programs/gfsmclosure_cmdparser.h67
-rw-r--r--gfsm/gfsm/src/programs/gfsmclosure_main.c100
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompile.gog102
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompile_cmdparser.c569
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompile_cmdparser.h73
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompile_main.c132
-rw-r--r--gfsm/gfsm/src/programs/gfsmcomplement.gog73
-rw-r--r--gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.c473
-rw-r--r--gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.h65
-rw-r--r--gfsm/gfsm/src/programs/gfsmcomplement_main.c105
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompose.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompose_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompose_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompose_main.c123
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompre.gog94
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompre_cmdparser.c542
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompre_cmdparser.h71
-rw-r--r--gfsm/gfsm/src/programs/gfsmcompre_main.c143
-rw-r--r--gfsm/gfsm/src/programs/gfsmconcat.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmconcat_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmconcat_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmconcat_main.c118
-rw-r--r--gfsm/gfsm/src/programs/gfsmconnect.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmconnect_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmconnect_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmconnect_main.c99
-rw-r--r--gfsm/gfsm/src/programs/gfsmconvert.gog89
-rw-r--r--gfsm/gfsm/src/programs/gfsmconvert_cmdparser.c517
-rw-r--r--gfsm/gfsm/src/programs/gfsmconvert_cmdparser.h69
-rw-r--r--gfsm/gfsm/src/programs/gfsmconvert_main.c110
-rw-r--r--gfsm/gfsm/src/programs/gfsmdeterminize.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmdeterminize_main.c100
-rw-r--r--gfsm/gfsm/src/programs/gfsmdifference.gog71
-rw-r--r--gfsm/gfsm/src/programs/gfsmdifference_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmdifference_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmdifference_main.c123
-rw-r--r--gfsm/gfsm/src/programs/gfsmdraw.gog138
-rw-r--r--gfsm/gfsm/src/programs/gfsmdraw_cmdparser.c835
-rw-r--r--gfsm/gfsm/src/programs/gfsmdraw_cmdparser.h99
-rw-r--r--gfsm/gfsm/src/programs/gfsmdraw_main.c166
-rw-r--r--gfsm/gfsm/src/programs/gfsmheader.gog57
-rw-r--r--gfsm/gfsm/src/programs/gfsmheader_cmdparser.c403
-rw-r--r--gfsm/gfsm/src/programs/gfsmheader_cmdparser.h60
-rw-r--r--gfsm/gfsm/src/programs/gfsmheader_main.c129
-rw-r--r--gfsm/gfsm/src/programs/gfsmindex.gog75
-rw-r--r--gfsm/gfsm/src/programs/gfsmindex_cmdparser.c473
-rw-r--r--gfsm/gfsm/src/programs/gfsmindex_cmdparser.h65
-rw-r--r--gfsm/gfsm/src/programs/gfsmindex_main.c124
-rw-r--r--gfsm/gfsm/src/programs/gfsminfo.gog57
-rw-r--r--gfsm/gfsm/src/programs/gfsminfo_cmdparser.c403
-rw-r--r--gfsm/gfsm/src/programs/gfsminfo_cmdparser.h60
-rw-r--r--gfsm/gfsm/src/programs/gfsminfo_main.c123
-rw-r--r--gfsm/gfsm/src/programs/gfsmintersect.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmintersect_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmintersect_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmintersect_main.c123
-rw-r--r--gfsm/gfsm/src/programs/gfsminvert.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsminvert_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsminvert_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsminvert_main.c95
-rw-r--r--gfsm/gfsm/src/programs/gfsmlabels.gog78
-rw-r--r--gfsm/gfsm/src/programs/gfsmlabels_cmdparser.c523
-rw-r--r--gfsm/gfsm/src/programs/gfsmlabels_cmdparser.h69
-rw-r--r--gfsm/gfsm/src/programs/gfsmlabels_main.c208
-rw-r--r--gfsm/gfsm/src/programs/gfsmlookup.gog77
-rw-r--r--gfsm/gfsm/src/programs/gfsmlookup_cmdparser.c473
-rw-r--r--gfsm/gfsm/src/programs/gfsmlookup_cmdparser.h65
-rw-r--r--gfsm/gfsm/src/programs/gfsmlookup_main.c125
-rw-r--r--gfsm/gfsm/src/programs/gfsmoptional.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmoptional_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmoptional_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmoptional_main.c101
-rw-r--r--gfsm/gfsm/src/programs/gfsmprint.gog80
-rw-r--r--gfsm/gfsm/src/programs/gfsmprint_cmdparser.c498
-rw-r--r--gfsm/gfsm/src/programs/gfsmprint_cmdparser.h67
-rw-r--r--gfsm/gfsm/src/programs/gfsmprint_main.c125
-rw-r--r--gfsm/gfsm/src/programs/gfsmproduct.gog78
-rw-r--r--gfsm/gfsm/src/programs/gfsmproduct_cmdparser.c450
-rw-r--r--gfsm/gfsm/src/programs/gfsmproduct_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmproduct_main.c123
-rw-r--r--gfsm/gfsm/src/programs/gfsmproject.gog76
-rw-r--r--gfsm/gfsm/src/programs/gfsmproject_cmdparser.c523
-rw-r--r--gfsm/gfsm/src/programs/gfsmproject_cmdparser.h71
-rw-r--r--gfsm/gfsm/src/programs/gfsmproject_main.c100
-rw-r--r--gfsm/gfsm/src/programs/gfsmrenumber.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmrenumber_main.c95
-rw-r--r--gfsm/gfsm/src/programs/gfsmreplace.gog79
-rw-r--r--gfsm/gfsm/src/programs/gfsmreplace_cmdparser.c514
-rw-r--r--gfsm/gfsm/src/programs/gfsmreplace_cmdparser.h69
-rw-r--r--gfsm/gfsm/src/programs/gfsmreplace_main.c108
-rw-r--r--gfsm/gfsm/src/programs/gfsmreverse.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmreverse_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmreverse_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmreverse_main.c101
-rw-r--r--gfsm/gfsm/src/programs/gfsmrmepsilon.gog80
-rw-r--r--gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmrmepsilon_main.c95
-rw-r--r--gfsm/gfsm/src/programs/gfsmsigma.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmsigma_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmsigma_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmsigma_main.c100
-rw-r--r--gfsm/gfsm/src/programs/gfsmstrings.gog76
-rw-r--r--gfsm/gfsm/src/programs/gfsmstrings_cmdparser.c525
-rw-r--r--gfsm/gfsm/src/programs/gfsmstrings_cmdparser.h69
-rw-r--r--gfsm/gfsm/src/programs/gfsmstrings_main.c153
-rw-r--r--gfsm/gfsm/src/programs/gfsmunion.gog70
-rw-r--r--gfsm/gfsm/src/programs/gfsmunion_cmdparser.c449
-rw-r--r--gfsm/gfsm/src/programs/gfsmunion_cmdparser.h63
-rw-r--r--gfsm/gfsm/src/programs/gfsmunion_main.c123
-rwxr-xr-xgfsm/gfsm/src/programs/gfsmview.sh6
-rw-r--r--gfsm/gfsm/src/programs/gfsmviterbi.gog88
-rw-r--r--gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.c473
-rw-r--r--gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.h65
-rw-r--r--gfsm/gfsm/src/programs/gfsmviterbi_main.c125
-rw-r--r--gfsm/gfsm/src/programs/isect1.tfst4
-rw-r--r--gfsm/gfsm/src/programs/isect2.tfst5
-rw-r--r--gfsm/gfsm/src/programs/lkptest.tfst13
-rw-r--r--gfsm/gfsm/src/programs/p1.tfst5
-rw-r--r--gfsm/gfsm/src/programs/p2.tfst3
-rw-r--r--gfsm/gfsm/src/programs/prunetest.tfst6
-rw-r--r--gfsm/gfsm/src/programs/r1.tfst9
-rw-r--r--gfsm/gfsm/src/programs/r2.tfst4
-rw-r--r--gfsm/gfsm/src/programs/renumber.tfst5
-rw-r--r--gfsm/gfsm/src/programs/renumber2.tfst8
-rw-r--r--gfsm/gfsm/src/programs/rev1.tfst7
-rw-r--r--gfsm/gfsm/src/programs/rme.tfst6
-rw-r--r--gfsm/gfsm/src/programs/rme2.tfst8
-rw-r--r--gfsm/gfsm/src/programs/rme2b.tfst8
-rw-r--r--gfsm/gfsm/src/programs/rme3.tfst5
-rw-r--r--gfsm/gfsm/src/programs/sort.tfst7
-rw-r--r--gfsm/gfsm/src/programs/sortme.tfst15
-rw-r--r--gfsm/gfsm/src/programs/symtest.lab15
-rw-r--r--gfsm/gfsm/src/programs/symtest.sym8
-rw-r--r--gfsm/gfsm/src/programs/test+lab.tfst3
-rw-r--r--gfsm/gfsm/src/programs/test-rn.tfst8
-rw-r--r--gfsm/gfsm/src/programs/test.lab15
-rw-r--r--gfsm/gfsm/src/programs/test.tfst3
-rw-r--r--gfsm/gfsm/src/programs/test2.tfst7
-rw-r--r--gfsm/gfsm/src/programs/test3.tfst6
-rw-r--r--gfsm/gfsm/src/programs/test4.tfst9
-rw-r--r--gfsm/gfsm/src/programs/test4b.tfst9
-rw-r--r--gfsm/gfsm/src/programs/test5.tfst3
-rw-r--r--gfsm/gfsm/src/programs/test6.tfst12
-rw-r--r--gfsm/gfsm/src/programs/test7.lab4
-rw-r--r--gfsm/gfsm/src/programs/test7.tfst2
-rw-r--r--gfsm/gfsm/src/programs/test8.tfst4
-rw-r--r--gfsm/gfsm/src/programs/test9.tfst4
-rw-r--r--gfsm/gfsm/src/programs/testa.tfsa6
-rw-r--r--gfsm/gfsm/src/programs/testa.tfst6
-rw-r--r--gfsm/gfsm/src/programs/testrn.tfst3
-rw-r--r--gfsm/gfsm/src/programs/vit-in.lab3
-rw-r--r--gfsm/gfsm/src/programs/vit-out.lab7
-rw-r--r--gfsm/gfsm/src/programs/vit-q.lab3
-rw-r--r--gfsm/gfsm/src/programs/vit.tfst17
-rw-r--r--gfsm/gfsm/src/programs/vit2.tfst15
-rw-r--r--gfsm/gfsm/tests/.cvsignore11
-rw-r--r--gfsm/gfsm/tests/01_basic.at54
-rw-r--r--gfsm/gfsm/tests/02_arith.at107
-rw-r--r--gfsm/gfsm/tests/03_algebra.at223
-rw-r--r--gfsm/gfsm/tests/Makefile.am159
-rw-r--r--gfsm/gfsm/tests/atlocal.in37
-rw-r--r--gfsm/gfsm/tests/data/.cvsignore4
-rw-r--r--gfsm/gfsm/tests/data/basic1.inf14
-rw-r--r--gfsm/gfsm/tests/data/basic1.tfst2
-rw-r--r--gfsm/gfsm/tests/data/basic2.labs.inf14
-rw-r--r--gfsm/gfsm/tests/data/basic2.labs.tfst4
-rw-r--r--gfsm/gfsm/tests/data/closure-plus-in.tfst4
-rw-r--r--gfsm/gfsm/tests/data/closure-plus-want.tfst6
-rw-r--r--gfsm/gfsm/tests/data/closure-star-in.tfst4
-rw-r--r--gfsm/gfsm/tests/data/closure-star-want.tfst7
-rw-r--r--gfsm/gfsm/tests/data/complement-b-in.tfst4
-rw-r--r--gfsm/gfsm/tests/data/complement-b-want.tfst43
-rw-r--r--gfsm/gfsm/tests/data/complement-in.tfst4
-rw-r--r--gfsm/gfsm/tests/data/complement-want.tfst11
-rw-r--r--gfsm/gfsm/tests/data/compose-in-1.tfst4
-rw-r--r--gfsm/gfsm/tests/data/compose-in-2.tfst4
-rw-r--r--gfsm/gfsm/tests/data/compose-want.tfst6
-rw-r--r--gfsm/gfsm/tests/data/concat-in-1.tfst4
-rw-r--r--gfsm/gfsm/tests/data/concat-in-2.tfst4
-rw-r--r--gfsm/gfsm/tests/data/concat-want.tfst8
-rw-r--r--gfsm/gfsm/tests/data/connect-in.tfst7
-rw-r--r--gfsm/gfsm/tests/data/connect-want.tfst5
-rw-r--r--gfsm/gfsm/tests/data/determinize-in.tfst7
-rw-r--r--gfsm/gfsm/tests/data/determinize-want.tfst9
-rw-r--r--gfsm/gfsm/tests/data/difference-in-1.tfst6
-rw-r--r--gfsm/gfsm/tests/data/difference-in-2.tfst5
-rw-r--r--gfsm/gfsm/tests/data/difference-want.tfst21
-rw-r--r--gfsm/gfsm/tests/data/intersect-in-1.tfst4
-rw-r--r--gfsm/gfsm/tests/data/intersect-in-2.tfst5
-rw-r--r--gfsm/gfsm/tests/data/intersect-want.tfst11
-rw-r--r--gfsm/gfsm/tests/data/intersect2-in-1.tfst6
-rw-r--r--gfsm/gfsm/tests/data/intersect2-in-2.tfst29
-rw-r--r--gfsm/gfsm/tests/data/intersect2-want.tfst21
-rw-r--r--gfsm/gfsm/tests/data/invert-in.tfst5
-rw-r--r--gfsm/gfsm/tests/data/invert-want.tfst5
-rw-r--r--gfsm/gfsm/tests/data/lookup-123-want.tfst7
-rw-r--r--gfsm/gfsm/tests/data/lookup-223-want.tfst9
-rw-r--r--gfsm/gfsm/tests/data/lookup.tfst13
-rw-r--r--gfsm/gfsm/tests/data/n_closure-in.tfst4
-rw-r--r--gfsm/gfsm/tests/data/n_closure-want.tfst14
-rw-r--r--gfsm/gfsm/tests/data/null.inf14
-rw-r--r--gfsm/gfsm/tests/data/null.tfst0
-rw-r--r--gfsm/gfsm/tests/data/optional-in.tfst2
-rw-r--r--gfsm/gfsm/tests/data/optional-want.tfst3
-rw-r--r--gfsm/gfsm/tests/data/project-hi-in.tfst6
-rw-r--r--gfsm/gfsm/tests/data/project-hi-want.tfst6
-rw-r--r--gfsm/gfsm/tests/data/project-lo-in.tfst6
-rw-r--r--gfsm/gfsm/tests/data/project-lo-want.tfst6
-rw-r--r--gfsm/gfsm/tests/data/renumber-in.tfst8
-rw-r--r--gfsm/gfsm/tests/data/renumber-want.tfst8
-rw-r--r--gfsm/gfsm/tests/data/rmepsilon-in.tfst8
-rw-r--r--gfsm/gfsm/tests/data/rmepsilon-want.tfst8
-rw-r--r--gfsm/gfsm/tests/data/t1.linf14
-rw-r--r--gfsm/gfsm/tests/data/test.lab11
-rw-r--r--gfsm/gfsm/tests/data/union-in-1.tfst4
-rw-r--r--gfsm/gfsm/tests/data/union-in-2.tfst4
-rw-r--r--gfsm/gfsm/tests/data/union-want.tfst10
-rwxr-xr-xgfsm/gfsm/tests/data/zzz-compile-all.sh12
-rw-r--r--gfsm/gfsm/tests/package.m46
-rwxr-xr-xgfsm/gfsm/tests/testsuite5251
-rw-r--r--gfsm/gfsm/tests/testsuite.at10
-rw-r--r--gfsm/gfsm/wishlist.txt44
-rw-r--r--gfsm/src/gfsm-help.pd4
-rw-r--r--gfsm/src/noconfig.h42
-rw-r--r--gfsm/src/pd_gfsm.c5
517 files changed, 67496 insertions, 22 deletions
diff --git a/gfsm/Changes b/gfsm/Changes
index fb46c02..82abe51 100644
--- a/gfsm/Changes
+++ b/gfsm/Changes
@@ -1,5 +1,9 @@
Change log for PD external 'pd-gfsm'
+v0.05 Sun, 30 Nov 2008 00:08:06 +0100
+ + added local copy of gfsm source tree in gfsm/ subdir (for pd-extended auto-builds)
+ + external builds now use static local libgfsm by default (insulates vs. API change, etc.)
+
v0.0403 Tue, 11 Dec 2007 22:33:18 +0100
+ updated for gfsm-0.0.10-pre1 (noconfig.h, config.h preprocessor magic)
diff --git a/gfsm/Makefile.am b/gfsm/Makefile.am
index 4983beb..8e89e71 100644
--- a/gfsm/Makefile.am
+++ b/gfsm/Makefile.am
@@ -15,7 +15,8 @@
AUTOMAKE_OPTIONS = foreign
## --- recursion subdirectories
-SUBDIRS = config src
+#SUBDIRS = config src
+SUBDIRS = @PD_GFSM_SUBDIRS@ config src
## --- pseudo-deps for '.SUFFIXES'
SUFFIXES = .pod .txt
diff --git a/gfsm/README.pod b/gfsm/README.pod
index 1155c8c..6395628 100644
--- a/gfsm/README.pod
+++ b/gfsm/README.pod
@@ -2,7 +2,7 @@
README for pd external package 'gfsm'
-Last updated for pd-gfsm v0.04
+Last updated for pd-gfsm v0.05
=head1 DESCRIPTION
@@ -16,9 +16,13 @@ pd-gfsm provides Pd bindings for the GFSM finite-state machine library.
Available from http://crca.ucsd.edu/~msp/software.html
-=item libgfsm >= v0.0.8-pre6
+=item libgfsm >= v0.0.8-pre6 (optional)
-Available from http://www.ling.uni-potsdam.de/~moocow/projects/gfsm
+A local copy of the libgfsm source tree is included with this distribution,
+and should be built and used by default.
+
+Newer versions should be
+available from http://www.ling.uni-potsdam.de/~moocow/projects/gfsm
=back
diff --git a/gfsm/README.txt b/gfsm/README.txt
index f889241..9af7b62 100644
--- a/gfsm/README.txt
+++ b/gfsm/README.txt
@@ -1,6 +1,6 @@
README for pd external package 'gfsm'
- Last updated for pd-gfsm v0.04
+ Last updated for pd-gfsm v0.05
DESCRIPTION
pd-gfsm provides Pd bindings for the GFSM finite-state machine library.
@@ -8,8 +8,12 @@ DESCRIPTION
PREREQUISITES
Pd Available from http://crca.ucsd.edu/~msp/software.html
- libgfsm >= v0.0.8-pre6
- Available from http://www.ling.uni-potsdam.de/~moocow/projects/gfsm
+ libgfsm >= v0.0.8-pre6 (optional)
+ A local copy of the libgfsm source tree is included with this
+ distribution, and should be built and used by default.
+
+ Newer versions should be available from
+ http://www.ling.uni-potsdam.de/~moocow/projects/gfsm
INSTALLATION
Issue the following commands to the shell:
diff --git a/gfsm/autogen.sh b/gfsm/autogen.sh
index 845f276..a7360a1 100755
--- a/gfsm/autogen.sh
+++ b/gfsm/autogen.sh
@@ -11,6 +11,8 @@ MY_AHDIRS="."
MY_AMDIRS="."
MY_ACDIRS="."
+MY_AGDIRS="./gfsm"
+
test -z "$ACLOCAL" && ACLOCAL=aclocal
test -z "$AUTOHEADER" && AUTOHEADER=autoheader
test -z "$AUTOMAKE" && AUTOMAKE=automake
@@ -44,5 +46,12 @@ if test -n "$MY_ACDIRS"; then
done
fi
+if test -n "$MY_AGDIRS"; then
+ for d in $MY_AGDIRS ; do
+ echo "(cd $d ; ./autogen.sh)"
+ (cd $d ; ./autogen.sh)
+ done
+fi
+
#echo "(./configure)"
#./configure $*
diff --git a/gfsm/configure.in b/gfsm/configure.in
index e1c5ef9..efaf727 100644
--- a/gfsm/configure.in
+++ b/gfsm/configure.in
@@ -4,7 +4,7 @@ AC_PREREQ(2.5)
dnl Some handy macros
define([THE_PACKAGE_NAME], [pd-gfsm])
-define([THE_PACKAGE_VERSION], [0.0403])
+define([THE_PACKAGE_VERSION], [0.05])
define([THE_PACKAGE_AUTHOR], [moocow@ling.uni-potsdam.de])
AC_INIT(THE_PACKAGE_NAME, THE_PACKAGE_VERSION, THE_PACKAGE_AUTHOR)
@@ -39,6 +39,9 @@ dnl AC_PROG_CXX
AC_PROG_INSTALL
AC_PREFIX_DEFAULT(/usr/local)
+dnl v--- needed if Makefile.am uses _LTLIBRARIES targets
+AC_PROG_LIBTOOL
+
dnl
dnl Substitutions
dnl
@@ -126,18 +129,48 @@ if test -z "$ac_cv_pkgconfigdir" ; then
fi
pkgconfigdir="$ac_cv_pkgconfigdir"
AC_SUBST(pkgconfigdir)
+AC_SUBST(PKG_CONFIG)
dnl
dnl pkg-config
dnl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## gfsm:local
+AC_ARG_ENABLE([static-gfsm],
+ AC_HELP_STRING([--enable-static-gfsm], [Use local static libgfsm rather than system library (default=yes)]),
+ [ac_cv_enable_static_gfsm="$enableval"],
+ [ac_cv_enable_static_gfsm="yes"])
+
+AC_MSG_CHECKING([whether to build static local libgfsm])
+if test "$ac_cv_enable_static_gfsm" = "yes"; then
+ AC_MSG_RESULT(yes)
+ AC_CONFIG_SUBDIRS(gfsm)
+ PD_GFSM_SUBDIRS="gfsm"
+
+ IFLAGS="$IFLAGS -I\$(top_srcdir)/gfsm/src/libgfsm -I\$(top_builddir)/gfsm/src/libgfsm \`\$(PKG_CONFIG) --cflags-only-I \$(top_srcdir)/gfsm/gfsm.pc\`"
+ LFLAGS="$LFLAGS -L\$(top_builddir)/gfsm/src/libgfsm \`\$(PKG_CONFIG) --cflags-only-I \$(top_srcdir)/gfsm/gfsm.pc\`"
+ LIBS="$LIBS \$(top_builddir)/gfsm/src/libgfsm/libgfsm.la \`\$(PKG_CONFIG) --libs-only-l \$(top_srcdir)/gfsm/gfsm.pc | sed -e's/\-lgfsm//g'\`"
+
+ AC_DEFINE(PD_GFSM_WHICH, ["static"], [Which version of gfsm are we using?])
+else
+ PD_GFSM_SUBDIRS=""
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST(PD_GFSM_SUBDIRS)
+
+AC_DEFINE_UNQUOTED(PD_GFSM_DATE, "`date`", [Date this external was configured])
+AC_DEFINE_UNQUOTED(PD_GFSM_USER, "$USER", [User who configured this external])
+## /gfsm:local
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-## gfsm (pkg-config)
-PKG_CHECK_MODULES(GFSM, gfsm >= 0.0.8,
+## gfsm:system (pkg-config)
+if test "$ac_cv_enable_static_gfsm" = "no"; then
+ PKG_CHECK_MODULES(GFSM, gfsm >= 0.0.8,
[PC_HAVE_GFSM="yes"],
[PC_HAVE_GFSM=""])
-if test "$PC_HAVE_GFSM" != "yes" ; then
+ if test "$PC_HAVE_GFSM" != "yes" ; then
AC_MSG_WARN([])
AC_MSG_WARN([----------------------------------------------------------------])
AC_MSG_WARN([ gfsm library not found!])
@@ -147,21 +180,23 @@ if test "$PC_HAVE_GFSM" != "yes" ; then
AC_MSG_WARN([----------------------------------------------------------------])
AC_MSG_WARN([])
ac_cv_have_gfsm="no"
-else
+ else
ac_cv_have_gfsm="yes"
-fi
+ fi
-if test "$ac_cv_have_gfsm" != "no" ; then
+ if test "$ac_cv_have_gfsm" != "no" ; then
##-- gfsm: library
IFLAGS="$IFLAGS `$PKG_CONFIG --cflags-only-I gfsm`"
LFLAGS="$LFLAGS `$PKG_CONFIG --libs-only-L gfsm`"
LIBS="$LIBS `$PKG_CONFIG --libs-only-l gfsm`"
+ AC_DEFINE(PD_GFSM_WHICH, ["system"], [Which version of gfsm are we using?])
+ fi
fi
-## /gfsm
+## /gfsm:system
##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-## gfsm (global)
+## gfsm:any
AC_ARG_ENABLE(gfsm,
AC_HELP_STRING([--disable-gfsm], [Globally disable gfsm support (causes build to fail!)]),
[ac_cv_enable_gfsm="$enableval"],
@@ -170,11 +205,9 @@ AC_ARG_ENABLE(gfsm,
if test "$ac_cv_enable_gfsm" != "yes" ; then
AC_MSG_ERROR([gfsm support disabled by user],1)
fi
-
-## /gfsm (global)
+## /gfsm:any
##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
dnl --------------------------------------------------------------------
dnl BEGIN import from pd configure.in
dnl --------------------------------------------------------------------
diff --git a/gfsm/gfsm/AUTHORS b/gfsm/gfsm/AUTHORS
new file mode 100644
index 0000000..6fc2155
--- /dev/null
+++ b/gfsm/gfsm/AUTHORS
@@ -0,0 +1,31 @@
+Bryan Jurish <moocow@ling.uni-potsdam.de> wrote and maintains the 'gfsm'
+package.
+
+Code from the gnulib project is included.
+See the files in src/libgfsm/gnulib for details.
+
+Some modified code from the GLib project is included:
++ Code from glib/gslist.c adapted in src/libgfsm/gfsmArcList.c:
+ /* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
diff --git a/gfsm/gfsm/COPYING b/gfsm/gfsm/COPYING
new file mode 100644
index 0000000..cf9b6b9
--- /dev/null
+++ b/gfsm/gfsm/COPYING
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+^L
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+^L
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+^L
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+^L
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+^L
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+^L
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+^L
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+^L
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/gfsm/gfsm/Changes b/gfsm/gfsm/Changes
new file mode 100644
index 0000000..ab5a67a
--- /dev/null
+++ b/gfsm/gfsm/Changes
@@ -0,0 +1,112 @@
+Change log for gfsm
+
+v0.0.10 Mon, Fri, 31 Oct 2008 14:29:52 +0100
+ + added configure flag --disable-programs for static builds
+ + gfsmio_getdelim (local implementation): changed handling of GString data buffers
+ - formerly, GString data was literally returned as (*lineptr)
+ - old behavior breaks perl wrappers (e.g. _compile()) on OpenSuSE 11.0
+ - workaround: GString data is copied to a new (char*) locally allocated with malloc()
+ + automaton I/O: changed header struct; added hacks for v0.0.9 header detection & parsing
+ + fixed an overflow bug in default gfsmio_getdelim() func
+ + added at&t-style escaped-string paring function: gfsm_alphabet_att_string_to_labels()
+ - wrapper:gfsm_alphabet_generic_string_to_labels()
+ ~ choose character-wise or att-style parsing via 'att_mode' flag
+ - added '--att-mode', '--map-mode', '--quiet' options to gfsmlabels
+ + moved gfsmArcList to a native linked-list type, rather than GSList
+ - saves 1 pointer per arc
+ - adapted some code from glib/gslist.c (sort, remove_link, etc)
+ + moved autoheader config file to gfsmAutoConfig.h
+ - added header-safe gfsmConfig.h hack to "safely" read in autoheader config
+ - requires clobbering any existing autoheader type macros with gfsmNoConfig.h
+ ~ there are better ways of doing this (e.g. sed), but this should suffice for most purposes
+ + altered behavior of gfsm_automaton_copy_shallow(), gfsm_automaton_shadow()
+ - root state id is no longer copied: not considered 'shallow' data
+ + moved most simple accessor function code from macros to 'static inline' defined in *.hi
+ - added configure option '--disable-inline' to disable function inlining
+
+v0.0.9 Fri, 23 Nov 2007 22:43:52 +0100
+ + added "source" field to gfsmArc: source gfsmStateId
+ - fixed gfsm_automaton_reverse() and gfsmReverseArcIndex to use new feature
+ - added additional argument to various methods in gfsmArc.h to deal with new datum
+ + added shell tool gfsmindex, source files gfsmIndexed.[ch], gfsmIndexedIO.[ch]
+ - the "right way" to do this would be to go for a truly abstract automaton API,
+ but the price (virtualization, extraneous flag & limit checking, etc.) is daunting
+ + changed static int<->pointer casts to GPOINTER_TO_(U)INT, G(U)INT_TO_POINTER
+ + fixed gfsmWeight-related segfault bugs on 64-bit linux
+ - gfsm_weight2ptr() and gfsm_ptr2weight() are now implemented as true functions
+ using a "hidden" union type gfsmWeightOrPointer to handle memory stuff
+ - this happily also allows gcc to compile without -fno-strict-aliasing
+ + fixed bug reported by Alexis Nasr in gfsm_pointer_alphabet_new() macro
+ + fixed nasty bug in gfsm_alphabet_load_handle() and gfsmio_getc() causing
+ char decimal 255 to return as EOF
+ + re-implemented gfsm_automaton_compose() using implicit Mohri-Pereira-Riley filter
+ + fixed output-filename parsing bug in gfsmlabels
+ + added check for fsm->states->len==0 in is_cyclic(), fixes bug in gfsminfo
+ for empty automata created with gfsm_automaton_copy_shallow() (aka 'shadow')
+ - the real problem here is probably that copy_shallow() also copies root_id, even
+ though the corresponding state doesn't exist
+ + added gfsmArcIter copy() and clone() methods
+
+v0.0.9-pre? Mon, 29 Oct 2007 12:54:19 +0100
+ + exposed guts of gfsm_automaton_compose()
+ - compose_prepare() into compose_old_prepare_fsm1(), compose_old_prepare_fsm2()
+ - should make it easier to hack a cascade implementation
+
+v0.0.8 Thu, 15 Feb 2007 12:05:41 +0100
+ + updated build system to build more cleanly on non-development systems
+ - e.g. missing optgen.perl, flex, bison, pod2x, perl, etc.
+ + added gfsm.magic snippet for /etc/magic
+ - added 'install-magic' and 'uninstall-magic' targets for
+ manual magic maintainance, since there seems to be no good and safe
+ way to do this automagically (ugh)...
+ + added support for final weights
+ + changed binary format (backwards-compatible with dispatch function)
+ + added final-weight operations final_weight_(plus|times)()
+ + added optional(), replace(), insert_automaton()
+ + added lookup_viterbi(), viterbi_trellis_paths(), viterbi_trellis_bestpath()
+ + fixed a bug in gfsm_automaton_renumber_states()
+ + fixed a really stupid bug in gfsm_arclist_insert_link() for sorted insertion
+ + fixed some bugs in gfsm_automaton_rmepsilon()
+ + fixed an epsilon-related bug in compose() and intersect()
+ + fixed another epsilon-related bug in compose()
+ - implemented algorithm from:
+ Mohri, Pereira, & Riley (1996), "Weighted Automata in Text and Speech
+ Processing", Proc. ECAI '96, John Wiley & Sons, Ltd.
+ - calling conventions changed for compose_full()
+ + added gfsmScanner.[ch], gfsmRegexCompiler.[ch]
+ + added gfsmTrie, (quasi-)deterministic input acceptor (i/o pairs)
+ - currently geared towards storing frequencies
+ + added gfsmIO.[ch] : abstract I/O layer
+ - includes basic zlib compression support
+ - currently used only for text & binary automaton I/O, also text alphabet I/O
+ - TODO: use I/O layer for alphabet draw methods? regex compiler?
+ + added gnulib code for vasprintf(), getdelim()
+ - removed old gfsmCompat.h hack
+
+v0.0.7 Sun, 20 Nov 2005 14:39:33 +0100
+ + added lookup(), paths(), path<->string conversion functions
+ + added semiring type "plog" (positive logs), added stable gfsm_log_add() function
+ + added intersect(), compose(), difference(), product(), rmepsilon() operations
+ + gobble less memory on load_bin_file() -- load states & arcs incrementally
+ - doing this right would require a stored binary file incompatibility, currently hacked.
+ + fixed a number of small bugs
+
+v0.0.6 Mon, 12 Sep 2005 01:45:46 +0200
+ + added mingw32 patch (getline)
+
+v0.0.5 Wed, 22 Sep 2004 00:23:49 +0200
+ + removed references to file "LICENSE" in header comments
+ + fixed small size bug in clear() for gfsmUserAlphabet
+ + added key-stringification to gfsm_automaton_draw() methods
+
+v0.0.4 Tue, 14 Sep 2004 15:57:56 +0200
+ + fixed bug in gfsm_alphabet_size() for user alphabets
+
+v0.0.3 Mon, 13 Sep 2004 10:25:23 +0200
+ + added some algebraic operations, fixed some bugs
+
+v0.0.2 Thu, 2 Sep 2004 17:34:18 +0200
+ + basic accessors and algebra
+
+v0.0.1 Tue, 24 Aug 2004 11:34:59 +0200
+ + created
diff --git a/gfsm/gfsm/INSTALL b/gfsm/gfsm/INSTALL
new file mode 100644
index 0000000..54caf7c
--- /dev/null
+++ b/gfsm/gfsm/INSTALL
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/gfsm/gfsm/Makefile.am b/gfsm/gfsm/Makefile.am
new file mode 100644
index 0000000..6a9780c
--- /dev/null
+++ b/gfsm/gfsm/Makefile.am
@@ -0,0 +1,155 @@
+# File: ./Makefile.am
+# Package: gfsm
+# Description:
+# + top-level automake file
+#
+# Process this file with Automake to create Makefile.in.
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# Options & Subdirectories
+#-----------------------------------------------------------------------
+
+## --- automake options
+#AUTOMAKE_OPTIONS = foreign dist-bzip2 dist-zip
+AUTOMAKE_OPTIONS = foreign
+
+## --- recursion subdirectories
+#SUBDIRS = config src doc tests
+SUBDIRS = config src $(GFSM_SUBDIRS)
+
+## --- pseudo-deps for '.SUFFIXES'
+SUFFIXES = .pc .pod .txt .html
+
+## --- package config data
+pkgconfig_DATA = @PACKAGE@.pc
+
+##-- for gnulib
+ACLOCAL_AMFLAGS = -I m4
+
+#-----------------------------------------------------------------------
+# Variables: cleanup
+#-----------------------------------------------------------------------
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+#CLEANFILES =
+
+## --- distclean: built by 'configure'
+DISTCLEANFILES = \
+ config.log \
+ config.cache \
+ config.status
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = *~ \
+ Makefile Makefile.in \
+ aclocal.m4 \
+ configure \
+ install-sh \
+ stamp-h.in \
+ config.h.in \
+ magic.local \
+ magic \
+ *.tmp
+
+# $(PODS:.pod=.txt)
+# $(PODS:.pod=.html)
+
+maintainer-clean-local:
+ rm -rf autom4te.cache
+
+#CVSCLEAN_SUBDIRS = $(SUBDIRS)
+
+#CVSCLEANFILES = Makefile.in Makefile
+
+
+#-----------------------------------------------------------------------
+# Additional Variables & Rules: PODS
+#-----------------------------------------------------------------------
+PODS = README.pod
+
+if HAVE_POD2TEXT
+.pod.txt:
+ pod2text $< $@
+endif
+
+if HAVE_POD2HTML
+.pod.html:
+ pod2html --outfile $@ $<
+endif
+
+pkgdoc_DATA = \
+ $(PODS:.pod=.txt) \
+ $(PODS:.pod=.html)
+
+#-----------------------------------------------------------------------
+# Additional Variables & Rules: magic
+#-----------------------------------------------------------------------
+
+pkgdoc_DATA += gfsm.magic
+
+##-- phony
+.PHONY: install-magic unintall-magic
+
+MAGIC_ADDRS='/^\#\#--BEGIN gfsm\.magic$$/,/^\#\#--END gfsm\.magic/'
+magic ?=/etc/magic
+
+install-magic: magic
+ $(INSTALL_DATA) $< $(magic)
+
+uninstall-magic: magic.local
+ $(INSTALL_DATA) $< $(magic)
+
+magic: gfsm.magic magic.local
+ cat magic.local > "$@"
+ sed -n -e$(MAGIC_ADDRS)p @srcdir@/gfsm.magic >> "$@"
+
+magic.local: $(ETC_MAGIC)
+ sed -e$(MAGIC_ADDRS)d $(magic) > $@
+
+
+#-----------------------------------------------------------------------
+# Variables: distribution
+#-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ INSTALL \
+ AUTHORS \
+ Changes \
+ $(PODS) \
+ $(PODS:.pod=.txt) \
+ $(PODS:.pod=.html) \
+ autogen.sh \
+ configure \
+ README.cvs \
+ gfsm.magic
+
+#COPYING
+
+## --- recursion subdirectories for 'make dist'
+#DIST_SUBDIRS = $(SUBDIRS)
+
+## --- dist-hook: when another 'Makefile.am' is overkill
+#DISTHOOK_DIRS = foo
+#DISTHOOK_FILES = foo/bar.txt foo/baz.txt
+#dist-hook:
+# for d in $(DISTHOOK_DIRS); do\
+# mkdir -p $(distdir)/$$d ;\
+# done
+# for f in $(DISTHOOK_FILES); do\
+# cp -p $(srcdir)/$$f $(distdir)/$$f ;\
+# done
+
+#dist-bz2: dist-bzip2 ;
+
+
+#-----------------------------------------------------------------------
+# Rules: cleanup
+#-----------------------------------------------------------------------
+.PHONY: cvsclean cvsclean-hook
+
+cvsclean: maintainer-clean ;
+
diff --git a/gfsm/gfsm/README.cvs b/gfsm/gfsm/README.cvs
new file mode 100644
index 0000000..a74e38a
--- /dev/null
+++ b/gfsm/gfsm/README.cvs
@@ -0,0 +1,19 @@
+To build from cvs, do the following:
+
+ ./autogen.sh
+ ./configure
+ make
+ make install
+
+NOTE: The README.txt file in the distribution
+is auto-generated from perl ".pod" format by
+the "pod2text" included in most perl distributions.
+
+You might (i.e. if you see complaints about 'optgen.perl')
+also need the 'Getopt::Gen' perl module, which should
+be available from:
+
+ http://www.ling.uni-potsdam.de/~moocow/projects/perl
+
+marmosets,
+ Bryan
diff --git a/gfsm/gfsm/README.html b/gfsm/gfsm/README.html
new file mode 100644
index 0000000..927bd8d
--- /dev/null
+++ b/gfsm/gfsm/README.html
@@ -0,0 +1,220 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>DESCRIPTION</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+<p><a name="__index__"></a></p>
+<!-- INDEX BEGIN -->
+
+<ul>
+
+ <li><a href="#description">DESCRIPTION</a></li>
+ <li><a href="#dependencies">DEPENDENCIES</a></li>
+ <li><a href="#installation">INSTALLATION</a></li>
+ <ul>
+
+ <li><a href="#additional_installation_targets">Additional installation targets</a></li>
+ </ul>
+
+ <li><a href="#build_options">BUILD OPTIONS</a></li>
+ <li><a href="#acknowledgements">ACKNOWLEDGEMENTS</a></li>
+ <li><a href="#known_bugs">KNOWN BUGS</a></li>
+ <li><a href="#author">AUTHOR</a></li>
+</ul>
+<!-- INDEX END -->
+
+<hr />
+<p>README for package gfsm</p>
+<p>Last updated for gfsm v0.0.8</p>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>The gfsm package consists of libgfsm, an abstract C library
+of tools for manipulation of finite state machines, and the
+gfsm utilities, a suite of command-line tools built on libgfsm.
+gfsm currently supports AT&amp;T style weighted transducer
+text input and label definition files, as well as a number
+of common algebraic operations on finite state machines.</p>
+<p>
+</p>
+<hr />
+<h1><a name="dependencies">DEPENDENCIES</a></h1>
+<dl>
+<dt><strong><a name="item_0">glib-2.0 (REQUIRED)</a></strong>
+
+<dd>
+<p>Available from:
+<a href="http://www.gtk.org/">http://www.gtk.org/</a></p>
+</dd>
+<dd>
+<p>C library for common data structures.
+Tested versions 2.4.6, 2.8.3.</p>
+</dd>
+</li>
+<dt><strong><a name="item_zlib">zlib (Optional)</a></strong>
+
+<dd>
+<p>Compression library by Jean-loup Gailly and Mark Adler
+which can be used for transparent (de)compression.
+Available from:
+<a href="http://www.gzip.org/zlib">http://www.gzip.org/zlib</a></p>
+</dd>
+<dd>
+<p>Tested version 1.2.1.</p>
+</dd>
+</li>
+<dt><strong><a name="item_pkg_2dconfig">pkg-config</a></strong>
+
+<dd>
+<p>Available from:
+<a href="http://www.freedesktop.org/software/pkgconfig/">http://www.freedesktop.org/software/pkgconfig/</a></p>
+</dd>
+<dd>
+<p>To build from CVS, you will also need the pkg-config
+autoconf macros which come with the source distribution
+of pkg-config.</p>
+</dd>
+</li>
+<dt><strong><a name="item_doxygen">doxygen (Optional)</a></strong>
+
+<dd>
+<p>Required for building library documentation.
+Available from:
+<a href="http://www.doxygen.org">http://www.doxygen.org</a></p>
+</dd>
+<dd>
+<p>Tested versions 1.2.15, 1.3.8, 1.4.4.</p>
+</dd>
+</li>
+<dt><strong><a name="item_perl">Perl (Optional)</a></strong>
+
+<dd>
+<p>Get it from <a href="http://www.cpan.org">http://www.cpan.org</a> or <a href="http://www.perl.com">http://www.perl.com</a></p>
+</dd>
+<dd>
+<p>Required for re-building command-line parsers
+and/or non-standard documentation formats.</p>
+</dd>
+</li>
+<dt><strong><a name="item_gen">Getopt::Gen (Optional)</a></strong>
+
+<dd>
+<p>A Perl module used to generate command-line option parsers.
+Should be available from the author of this package at:</p>
+</dd>
+<dd>
+<p><a href="http://www.ling.uni-potsdam.de/~moocow/projects/perl">http://www.ling.uni-potsdam.de/~moocow/projects/perl</a></p>
+</dd>
+<dd>
+<p>Tested versions 0.09, 0.10.</p>
+</dd>
+<dd>
+<p>Note that Getopt::Gen depends on several 3rd-party perl
+modules, including Text::Template and Parse::Lex,
+which are available from CPAN.</p>
+</dd>
+<dd>
+<p>Note additionally that Parse::Lex v2.15 is broken: if
+it gives you grief, use the hacked version available
+at:</p>
+</dd>
+<dd>
+<p><a href="http://www.ling.uni-potsdam.de/~moocow/projects/perl/ParseLex-2.15-hacked.tar.gz">http://www.ling.uni-potsdam.de/~moocow/projects/perl/ParseLex-2.15-hacked.tar.gz</a></p>
+</dd>
+</li>
+<dt><strong><a name="item_pod2latex">pod2man, pod2text, pod2html, pod2latex (Optional)</a></strong>
+
+<dd>
+<p>The Perl documentation converstion utilities, required
+for building the correspdonding program documentation
+formats, should have come with your Perl. These are
+only required if you wish to build program documentation
+formats other than the defaults which come with the
+distribution.</p>
+</dd>
+</li>
+</dl>
+<p>
+</p>
+<hr />
+<h1><a name="installation">INSTALLATION</a></h1>
+<p>Issue the following commands to the shell:</p>
+<pre>
+ cd gfsm-X.Y.Z (or wherever you extracted the distribution)
+ sh ./configure
+ make
+ make install</pre>
+<p>
+</p>
+<h2><a name="additional_installation_targets">Additional installation targets</a></h2>
+<p>The build system supports the following optional installation targets;
+call them with:</p>
+<pre>
+ make SOME_TARGET</pre>
+<p>from the distribution root directory.</p>
+<dl>
+<dt><strong><a name="item_install_2dmagic">install-magic</a></strong>
+
+<dd>
+<p>Adds recognition support for stored binary gfsm files
+to the database for the <code>file(1)</code> utility. If your <code>file(1)</code>
+database lives somewhere other than /etc/magic (see <code>magic(5)</code> for details),
+call this target as:</p>
+</dd>
+<dd>
+<pre>
+ make magic=/full/path/to/my/file/magic install-magic</pre>
+</dd>
+</li>
+<dt><strong><a name="item_uninstall_2dmagic">uninstall-magic</a></strong>
+
+<dd>
+<p>Removes gfsm recognition support (if present) from your
+/etc/magic database, or from whatever database you specified
+with the 'magic' variable.</p>
+</dd>
+</li>
+</dl>
+<p>
+</p>
+<hr />
+<h1><a name="build_options">BUILD OPTIONS</a></h1>
+<p>The 'configure' script supports the following options, among others:</p>
+<dl>
+<dt><strong><a name="item__2d_2denable_2ddebug__2c__2d_2ddisable_2ddebug">--enable-debug , --disable-debug</a></strong>
+
+<dd>
+<p>Whether to enable verbose debugging messages.
+Default=no.</p>
+</dd>
+</li>
+</dl>
+<p>See the output of `./configure --help` for details on additional
+supported options.</p>
+<p>
+</p>
+<hr />
+<h1><a name="acknowledgements">ACKNOWLEDGEMENTS</a></h1>
+<p>Ideas and code adapted from the SFST package by Helmut Schmid.</p>
+<p>Many thanks to Thomas Hanneforth for useful advice.</p>
+<p>
+</p>
+<hr />
+<h1><a name="known_bugs">KNOWN BUGS</a></h1>
+<p>Many.</p>
+<p>
+</p>
+<hr />
+<h1><a name="author">AUTHOR</a></h1>
+<p>Bryan Jurish &lt;<a href="mailto:moocow@ling.uni-potsdam.de">moocow@ling.uni-potsdam.de</a>&gt;</p>
+
+</body>
+
+</html>
diff --git a/gfsm/gfsm/README.pod b/gfsm/gfsm/README.pod
new file mode 100644
index 0000000..87c57fd
--- /dev/null
+++ b/gfsm/gfsm/README.pod
@@ -0,0 +1,166 @@
+=pod
+
+README for package gfsm
+
+Last updated for gfsm v0.0.8
+
+=head1 DESCRIPTION
+
+The gfsm package consists of libgfsm, an abstract C library
+of tools for manipulation of finite state machines, and the
+gfsm utilities, a suite of command-line tools built on libgfsm.
+gfsm currently supports AT&T style weighted transducer
+text input and label definition files, as well as a number
+of common algebraic operations on finite state machines.
+
+=head1 DEPENDENCIES
+
+=over 4
+
+=item glib-2.0 (REQUIRED)
+
+Available from:
+http://www.gtk.org/
+
+C library for common data structures.
+Tested versions 2.4.6, 2.8.3.
+
+
+=item zlib (Optional)
+
+Compression library by Jean-loup Gailly and Mark Adler
+which can be used for transparent (de)compression.
+Available from:
+http://www.gzip.org/zlib
+
+Tested version 1.2.1.
+
+
+=item pkg-config
+
+Available from:
+http://www.freedesktop.org/software/pkgconfig/
+
+To build from CVS, you will also need the pkg-config
+autoconf macros which come with the source distribution
+of pkg-config.
+
+=item doxygen (Optional)
+
+Required for building library documentation.
+Available from:
+http://www.doxygen.org
+
+Tested versions 1.2.15, 1.3.8, 1.4.4.
+
+=item Perl (Optional)
+
+Get it from http://www.cpan.org or http://www.perl.com
+
+Required for re-building command-line parsers
+and/or non-standard documentation formats.
+
+
+=item Getopt::Gen (Optional)
+
+A Perl module used to generate command-line option parsers.
+Should be available from the author of this package at:
+
+http://www.ling.uni-potsdam.de/~moocow/projects/perl
+
+Tested versions 0.09, 0.10.
+
+Note that Getopt::Gen depends on several 3rd-party perl
+modules, including Text::Template and Parse::Lex,
+which are available from CPAN.
+
+Note additionally that Parse::Lex v2.15 is broken: if
+it gives you grief, use the hacked version available
+at:
+
+http://www.ling.uni-potsdam.de/~moocow/projects/perl/ParseLex-2.15-hacked.tar.gz
+
+
+=item pod2man, pod2text, pod2html, pod2latex (Optional)
+
+The Perl documentation converstion utilities, required
+for building the correspdonding program documentation
+formats, should have come with your Perl. These are
+only required if you wish to build program documentation
+formats other than the defaults which come with the
+distribution.
+
+=back
+
+
+=head1 INSTALLATION
+
+Issue the following commands to the shell:
+
+ cd gfsm-X.Y.Z (or wherever you extracted the distribution)
+ sh ./configure
+ make
+ make install
+
+=head2 Additional installation targets
+
+The build system supports the following optional installation targets;
+call them with:
+
+ make SOME_TARGET
+
+from the distribution root directory.
+
+
+=over 4
+
+=item install-magic
+
+Adds recognition support for stored binary gfsm files
+to the database for the file(1) utility. If your file(1)
+database lives somewhere other than /etc/magic (see magic(5) for details),
+call this target as:
+
+ make magic=/full/path/to/my/file/magic install-magic
+
+=item uninstall-magic
+
+Removes gfsm recognition support (if present) from your
+/etc/magic database, or from whatever database you specified
+with the 'magic' variable.
+
+=back
+
+=head1 BUILD OPTIONS
+
+The 'configure' script supports the following options, among others:
+
+=over 4
+
+=item --enable-debug , --disable-debug
+
+Whether to enable verbose debugging messages.
+Default=no.
+
+=back
+
+See the output of `./configure --help` for details on additional
+supported options.
+
+
+
+=head1 ACKNOWLEDGEMENTS
+
+Ideas and code adapted from the SFST package by Helmut Schmid.
+
+Many thanks to Thomas Hanneforth for useful advice.
+
+
+=head1 KNOWN BUGS
+
+Many.
+
+
+=head1 AUTHOR
+
+Bryan Jurish E<lt>moocow@ling.uni-potsdam.deE<gt>
diff --git a/gfsm/gfsm/README.txt b/gfsm/gfsm/README.txt
new file mode 100644
index 0000000..26c5061
--- /dev/null
+++ b/gfsm/gfsm/README.txt
@@ -0,0 +1,116 @@
+ README for package gfsm
+
+ Last updated for gfsm v0.0.8
+
+DESCRIPTION
+ The gfsm package consists of libgfsm, an abstract C library of tools for
+ manipulation of finite state machines, and the gfsm utilities, a suite
+ of command-line tools built on libgfsm. gfsm currently supports AT&T
+ style weighted transducer text input and label definition files, as well
+ as a number of common algebraic operations on finite state machines.
+
+DEPENDENCIES
+ glib-2.0 (REQUIRED)
+ Available from: http://www.gtk.org/
+
+ C library for common data structures. Tested versions 2.4.6, 2.8.3.
+
+ zlib (Optional)
+ Compression library by Jean-loup Gailly and Mark Adler which can be
+ used for transparent (de)compression. Available from:
+ http://www.gzip.org/zlib
+
+ Tested version 1.2.1.
+
+ pkg-config
+ Available from: http://www.freedesktop.org/software/pkgconfig/
+
+ To build from CVS, you will also need the pkg-config autoconf macros
+ which come with the source distribution of pkg-config.
+
+ doxygen (Optional)
+ Required for building library documentation. Available from:
+ http://www.doxygen.org
+
+ Tested versions 1.2.15, 1.3.8, 1.4.4.
+
+ Perl (Optional)
+ Get it from http://www.cpan.org or http://www.perl.com
+
+ Required for re-building command-line parsers and/or non-standard
+ documentation formats.
+
+ Getopt::Gen (Optional)
+ A Perl module used to generate command-line option parsers. Should
+ be available from the author of this package at:
+
+ http://www.ling.uni-potsdam.de/~moocow/projects/perl
+
+ Tested versions 0.09, 0.10.
+
+ Note that Getopt::Gen depends on several 3rd-party perl modules,
+ including Text::Template and Parse::Lex, which are available from
+ CPAN.
+
+ Note additionally that Parse::Lex v2.15 is broken: if it gives you
+ grief, use the hacked version available at:
+
+ http://www.ling.uni-potsdam.de/~moocow/projects/perl/ParseLex-2.15-h
+ acked.tar.gz
+
+ pod2man, pod2text, pod2html, pod2latex (Optional)
+ The Perl documentation converstion utilities, required for building
+ the correspdonding program documentation formats, should have come
+ with your Perl. These are only required if you wish to build program
+ documentation formats other than the defaults which come with the
+ distribution.
+
+INSTALLATION
+ Issue the following commands to the shell:
+
+ cd gfsm-X.Y.Z (or wherever you extracted the distribution)
+ sh ./configure
+ make
+ make install
+
+ Additional installation targets
+ The build system supports the following optional installation targets;
+ call them with:
+
+ make SOME_TARGET
+
+ from the distribution root directory.
+
+ install-magic
+ Adds recognition support for stored binary gfsm files to the
+ database for the file(1) utility. If your file(1) database lives
+ somewhere other than /etc/magic (see magic(5) for details), call
+ this target as:
+
+ make magic=/full/path/to/my/file/magic install-magic
+
+ uninstall-magic
+ Removes gfsm recognition support (if present) from your /etc/magic
+ database, or from whatever database you specified with the 'magic'
+ variable.
+
+BUILD OPTIONS
+ The 'configure' script supports the following options, among others:
+
+ --enable-debug , --disable-debug
+ Whether to enable verbose debugging messages. Default=no.
+
+ See the output of `./configure --help` for details on additional
+ supported options.
+
+ACKNOWLEDGEMENTS
+ Ideas and code adapted from the SFST package by Helmut Schmid.
+
+ Many thanks to Thomas Hanneforth for useful advice.
+
+KNOWN BUGS
+ Many.
+
+AUTHOR
+ Bryan Jurish <moocow@ling.uni-potsdam.de>
+
diff --git a/gfsm/gfsm/autogen.sh b/gfsm/gfsm/autogen.sh
new file mode 100755
index 0000000..686b20b
--- /dev/null
+++ b/gfsm/gfsm/autogen.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+#-----------------------------------------------------------------------
+# File: autogen.sh
+# Description:
+# + wrapper for m4 black-magic
+#-----------------------------------------------------------------------
+
+MY_ALDIRS="."
+MY_AHDIRS="."
+MY_LTDIRS="."
+MY_AMDIRS="."
+MY_ACDIRS="."
+
+test -z "$ACLOCAL" && ACLOCAL="aclocal -I m4"
+test -z "$AUTOHEADER" && AUTOHEADER=autoheader
+test -z "$LIBTOOLIZE" && LIBTOOLIZE="libtoolize --automake"
+test -z "$AUTOMAKE" && AUTOMAKE=automake
+test -z "$AUTOCONF" && AUTOCONF=autoconf
+
+if test -n "$MY_ALDIRS"; then
+ for d in $MY_ALDIRS ; do
+ echo "(cd $d ; $ACLOCAL)"
+ (cd $d ; $ACLOCAL)
+ done
+fi
+
+if test -n "$MY_AHDIRS"; then
+ for d in $MY_AHDIRS ; do
+ echo "(cd $d ; $AUTOHEADER)"
+ (cd $d ; $AUTOHEADER)
+ done
+fi
+
+if test -n "$MY_LTDIRS"; then
+ for d in $MY_LTDIRS ; do
+ echo "(cd $d ; $LIBTOOLIZE)"
+ (cd $d ; $LIBTOOLIZE)
+ done
+fi
+
+if test -n "$MY_AMDIRS"; then
+ for d in $MY_AMDIRS ; do
+ echo "(cd $d ; $AUTOMAKE -a)"
+ (cd $d ; $AUTOMAKE -a)
+ done
+fi
+
+if test -n "$MY_ACDIRS"; then
+ for d in $MY_ACDIRS ; do
+ echo "(cd $d ; $AUTOCONF)"
+ (cd $d ; $AUTOCONF)
+ done
+fi
+
+#echo "(./configure)"
+#./configure $*
diff --git a/gfsm/gfsm/config/.cvsignore b/gfsm/gfsm/config/.cvsignore
new file mode 100644
index 0000000..9e07817
--- /dev/null
+++ b/gfsm/gfsm/config/.cvsignore
@@ -0,0 +1,23 @@
+*~
+.*~
+*.o
+*.lo
+*.la
+.libs
+*.a
+*.so
+aclocal.m4
+Makefile
+Makefile.in
+README.txt
+configure
+.deps
+
+depcomp
+missing
+config.guess
+config.sub
+ltmain.sh
+install-sh
+ylwrap
+
diff --git a/gfsm/gfsm/config/Makefile.am b/gfsm/gfsm/config/Makefile.am
new file mode 100644
index 0000000..80893dc
--- /dev/null
+++ b/gfsm/gfsm/config/Makefile.am
@@ -0,0 +1,67 @@
+## File: config/Makefile.am
+## Package:
+## Description:
+## + automake file for 'config' package-subdir
+##
+## Process this file with Automake to create Makefile.in.
+##-----------------------------------------------------------------------
+
+##-----------------------------------------------------------------------
+## Variables: options
+##-----------------------------------------------------------------------
+
+##-----------------------------------------------------------------------
+## Variables: cleanup
+##-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+#CLEANFILES =
+
+## --- distclean: built by 'configure'
+#DISTCLEANFILES =
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = \
+ *~ .*~ \
+ compile Makefile Makefile.in \
+ config.guess \
+ config.sub \
+ depcomp \
+ install-sh \
+ ltmain.sh \
+ missing \
+ texinfo.tex \
+ mkinstalldirs \
+ ylwrap
+
+
+
+##-----------------------------------------------------------------------
+## Variables: distribution
+##-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ Makefile.in \
+ depcomp \
+ install-sh \
+ missing
+
+# mkinstalldirs
+# config.guess
+# config.sub
+# ltmain.sh
+# texinfo.tex
+
+## --- recursion subdirectories for 'make dist'
+#DIST_SUBDIRS = $(SUBDIRS)
+
+#-----------------------------------------------------------------------
+# Rules: cleanup
+#-----------------------------------------------------------------------
+.PHONY: cvsclean cvsclean-hook
+
+cvsclean: maintainer-clean ;
diff --git a/gfsm/gfsm/configure.ac b/gfsm/gfsm/configure.ac
new file mode 100644
index 0000000..18ca41c
--- /dev/null
+++ b/gfsm/gfsm/configure.ac
@@ -0,0 +1,870 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.5)
+
+dnl Some handy macros
+define([THE_PACKAGE_NAME], [gfsm])
+define([THE_PACKAGE_VERSION], [0.0.10-pre8])
+define([THE_PACKAGE_MAINTAINER], [moocow@ling.uni-potsdam.de])
+
+AC_INIT(THE_PACKAGE_NAME, THE_PACKAGE_VERSION, THE_PACKAGE_MAINTAINER)
+dnl AC_INIT(gfsm, 0.01, moocow@ling.uni-potsdam.de)
+
+dnl source && aux dir
+AC_CONFIG_AUX_DIR(config)
+
+dnl canonical target (sets $target, $target_(cpu|vendor|os) : used for bindist)
+AC_CANONICAL_TARGET
+
+dnl use automake
+AM_INIT_AUTOMAKE(THE_PACKAGE_NAME, THE_PACKAGE_VERSION)
+
+dnl use autoheader
+AM_CONFIG_HEADER([src/libgfsm/gfsmConfigAuto.h])
+
+dnl default prefix
+AC_PREFIX_DEFAULT(/usr/local)
+
+#-------------------------------------------------------------
+# save user's *FLAGS
+#USER_LIBS="$LIBS"
+#USER_LDFLAGS="$LDFLAGS"
+#USER_CPPFLAGS="$CPPFLAGS"
+USER_CFLAGS="$CFLAGS"
+
+dnl
+dnl check for programs
+dnl
+AC_PROG_CC
+dnl AC_PROG_CXX
+dnl AC_LANG(C++)
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## gnulib
+gl_EARLY
+gl_INIT
+dnl /gnulib
+dnl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##----------------------------------------------------------------------
+## DISTCHECK: simulate missing development-only packages
+AC_ARG_VAR(DISTCHECK,
+ [(Maintainer): set to nonempty value to simulate missing development packages])
+if test -n "$DISTCHECK" ; then
+ test -z "$PERL" && PERL=no
+ test -z "$OPTGEN_PERL" && OPTGEN_PERL=no
+ test -z "$DOXYGEN" && DOXYGEN=no
+ test -z "$POD2X" && POD2TEXT=no
+ test -z "$POD2X" && POD2MAN=no
+ test -z "$POD2X" && POD2HTML=no
+ test -z "$POD2X" && POD2LATEX=no
+ test -z "$FLEX" && FLEX=no
+ test -z "$BISON" && BISON=no
+fi
+## /DISTCHECK
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## flex
+##
+AC_ARG_VAR(FLEX, [Path to GNU flex; "no" to disable])
+if test -z "$FLEX" ; then
+ AC_PATH_PROG(FLEX,flex,[no])
+fi
+
+AC_MSG_NOTICE([setting FLEX=$FLEX])
+
+if test "$FLEX" = "no"; then
+ AC_MSG_WARN([GNU flex is missing, broken, or disabled])
+ AC_MSG_WARN([- compilation from .l lexer source files disabled])
+fi
+
+AM_CONDITIONAL(HAVE_FLEX,[test "$FLEX" != "no"])
+##
+## /flex
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## bison
+##
+AC_ARG_VAR(BISON, [Path to GNU bison; "no" to disable])
+if test -z "$BISON" ; then
+ AC_PATH_PROG(BISON,bison,[no])
+fi
+
+AC_MSG_NOTICE([setting BISON=$BISON])
+
+if test "$BISON" = "no"; then
+ AC_MSG_WARN([GNU bison is missing, broken, or disabled])
+ AC_MSG_WARN([- compilation from .y parser source files disabled])
+fi
+
+AM_CONDITIONAL(HAVE_BISON,[test "$BISON" != "no"])
+##
+## /bison
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## flex+bison: automake woes
+
+###-- automake wants these, we want flex & bison
+dnl ... and these wreak havoc
+dnl AM_PROG_LEX
+dnl AC_PROG_YACC
+dnl
+dnl ... these are goofy too
+dnl LEX="$FLEX"
+dnl YACC="$BISON"
+dnl AC_SUBST(LEX)
+dnl AC_SUBST(YACC)
+dnl
+dnl ... with some hacking in src/libgfsm/Makefile.am, we get:
+dnl : AM_YFLAGS = --defines --fixed-output-files --name-prefix="$*_yy"
+AM_PROG_LEX
+AC_PROG_YACC
+LEX="$FLEX"
+YACC="$BISON"
+## /flex+bison: automake woes
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## zlib
+##
+AC_ARG_ENABLE(zlib,
+ AC_HELP_STRING([--disable-zlib],
+ [Disable zlib compression support]),
+ [ac_cv_enable_zlib="$enableval"],
+ [ac_cv_enable_zlib="yes"])
+
+if test "$ac_cv_enable_zlib" != "no" ; then
+ for h in zlib.h ; do
+ AC_CHECK_HEADER($h,
+ [gfsm_have_header="yes"], [gfsm_have_header="no"], [ ])
+ if test "$gfsm_have_header" = "no" ; then
+ AC_MSG_WARN([zlib header '$h' not found!])
+ AC_MSG_WARN([- Is the directory containing the zlib headers in your])
+ AC_MSG_WARN([ 'CPPFLAGS' environment variable?])
+ AC_MSG_NOTICE([zlib support disabled])
+ ac_cv_enable_zlib="no"
+ fi
+ done
+fi
+
+if test "$ac_cv_enable_zlib" != "no" ; then
+ ##-- zlib: library: compile
+ AC_CHECK_LIB(z,deflate,[ac_cv_have_libz="yes"])
+ if test "$ac_cv_have_libz" != "yes" ; then
+ AC_MSG_WARN([could not link to zlib library!])
+ AC_MSG_WARN([- Is the directory containing the zlib binary in your])
+ AC_MSG_WARN([ 'LDFLAGS' environment variable?])
+ AC_MSG_NOTICE([zlib support disabled])
+ ac_cv_enable_zlib="no"
+ else
+ gfsm_LIBS="$gfsm_LIBS -lz"
+ fi
+fi
+
+##-- zlib: config.h flag
+if test "$ac_cv_enable_zlib" != "no" ; then
+ AC_DEFINE(GFSM_ZLIB_ENABLED,1,
+ [Define this to enable zlib compression support])
+ DOXY_DEFINES="$DOXY_DEFINES GFSM_ZLIB_ENABLED=1"
+fi
+##
+## /zlib
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## gnulib: funcs
+##
+dnl AC_CHECK_FUNCS(getline)
+
+gl_FUNC_GETDELIM
+gl_FUNC_VASPRINTF
+
+AC_CHECK_FUNCS([vfprintf],[],[])
+##
+## /gnulib: funcs
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+dnl v--- needed if Makefile.am uses _LTLIBRARIES targets
+AC_PROG_LIBTOOL
+
+dnl v--- for static-only libraries (non-libtool)
+dnl AC_PROG_RANLIB
+
+dnl v--- needed if Makefile.am uses lex sources (see above)
+dnl AM_PROG_LEX
+
+
+### --- unmangle user *FLAGS
+if test "$CFLAGS" != "$USER_CFLAGS" ; then
+ # autoconf likes to set this (to '-g -O2')... who knows why...
+ AC_MSG_NOTICE([Restoring user's original CFLAGS value])
+ CFLAGS="$USER_CFLAGS"
+fi
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## config options: init
+CONFIG_OPTIONS=""
+## /config options
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## inline ?
+##
+AC_MSG_CHECKING([whether to enable inline functions])
+AC_ARG_ENABLE(inline,
+ AC_HELP_STRING([--disable-inline], [disable function inlining (default=enabled)]))
+
+if test "$enable_inline" != "no" ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(GFSM_INLINE_ENABLED,1,
+ [Define this to enable inline functions])
+ DOXY_DEFINES="$DOXY_DEFINES GFSM_INLINE_ENABLED=1 GFSM_INLINE:=\"static inline\""
+ CONFIG_INLINE_ENABLED="1"
+else
+ AC_MSG_RESULT(no)
+ CONFIG_INLINE_ENABLED="0"
+fi
+CONFIG_OPTIONS="$CONFIG_OPTIONS INLINE=$CONFIG_INLINE_ENABLED"
+##
+## /inline ?
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## debug ?
+##
+AC_MSG_CHECKING([whether to build debug version])
+AC_ARG_ENABLE(debug,
+ AC_HELP_STRING([--enable-debug], [build debug version (default=no)]))
+
+if test "$enable_debug" == "yes" ; then
+ AC_MSG_RESULT(yes)
+
+ dnl-- this breaks default shared-library building
+ dnl-- on debian/sid:
+ dnl + automake 1.9.6
+ dnl + autoconf 2.59
+ dnl + libtool 1.5.20
+ dnl
+ dnl AC_DISABLE_SHARED
+ if test "$GCC" == "yes" ; then
+ AC_MSG_NOTICE([GNU C compiler detected: setting appropriate debug flags])
+ gfsm_OFLAGS="-g"
+ else
+ AC_MSG_WARN([GNU C compiler not detected: you must use CFLAGS to set compiler debugging flags])
+ gfsm_OFLAGS=""
+ fi
+
+ AC_DEFINE(GFSM_DEBUG_ENABLED,1,
+ [Define this to enable debugging code])
+ DOXY_DEFINES="$DOXY_DEFINES GFSM_DEBUG_ENABLED=1"
+ #CONFIG_OPTIONS="$CONFIG_OPTIONS DEBUG=1"
+ CONFIG_OPTIONS="DEBUG=1"
+else
+ AC_MSG_RESULT(no)
+ if test "$GCC" == "yes"; then
+ case "$CFLAGS" in
+ *-O*)
+ AC_MSG_NOTICE([CFLAGS appears already to contain optimization flags - skipping])
+ gfsm_OFLAGS=""
+ ;;
+ *)
+ AC_MSG_NOTICE([GNU C compiler detected: setting appropriate optimization flags])
+ #gfsm_OFLAGS="-O3 -finline-limit-10000 --param inline-unit-growth=1000"
+ gfsm_OFLAGS="-O2"
+ ;;
+ esac
+ else
+ AC_MSG_WARN([GNU C compiler not detected: you must use CFLAGS to set compiler optimization flags])
+ gfsm_OFLAGS=""
+ fi
+ #CONFIG_OPTIONS="$CONFIG_OPTIONS DEBUG=0"
+ CONFIG_OPTIONS="DEBUG=0"
+fi
+
+AC_SUBST(gfsm_OFLAGS)
+##
+## /debug ?
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+#---------------------------------------------------------------
+# short package includes
+spkgincludedir="\${includedir}/AC_PACKAGE_NAME"
+AC_SUBST(spkgincludedir)
+# short package includes
+#---------------------------------------------------------------
+
+#---------------------------------------------------------------
+# get real prefix
+AC_CACHE_CHECK([for installation prefix], [ac_cv_install_prefix],
+ [if test "$prefix" = "NONE" ; then
+ ac_cv_install_prefix="/usr/local"
+ else
+ ac_cv_install_prefix="$prefix"
+ fi
+ ])
+dnl # ... and add it to our flags
+dnl CPPFLAGS="$CPPFLAGS -I${ac_cv_install_prefix}/include"
+dnl LDFLAGS="$LDFLAGS -L${ac_cv_install_prefix}/lib"
+
+
+dnl check for strdup
+AC_CHECK_FUNC(strdup,[AC_DEFINE(HAVE_STRDUP,1,[Define this if you have the strdup() function])])
+
+
+dnl ---------------------------------------------------------------
+dnl pkg-config : program
+dnl
+AC_ARG_VAR(PKG_CONFIG, [How to run the pkg-config program])
+AC_ARG_VAR(PKG_CONFIG_PATH, [Directories to search for pkg-config])
+if test -z "$PKG_CONFIG" ; then
+ AC_PATH_PROG(PKG_CONFIG,pkg-config,[])
+fi
+dnl pkg-config: destination directory
+AC_ARG_WITH(pkgconfig-dir,
+ AC_HELP_STRING([--with-pkgconfig-dir=DIR],
+ [install pkg-config metafile(s) in DIR (default=LIBDIR/pkgconfig)]),
+ [ac_cv_pkgconfigdir="$withval"])
+if test -z "$ac_cv_pkgconfigdir" ; then
+ ac_cv_pkgconfigdir="\$(libdir)/pkgconfig"
+fi
+pkgconfigdir="$ac_cv_pkgconfigdir"
+AC_SUBST(pkgconfigdir)
+dnl
+dnl pkg-config
+dnl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## glib (pkg-config)
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.0.0,
+ [PC_HAVE_GLIB="yes"],
+ [PC_HAVE_GLIB=""])
+
+if test "$PC_HAVE_GLIB" != "yes" ; then
+ AC_MSG_WARN([glib-2.0 not found via pkg-config])
+ AC_MSG_WARN([- Is the directory containing glib-2.0.pc in your])
+ AC_MSG_WARN([ 'PKG_CONFIG_PATH' environment variable?])
+ AC_MSG_WARN([- I'll assume that you have set the variables CFLAGS, LDFLAGS,])
+ AC_MSG_WARN([ and LIBS for compling and linking with glib-2.0])
+ ac_cv_enable_glib="no"
+else
+ ac_cv_enable_glib="yes"
+fi
+
+if test "$ac_cv_enable_glib" != "no" ; then
+ ##-- glib: library
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs-only-L glib-2.0`"
+ gfsm_LIBS="$gfsm_LIBS `$PKG_CONFIG --libs-only-l glib-2.0`"
+fi
+##
+## /glib
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## version-info
+GFSM_VERSION_MAJOR=`[echo ${PACKAGE_VERSION} | sed -e's/^\([0-9][0-9]*\)\..*/\1/']`
+test -z "$GFSM_VERSION_MAJOR" -o "$GFSM_VERSION_MAJOR" = "$PACKAGE_VERSION" \
+ && GFSM_VERSION_MAJOR=0
+
+GFSM_VERSION_MINOR=`[echo ${PACKAGE_VERSION} | sed -e's/^[^\.]*\.0*\([0-9][0-9]*\).*/\1/']`
+test -z "$GFSM_VERSION_MINOR" -o "$GFSM_VERSION_MINOR" = "$PACKAGE_VERSION" \
+ && GFSM_VERSION_MINOR=0
+
+GFSM_VERSION_MICRO=`[echo ${PACKAGE_VERSION} | sed -e's/^[^\.]*\.[^\.]*\.0*\([0-9][0-9]*\).*/\1/']`
+test -z "$GFSM_VERSION_MICRO" -o "$GFSM_VERSION_MICRO" = "$PACKAGE_VERSION" \
+ && GFSM_VERSION_MICRO=0
+
+AC_DEFINE_UNQUOTED(GFSM_VERSION_MAJOR, $GFSM_VERSION_MAJOR, [Major gfsm version])
+AC_DEFINE_UNQUOTED(GFSM_VERSION_MINOR, $GFSM_VERSION_MINOR, [Minor gfsm version])
+AC_DEFINE_UNQUOTED(GFSM_VERSION_MICRO, $GFSM_VERSION_MICRO, [Micro gfsm version])
+AC_SUBST(GFSM_VERSION_MAJOR)
+AC_SUBST(GFSM_VERSION_MINOR)
+AC_SUBST(GFSM_VERSION_MICRO)
+## /version-info
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## exp()
+AC_CHECK_FUNC(exp,[gfsm_have_exp="yes"],[gfsm_have_exp=""])
+if test "$gfsm_have_exp" != "yes" ; then
+ AC_CHECK_LIB(m,exp,[gfsm_have_exp="yes"],[gfsm_have_exp=""])
+ if test "$gfsm_have_exp" != "yes" ; then
+ AC_MSG_ERROR([C function exp() not found: oops!])
+ else
+ gfsm_LIBS="$gfsm_LIBS -lm"
+ fi
+fi
+## /exp()
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## perl
+AC_ARG_VAR(PERL, [Path to your perl interpreter, "no" to disable])
+if test -z "$PERL" ; then
+ AC_PATH_PROG(PERL,[perl],[no])
+fi
+if test -z "$PERL" -o "$PERL" = "no"; then
+ AC_MSG_WARN([perl missing or disabled])
+ AC_MSG_WARN([- generation of alternate documentation formats disabled.])
+ PERL=no
+fi
+AC_SUBST(PERL)
+## /perl
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## optgen.perl & Getopt::Gen
+##
+AC_ARG_VAR(OPTGEN_PERL, [Path to the 'optgen.perl' script; "no" to disable])
+
+##-- test for working optgen.perl
+AC_MSG_CHECKING([whether Getopt::Gen works])
+ if test "$PERL" != "no" && $PERL -MGetopt::Gen -e'exit 0;' >>config.log 2>&1; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+ AC_MSG_WARN([Getopt::Gen (or something it depends on) is broken!])
+ AC_MSG_WARN([- you probably need to fix your Parse::Lex module])
+ OPTGEN_PERL="no"
+fi
+
+if test -z "$OPTGEN_PERL" ; then
+ AC_PATH_PROG(OPTGEN_PERL,[optgen.perl],[no])
+fi
+
+AC_MSG_NOTICE([setting OPTGEN_PERL=$OPTGEN_PERL])
+AC_SUBST(OPTGEN_PERL)
+
+if test "$OPTGEN_PERL" = "no" ; then
+ AC_MSG_WARN([optgen.perl script is missing, broken, or disabled.])
+ AC_MSG_WARN([- regeneration of command-line parsers from .gog specifications disabled.])
+ AC_MSG_WARN([- regeneration of POD documentation from .gog specifications disabled.])
+fi
+AM_CONDITIONAL(HAVE_OPTGEN, [test "$OPTGEN_PERL" != "no"])
+##
+## /optgen.perl
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## Documentation
+##
+AC_ARG_WITH(docdir,
+ AC_HELP_STRING([--with-docdir=DIR],
+ [install documentation in DIR/AC_PACKAGE_NAME (default=DATADIR/doc)]),
+ [docdir="$withval"],
+ [docdir="\${datadir}/doc"])
+pkgdocdir="\${docdir}/\${PACKAGE}"
+pkgdocprogdir="\${docdir}/\${PACKAGE}/programs"
+pkgdoctutdir="\${docdir}/\${PACKAGE}/tutorial"
+pkgdoclibdir="\${docdir}/\${PACKAGE}/lib\${PACKAGE}"
+
+AC_SUBST(docdir)
+AC_SUBST(pkgdocdir)
+AC_SUBST(pkgdocprogdir)
+AC_SUBST(pkgdoctutdir)
+AC_SUBST(pkgdoclibdir)
+
+AC_ARG_WITH(doc-formats,
+ AC_HELP_STRING([--with-doc-formats=LIST],
+ [Build documentation formats in LIST. \
+ Available formats: txt, man, html, dvi, ps, pdf, none.
+ Default='man html'. Requires Perl, pod2xxx.]),
+ [ac_cv_doc_formats="$withval"])
+AC_ARG_ENABLE(doc,
+ AC_HELP_STRING([--disable-doc],[Synonym for --with-doc-formats="none"]),
+ [enable_doc="$enableval"],[enable_doc="yes"])
+
+AC_MSG_CHECKING([which documentation formats to build])
+## -- set default doc formats if unspecified
+if test -z "$ac_cv_doc_formats" ; then
+ ac_cv_doc_formats="man html"
+fi
+
+## -- un-comma-tize the doc-formats
+gfsm_doc_formats=`echo "$ac_cv_doc_formats" | sed 's/\,/ /g'`
+
+if test "$enable_doc" != "yes" ; then
+ ##-- disable all docs
+ gfsm_doc_formats="none"
+fi
+AC_MSG_RESULT($gfsm_doc_formats)
+#echo ">> post RESULT"
+
+##-- doxygen: var
+AC_ARG_VAR(DOXYGEN,[Path to doxygen documentation generator; "no" to disable])
+
+if test "$gfsm_doc_formats" != "none" ; then
+
+ ##-- doxygen: prog
+ ##
+ if test -z "$DOXYGEN" ; then
+ AC_PATH_PROG(DOXYGEN,doxygen,[no])
+ fi
+ AC_MSG_NOTICE([setting DOXYGEN=$DOXYGEN])
+ ##
+ if test -z "$DOXYGEN" -o "$DOXYGEN" = "no"; then
+ AC_MSG_WARN([doxygen missing or disabled])
+ AC_MSG_WARN([- generation of library documentation disabled])
+ DOXYGEN=no
+ fi
+ ##
+ ##--/doxygen:prog
+
+ ##-- doxygen: filter: doc/lib*/'doxy-filter.perl'
+ ##
+ AC_ARG_VAR(DOXY_FILTER,[doxygen input filter; "no" to disable (default)])
+ AC_MSG_CHECKING([for doxygen input filter])
+ if test -z "$DOXY_FILTER"; then
+ DOXY_FILTER="no"
+ #DOXY_SRCDIR="`find ${srcdir}/doc/ -name 'lib*' -print | head -n1`"
+ #if test -d "$DOXY_SRCDIR" -a -f "$DOXY_SRCDIR/doxy-filter.perl" -a "$PERL" != "no" ; then
+ # DOXY_SRCDIR=`cd "$DOXY_SRCDIR"; pwd`
+ # DOXY_FILTER="$PERL $DOXY_SRCDIR/doxy-filter.perl"
+ #else
+ # DOXY_FILTER="no"
+ #fi
+ fi
+ AC_MSG_RESULT([$DOXY_FILTER])
+ ##
+ if test "$DOXY_FILTER" != "no"; then
+ AC_MSG_CHECKING([whether doxygen input filter works])
+ if test -n "$DOXY_FILTER" && $DOXY_FILTER </dev/null 2>&1 >>config.log ; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ DOXY_FILTER="no"
+ fi
+ fi
+ AC_MSG_NOTICE([setting DOXY_FILTER=$DOXY_FILTER])
+ ##
+ if test "$DOXY_FILTER" != "no"; then
+ DOXY_INPUT_FILTER="$DOXY_FILTER"
+ else
+ DOXY_INPUT_FILTER=""
+ fi
+ AC_SUBST(DOXY_FILTER)
+ AC_SUBST(DOXY_INPUT_FILTER)
+ ##
+ ##--/doxygen:filter
+
+ ##-- doxygen: sources
+ AC_SUBST(DOXYGEN_SOURCES)
+
+ ##-- docs:pod2x
+ ##
+ AC_ARG_VAR(POD2TEXT, [Path to perl 'pod2text' script; "no" for none])
+ AC_ARG_VAR(POD2MAN, [Path to perl 'pod2man' script; "no" for none])
+ AC_ARG_VAR(POD2HTML, [Path to perl 'pod2html' script; "no" for none])
+ AC_ARG_VAR(POD2LATEX,[Path to perl 'pod2latex' script; "no" for none])
+ if test -z "$POD2TEXT" ; then
+ AC_PATH_PROG(POD2TEXT,pod2text,[no])
+ fi
+ if test -z "$POD2MAN" ; then
+ AC_PATH_PROG(POD2MAN,pod2man,[no])
+ fi
+ if test -z "$POD2HTML" ; then
+ AC_PATH_PROG(POD2HTML,pod2html,[no])
+ fi
+ if test -z "$POD2LATEX"; then
+ AC_PATH_PROG(POD2LATEX,pod2latex,[no])
+ fi
+ AC_SUBST(POD2TEXT)
+ AC_SUBST(POD2MAN)
+ AC_SUBST(POD2HTML)
+ AC_SUBST(POD2LATEX)
+ ##
+ ##--/docs:pod2x
+
+ ##-- docs: .gog sources
+ ##
+ DOC_MAN1_GOGS="\
+ gfsmarcsort.gog \
+ gfsmarith.gog \
+ gfsmclosure.gog \
+ gfsmcompile.gog \
+ gfsmcomplement.gog \
+ gfsmcompose.gog \
+ gfsmcompre.gog \
+ gfsmconcat.gog \
+ gfsmconnect.gog \
+ gfsmconvert.gog \
+ gfsmdeterminize.gog \
+ gfsmdifference.gog \
+ gfsmdraw.gog \
+ gfsmheader.gog \
+ gfsminfo.gog \
+ gfsmintersect.gog \
+ gfsminvert.gog \
+ gfsmlabels.gog \
+ gfsmlookup.gog \
+ gfsmoptional.gog \
+ gfsmprint.gog \
+ gfsmproduct.gog \
+ gfsmproject.gog \
+ gfsmrenumber.gog \
+ gfsmreplace.gog \
+ gfsmreverse.gog \
+ gfsmrmepsilon.gog \
+ gfsmsigma.gog \
+ gfsmstrings.gog \
+ gfsmunion.gog \
+ gfsmviterbi.gog \
+ gfsmindex.gog \
+ "
+ DOC_MAN1_GOGS="$DOC_MAN1_GOGS"
+ for g in $DOC_MAN1_GOGS ; do
+ AC_CONFIG_LINKS(doc/programs/${g}:src/programs/${g})
+ done
+ DOC_GOGS="$DOC_MAN1_GOGS"
+ AC_SUBST(DOC_MAN1_GOGS)
+ AC_SUBST(DOC_GOGS)
+ dnl AC_CONFIG_LINKS(doc/programs/acknowledge.pod:src/programs/acknowledge.pod)
+ ##
+ ##--/docs: .gog sources
+
+ ##-- docs: index-skeleton (section 1)
+ DOC_PROG_INDEX_SKEL="gfsmutils.skel"
+ AC_SUBST(DOC_PROG_INDEX_SKEL)
+
+ ##-- docs: section 5 (static pods)
+ DOC_MAN5_PODS=""
+ AC_SUBST(DOC_MAN5_PODS)
+
+ ##-- docs: pods (all)
+ DOC_PODS="gfsmutils.pod $DOC_MAN5_PODS `echo \"$DOC_MAN1_GOGS\" | sed 's/\.gog/\.pod/g'`"
+ AC_SUBST(DOC_PODS)
+
+ ##-- set "CONFIG_DOC_WANT_*" variables
+ ## + test with automake conditionals "DOC_WANT_*"
+ CONFIG_DOC_WANT_TXT="no"
+ CONFIG_DOC_WANT_MAN="no"
+ CONFIG_DOC_WANT_HTML="no"
+ CONFIG_DOC_WANT_LATEX="no"
+ CONFIG_DOC_WANT_DVI="no"
+ CONFIG_DOC_WANT_PS="no"
+ CONFIG_DOC_WANT_PDF="no"
+
+ ##-- docs: parse user request
+ ##
+ for fmt in $gfsm_doc_formats ; do
+ case "$fmt" in
+ txt)
+ CONFIG_DOC_WANT_TXT="yes"
+ ;;
+ man)
+ CONFIG_DOC_WANT_MAN="yes"
+ ;;
+ html)
+ CONFIG_DOC_WANT_HTML="yes"
+ ;;
+ dvi)
+ CONFIG_DOC_WANT_LATEX="yes"
+ CONFIG_DOC_WANT_DVI="yes"
+ ;;
+ ps)
+ CONFIG_DOC_WANT_LATEX="yes"
+ CONFIG_DOC_WANT_PS="yes"
+ ;;
+ pdf)
+ CONFIG_DOC_WANT_LATEX="yes"
+ CONFIG_DOC_WANT_PDF="yes"
+ ;;
+ *)
+ AC_MSG_WARN(ignoring unknown documentation format: $fmt)
+ ;;
+ esac; # case "$fmt" in ...
+ done; # for fmt in $gfsm_doc_formats ...
+ ##
+ ##--/docs: parse user request
+
+ ##-- docs: requested: automake conditionals: indicator values
+ AC_SUBST(CONFIG_DOC_WANT_TXT)
+ AC_SUBST(CONFIG_DOC_WANT_MAN)
+ AC_SUBST(CONFIG_DOC_WANT_HTML)
+ AC_SUBST(CONFIG_DOC_WANT_LATEX)
+ AC_SUBST(CONFIG_DOC_WANT_DVI)
+ AC_SUBST(CONFIG_DOC_WANT_PS)
+ AC_SUBST(CONFIG_DOC_WANT_PDF)
+
+ ##-- docs: doxygen vars (compatibility)
+ DOXY_WANT_MAN="$CONFIG_DOC_WANT_MAN"
+ DOXY_WANT_HTML="$CONFIG_DOC_WANT_HTML"
+ DOXY_WANT_LATEX="$CONFIG_DOC_WANT_LATEX"
+ DOXY_WANT_HTMLHELP="NO"
+ AC_SUBST(DOXY_WANT_HTML)
+ AC_SUBST(DOXY_WANT_MAN)
+ AC_SUBST(DOXY_WANT_LATEX)
+
+ ##-- docs: doxygen: defines
+ AC_SUBST(DOXY_DEFINES)
+
+ ##-- doxygen: external tag-files (this needs an overhaul!)
+ ##
+ #for ext in gfsmm ; do
+ # extdocdir="`$PKG_CONFIG --variable=pkgdocdir ${ext}`"
+ # if test -n "$extdocdir" -a "$extdocdir" != "no" ; then
+ # exttagfiles="`find $extdocdir -name '*.tag'`"
+ # for exttag in $exttagfiles ; do
+ # exttagdir="`dirname $exttag`/html"
+ # if test -d "$exttagdir" ; then
+ # DOXY_TAGFILES="$DOXY_TAGFILES $exttag=$exttagdir"
+ # fi
+ # done
+ # fi
+ #done
+ AC_SUBST(DOXY_TAGFILES)
+ ##
+ ##--/doxyxgen: tag-files
+
+fi; # if "$gfsm_doc_formats" != "none" ...
+
+##-- conditionals
+AM_CONDITIONAL(HAVE_DOXYGEN, [test -n "$DOXYGEN" -a "$DOXYGEN" != "no"])
+AM_CONDITIONAL(HAVE_DOXY_FILTER, [test -n "$DOXY_FILTER" -a "$DOXY_FILTER" != "no"])
+
+AM_CONDITIONAL(HAVE_POD2TEXT, [test -n "$POD2TEXT" -a "$POD2TEXT" != "no"])
+AM_CONDITIONAL(HAVE_POD2MAN, [test -n "$POD2MAN" -a "$POD2MAN" != "no"])
+AM_CONDITIONAL(HAVE_POD2HTML, [test -n "$POD2HTML" -a "$POD2HTML" != "no"])
+AM_CONDITIONAL(HAVE_POD2LATEX, [test -n "$POD2LATEX" -a "$POD2LATEX" != "no"])
+
+AM_CONDITIONAL(DOC_WANT_TXT, [test -n "$CONFIG_DOC_WANT_TXT" -a "$CONFIG_DOC_WANT_TXT" != "no"])
+AM_CONDITIONAL(DOC_WANT_MAN, [test -n "$CONFIG_DOC_WANT_MAN" -a "$CONFIG_DOC_WANT_MAN" != "no"])
+AM_CONDITIONAL(DOC_WANT_HTML, [test -n "$CONFIG_DOC_WANT_HTML" -a "$CONFIG_DOC_WANT_HTML" != "no"])
+AM_CONDITIONAL(DOC_WANT_LATEX, [test -n "$CONFIG_DOC_WANT_LATEX" -a "$CONFIG_DOC_WANT_LATEX" != "no"])
+AM_CONDITIONAL(DOC_WANT_DVI, [test -n "$CONFIG_DOC_WANT_DVI" -a "$CONFIG_DOC_WANT_DVI" != "no"])
+AM_CONDITIONAL(DOC_WANT_PS, [test -n "$CONFIG_DOC_WANT_PS" -a "$CONFIG_DOC_WANT_PS" != "no"])
+AM_CONDITIONAL(DOC_WANT_PDF, [test -n "$CONFIG_DOC_WANT_PDF" -a "$CONFIG_DOC_WANT_PDF" != "no"])
+
+##
+## /Documentation
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## subdirs
+AC_ARG_ENABLE(programs,
+ AC_HELP_STRING([--disable-programs],[Disable building of command-line utility suite]),
+ [enable_programs="$enableval"],[enable_programs="yes"])
+
+GFSM_SUBDIRS=""
+GFSM_SRC_SUBDIRS=""
+
+AC_MSG_CHECKING([whether to build any documentation])
+if test "$enable_doc" = "yes"; then
+ AC_MSG_RESULT(yes)
+ GFSM_SUBDIRS="doc"
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING([whether to build command-line utility suite])
+if test "$enable_programs" = "yes"; then
+ AC_MSG_RESULT(yes)
+ GFSM_SUBDIRS="$GFSM_SUBDIRS tests"
+ GFSM_SRC_SUBDIRS="programs"
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_SUBST(GFSM_SUBDIRS)
+AC_SUBST(GFSM_SRC_SUBDIRS)
+## /subdirs
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+#---------------------------------------------------------------
+# Binary distribution
+BINDIST_RELEASE=0
+
+## -- hack: canonicalize package-name to lower-case (for debian)
+BINDIST_PKGNAME=`echo "$PACKAGE" | tr '[[:upper:]]' '[[:lower:]]'`
+
+## -- hack: downgrade ix86 -> i386
+case "$target_cpu" in
+ i[[3-9]]86)
+ BINDIST_CPU=i386
+ ;;
+ *)
+ BINDIST_CPU="$target_cpu"
+ ;;
+esac
+BINDIST_OS="$target_os"
+
+AC_SUBST(BINDIST_PKGNAME)
+AC_SUBST(BINDIST_RELEASE)
+AC_SUBST(BINDIST_CPU)
+AC_SUBST(BINDIST_OS)
+# Binary distribution
+#---------------------------------------------------------------
+
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## warnings ?
+##
+AC_MSG_CHECKING([whether to display compiler warnings])
+AC_ARG_ENABLE(warnings,
+ AC_HELP_STRING([--disable-warnings],[disable compiler warnings (default=no)]))
+
+if test "$enable_warnings" != "no" ; then
+ AC_MSG_RESULT(yes)
+ if test "$GCC" == "yes"; then
+ AC_MSG_NOTICE([GNU C compiler detected: setting appropriate warning flags])
+ gfsm_WFLAGS="-Wall" #-Winline
+ else
+ AC_MSG_NOTICE([GNU C compiler not detected: not setting warning flags])
+ gfsm_WFLAGS=""
+ fi
+else
+ AC_MSG_RESULT(no)
+ gfsm_WFLAGS=""
+fi
+AC_SUBST(gfsm_WFLAGS)
+##
+## /warnings
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## autotest
+AC_CONFIG_TESTDIR(tests,tests)
+## /autotest
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## no-autoheader
+AC_CONFIG_LINKS(src/libgfsm/gfsmConfigNoAuto.h:src/libgfsm/gfsmConfigAuto.h.in)
+## /no-autoheader
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+## configuration options
+AC_SUBST(CONFIG_OPTIONS)
+AC_SUBST(gfsm_LIBS)
+## /config options
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+dnl
+dnl output
+dnl
+AC_CONFIG_FILES(src/libgfsm/gnulib/Makefile)
+AC_CONFIG_FILES(src/libgfsm/Makefile)
+AC_CONFIG_FILES(src/programs/Makefile)
+dnl AC_CONFIG_FILES(src/programs/gfsmconfig, [chmod 0755 src/programs/gfsmconfig])
+AC_CONFIG_FILES(src/Makefile)
+AC_CONFIG_FILES(doc/libgfsm/mainpage.dox doc/libgfsm/libgfsm.doxy doc/libgfsm/Makefile)
+AC_CONFIG_FILES(doc/programs/Makefile)
+dnl AC_CONFIG_FILES(doc/tutorial/Makefile)
+AC_CONFIG_FILES(doc/Makefile)
+AC_CONFIG_FILES(config/Makefile)
+AC_CONFIG_FILES(tests/atlocal tests/Makefile)
+AC_CONFIG_FILES(Makefile)
+AC_CONFIG_FILES(gfsm.pc)
+AC_OUTPUT
diff --git a/gfsm/gfsm/configure.gnu b/gfsm/gfsm/configure.gnu
new file mode 100755
index 0000000..720631a
--- /dev/null
+++ b/gfsm/gfsm/configure.gnu
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec ./configure --disable-doc --disable-programs --disable-shared "$@"
diff --git a/gfsm/gfsm/doc/.cvsignore b/gfsm/gfsm/doc/.cvsignore
new file mode 100644
index 0000000..8124700
--- /dev/null
+++ b/gfsm/gfsm/doc/.cvsignore
@@ -0,0 +1,27 @@
+html
+latex
+man
+*.stamp
+*~
+.*~
+*.o
+*.lo
+*.la
+.libs
+*.a
+*.so
+*.gz
+*.bz2
+*.zip
+.deps
+autom4te.cache
+aclocal.m4
+Makefile
+Makefile.in
+README.txt
+configure
+config.log
+config.status
+config.cache
+libtool
+tmp
diff --git a/gfsm/gfsm/doc/Makefile.am b/gfsm/gfsm/doc/Makefile.am
new file mode 100644
index 0000000..d41ba6f
--- /dev/null
+++ b/gfsm/gfsm/doc/Makefile.am
@@ -0,0 +1,56 @@
+## File: doc/Makefile.am
+## Package: gfsm
+## Description:
+## + automake file for doc/ subdir
+##
+## Process this file with Automake to create Makefile.in.
+##-----------------------------------------------------------------------
+
+##-----------------------------------------------------------------------
+## Primaries: headers
+##-----------------------------------------------------------------------
+
+## --- recursion subdirectories
+SUBDIRS = libgfsm programs
+
+#-----------------------------------------------------------------------
+# Variables: cleanup
+#-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+#CLEANFILES =
+
+## --- distclean: built by 'configure'
+#DISTCLEANFILES =
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = *~ .*~ Makefile Makefile.in
+
+#-----------------------------------------------------------------------
+# Variables: (un)install
+#-----------------------------------------------------------------------
+pkgdoc_UNINSTALL_FILES = libgfsm programs README.txt
+uninstall-local:
+ for f in $(pkgdoc_UNINSTALL_FILES) ; do \
+ rm -rf $(DESTDIR)$(pkgdocdir)/$$f ;\
+ done
+
+#-----------------------------------------------------------------------
+# Variables: distribution
+#-----------------------------------------------------------------------
+
+## --- extra distribution files
+#EXTRA_DIST = $(man_MANS) $(pkgdata_DATA)
+
+## --- recursion subdirectories for 'make dist'
+#DIST_SUBDIRS =
+
+#-----------------------------------------------------------------------
+# Rules: cleanup
+#-----------------------------------------------------------------------
+.PHONY: cvsclean
+
+cvsclean: maintainer-clean ;
diff --git a/gfsm/gfsm/doc/libgfsm/.cvsignore b/gfsm/gfsm/doc/libgfsm/.cvsignore
new file mode 100644
index 0000000..267ef0a
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/.cvsignore
@@ -0,0 +1,32 @@
+mainpage.dox
+html
+latex
+man
+libgfsm.doxy
+doxy-filter.log
+libgfsm.log
+libgfsm.tag
+*.stamp
+*~
+.*~
+*.o
+*.lo
+*.la
+.libs
+*.a
+*.so
+*.gz
+*.bz2
+*.zip
+.deps
+autom4te.cache
+aclocal.m4
+Makefile
+Makefile.in
+README.txt
+configure
+config.log
+config.status
+config.cache
+libtool
+doxy-filter.cfg
diff --git a/gfsm/gfsm/doc/libgfsm/Makefile.am b/gfsm/gfsm/doc/libgfsm/Makefile.am
new file mode 100644
index 0000000..ff92d8a
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/Makefile.am
@@ -0,0 +1,235 @@
+## File: doc/libX/Makefile.am
+## Package: *
+## Description:
+## + automake file for library documentation subdir
+##
+## Process this file with Automake to create Makefile.in.
+##-----------------------------------------------------------------------
+
+SUFFIXES = .doxy .stamp .tag .log
+
+##-----------------------------------------------------------------------
+## Literals
+##-----------------------------------------------------------------------
+
+LIBBASE=libgfsm
+LIBCSS=$(LIBBASE).css
+
+##-----------------------------------------------------------------------
+## Conditional targets
+##-----------------------------------------------------------------------
+
+DOXY_MAN3_MANS=
+DOXY_HTML_STATIC=
+DOXY_INSTALL_SUBDIRS=
+DOXY_LATEX_TARGETS=
+
+if HAVE_DOXYGEN
+
+if DOC_WANT_MAN
+DOXY_MAN3_MANS +=man/man3/*
+endif
+
+if DOC_WANT_HTML
+DOXY_HTML_STATIC +=$(LIBCSS)
+DOXY_INSTALL_SUBDIRS +=html
+endif
+
+##-- LaTeX
+if DOC_WANT_LATEX
+if DOC_WANT_DVI
+DOXY_LATEX_TARGETS +=refman.dvi
+endif
+if DOC_WANT_PS
+DOXY_LATEX_TARGETS +=refman.ps
+endif
+
+if DOC_WANT_PDF
+DOXY_LATEX_TARGETS +=refman.pdf
+endif
+endif
+##--/DOC_WANT_LATEX
+
+endif
+##--/HAVE_DOXYGEN
+
+##-----------------------------------------------------------------------
+## Primaries: documentation (real)
+##-----------------------------------------------------------------------
+
+## --- recursion subdirectories
+#SUBDIRS =
+
+## --- doxygen hack: doxy config files
+DOXYBASE = $(LIBBASE)
+DOXYFILE = $(DOXYBASE).doxy
+
+## --- doxygen hack: doxy stamp files: dependencies
+STAMPFILE = $(DOXYFILE:.doxy=.stamp)
+TAGFILE = $(DOXYFILE:.doxy=.tag)
+
+## -- section 3 manpages
+man3_MANS = $(DOXY_MAN3_MANS)
+
+all-local: $(STAMPFILE)
+
+#-----------------------------------------------------------------------
+# doxygen hack: sources
+#-----------------------------------------------------------------------
+
+## -- directories for prerequisite-search
+DOXY_INCLUDES = $(top_srcdir)/src/libgfsm $(top_builddir)/src/libgfsm
+vpath %.h $(DOXY_INCLUDES)
+
+DOXY_INPUTS = \
+ mainpage.dox \
+ $(foreach dir,$(DOXY_INCLUDES),$(wildcard $(dir)/*.h))
+
+#-----------------------------------------------------------------------
+# Additional dependencies
+#-----------------------------------------------------------------------
+
+## --- doxygen hacks: dependencies
+DOXY_FILTER_DEPS=
+
+if HAVE_DOXY_FILTER
+DOXY_FILTER_DEPS += doxy-filter.cfg
+endif
+
+if HAVE_DOXYGEN
+$(man3_MANS): $(STAMPFILE)
+
+$(STAMPFILE): $(DOXY_INPUTS) $(DOXY_FILTER_DEPS)
+endif
+
+
+#-----------------------------------------------------------------------
+# doxygen hack: build rules (recurse in this directory)
+#-----------------------------------------------------------------------
+doxy-filter.cfg:
+ echo '$$config_cppflags .= "-C -x c $(patsubst %,-I%,$(DOXY_INCLUDES))";' > $@
+ echo '$$config_cpp = "$(CPP)";' >> $@
+ echo '$$config_tmpdir = "$(PWD)";' >> $@
+ echo '1;' >> $@
+
+builddir ?= $(top_builddir)/doc/libgfsm
+
+if HAVE_DOXYGEN
+.doxy.stamp: $(DOXY_FILTER_DEPS) @srcdir@/$(LIBCSS)
+ $(DOXYGEN) $<
+if DOC_WANT_LATEX
+ if test \( -n "$(DOXY_LATEX_TARGETS)" -a -d ./latex \) ; then \
+ for t in $(DOXY_LATEX_TARGETS); do \
+ $(MAKE) -i -C ./latex $$t ;\
+ done;\
+ fi
+endif
+##--/DOC_WANT_LATEX
+if DOC_WANT_HTML
+ if test \( -d "$(builddir)html" \) ; then \
+ $(INSTALL_DATA) @srcdir@/$(LIBCSS) $(builddir)html/$(LIBCSS) ;\
+ fi
+endif
+##--/DOC_WANT_HTML
+else
+##--!HAVE_DOXYGEN
+.doxy.stamp:
+ @echo "-------------------------------------------------------------------"
+ @echo "doxygen support disabled:"
+ @echo "not building library documentation from $(DOXYFILE)"
+ @echo "-------------------------------------------------------------------"
+endif
+ touch $@
+##--/HAVE_DOXYGEN
+
+#-----------------------------------------------------------------------
+# Variables: cleanup
+#-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+CLEANFILES = $(STAMPFILE) $(TAGFILE) $(DOXYBASE).log \
+ doxy-filter.log \
+ doxy-filter.cfg
+
+clean-local:
+ rm -rf html latex man
+
+## --- distclean: built by 'configure'
+#DISTCLEANFILES =
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = \
+ *~ .*~ Makefile Makefile.in \
+ $(DOXYFILE) $(DOXYFILE:.doxy=.log)
+
+##-----------------------------------------------------------------------
+## installation rules: local
+##-----------------------------------------------------------------------
+.PHONY: install-data-local install-doc-sub install-latex-sub
+
+##-- always install the .doxy file
+pkgdoclib_DATA = $(DOXYBASE).doxy
+
+
+if HAVE_DOXYGEN
+
+pkgdoclib_DATA +=$(DOXYBASE).tag
+
+$(DOXYBASE).tag: $(STAMPFILE)
+
+install-data-local:
+ if test -n "$(DOXY_INSTALL_SUBDIRS)"; then \
+ $(MAKE) $(AM_MAKEFLAGS) install-doc-sub ;\
+ fi
+
+install-doc-sub:
+ $(mkinstalldirs) $(DESTDIR)$(pkgdocdir)/$(DOXYBASE)
+ for d in $(DOXY_INSTALL_SUBDIRS) ; do \
+ if test -d "$$d" ; then \
+ $(mkinstalldirs) $(DESTDIR)$(pkgdocdir)/$(DOXYBASE)/$$d ;\
+ (cd $$d ;\
+ for f in * ; do \
+ $(INSTALL_DATA) $$f $(DESTDIR)$(pkgdocdir)/$(DOXYBASE)/$$d/$$f ;\
+ done) ;\
+ fi ;\
+ done
+
+if DOC_WANT_LATEX
+if DOC_WANT_DVI
+pkgdoclib_DATA += latex/refman.dvi
+endif
+if DOC_WANT_PS
+pkgdoclib_DATA += latex/refman.ps
+endif
+if DOC_WANT_PDF
+pkgdoclib_DATA += latex/refman.pdf
+endif
+endif
+##--/DOC_WANT_LATEX
+
+endif
+##--/HAVE_DOXYGEN
+
+#-----------------------------------------------------------------------
+# Variables: distribution
+#-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ doxy-filter.perl \
+ mainpage.dox \
+ $(LIBCSS) \
+ libgfsm-header.html
+
+## --- recursion subdirectories for 'make dist'
+#DIST_SUBDIRS =
+
+#-----------------------------------------------------------------------
+# Rules: cleanup
+#-----------------------------------------------------------------------
+.PHONY: cvsclean
+
+cvsclean: maintainer-clean ;
diff --git a/gfsm/gfsm/doc/libgfsm/doxy-filter.perl b/gfsm/gfsm/doc/libgfsm/doxy-filter.perl
new file mode 100755
index 0000000..632c54d
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/doxy-filter.perl
@@ -0,0 +1,145 @@
+#!/usr/bin/perl -w
+
+#----------------------------------------------------------------------
+# File: doxy-filter.perl
+# Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+# Description: doxygen filter for use with the GNU C preprocessor
+#
+# Usage: $0 INPUT_FILENAME
+#-----------------------------------------------------------------------
+
+use Getopt::Long;
+use File::Basename qw(basename fileparse);
+use vars qw($filepath $filesuff $pppath);
+
+$PP_ONLY = 0;
+$DO_CPP = 1;
+$logfile = undef;
+#$logfile = 'doxy-filter.log';
+@includes = qw();
+$cmdline = join(' ', $0, @ARGV);
+GetOptions(
+ "only-preprocess|o!"=>\$PP_ONLY,
+ "preprocess|do-cpp|p"=>\$DO_CPP,
+ "no-preprocess|no-cpp|np|n"=>sub { $DO_CPP = 0; },
+ "logfile|l=s"=>\$logfile,
+ "I=s"=>\@includes,
+ 'help|h'=>\$help,
+ );
+
+if ($help) {
+ print STDERR "Usage: $0 [-(only|no|)-preprocess|-logfile FILE|-IDIR] FILE(s)...\n";
+ exit 0;
+}
+
+$config_cppflags = join(' ', map { "-I$_" } @includes);
+do "doxy-filter.cfg";
+
+#-----------------------------------------------------------------------
+# Globals
+#-----------------------------------------------------------------------
+$CPP = $ENV{CPP} || 'cpp';
+$CPP = $config_cpp if (defined($config_cpp));
+$CPPFLAGS = (''
+ #.' -C ' ## -- preserve comments
+ #.' -x c++' ## -- parse c++ code
+ .' '.($ENV{CPPFLAGS} || '')
+ .' '.$config_cppflags
+ );
+
+$ppextra = '(?s:\bbison\.h\b)|(?s:\bflexskel\.h\b)';
+%ppextra =
+ ('(?:Lexer)' => '(?s:\bflexskel\.h\b)',
+ '(?:Parser)' => '(?s:\bbison\.h\b)',
+ );
+@suffixes = qw(\.c \.h \.cc \.cpp \.cxx \.l \.y \.ll \.yy);
+
+##-- temp
+$TMPDIR = $ENV{TMP} || '/tmp';
+$TMPDIR = $config_tmpdir if (defined($config_tmpdir));
+
+#-----------------------------------------------------------------------
+# DEBUG
+#-----------------------------------------------------------------------
+#$DEBUG = 2;
+#$DEBUG = 1;
+$DEBUG=0;
+sub logopen {
+ $logfile = 'doxy-filter.log' if (!defined($logfile));
+ if ($logfile ne '-') {
+ open(LOG,">>$logfile") or die("$0: open failed for log-file '$logfile': $!");
+ open(STDERR,">&LOG") or die("$0: could not redirect STDERR to LOG: $!");
+ } else {
+ open(LOG, ">&STDERR") or die ("$0: could not redirect LOG to STDERR: $!");
+ }
+ print LOG
+ ("\n", ("-" x 72), "\n", `date`,
+ "> ARGV=$cmdline\n",
+ "> PWD=", `pwd`,
+ "> PP_ONLY=", $PP_ONLY ? 1 : 0, "\n",
+ "> DO_CPP=", $DO_CPP ? 1 : 0, "\n",
+ "> CPPFLAGS=$CPPFLAGS\n",
+ );
+}
+
+#-----------------------------------------------------------------------
+# MAIN
+#-----------------------------------------------------------------------
+push(@ARGV,'-') if (!@ARGV);
+logopen() if ($DEBUG>0);
+foreach $file (@ARGV) {
+ print LOG ("> CPPCMD=$CPP $CPPFLAGS $file |\n") if ($DEBUG>0);
+
+ if ($DO_CPP) {
+ open(CPP,"$CPP $CPPFLAGS $file|")
+ or die("$0: could not open pipe from '$CPP $CPPFLAGS $file': $!");
+ } else {
+ open(CPP, "${file}.pp")
+ or die("$0: could not open '${file}.pp': $!");
+ }
+
+
+ ($filebase,$filepath,$filesuff) = fileparse($file, @suffixes);
+ $ppfile = undef;
+ while (defined($line = <CPP>)) {
+ if (!$PP_ONLY) {
+ if ($line =~ /^\#\s*\d+\s*\"([^\"]*)\"/) {
+ ## -- data from a different file
+ $ppfile = $1;
+ ($ppbase,$pppath,$ppsuff) = fileparse($ppfile, @suffixes);
+
+ if ($DEBUG>2) {
+ print LOG ("> filebase='$filebase', ppbase='$ppbase', ppsuff='$ppsuff'\n");
+ }
+
+ if ($ppfile eq $file) {
+ $wantline = 1;
+ print LOG ("> ACCEPT: literal filename match: $line") if ($DEBUG>1);
+ }
+ elsif (grep { $file =~ $_ && $ppfile =~ $ppextra{$_} } keys(%ppextra)) {
+ $wantline = 1;
+ print LOG ("> ACCEPT: filename convention match: $line\n") if ($DEBUG>1);
+ }
+ elsif (grep { $ppbase eq $filebase && $ppsuff =~ /$_$/ } @suffixes) {
+ $wantline = 1;
+ print LOG ("> ACCEPT: suffix match: $line\n") if ($DEBUG>1);
+ }
+ else {
+ $wantline = 0;
+ print LOG ("> REJECT: $line") if ($DEBUG>1);
+ }
+
+ next;
+ }
+ next if (!defined($ppfile) || !$wantline);
+ }
+ print $line;
+ }
+
+ close(CPP);
+}
+
+close(LOG) if ($DEBUG>0);
+
+# useless comment
+# again
diff --git a/gfsm/gfsm/doc/libgfsm/libgfsm-header.html b/gfsm/gfsm/doc/libgfsm/libgfsm-header.html
new file mode 100644
index 0000000..a0cbf41
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/libgfsm-header.html
@@ -0,0 +1,8 @@
+<HTML>
+ <HEAD>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>$title</title>
+ <LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
+ <LINK HREF="tabs.css" REL="stylesheet" TYPE="text/css">
+ <LINK HREF="libgfsm.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
diff --git a/gfsm/gfsm/doc/libgfsm/libgfsm.css b/gfsm/gfsm/doc/libgfsm/libgfsm.css
new file mode 100644
index 0000000..e760333
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/libgfsm.css
@@ -0,0 +1,216 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+H1 {
+ text-align: center;
+}
+CAPTION { font-weight: bold }
+DIV.qindex {
+ width: 100%;
+ background-color: #eeeeee;
+ border: 1px solid #b0b0b0;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.nav {
+ width: 100%;
+ background-color: #eeeeee;
+ border: 1px solid #b0b0b0;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+A.qindex {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D;
+}
+A.qindex:visited {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D
+}
+A.qindex:hover {
+ text-decoration: none;
+ background-color: #ddddd;
+}
+A.qindexHL {
+ text-decoration: none;
+ font-weight: bold;
+ background-color: #666666;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+ text-decoration: none;
+ background-color: #dddddd;
+ color: #ffffff;
+}
+A.qindexHL:visited { text-decoration: none; background-color: #666666; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { font-weight: bold }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { font-weight: normal; color: #0000FF}
+A.codeRef:visited { font-weight: normal; color: #0000FF}
+A:hover { text-decoration: none; background-color: #f2f2f2 }
+DL.el { margin-left: -1cm }
+.fragment {
+ font-family: monospace
+}
+PRE.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 2px;
+ margin-right: 8px;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+TD.md { background-color: #F4F4F4; font-weight: bold; }
+TD.mdname1 { background-color: #F4F4F4; font-weight: bold; color: #602020; }
+TD.mdname { background-color: #F4F4F4; font-weight: bold; color: #602020; width: 600px; }
+DIV.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 14px }
+BODY {
+ background: white;
+ color: black;
+ margin-right: 20px;
+ margin-left: 20px;
+}
+TD.indexkey {
+ background-color: #eeeeee;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #eeeeee;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword { color: #008000 }
+SPAN.keywordtype { color: #604020 }
+SPAN.keywordflow { color: #e08000 }
+SPAN.comment { color: #800000 }
+SPAN.preprocessor { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral { color: #008080 }
+.mdTable {
+ border: 1px solid #868686;
+ background-color: #F4F4F4;
+}
+.mdRow {
+ padding: 8px 10px;
+}
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 14px;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 14px;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-style: solid;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 12px;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-style: solid;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 13px;
+}
+.search { color: #003399;
+ font-weight: bold;
+}
+FORM.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+INPUT.search { font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #eeeeee;
+}
+TD.tiny { font-size: 75%;
+}
+a {
+ color: #252E78;
+}
+a:visited {
+ color: #3D2185;
+}
diff --git a/gfsm/gfsm/doc/libgfsm/libgfsm.doxy.dev b/gfsm/gfsm/doc/libgfsm/libgfsm.doxy.dev
new file mode 100644
index 0000000..a068f3e
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/libgfsm.doxy.dev
@@ -0,0 +1,227 @@
+# Doxyfile 1.2.17
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "libgfsm"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = .
+OUTPUT_LANGUAGE = English
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = YES
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+#HIDE_FRIEND_COMPOUNDS = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+INTERNAL_DOCS = NO
+STRIP_CODE_COMMENTS = YES
+CASE_SENSE_NAMES = YES
+SHORT_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+VERBATIM_HEADERS = YES
+SHOW_INCLUDE_FILES = YES
+JAVADOC_AUTOBRIEF = NO
+#MULTILINE_CPP_IS_BRIEF = YES
+#DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+INLINE_INFO = YES
+#SORT_MEMBER_DOCS = YES
+SORT_MEMBER_DOCS = NO
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+#GENERATE_DEPRECATEDLIST= YES
+ALIASES =
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE = libgfsm.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = \
+ ../../src/libgfsm \
+ ../../src/libgfsm \
+ .
+#FILE_PATTERNS = *.h
+FILE_PATTERNS = *.h *.hi
+#FILE_PATTERNS = *.h *.hi *.c
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS = flexskel.h bison.h
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+
+##
+## Our input-filter runs the real C preprocessor,
+## because doxygen is too stupid to handle heavy-duty
+## macro usage a la flex++/bison++.
+## --> disabled!
+#INPUT_FILTER = "perl ./doxy-filter.perl"
+#INPUT_FILTER = ""
+##
+## Whether to use filtered output for the source browser
+##
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 2
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = yes
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+#HTML_HEADER =
+HTML_HEADER = ./libgfsm-header.html
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = NO
+#GENERATE_HTMLHELP = @DOXY_WANT_HTMLHELP@
+GENERATE_HTMLHELP = NO
+#CHM_FILE = FSM.chm
+#HHC_LOCATION = "C:\Programme\HTML Help Workshop\hhc.exe"
+#HHC_LOCATION = @DOXY_HHC_PROGRAM@
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = no
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = YES
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = no
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+#XML_SCHEMA =
+#XML_DTD =
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+#ENABLE_PREPROCESSING = NO
+#MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+#INCLUDE_PATH = ../../src/libgfsm ../..src/libgfsm
+INCLUDE_FILE_PATTERNS =
+#PREDEFINED = __cplusplus
+PREDEFINED = GFSM_DOXYGEN
+EXPAND_AS_DEFINED =
+#SKIP_FUNCTION_MACROS = YES
+SKIP_FUNCTION_MACROS = NO
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+#TAGFILES = ../FSM/FSM.tag=../../FSM/html
+TAGFILES =
+GENERATE_TAGFILE = libgfsm.tag
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/local/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+CALL_GRAPH = YES
+CALLER_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+##-- obsolete (?)
+#CGI_NAME = search.cgi
+#CGI_URL =
+#DOC_URL =
+#DOC_ABSPATH =
+#BIN_ABSPATH = /usr/local/bin/
+#EXT_DOC_PATHS =
diff --git a/gfsm/gfsm/doc/libgfsm/libgfsm.doxy.in b/gfsm/gfsm/doc/libgfsm/libgfsm.doxy.in
new file mode 100644
index 0000000..e907846
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/libgfsm.doxy.in
@@ -0,0 +1,229 @@
+# Doxyfile 1.2.17
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "libgfsm"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = .
+OUTPUT_LANGUAGE = English
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = YES
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+#HIDE_FRIEND_COMPOUNDS = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+INTERNAL_DOCS = NO
+STRIP_CODE_COMMENTS = YES
+CASE_SENSE_NAMES = YES
+SHORT_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+VERBATIM_HEADERS = YES
+SHOW_INCLUDE_FILES = YES
+JAVADOC_AUTOBRIEF = NO
+#MULTILINE_CPP_IS_BRIEF = YES
+#DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+INLINE_INFO = YES
+#SORT_MEMBER_DOCS = YES
+SORT_MEMBER_DOCS = NO
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+#GENERATE_DEPRECATEDLIST= YES
+ALIASES =
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE = libgfsm.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = \
+ @top_srcdir@/src/libgfsm \
+ ../../src/libgfsm \
+ @srcdir@
+FILE_PATTERNS = *.h *.dox
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS = flexskel.h bison.h
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+
+##
+## Our input-filter runs the real C preprocessor,
+## because doxygen is too stupid to handle heavy-duty
+## macro usage a la flex++/bison++.
+## --> disabled!
+#INPUT_FILTER = "perl ./doxy-filter.perl"
+#INPUT_FILTER = "@DOXY_INPUT_FILTER@"
+##
+## Whether to use filtered output for the source browser
+##
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 2
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = @DOXY_WANT_HTML@
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+#HTML_HEADER =
+HTML_HEADER = @srcdir@/libgfsm-header.html
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = NO
+#GENERATE_HTMLHELP = @DOXY_WANT_HTMLHELP@
+GENERATE_HTMLHELP = NO
+#CHM_FILE = FSM.chm
+#HHC_LOCATION = "C:\Programme\HTML Help Workshop\hhc.exe"
+#HHC_LOCATION = @DOXY_HHC_PROGRAM@
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = @DOXY_WANT_LATEX@
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = YES
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = @DOXY_WANT_MAN@
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+#XML_SCHEMA =
+#XML_DTD =
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+#ENABLE_PREPROCESSING = NO
+#MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+#INCLUDE_PATH = @top_srcdir@/src/libgfsm @top_builddir@src/libgfsm
+INCLUDE_FILE_PATTERNS =
+#PREDEFINED = __cplusplus
+PREDEFINED = @DOXY_DEFINES@
+EXPAND_AS_DEFINED =
+#SKIP_FUNCTION_MACROS = YES
+SKIP_FUNCTION_MACROS = NO
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+#TAGFILES = ../FSM/FSM.tag=../../FSM/html
+TAGFILES = @DOXY_TAGFILES@
+GENERATE_TAGFILE = libgfsm.tag
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = @PERL@
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+COLLABORATION_GRAPH = YES
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+#CLASS_GRAPH = YES
+CLASS_GRAPH = NO
+#GRAPHICAL_HIERARCHY = YES
+GRAPHICAL_HIERARCHY = NO
+#CALL_GRAPH = YES
+CALL_GRAPH = NO
+#CALLER_GRAPH = YES
+CALLER_GRAPH = NO
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+##-- obsolete (?)
+#CGI_NAME = search.cgi
+#CGI_URL =
+#DOC_URL =
+#DOC_ABSPATH =
+#BIN_ABSPATH = /usr/local/bin/
+#EXT_DOC_PATHS =
diff --git a/gfsm/gfsm/doc/libgfsm/mainpage.dox.in b/gfsm/gfsm/doc/libgfsm/mainpage.dox.in
new file mode 100644
index 0000000..909fda7
--- /dev/null
+++ b/gfsm/gfsm/doc/libgfsm/mainpage.dox.in
@@ -0,0 +1,102 @@
+/* -*- Mode: C++ -*- */
+/**
+\mainpage libgfsm : finite state utility library
+
+\author Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+\version @VERSION@
+
+<b>Project URL:</b> http://www.ling.uni-potsdam.de/~moocow/projects/gfsm
+
+\section Intro Introduction
+
+libgfsm is an abstract C library for the manipulation of finite
+state machines using <A HREF="http://www.gtk.org">glib</A>
+for basic data structures. libgfsm currently supports AT&T style
+weighted transducer text input and label definition files, a
+number of common algebraic operations on finite
+state machines, as well as a low-level automaton interface.
+
+\section building Building gfsm
+
+Run the \a configure script in the distribution directory, and then call \a make:
+
+\verbatim
+bash:~$ cd gfsm-XX.YY.ZZ
+
+bash:~/gfsm-XX.YY.ZZ$ ./configure
+> checking build system type... i686-pc-linux-gnu
+> checking host system type... i686-pc-linux-gnu
+> checking target system type... i686-pc-linux-gnu
+> checking for a BSD-compatible install... /usr/bin/install -c
+...
+> config.status: linking ./src/programs/gfsmunion.gog to doc/programs/gfsmunion.gog
+> config.status: executing depfiles commands
+
+bash:~/gfsm-XX.YY.ZZ$ make
+> Making all in config
+...
+> make[1]: Nothing to be done for `all-am'.
+> make: Leaving directory `/home/moocow/gfsm-XX.YY.ZZ'
+
+bash:~/gfsm-XX.YY.ZZ$ make install
+> Making install in config
+...
+> make: Leaving directory `/home/moocow/gfsm-XX.YY.ZZ'
+
+\endverbatim
+
+libgfsm will install itself in /usr/local by default.
+
+See the file \a INSTALL in the gfsm distribution root directory
+for more details.
+
+
+\section knowgfsm Getting to know gfsm
+
+- Have a look at gfsmAutomaton.h , gfsmArc.h , and gfsmState.h
+ to get familiar with the basic automaton API and data structures,
+ ::gfsmAutomaton , ::gfsmArc , and ::gfsmState .
+
+- Have a look at gfsmAlgebra.h to see the basic algebraic operations
+ on automata provided by gfsm.
+
+- Have a look at the gfsmAutomatonIO.h documentation to learn how to
+ load and save automata to named files, or even to abstract I/O handles.
+
+- Have a look at gfsmAlphabet.h for details on fun things you can
+ do with alphabets, including defining your own.
+
+- Have a look at gfsmSemiring.h for details on the built-in semirings, as
+ well as an API for creating your own user-defined semiring for
+ weighted automaton operations.
+
+- Have a look at gfsmRegexCompiler.h if you need a basic regular expression compiler.
+
+.
+
+\section usinggfsm Using gfsm
+
+- Include the main gfsm header in your code:
+
+ \code
+#include <gfsm.h>
+int main(void) {
+ do_stuff();
+ return 0;
+}
+ \endcode
+
+- Compile and link your program against libgfsm:
+
+ \verbatim
+bash$ gcc `pkg-config --cflags gfsm` -o myprog.o -c myprog.c
+bash$ gcc -o myprog myprog.o `pkg-config --libs gfsm`
+ \endverbatim
+
+- ... and things ought to work
+
+.
+
+*/
+
diff --git a/gfsm/gfsm/doc/programs/.cvsignore b/gfsm/gfsm/doc/programs/.cvsignore
new file mode 100644
index 0000000..dd32bb8
--- /dev/null
+++ b/gfsm/gfsm/doc/programs/.cvsignore
@@ -0,0 +1,41 @@
+*.tmp
+
+#*.pod
+acknowledge.pod
+
+*.gog
+*.html
+*.txt
+*.tex
+*.1
+*.man
+*.ps
+*.pdf
+*.dvi
+*.aux
+*.log
+*.toc
+*.idx
+*.stamp
+*~
+.*~
+*.o
+*.lo
+*.la
+.libs
+*.a
+*.so
+*.gz
+*.bz2
+*.zip
+.deps
+autom4te.cache
+aclocal.m4
+Makefile
+Makefile.in
+README.txt
+configure
+config.log
+config.status
+config.cache
+libtool
diff --git a/gfsm/gfsm/doc/programs/Makefile.am b/gfsm/gfsm/doc/programs/Makefile.am
new file mode 100644
index 0000000..6fba9ba
--- /dev/null
+++ b/gfsm/gfsm/doc/programs/Makefile.am
@@ -0,0 +1,309 @@
+## File: doc/programs/Makefile.am
+## Package: *
+## Description:
+## + program-doc-level automake file
+##
+## Process this file with Automake to create Makefile.in.
+##-----------------------------------------------------------------------
+
+##-----------------------------------------------------------------------
+## Misc flags
+##-----------------------------------------------------------------------
+
+HTML_CSS_FILE =gfsmprogs.css
+POD2MAN_CENTER_STR ="GFSM Utiltiies"
+POD2MAN_RELEASE_STR ="GFSM v$(VERSION)"
+
+##-----------------------------------------------------------------------
+## static vs. built: PODs
+##-----------------------------------------------------------------------
+
+DYNAMIC_MAN1_PODS =$(DOC_MAN1_GOGS:.gog=.pod) $(DOC_PROG_INDEX_SKEL:.skel=.pod)
+DYNAMIC_MAN5_PODS =
+STATIC_MAN1_PODS =
+STATIC_MAN5_PODS =
+
+DYNAMIC_PODS = $(DYNAMIC_MAN1_PODS) $(DYNAMIC_MAN5_PODS)
+STATIC_PODS = $(STATIC_MAN1_PODS) $(STATIC_MAN5_PODS)
+
+##-----------------------------------------------------------------------
+## Potential targets
+##-----------------------------------------------------------------------
+
+##-- pods
+DOC_MAN1_PODS = $(DYNAMIC_MAN1_PODS) $(STATIC_MAN1_PODS)
+DOC_MAN5_PODS = $(DYNAMIC_MAN5_PODS) $(STATIC_MAN5_PODS)
+DOC_PODS = $(DOC_MAN1_PODS) $(DOC_MAN5_PODS)
+
+##--- manpages (section 1: always)
+DOC_MAN1_TARGETS = $(DOC_MAN1_PODS:.pod=.1)
+DOC_MAN5_TARGETS = $(DOC_MAN5_PODS:.pod=.5)
+DOC_MAN_TARGETS = $(DOC_MAN1_TARGETS) $(DOC_MAN5_TARGETS)
+
+##-- text
+DOC_TXT_TARGETS = $(DOC_PODS:.pod=.txt)
+
+##-- html
+DOC_HTML_STATIC = $(HTML_CSS_FILE)
+DOC_HTML_TARGETS = $(DOC_PODS:.pod=.html)
+
+##-- latex
+DOC_LATEX_TARGETS = $(DOC_PODS:.pod=.tex)
+DOC_DVI_TARGETS = $(DOC_PODS:.pod=.dvi)
+DOC_PS_TARGETS = $(DOC_PODS:.pod=.ps)
+DOC_PDF_TARGETS = $(DOC_PODS:.pod=.pdf)
+
+
+##-----------------------------------------------------------------------
+## Conditional targets: chosen by 'configure' & co. [should be safe]
+##-----------------------------------------------------------------------
+
+##-- automake 'EXTRA_*' vars
+EXTRA_man1_MANS = $(DOC_MAN1_TARGETS)
+EXTRA_man5_MANS = $(DOC_MAN5_TARGETS)
+
+##-- automake doesn't appear to understand EXTRA_${whatever}_DATA
+EXTRA_pkgdocprog_DATAFILES = \
+ $(DOC_PODS) \
+ $(DOC_TXT_TARGETS) \
+ $(DOC_HTML_TARGETS) $(DOC_HTML_STATIC) \
+ $(DOC_DVI_TARGETS) \
+ $(DOC_PS_TARGETS) \
+ $(DOC_PDF_TARGETS)
+
+##-- accumulation variables
+BUILD_PODS=
+BUILD_MAN1_MANS=
+BUILD_MAN5_MANS=
+BUILD_DOCS=
+
+STATIC_MAN1_MANS=
+STATIC_MAN5_MANS=
+STATIC_DOCS=
+
+##--- selected: pods
+if HAVE_OPTGEN
+BUILD_PODS += $(DYNAMIC_PODS)
+else
+STATIC_PODS += $(DYNAMIC_PODS)
+endif
+
+##--- selected: manpages (section 1: always)
+if DOC_WANT_MAN
+if HAVE_POD2MAN
+BUILD_MAN1_MANS += $(DYNAMIC_MAN1_PODS:.pod=.1)
+BUILD_MAN5_MANS += $(DYNAMIC_MAN5_PODS:.pod=.5)
+else
+STATIC_MAN1_MANS += $(DYNAMIC_MAN1_PODS:.pod=.1)
+STATIC_MAN5_MANS += $(DYNAMIC_MAN5_PODS:.pod=.5)
+endif
+endif
+
+##-- selected: text
+if DOC_WANT_TXT
+if HAVE_POD2TEXT
+BUILD_DOCS += $(DYNAMIC_PODS:.pod=.txt)
+endif
+endif
+
+##-- selected: html
+if DOC_WANT_HTML
+if HAVE_POD2HTML
+BUILD_DOCS += $(DYNAMIC_PODS:.pod=.html)
+STATIC_DOCS += $(DOC_HTML_STATIC)
+else
+STATIC_DOCS += $(DYNAMIC_PODS:.pod=.html) $(DOC_HTML_STATIC)
+endif
+endif
+
+##-- selected: latex->(dvi|ps|pdf)
+if HAVE_POD2LATEX
+
+if DOC_WANT_DVI
+BUILD_DOCS += $(DYNAMIC_PODS:.pod=.dvi)
+endif
+
+if DOC_WANT_PS
+BUILD_DOCS += $(DYNAMIC_PODS:.pod=.ps)
+endif
+
+if DOC_WANT_PDF
+BUILD_DOCS += $(DYNAMIC_PODS:.pod=.pdf)
+endif
+
+endif
+
+##-----------------------------------------------------------------------
+## Primary targets
+##-----------------------------------------------------------------------
+
+##-- primaries
+man1_MANS = $(BUILD_MAN1_MANS) $(STATIC_MAN1_MANS)
+man5_MANS = $(BUILD_MAN5_MANS) $(STATIC_MAN5_MANS)
+pkgdocprog_DATA = $(BUILD_DOCS) $(STATIC_DOCS)
+
+##-----------------------------------------------------------------------
+## sources
+##-----------------------------------------------------------------------
+
+SUFFIXES = .skel .gog .pod .txt .1 .5 .html .tex .dvi .ps .pdf
+
+##-----------------------------------------------------------------------
+## local hooks
+##-----------------------------------------------------------------------
+all-local: $(man_MANS)
+
+txt: $(DOC_TXT_TARGETS)
+man: $(DOC_MAN_TARGETS)
+html: $(DOC_HTML_TARGETS)
+latex: $(DOC_LATEX_TARGETS)
+dvi-doc: $(DOC_DVI_TARGETS)
+ps: $(DOC_PS_TARGETS)
+pdf: $(DOC_PDF_TARGETS)
+
+.SECONDARY:
+
+##-----------------------------------------------------------------------
+## pod compilation rules: Getopt::Gen
+##-----------------------------------------------------------------------
+
+OPTGENFLAGS = -l
+
+if HAVE_OPTGEN
+.gog.pod:
+ $(OPTGEN_PERL) $(OPTGENFLAGS) --nocfile --nohfile --notimestamp -F $* $<
+endif
+
+##-----------------------------------------------------------------------
+## pod compilation rules: Getopt::Gen (from skel)
+##-----------------------------------------------------------------------
+OPTGEN_SKELFLAGS = \
+ --nocfile --nohfile --nopod \
+ --no-handle-help \
+ --no-handle-version \
+ --no-handle-rcfile \
+ --no-handle-error \
+ --notimestamp
+
+if HAVE_OPTGEN
+.skel.pod:
+ echo | $(OPTGEN_PERL) $(OPTGEN_SKELFLAGS) --template=$< - > $@ 2>/dev/null
+endif
+
+##-----------------------------------------------------------------------
+## pod conversion rules
+##-----------------------------------------------------------------------
+
+POD2MANFLAGS = \
+ --center $(POD2MAN_CENTER_STR) \
+ --release $(POD2MAN_RELEASE_STR)
+
+POD2HTMLFLAGS = --podpath="$(srcdir):." --htmlroot="." --css "$(HTML_CSS_FILE)"
+
+if HAVE_POD2MAN
+.pod.1:
+ $(POD2MAN) $(POD2MANFLAGS) --section=1 $< $@
+
+.pod.5:
+ $(POD2MAN) $(POD2MANFLAGS) --section=5 $< $@
+endif
+
+if HAVE_POD2TEXT
+.pod.txt:
+ $(POD2TEXT) $< $@
+endif
+
+if HAVE_POD2HTML
+.pod.html:
+ $(POD2HTML) $(POD2HTMLFLAGS) --infile=$< --outfile=$@
+endif
+
+if HAVE_POD2LATEX
+.pod.tex:
+ $(POD2LATEX) --full --out $@ $<
+endif
+
+##-----------------------------------------------------------------------
+## latex compilation
+##-----------------------------------------------------------------------
+.tex.dvi:
+ latex -interaction=nonstopmode $*
+ latex -interaction=nonstopmode $*
+
+.dvi.ps:
+ dvips $*
+
+.tex.pdf:
+ ps2pdf $* $@
+
+##-----------------------------------------------------------------------
+## Variables: cleanup
+##-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+CLEANFILES = \
+ *.dvi *.ps *.pdf \
+ *.log *.aux *.toc *.idx *~~ *.tmp
+
+if HAVE_OPTGEN
+CLEANFILES += $(DYNAMIC_PODS)
+endif
+if HAVE_POD2MAN
+CLEANFILES += *.man *.1 *.5
+endif
+if HAVE_POD2HTML
+CLEANFILES += *.html
+endif
+if HAVE_POD2TEXT
+CLEANFILES += *.txt
+endif
+if HAVE_POD2LATEX
+CLEANFILES += *.tex
+endif
+
+## --- distclean: built by 'configure'
+DISTCLEANFILES = \
+ *.gog acknowledge.pod
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = \
+ *~ .*~ Makefile Makefile.in \
+ *.man *.1 *.5 *.html *.txt *.tex \
+ $(CLEANFILES) \
+ $(DYNAMIC_PODS)
+
+##-----------------------------------------------------------------------
+## Variables: distribution
+##-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ $(DOC_PROG_INDEX_SKEL) \
+ $(DOC_PODS) \
+ $(DOC_MAN_TARGETS) \
+ $(DOC_HTML_TARGETS) \
+ $(HTML_CSS_FILE)
+
+## --- recursion subdirectories for 'make dist'
+#DIST_SUBDIRS = $(SUBDIRS)
+
+## --- dist-hook: when another 'Makefile.am' is overkill
+#DISTHOOK_DIRS = foo
+#DISTHOOK_FILES = foo/bar.txt foo/baz.txt
+#dist-hook:
+# for d in $(DISTHOOK_DIRS); do\
+# mkdir -p $(distdir)/$$d ;\
+# done
+# for f in $(DISTHOOK_FILES); do\
+# cp -p $(srcdir)/$$f $(distdir)/$$f ;\
+# done
+
+##-----------------------------------------------------------------------
+## Rules: cleanup
+##-----------------------------------------------------------------------
+.PHONY: cvsclean
+
+cvsclean: maintainer-clean ;
diff --git a/gfsm/gfsm/doc/programs/gfsmprogs.css b/gfsm/gfsm/doc/programs/gfsmprogs.css
new file mode 100644
index 0000000..f5dc6d5
--- /dev/null
+++ b/gfsm/gfsm/doc/programs/gfsmprogs.css
@@ -0,0 +1,38 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+HR,BODY {
+ margin-left: 4px;
+ margin-right: 4px;
+}
+H1,H2 {
+ margin-bottom: 0px;
+ padding-bottom: 0px;
+ text-align: left;
+ color: #000099;
+}
+H1 { margin-left: 4px; }
+H2,H3,H4,H5,H6,P,CENTER,CL,DIV,TD,TH,DL,DT,DIV {
+ margin-left: 24px;
+}
+PRE {
+ border: 1px dashed #0000ff;
+ background-color: #f5f5f5;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 48px;
+ margin-right: 24px;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+/*UL {
+ background-color: #eeeeee;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 16px;
+ margin-right: 16px;
+ padding-top: 4px;
+ padding-bottom: 8px;
+}*/ \ No newline at end of file
diff --git a/gfsm/gfsm/doc/programs/gfsmutils.skel b/gfsm/gfsm/doc/programs/gfsmutils.skel
new file mode 100644
index 0000000..cc25d9d
--- /dev/null
+++ b/gfsm/gfsm/doc/programs/gfsmutils.skel
@@ -0,0 +1,90 @@
+[@ # -*- Mode: Perl -*-
+ my @gogs = glob('*.gog');
+ @subogs = qw();
+ foreach my $gog (sort(@gogs)) {
+ my $subog = Getopt::Gen->new(handle_rcfile=>0);
+ $subog->parse($gog);
+ push(@subogs, $subog);
+ }
+@]
+=pod
+
+=head1 NAME
+
+gfsmutils - finite state machine command-line utilities
+
+=head1 PROGRAMS
+
+The following is a list of the programs
+and user documentation contained in the gfsm package.
+See the individual manpages for details.
+
+[@
+ foreach my $subog (@subogs) {
+ next if (!defined($subog->{USER}{program})
+ || $subog->{USER}{program} =~ /^\s*$/);
+ $OUT .= ("=head2 $subog->{USER}{program}\n"
+ ."\n"
+ ."$subog->{purpose}\n"
+ ."\n"
+ ."See L<$subog->{USER}{program}> for details.\n"
+ ."\n"
+ ."\n"
+ );
+ }
+@]
+
+=cut
+
+###############################################################
+# Description
+###############################################################
+=pod
+
+=head1 DESCRIPTION
+
+The gfsmutils package provides a suite of command-line tools
+for manipulation of finite state machines (FSMs) using
+the libgfsm library.
+
+=cut
+
+###############################################################
+# Addenda
+###############################################################
+=pod
+
+=head1 ADDENDA
+
+=head2 About this Document
+
+Documentation file auto-generated by [@$og{name}@] version [@$OptGenVersion@].
+Translation was initiated
+as:
+
+ [@$CMDLINE_OPTIONS@]
+
+=cut
+
+
+###############################################################
+# Footer
+###############################################################
+#=pod
+#
+#=head1 ACKNOWLEDGEMENTS
+#
+##[ @ join('',`cat acknowledge.pod`); @ ]
+
+=head1 SEE ALSO
+
+[@
+ join(",\n", (map { $_->{USER}{program}."(1)" } @subogs));
+@],
+fsm(1), fsm(5)
+
+=head1 AUTHOR
+
+Bryan Jurish E<lt>moocow@ling.uni-potsdam.deE<gt>
+
+=cut
diff --git a/gfsm/gfsm/gfsm.magic b/gfsm/gfsm/gfsm.magic
new file mode 100644
index 0000000..502dae5
--- /dev/null
+++ b/gfsm/gfsm/gfsm.magic
@@ -0,0 +1,17 @@
+## magic data for binary gfsm automata, for use with file(1).
+## Add the contents of this file to /etc/magic or equivalent.
+
+##--BEGIN gfsm.magic
+## - Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+## stored binary gfsm automata
+0 string gfsm_ gfsm
+>5 string automaton\0 stored automaton
+>5 string indexed\0 indexed automaton
+>5 string cascade\0 automaton cascade
+>5 byte x data
+>16 ulong x (libgfsm v%u
+>20 ulong x \b.%u
+>24 ulong x \b.%u)
+
+##--END gfsm.magic
diff --git a/gfsm/gfsm/gfsm.pc.in b/gfsm/gfsm/gfsm.pc.in
new file mode 100644
index 0000000..0dd410d
--- /dev/null
+++ b/gfsm/gfsm/gfsm.pc.in
@@ -0,0 +1,26 @@
+# -*- Mode: Shell-Script -*-
+#
+# File: gfsm.pc
+# Description: pkg-config data, auto-generated
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+includedir=@includedir@
+libdir=@libdir@
+
+PACKAGE=@PACKAGE@
+datadir=@datadir@
+docdir=@docdir@
+pkgdocdir=@pkgdocdir@
+
+build_options=@CONFIG_OPTIONS@
+cflags=@CFLAGS@
+cppflags=-I@spkgincludedir@ @CPPFLAGS@
+ldadd=-lgfsm @gfsm_LIBS@
+
+
+Name: @PACKAGE@
+Description: abstract finite state machine library
+Version: @VERSION@
+Libs: -L${libdir} ${ldadd}
+Cflags: ${cppflags} ${cflags}
diff --git a/gfsm/gfsm/m4/.cvsignore b/gfsm/gfsm/m4/.cvsignore
new file mode 100644
index 0000000..6b97380
--- /dev/null
+++ b/gfsm/gfsm/m4/.cvsignore
@@ -0,0 +1,4 @@
+*~
+.*~
+Makefile.in
+Makefile \ No newline at end of file
diff --git a/gfsm/gfsm/m4/alloca.m4 b/gfsm/gfsm/m4/alloca.m4
new file mode 100644
index 0000000..a9e3f45
--- /dev/null
+++ b/gfsm/gfsm/m4/alloca.m4
@@ -0,0 +1,42 @@
+# alloca.m4 serial 5
+dnl Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_ALLOCA],
+[
+ dnl Work around a bug of AC_EGREP_CPP in autoconf-2.57.
+ AC_REQUIRE([AC_PROG_CPP])
+ AC_REQUIRE([AC_PROG_EGREP])
+
+ AC_REQUIRE([AC_FUNC_ALLOCA])
+ if test $ac_cv_func_alloca_works = no; then
+ gl_PREREQ_ALLOCA
+ fi
+
+ # Define an additional variable used in the Makefile substitution.
+ if test $ac_cv_working_alloca_h = yes; then
+ AC_EGREP_CPP([Need own alloca], [
+#if defined __GNUC__ || defined _AIX || defined _MSC_VER
+ Need own alloca
+#endif
+ ],
+ [AC_DEFINE(HAVE_ALLOCA, 1,
+ [Define to 1 if you have `alloca' after including <alloca.h>,
+ a header that may be supplied by this distribution.])
+ ALLOCA_H=alloca.h],
+ [ALLOCA_H=])
+ else
+ ALLOCA_H=alloca.h
+ fi
+ AC_SUBST([ALLOCA_H])
+
+ AC_DEFINE(HAVE_ALLOCA_H, 1,
+ [Define HAVE_ALLOCA_H for backward compatibility with older code
+ that includes <alloca.h> only if HAVE_ALLOCA_H is defined.])
+])
+
+# Prerequisites of lib/alloca.c.
+# STACK_DIRECTION is already handled by AC_FUNC_ALLOCA.
+AC_DEFUN([gl_PREREQ_ALLOCA], [:])
diff --git a/gfsm/gfsm/m4/eoverflow.m4 b/gfsm/gfsm/m4/eoverflow.m4
new file mode 100644
index 0000000..8c28ca3
--- /dev/null
+++ b/gfsm/gfsm/m4/eoverflow.m4
@@ -0,0 +1,64 @@
+# eoverflow.m4 serial 1
+dnl Copyright (C) 2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+# The EOVERFLOW errno value ought to be defined in <errno.h>, according to
+# POSIX. But some systems (like AIX 3) don't define it, and some systems
+# (like OSF/1) define it when _XOPEN_SOURCE_EXTENDED is defined.
+
+# Define EOVERFLOW as a C macro and as a substituted macro in such a way that
+# 1. on all systems, after inclusion of <errno.h>, EOVERFLOW is usable,
+# 2. on systems where EOVERFLOW is defined elsewhere, we use the same numeric
+# value.
+
+AC_DEFUN([gl_EOVERFLOW],
+[
+ AC_REQUIRE([AC_PROG_CC])dnl
+
+ AC_CACHE_CHECK([for EOVERFLOW], ac_cv_decl_EOVERFLOW, [
+ AC_EGREP_CPP(yes,[
+#include <errno.h>
+#ifdef EOVERFLOW
+yes
+#endif
+ ], have_eoverflow=1)
+ if test -n "$have_eoverflow"; then
+ dnl EOVERFLOW exists in <errno.h>. Don't need to define EOVERFLOW ourselves.
+ ac_cv_decl_EOVERFLOW=yes
+ else
+ AC_EGREP_CPP(yes,[
+#define _XOPEN_SOURCE_EXTENDED 1
+#include <errno.h>
+#ifdef EOVERFLOW
+yes
+#endif
+ ], have_eoverflow=1)
+ if test -n "$have_eoverflow"; then
+ dnl EOVERFLOW exists but is hidden.
+ dnl Define it to the same value.
+ _AC_COMPUTE_INT([EOVERFLOW], ac_cv_decl_EOVERFLOW, [
+#define _XOPEN_SOURCE_EXTENDED 1
+#include <errno.h>
+/* The following two lines are a workaround against an autoconf-2.52 bug. */
+#include <stdio.h>
+#include <stdlib.h>
+])
+ else
+ dnl EOVERFLOW isn't defined by the system. Define EOVERFLOW ourselves, but
+ dnl don't define it as EINVAL, because snprintf() callers want to
+ dnl distinguish EINVAL and EOVERFLOW.
+ ac_cv_decl_EOVERFLOW=E2BIG
+ fi
+ fi
+ ])
+ if test "$ac_cv_decl_EOVERFLOW" != yes; then
+ AC_DEFINE_UNQUOTED([EOVERFLOW], [$ac_cv_decl_EOVERFLOW],
+ [Define as good substitute value for EOVERFLOW.])
+ EOVERFLOW="$ac_cv_decl_EOVERFLOW"
+ AC_SUBST(EOVERFLOW)
+ fi
+])
diff --git a/gfsm/gfsm/m4/getdelim.m4 b/gfsm/gfsm/m4/getdelim.m4
new file mode 100644
index 0000000..340bb71
--- /dev/null
+++ b/gfsm/gfsm/m4/getdelim.m4
@@ -0,0 +1,30 @@
+# getdelim.m4 serial 1
+
+dnl Copyright (C) 2005 Free Software dnl Foundation, Inc.
+dnl
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_PREREQ(2.52)
+
+AC_DEFUN([gl_FUNC_GETDELIM],
+[
+ AC_LIBSOURCES([getdelim.c, getdelim.h])
+
+ dnl Persuade glibc <stdio.h> to declare getdelim().
+ AC_REQUIRE([AC_GNU_SOURCE])
+
+ AC_REPLACE_FUNCS(getdelim)
+ AC_CHECK_DECLS_ONCE(getdelim)
+
+ if test $ac_cv_func_getdelim = no; then
+ gl_PREREQ_GETDELIM
+ fi
+])
+
+# Prerequisites of lib/getdelim.c.
+AC_DEFUN([gl_PREREQ_GETDELIM],
+[
+ AC_CHECK_FUNCS([flockfile funlockfile])
+])
diff --git a/gfsm/gfsm/m4/gnulib-cache.m4 b/gfsm/gfsm/m4/gnulib-cache.m4
new file mode 100644
index 0000000..308366d
--- /dev/null
+++ b/gfsm/gfsm/m4/gnulib-cache.m4
@@ -0,0 +1,28 @@
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# This file is free software, distributed under the terms of the GNU
+# General Public License. As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+#
+# This file represents the specification of how gnulib-tool is used.
+# It acts as a cache: It is written and read by gnulib-tool.
+# In projects using CVS, this file is meant to be stored in CVS,
+# like the configure.ac and various Makefile.am files.
+
+
+# Specification in the form of a command-line invocation:
+# gnulib-tool --import --dir=. --lib=libgnu --source-base=src/libgfsm/gnulib --m4-base=m4 --aux-dir=config --lgpl --libtool --macro-prefix=gl getdelim vasprintf
+
+# Specification in the form of a few gnulib-tool.m4 macro invocations:
+gl_MODULES([getdelim vasprintf])
+gl_AVOID([])
+gl_SOURCE_BASE([src/libgfsm/gnulib])
+gl_M4_BASE([m4])
+gl_TESTS_BASE([tests])
+gl_LIB([libgnu])
+gl_LGPL
+gl_LIBTOOL
+gl_MACRO_PREFIX([gl])
diff --git a/gfsm/gfsm/m4/gnulib-comp.m4 b/gfsm/gfsm/m4/gnulib-comp.m4
new file mode 100644
index 0000000..dbe52f1
--- /dev/null
+++ b/gfsm/gfsm/m4/gnulib-comp.m4
@@ -0,0 +1,70 @@
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# This file is free software, distributed under the terms of the GNU
+# General Public License. As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+#
+# This file represents the compiled summary of the specification in
+# gnulib-cache.m4. It lists the computed macro invocations that need
+# to be invoked from configure.ac.
+# In projects using CVS, this file can be treated like other built files.
+
+
+# This macro should be invoked from ./configure.in, in the section
+# "Checks for programs", right after AC_PROG_CC, and certainly before
+# any checks for libraries, header files, types and library functions.
+AC_DEFUN([gl_EARLY],
+[
+ AC_REQUIRE([AC_GNU_SOURCE])
+])
+
+# This macro should be invoked from ./configure.in, in the section
+# "Check for header files, types and library functions".
+AC_DEFUN([gl_INIT],
+[
+ gl_FUNC_ALLOCA
+ gl_FUNC_GETDELIM
+ gl_SIZE_MAX
+ gl_FUNC_VASNPRINTF
+ gl_FUNC_VASPRINTF
+ gl_XSIZE
+])
+
+# This macro records the list of files which have been installed by
+# gnulib-tool and may be removed by future gnulib-tool invocations.
+AC_DEFUN([gl_FILE_LIST], [
+ lib/alloca_.h
+ lib/asnprintf.c
+ lib/asprintf.c
+ lib/getdelim.c
+ lib/getdelim.h
+ lib/printf-args.c
+ lib/printf-args.h
+ lib/printf-parse.c
+ lib/printf-parse.h
+ lib/size_max.h
+ lib/vasnprintf.c
+ lib/vasnprintf.h
+ lib/vasprintf.c
+ lib/vasprintf.h
+ lib/xsize.h
+ m4/alloca.m4
+ m4/eoverflow.m4
+ m4/getdelim.m4
+ m4/intmax_t.m4
+ m4/inttypes_h.m4
+ m4/longdouble.m4
+ m4/longlong.m4
+ m4/onceonly_2_57.m4
+ m4/signed.m4
+ m4/size_max.m4
+ m4/stdint_h.m4
+ m4/vasnprintf.m4
+ m4/vasprintf.m4
+ m4/wchar_t.m4
+ m4/wint_t.m4
+ m4/xsize.m4
+])
diff --git a/gfsm/gfsm/m4/gnulib-tool.m4 b/gfsm/gfsm/m4/gnulib-tool.m4
new file mode 100644
index 0000000..ef59320
--- /dev/null
+++ b/gfsm/gfsm/m4/gnulib-tool.m4
@@ -0,0 +1,33 @@
+# gnulib-tool.m4 serial 1
+dnl Copyright (C) 2004-2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl The following macros need not be invoked explicitly.
+dnl Invoking them does nothing except to declare default arguments
+dnl for "gnulib-tool --import".
+
+dnl Usage: gl_MODULES([module1 module2 ...])
+AC_DEFUN([gl_MODULES], [])
+
+dnl Usage: gl_AVOID([module1 module2 ...])
+AC_DEFUN([gl_AVOID], [])
+
+dnl Usage: gl_SOURCE_BASE([DIR])
+AC_DEFUN([gl_SOURCE_BASE], [])
+
+dnl Usage: gl_M4_BASE([DIR])
+AC_DEFUN([gl_M4_BASE], [])
+
+dnl Usage: gl_LIB([LIBNAME])
+AC_DEFUN([gl_LIB], [])
+
+dnl Usage: gl_LGPL
+AC_DEFUN([gl_LGPL], [])
+
+dnl Usage: gl_LIBTOOL
+AC_DEFUN([gl_LIBTOOL], [])
+
+dnl Usage: gl_MACRO_PREFIX([PREFIX])
+AC_DEFUN([gl_MACRO_PREFIX], [])
diff --git a/gfsm/gfsm/m4/intmax_t.m4 b/gfsm/gfsm/m4/intmax_t.m4
new file mode 100644
index 0000000..44b1652
--- /dev/null
+++ b/gfsm/gfsm/m4/intmax_t.m4
@@ -0,0 +1,61 @@
+# intmax_t.m4 serial 4
+dnl Copyright (C) 1997-2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+AC_PREREQ(2.13)
+
+# Define intmax_t to 'long' or 'long long'
+# if it is not already defined in <stdint.h> or <inttypes.h>.
+
+AC_DEFUN([gl_AC_TYPE_INTMAX_T],
+[
+ dnl For simplicity, we assume that a header file defines 'intmax_t' if and
+ dnl only if it defines 'uintmax_t'.
+ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+ AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+ if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then
+ AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
+ test $ac_cv_type_long_long = yes \
+ && ac_type='long long' \
+ || ac_type='long'
+ AC_DEFINE_UNQUOTED(intmax_t, $ac_type,
+ [Define to long or long long if <inttypes.h> and <stdint.h> don't define.])
+ else
+ AC_DEFINE(HAVE_INTMAX_T, 1,
+ [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
+ fi
+])
+
+dnl An alternative would be to explicitly test for 'intmax_t'.
+
+AC_DEFUN([gt_AC_TYPE_INTMAX_T],
+[
+ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+ AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+ AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t,
+ [AC_TRY_COMPILE([
+#include <stddef.h>
+#include <stdlib.h>
+#if HAVE_STDINT_H_WITH_UINTMAX
+#include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+#include <inttypes.h>
+#endif
+], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)])
+ if test $gt_cv_c_intmax_t = yes; then
+ AC_DEFINE(HAVE_INTMAX_T, 1,
+ [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
+ else
+ AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
+ test $ac_cv_type_long_long = yes \
+ && ac_type='long long' \
+ || ac_type='long'
+ AC_DEFINE_UNQUOTED(intmax_t, $ac_type,
+ [Define to long or long long if <stdint.h> and <inttypes.h> don't define.])
+ fi
+])
diff --git a/gfsm/gfsm/m4/inttypes_h.m4 b/gfsm/gfsm/m4/inttypes_h.m4
new file mode 100644
index 0000000..a5d075d
--- /dev/null
+++ b/gfsm/gfsm/m4/inttypes_h.m4
@@ -0,0 +1,26 @@
+# inttypes_h.m4 serial 6
+dnl Copyright (C) 1997-2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_INTTYPES_H],
+[
+ AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h,
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <inttypes.h>],
+ [uintmax_t i = (uintmax_t) -1;],
+ gl_cv_header_inttypes_h=yes,
+ gl_cv_header_inttypes_h=no)])
+ if test $gl_cv_header_inttypes_h = yes; then
+ AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1,
+ [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
+ and declares uintmax_t. ])
+ fi
+])
diff --git a/gfsm/gfsm/m4/longdouble.m4 b/gfsm/gfsm/m4/longdouble.m4
new file mode 100644
index 0000000..40cd7ce
--- /dev/null
+++ b/gfsm/gfsm/m4/longdouble.m4
@@ -0,0 +1,28 @@
+# longdouble.m4 serial 1 (gettext-0.12)
+dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether the compiler supports the 'long double' type.
+dnl Prerequisite: AC_PROG_CC
+
+AC_DEFUN([gt_TYPE_LONGDOUBLE],
+[
+ AC_CACHE_CHECK([for long double], gt_cv_c_long_double,
+ [if test "$GCC" = yes; then
+ gt_cv_c_long_double=yes
+ else
+ AC_TRY_COMPILE([
+ /* The Stardent Vistra knows sizeof(long double), but does not support it. */
+ long double foo = 0.0;
+ /* On Ultrix 4.3 cc, long double is 4 and double is 8. */
+ int array [2*(sizeof(long double) >= sizeof(double)) - 1];
+ ], ,
+ gt_cv_c_long_double=yes, gt_cv_c_long_double=no)
+ fi])
+ if test $gt_cv_c_long_double = yes; then
+ AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.])
+ fi
+])
diff --git a/gfsm/gfsm/m4/longlong.m4 b/gfsm/gfsm/m4/longlong.m4
new file mode 100644
index 0000000..7b399e0
--- /dev/null
+++ b/gfsm/gfsm/m4/longlong.m4
@@ -0,0 +1,23 @@
+# longlong.m4 serial 5
+dnl Copyright (C) 1999-2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_LONG_LONG if 'long long' works.
+
+AC_DEFUN([gl_AC_TYPE_LONG_LONG],
+[
+ AC_CACHE_CHECK([for long long], ac_cv_type_long_long,
+ [AC_TRY_LINK([long long ll = 1LL; int i = 63;],
+ [long long llmax = (long long) -1;
+ return ll << i | ll >> i | llmax / ll | llmax % ll;],
+ ac_cv_type_long_long=yes,
+ ac_cv_type_long_long=no)])
+ if test $ac_cv_type_long_long = yes; then
+ AC_DEFINE(HAVE_LONG_LONG, 1,
+ [Define if you have the 'long long' type.])
+ fi
+])
diff --git a/gfsm/gfsm/m4/onceonly_2_57.m4 b/gfsm/gfsm/m4/onceonly_2_57.m4
new file mode 100644
index 0000000..14d3c0b
--- /dev/null
+++ b/gfsm/gfsm/m4/onceonly_2_57.m4
@@ -0,0 +1,86 @@
+# onceonly_2_57.m4 serial 3
+dnl Copyright (C) 2002-2003, 2005 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl This file defines some "once only" variants of standard autoconf macros.
+dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS
+dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS
+dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS
+dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC
+dnl The advantage is that the check for each of the headers/functions/decls
+dnl will be put only once into the 'configure' file. It keeps the size of
+dnl the 'configure' file down, and avoids redundant output when 'configure'
+dnl is run.
+dnl The drawback is that the checks cannot be conditionalized. If you write
+dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi
+dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to
+dnl empty, and the check will be inserted before the body of the AC_DEFUNed
+dnl function.
+
+dnl This is like onceonly.m4, except that it uses diversions to named sections
+dnl DEFAULTS and INIT_PREPARE in order to check all requested headers at once,
+dnl thus reducing the size of 'configure'. Works with autoconf-2.57. The
+dnl size reduction is ca. 9%.
+
+dnl Autoconf version 2.57 or newer is recommended.
+AC_PREREQ(2.57)
+
+# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of
+# AC_CHECK_HEADERS(HEADER1 HEADER2 ...).
+AC_DEFUN([AC_CHECK_HEADERS_ONCE], [
+ :
+ AC_FOREACH([gl_HEADER_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
+ [./-], [___])), [
+ m4_divert_text([INIT_PREPARE],
+ [gl_header_list="$gl_header_list gl_HEADER_NAME"])
+ gl_HEADERS_EXPANSION
+ AH_TEMPLATE(AS_TR_CPP([HAVE_]m4_defn([gl_HEADER_NAME])),
+ [Define to 1 if you have the <]m4_defn([gl_HEADER_NAME])[> header file.])
+ ])
+ AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
+ [./-], [___])))
+ ])
+])
+m4_define([gl_HEADERS_EXPANSION], [
+ m4_divert_text([DEFAULTS], [gl_header_list=])
+ AC_CHECK_HEADERS([$gl_header_list])
+ m4_define([gl_HEADERS_EXPANSION], [])
+])
+
+# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of
+# AC_CHECK_FUNCS(FUNC1 FUNC2 ...).
+AC_DEFUN([AC_CHECK_FUNCS_ONCE], [
+ :
+ AC_FOREACH([gl_FUNC_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME]), [
+ m4_divert_text([INIT_PREPARE],
+ [gl_func_list="$gl_func_list gl_FUNC_NAME"])
+ gl_FUNCS_EXPANSION
+ AH_TEMPLATE(AS_TR_CPP([HAVE_]m4_defn([gl_FUNC_NAME])),
+ [Define to 1 if you have the `]m4_defn([gl_FUNC_NAME])[' function.])
+ ])
+ AC_REQUIRE([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME]))
+ ])
+])
+m4_define([gl_FUNCS_EXPANSION], [
+ m4_divert_text([DEFAULTS], [gl_func_list=])
+ AC_CHECK_FUNCS([$gl_func_list])
+ m4_define([gl_FUNCS_EXPANSION], [])
+])
+
+# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of
+# AC_CHECK_DECLS(DECL1, DECL2, ...).
+AC_DEFUN([AC_CHECK_DECLS_ONCE], [
+ :
+ AC_FOREACH([gl_DECL_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME]), [
+ AC_CHECK_DECLS(m4_defn([gl_DECL_NAME]))
+ ])
+ AC_REQUIRE([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME]))
+ ])
+])
diff --git a/gfsm/gfsm/m4/signed.m4 b/gfsm/gfsm/m4/signed.m4
new file mode 100644
index 0000000..048f593
--- /dev/null
+++ b/gfsm/gfsm/m4/signed.m4
@@ -0,0 +1,17 @@
+# signed.m4 serial 1 (gettext-0.10.40)
+dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([bh_C_SIGNED],
+[
+ AC_CACHE_CHECK([for signed], bh_cv_c_signed,
+ [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)])
+ if test $bh_cv_c_signed = no; then
+ AC_DEFINE(signed, ,
+ [Define to empty if the C compiler doesn't support this keyword.])
+ fi
+])
diff --git a/gfsm/gfsm/m4/size_max.m4 b/gfsm/gfsm/m4/size_max.m4
new file mode 100644
index 0000000..0336f3a
--- /dev/null
+++ b/gfsm/gfsm/m4/size_max.m4
@@ -0,0 +1,59 @@
+# size_max.m4 serial 3
+dnl Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([gl_SIZE_MAX],
+[
+ AC_CHECK_HEADERS(stdint.h)
+ dnl First test whether the system already has SIZE_MAX.
+ AC_MSG_CHECKING([for SIZE_MAX])
+ result=
+ AC_EGREP_CPP([Found it], [
+#include <limits.h>
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef SIZE_MAX
+Found it
+#endif
+], result=yes)
+ if test -z "$result"; then
+ dnl Define it ourselves. Here we assume that the type 'size_t' is not wider
+ dnl than the type 'unsigned long'.
+ dnl The _AC_COMPUTE_INT macro works up to LONG_MAX, since it uses 'expr',
+ dnl which is guaranteed to work from LONG_MIN to LONG_MAX.
+ _AC_COMPUTE_INT([(size_t)~(size_t)0 / 10], res_hi,
+ [#include <stddef.h>], result=?)
+ _AC_COMPUTE_INT([(size_t)~(size_t)0 % 10], res_lo,
+ [#include <stddef.h>], result=?)
+ _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint,
+ [#include <stddef.h>], result=?)
+ if test "$fits_in_uint" = 1; then
+ dnl Even though SIZE_MAX fits in an unsigned int, it must be of type
+ dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'.
+ AC_TRY_COMPILE([#include <stddef.h>
+ extern size_t foo;
+ extern unsigned long foo;
+ ], [], fits_in_uint=0)
+ fi
+ if test -z "$result"; then
+ if test "$fits_in_uint" = 1; then
+ result="$res_hi$res_lo"U
+ else
+ result="$res_hi$res_lo"UL
+ fi
+ else
+ dnl Shouldn't happen, but who knows...
+ result='((size_t)~(size_t)0)'
+ fi
+ fi
+ AC_MSG_RESULT([$result])
+ if test "$result" != yes; then
+ AC_DEFINE_UNQUOTED([SIZE_MAX], [$result],
+ [Define as the maximum value of type 'size_t', if the system doesn't define it.])
+ fi
+])
diff --git a/gfsm/gfsm/m4/stdint_h.m4 b/gfsm/gfsm/m4/stdint_h.m4
new file mode 100644
index 0000000..3355f35
--- /dev/null
+++ b/gfsm/gfsm/m4/stdint_h.m4
@@ -0,0 +1,26 @@
+# stdint_h.m4 serial 5
+dnl Copyright (C) 1997-2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_STDINT_H],
+[
+ AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h,
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <stdint.h>],
+ [uintmax_t i = (uintmax_t) -1;],
+ gl_cv_header_stdint_h=yes,
+ gl_cv_header_stdint_h=no)])
+ if test $gl_cv_header_stdint_h = yes; then
+ AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1,
+ [Define if <stdint.h> exists, doesn't clash with <sys/types.h>,
+ and declares uintmax_t. ])
+ fi
+])
diff --git a/gfsm/gfsm/m4/vasnprintf.m4 b/gfsm/gfsm/m4/vasnprintf.m4
new file mode 100644
index 0000000..7ff3430
--- /dev/null
+++ b/gfsm/gfsm/m4/vasnprintf.m4
@@ -0,0 +1,58 @@
+# vasnprintf.m4 serial 5
+dnl Copyright (C) 2002-2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_VASNPRINTF],
+[
+ AC_REQUIRE([gl_EOVERFLOW])
+ AC_REPLACE_FUNCS(vasnprintf)
+ if test $ac_cv_func_vasnprintf = no; then
+ AC_LIBOBJ(printf-args)
+ AC_LIBOBJ(printf-parse)
+ AC_LIBOBJ(asnprintf)
+ gl_PREREQ_PRINTF_ARGS
+ gl_PREREQ_PRINTF_PARSE
+ gl_PREREQ_VASNPRINTF
+ gl_PREREQ_ASNPRINTF
+ fi
+])
+
+# Prequisites of lib/printf-args.h, lib/printf-args.c.
+AC_DEFUN([gl_PREREQ_PRINTF_ARGS],
+[
+ AC_REQUIRE([bh_C_SIGNED])
+ AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
+ AC_REQUIRE([gt_TYPE_LONGDOUBLE])
+ AC_REQUIRE([gt_TYPE_WCHAR_T])
+ AC_REQUIRE([gt_TYPE_WINT_T])
+])
+
+# Prequisites of lib/printf-parse.h, lib/printf-parse.c.
+AC_DEFUN([gl_PREREQ_PRINTF_PARSE],
+[
+ AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
+ AC_REQUIRE([gt_TYPE_LONGDOUBLE])
+ AC_REQUIRE([gt_TYPE_WCHAR_T])
+ AC_REQUIRE([gt_TYPE_WINT_T])
+ AC_REQUIRE([AC_TYPE_SIZE_T])
+ AC_CHECK_TYPES(ptrdiff_t)
+ AC_REQUIRE([gt_AC_TYPE_INTMAX_T])
+])
+
+# Prerequisites of lib/vasnprintf.c.
+AC_DEFUN([gl_PREREQ_VASNPRINTF],
+[
+ AC_REQUIRE([AC_FUNC_ALLOCA])
+ AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
+ AC_REQUIRE([gt_TYPE_LONGDOUBLE])
+ AC_REQUIRE([gt_TYPE_WCHAR_T])
+ AC_REQUIRE([gt_TYPE_WINT_T])
+ AC_CHECK_FUNCS(snprintf wcslen)
+])
+
+# Prerequisites of lib/asnprintf.c.
+AC_DEFUN([gl_PREREQ_ASNPRINTF],
+[
+])
diff --git a/gfsm/gfsm/m4/vasprintf.m4 b/gfsm/gfsm/m4/vasprintf.m4
new file mode 100644
index 0000000..385e92e
--- /dev/null
+++ b/gfsm/gfsm/m4/vasprintf.m4
@@ -0,0 +1,25 @@
+# vasprintf.m4 serial 1
+dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_VASPRINTF],
+[
+ AC_REPLACE_FUNCS(vasprintf)
+ if test $ac_cv_func_vasprintf = no; then
+ AC_LIBOBJ(asprintf)
+ gl_PREREQ_VASPRINTF
+ gl_PREREQ_ASPRINTF
+ fi
+])
+
+# Prerequisites of lib/vasprintf.c.
+AC_DEFUN([gl_PREREQ_VASPRINTF],
+[
+])
+
+# Prerequisites of lib/asprintf.c.
+AC_DEFUN([gl_PREREQ_ASPRINTF],
+[
+])
diff --git a/gfsm/gfsm/m4/wchar_t.m4 b/gfsm/gfsm/m4/wchar_t.m4
new file mode 100644
index 0000000..cde2129
--- /dev/null
+++ b/gfsm/gfsm/m4/wchar_t.m4
@@ -0,0 +1,20 @@
+# wchar_t.m4 serial 1 (gettext-0.12)
+dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether <stddef.h> has the 'wchar_t' type.
+dnl Prerequisite: AC_PROG_CC
+
+AC_DEFUN([gt_TYPE_WCHAR_T],
+[
+ AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t,
+ [AC_TRY_COMPILE([#include <stddef.h>
+ wchar_t foo = (wchar_t)'\0';], ,
+ gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)])
+ if test $gt_cv_c_wchar_t = yes; then
+ AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.])
+ fi
+])
diff --git a/gfsm/gfsm/m4/wint_t.m4 b/gfsm/gfsm/m4/wint_t.m4
new file mode 100644
index 0000000..b8fff9c
--- /dev/null
+++ b/gfsm/gfsm/m4/wint_t.m4
@@ -0,0 +1,20 @@
+# wint_t.m4 serial 1 (gettext-0.12)
+dnl Copyright (C) 2003 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether <wchar.h> has the 'wint_t' type.
+dnl Prerequisite: AC_PROG_CC
+
+AC_DEFUN([gt_TYPE_WINT_T],
+[
+ AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t,
+ [AC_TRY_COMPILE([#include <wchar.h>
+ wint_t foo = (wchar_t)'\0';], ,
+ gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)])
+ if test $gt_cv_c_wint_t = yes; then
+ AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.])
+ fi
+])
diff --git a/gfsm/gfsm/m4/xsize.m4 b/gfsm/gfsm/m4/xsize.m4
new file mode 100644
index 0000000..85bb721
--- /dev/null
+++ b/gfsm/gfsm/m4/xsize.m4
@@ -0,0 +1,13 @@
+# xsize.m4 serial 3
+dnl Copyright (C) 2003-2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_XSIZE],
+[
+ dnl Prerequisites of lib/xsize.h.
+ AC_REQUIRE([gl_SIZE_MAX])
+ AC_REQUIRE([AC_C_INLINE])
+ AC_CHECK_HEADERS(stdint.h)
+])
diff --git a/gfsm/gfsm/src/.cvsignore b/gfsm/gfsm/src/.cvsignore
new file mode 100644
index 0000000..45bc517
--- /dev/null
+++ b/gfsm/gfsm/src/.cvsignore
@@ -0,0 +1,20 @@
+*~
+.*~
+*.o
+*.lo
+*.la
+.libs
+*.a
+*.so
+.deps
+*.fst
+*.tfst
+*.lab
+stamp-h*
+config.h
+config.h.in
+aclocal.m4
+Makefile
+Makefile.in
+README.txt
+configure
diff --git a/gfsm/gfsm/src/Makefile.am b/gfsm/gfsm/src/Makefile.am
new file mode 100644
index 0000000..486aedb
--- /dev/null
+++ b/gfsm/gfsm/src/Makefile.am
@@ -0,0 +1,69 @@
+# File: ./src/Makefile.am
+# Package: *
+# Description:
+# + source-level automake file
+#
+# Process this file with Automake to create Makefile.in.
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# Options & Subdirectories
+#-----------------------------------------------------------------------
+
+## --- recursion subdirectories
+#SUBDIRS = libgfsm programs
+SUBDIRS = libgfsm $(GFSM_SRC_SUBDIRS)
+
+#-----------------------------------------------------------------------
+# Variables: cleanup
+#-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+#CLEANFILES =
+
+## --- distclean: built by 'configure'
+DISTCLEANFILES = \
+ autom4te.cache \
+ config.log \
+ config.status \
+ config.cache
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = *~ \
+ $(PODS:.pod=.txt) \
+ Makefile Makefile.in \
+ aclocal.m4 \
+ configure
+
+#-----------------------------------------------------------------------
+# Variables: distribution
+#-----------------------------------------------------------------------
+
+## --- extra distribution files
+#EXTRA_DIST =
+
+## --- recursion subdirectories for 'make dist'
+DIST_SUBDIRS = $(SUBDIRS)
+
+## --- dist-hook: when another 'Makefile.am' is overkill
+#DISTHOOK_DIRS = subdir
+#DISTHOOK_FILES = subdir/file1 subdir/file2
+#
+#dist-hook:
+# for d in $(DISTHOOK_DIRS); do\
+# mkdir -p $(distdir)/$$d ;\
+# done
+# for f in $(DISTHOOK_FILES); do\
+# cp -p $(srcdir)/$$f $(distdir)/$$f ;\
+# done
+
+#-----------------------------------------------------------------------
+# Rules: cleanup
+#-----------------------------------------------------------------------
+.PHONY: cvsclean cvsclean-hook
+
+cvsclean: maintainer-clean ;
+
diff --git a/gfsm/gfsm/src/libgfsm/.cvsignore b/gfsm/gfsm/src/libgfsm/.cvsignore
new file mode 100644
index 0000000..fcae916
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/.cvsignore
@@ -0,0 +1,43 @@
+*~
+.*~
+*.o
+*.lo
+*.la
+*.a
+*.so
+.libs
+.deps
+*.fst
+*.tfst
+*.lab
+*.loT
+gfsmConfigAuto.*
+gfsmConfigNoAuto.h
+gmon.out
+*.output
+stamp-h*
+###config.h
+config.h.in
+aclocal.m4
+Makefile
+Makefile.in
+README.txt
+configure
+graveyard
+*.tfst
+*.afst
+*.thfst
+*.gfst
+*.lab
+*.scl
+*.sym
+*.dot
+*.vcg
+*.ps
+*.tfst
+fsmlib
+SFST.moocow
+fsa6-src
+pd-fst
+save
+libgfsm.*
diff --git a/gfsm/gfsm/src/libgfsm/Makefile.am b/gfsm/gfsm/src/libgfsm/Makefile.am
new file mode 100644
index 0000000..aba4734
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/Makefile.am
@@ -0,0 +1,288 @@
+## File: src/Makefile.am
+## Package: gfsm
+## Description:
+## + source-level automake file
+##
+## Process this file with Automake to create Makefile.in.
+##-----------------------------------------------------------------------
+
+##-----------------------------------------------------------------------
+## subdirectories
+##-----------------------------------------------------------------------
+SUBDIRS = gnulib
+
+##-----------------------------------------------------------------------
+## primary targets
+##-----------------------------------------------------------------------
+
+## --- executable programs
+#bin_PROGRAMS = ${prog_1} ... ${prog_N}
+#bin_PROGRAMS = dwdspp moot moot-fstgen moot-pargen
+
+## --- libtool libraries
+#lib_LTLIBRARIES = ${lib_1}.la ... ${lib_N}.la
+lib_LTLIBRARIES = libgfsm.la
+
+## --- shared data in @pkgdatadir@
+#pkgdata_DATA = ${data_1} ... ${data_N}
+
+## --- manpages -- section is auto-detected
+#man_MANS = ${man_1} ... ${man_N}
+
+##-----------------------------------------------------------------------
+## sources
+##-----------------------------------------------------------------------
+
+## --- Required sources
+#${prog_i}_SOURCES =
+#${lib_i}_la_SOURCES =
+libgfsm_la_SOURCES = \
+ config.h \
+ gfsmCommon.c \
+ gfsmCompound.c \
+ gfsmDebug.c \
+ gfsmError.c \
+ gfsmIO.c \
+ gfsmMem.c \
+ gfsmVersion.c \
+ gfsmUtils.c \
+ gfsmEnum.c \
+ gfsmSet.c \
+ gfsmWeightMap.c \
+ gfsmBitVector.c \
+ gfsmAlphabet.c \
+ gfsmSemiring.c \
+ gfsmArc.c \
+ gfsmArcList.c \
+ gfsmArcIter.c \
+ gfsmArcIndex.c \
+ gfsmState.c \
+ gfsmStateSet.c \
+ gfsmAutomaton.c \
+ gfsmAutomatonIO.c \
+ gfsmDraw.c \
+ gfsmAlgebra.c \
+ gfsmArith.c \
+ gfsmLookup.c \
+ gfsmPaths.c \
+ gfsmTrie.c \
+ gfsmScanner.c \
+ gfsmRegex.lex.l \
+ gfsmRegex.tab.y \
+ gfsmRegexCompiler.c \
+ gfsmIndexed.c \
+ gfsmIndexedIO.c
+
+sources_argh = \
+ gfsmIndexed.c \
+ gfsmIndexed2.c \
+ gfsmIndexedIO.c
+
+## --- Extra (possible) sources
+#EXTRA_${prog_i}_SOURCES =
+#EXTRA_${lib_i}_la_SOURCES =
+
+## --- Additional dependencies
+
+##----------------------------------------------------
+## Additional rules
+
+#gfsmConfigNoAuto.h: gfsmConfigAuto.h.in
+# rm -f "$@"
+# cp "$<" "$@"
+
+##-----------------------------------------------------------------------
+## headers
+##-----------------------------------------------------------------------
+
+## --- installable headers: @includedir@/@pkgname@
+#pkginclude_HEADERS = ${hfile_1} ... ${hfile_N}
+pkginclude_HEADERS = \
+ gfsmAssert.h \
+ gfsmConfig.h \
+ gfsmConfigNoAuto.h \
+ gfsmConfigAuto.h \
+ gfsmCommon.h \
+ gfsmCompound.h \
+ gfsmCompound.hi \
+ gfsmDebug.h \
+ gfsmError.h \
+ gfsmIO.h \
+ gfsmMem.h \
+ gfsmMem.hi \
+ gfsmVersion.h \
+ gfsmUtils.h \
+ gfsmEnum.h \
+ gfsmEnum.hi \
+ gfsmSet.h \
+ gfsmSet.hi \
+ gfsmWeightMap.h \
+ gfsmWeightMap.hi \
+ gfsmBitVector.h \
+ gfsmBitVector.hi \
+ gfsmAlphabet.h \
+ gfsmSemiring.h \
+ gfsmSemiring.hi \
+ gfsmArc.h \
+ gfsmArc.hi \
+ gfsmArcList.h \
+ gfsmArcList.hi \
+ gfsmArcIter.h \
+ gfsmArcIter.hi \
+ gfsmArcIndex.h \
+ gfsmArcIndex.hi \
+ gfsmState.h \
+ gfsmState.hi \
+ gfsmStateSet.h \
+ gfsmStateSet.hi \
+ gfsmAutomaton.h \
+ gfsmAutomaton.hi \
+ gfsmAutomatonIO.h \
+ gfsmDraw.h \
+ gfsmAlgebra.h \
+ gfsmArith.h \
+ gfsmLookup.h \
+ gfsmPaths.h \
+ gfsmTrie.h \
+ gfsmScanner.h \
+ gfsmRegexCompiler.h \
+ gfsmIndexed.h \
+ gfsmIndexed.hi \
+ gfsmIndexedIO.h \
+ gfsm.h
+
+headers_argh = \
+ gfsmIndexed.h \
+ gfsmIndexed2.h \
+ gfsmIndexedIO.h
+
+## --- no-install headers
+#noinst_HEADERS = nopackage.h
+
+##-----------------------------------------------------------------------
+## pre-compile rules: flex ; bison
+##-----------------------------------------------------------------------
+SRCDIR = @srcdir@
+
+if HAVE_FLEX
+MY_LEX = @FLEX@
+MY_LFLAGS =
+else
+MY_LEX = sh $(SRCDIR)/dummy-flex.sh
+MY_LFLAGS =
+endif
+LEX = $(MY_LEX)
+AM_LFLAGS = $(MY_LFLAGS)
+
+if HAVE_BISON
+MY_YACC = @BISON@
+MY_YFLAGS = --defines --fixed-output-files --name-prefix="$(basename $*)_yy"
+else
+MY_YACC = sh $(SRCDIR)/dummy-bison.sh
+MY_YFLAGS =
+endif
+YACC = $(MY_YACC)
+AM_YFLAGS = $(MY_YFLAGS)
+
+SUFFIXES = .l .lex.l .y .tab.y .tab.c .tab.h .lex.c .lex.h
+
+##----------------------------------------
+gfsmRegex.lex.o: gfsmRegex.lex.c gfsmRegex.tab.c gfsmRegexCompiler.h
+gfsmRegex.tab.o: gfsmRegex.tab.c gfsmRegex.lex.c gfsmRegexCompiler.h
+gfsmRegexCompiler.o: gfsmRegexCompiler.c gfsmRegexCompiler.h gfsmRegex.lex.c gfsmRegex.tab.c
+
+##-----------------------------------------------------------------------
+## compile flags
+##-----------------------------------------------------------------------
+
+## --- preprocessor flags
+#AM_CPPFLAGS =
+AM_CPPFLAGS = -I. -I$(SRCDIR)/gnulib
+
+## --- compiler flags (cc)
+AM_CFLAGS = $(gfsm_WFLAGS) $(gfsm_OFLAGS)
+
+##-----------------------------------------------------------------------
+## Additional variable: library versioning
+## + for -version-info $(CUR):$(REV):$(AGE) :
+## + base lib is created as libMYLIB.so.$(CUR).$(AGE).$(REV)
+##-----------------------------------------------------------------------
+
+## --- The most recent interface number that this library implements.
+LIBCUR = $(GFSM_VERSION_MAJOR)
+
+## --- The difference between the newest and oldest interfaces that this
+## library implements. In other words, the library implements all the
+## interface numbers in the range from number `CURRENT - AGE' to
+## `CURRENT'.
+LIBAGE = 0
+
+## --- The implementation number of the CURRENT interface.
+LIBREV = $(GFSM_VERSION_MINOR)
+
+##-----------------------------------------------------------------------
+## linker flags
+## + library special handling of configure.in vars:
+##-----------------------------------------------------------------------
+#${prog_i}_LDFLAGS = -L. -static
+#${prog_i}_LDADD = ${non_src_file}.o -lsomelib
+
+#${lib_i}_la_LDFLAGS = -L. -version-info ${lib_i_current}:${lib_i_rev}:${lib_i_age}
+#${lib_i}_la_LIBADD = -lotherlib
+
+libgfsm_la_LDFLAGS = -version-info $(LIBCUR):$(LIBREV):$(LIBAGE)
+libgfsm_la_LIBADD = gnulib/libgnu.la @gfsm_LIBS@ $(LIBS)
+
+##-----------------------------------------------------------------------
+## Variables: cleanup
+##-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+#CLEANFILES =
+
+## --- distclean: built by 'configure'
+#DISTCLEANFILES =
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = \
+ *~ .*~ Makefile Makefile.in \
+ gmon.out
+
+##-----------------------------------------------------------------------
+## Variables: distribution
+##-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ config.h \
+ gfsmConfigNoAuto.h \
+ gfsmRegex.lex.c \
+ gfsmRegex.lex.h \
+ gfsmRegex.tab.c \
+ gfsmRegex.tab.h \
+ dummy-flex.sh \
+ dummy-bison.sh
+
+## --- recursion subdirectories for 'make dist'
+#DIST_SUBDIRS = $(SUBDIRS)
+
+## --- dist-hook: when another 'Makefile.am' is overkill
+#DISTHOOK_DIRS = foo
+#DISTHOOK_FILES = foo/bar.txt foo/baz.txt
+#dist-hook:
+# for d in $(DISTHOOK_DIRS); do\
+# mkdir -p $(distdir)/$$d ;\
+# done
+# for f in $(DISTHOOK_FILES); do\
+# cp -p $(srcdir)/$$f $(distdir)/$$f ;\
+# done
+
+##-----------------------------------------------------------------------
+## Rules: cleanup
+##-----------------------------------------------------------------------
+.PHONY: cvsclean
+
+cvsclean: maintainer-clean ;
diff --git a/gfsm/gfsm/src/libgfsm/config.h b/gfsm/gfsm/src/libgfsm/config.h
new file mode 100644
index 0000000..9f1ffb0
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/config.h
@@ -0,0 +1 @@
+#include "gfsmConfigAuto.h"
diff --git a/gfsm/gfsm/src/libgfsm/dummy-bison.sh b/gfsm/gfsm/src/libgfsm/dummy-bison.sh
new file mode 100755
index 0000000..ad2995f
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/dummy-bison.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+base=`basename $1 .y`
+cp -v -f "$base.c" y.tab.c
+cp -v -f "$base.h" y.tab.h
+if test -f "$base.output"; then cp -v -f "$base.output" y.output ; fi
diff --git a/gfsm/gfsm/src/libgfsm/dummy-flex.sh b/gfsm/gfsm/src/libgfsm/dummy-flex.sh
new file mode 100755
index 0000000..1b27ea2
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/dummy-flex.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+cp -v -f "`basename $1 .l`.c" lex.yy.c
+touch --no-create "`basename $1 .l`.h"
diff --git a/gfsm/gfsm/src/libgfsm/gfsm.c b/gfsm/gfsm/src/libgfsm/gfsm.c
new file mode 100644
index 0000000..10a3be7
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsm.c
@@ -0,0 +1,27 @@
+/*=============================================================================*\
+ * File: gfsm.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: top-level
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsm.h>
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsm.h b/gfsm/gfsm/src/libgfsm/gfsm.h
new file mode 100644
index 0000000..ae50be3
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsm.h
@@ -0,0 +1,78 @@
+
+/*=============================================================================*\
+ * File: gfsm.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: top-level
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsm.h
+ * \brief Top-level header.
+ */
+
+#ifndef _GFSM_H
+#define _GFSM_H
+
+/*
+#ifdef __cplusplus
+extern "C" {
+#endif
+*/
+
+#include <glib.h>
+#include <gfsmAssert.h>
+#include <gfsmCommon.h>
+#include <gfsmCompound.h>
+#include <gfsmVersion.h>
+#include <gfsmError.h>
+#include <gfsmUtils.h>
+#include <gfsmEnum.h>
+#include <gfsmSet.h>
+#include <gfsmWeightMap.h>
+#include <gfsmBitVector.h>
+#include <gfsmAlphabet.h>
+#include <gfsmSemiring.h>
+#include <gfsmArc.h>
+#include <gfsmState.h>
+#include <gfsmAutomaton.h>
+#include <gfsmArcIter.h>
+#include <gfsmArcIndex.h>
+#include <gfsmStateSet.h>
+#include <gfsmIO.h>
+#include <gfsmAutomatonIO.h>
+#include <gfsmDraw.h>
+#include <gfsmAlgebra.h>
+#include <gfsmArith.h>
+#include <gfsmLookup.h>
+#include <gfsmPaths.h>
+#include <gfsmTrie.h>
+#include <gfsmScanner.h>
+#include <gfsmRegexCompiler.h>
+#include <gfsmIndexed.h>
+#include <gfsmIndexedIO.h>
+
+/*
+#ifdef __cplusplus
+}
+#endif
+*/
+
+#endif /* _GFSM_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAlgebra.c b/gfsm/gfsm/src/libgfsm/gfsmAlgebra.c
new file mode 100644
index 0000000..4e9effe
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAlgebra.c
@@ -0,0 +1,1715 @@
+
+/*=============================================================================*\
+ * File: gfsmAlgebra.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <glib.h>
+#include <gfsmAlgebra.h>
+#include <gfsmAssert.h>
+#include <gfsmArcIter.h>
+#include <gfsmStateSet.h>
+#include <gfsmEnum.h>
+#include <gfsmUtils.h>
+#include <gfsmCompound.h>
+
+/*======================================================================
+ * Methods: algebra
+ */
+
+/*--------------------------------------------------------------
+ * closure_final_func()
+ * + called for each final @id of @fsm during closure(@fsm)
+ */
+static
+gboolean gfsm_automaton_closure_final_func_(gfsmStateId id, gpointer pw, gfsmAutomaton *fsm)
+{
+ gfsmWeight w = gfsm_ptr2weight(pw);
+ if (id != fsm->root_id)
+ gfsm_automaton_add_arc(fsm, id, fsm->root_id, gfsmEpsilon, gfsmEpsilon, w);
+ return FALSE;
+}
+
+
+/*--------------------------------------------------------------
+ * closure()
+ */
+gfsmAutomaton *gfsm_automaton_closure(gfsmAutomaton *fsm, gboolean is_plus)
+{
+ //-- sanity check(s)
+ if (!fsm || fsm->root_id == gfsmNoState) return fsm;
+
+ //-- add epsilon arcs from old final states to translated new root
+ gfsm_automaton_finals_foreach(fsm, (GTraverseFunc)gfsm_automaton_closure_final_func_, fsm);
+
+ //-- reflexive+transitive or reflexive?
+ if (!is_plus) gfsm_automaton_optional(fsm);
+
+ return fsm;
+}
+
+
+/*--------------------------------------------------------------
+ * n_closure()
+ */
+gfsmAutomaton *gfsm_automaton_n_closure(gfsmAutomaton *fsm, guint n)
+{
+ //-- sanity check(s)
+ if (!fsm || fsm->root_id == gfsmNoState) return fsm;
+
+ //-- check for simple closures
+ if (n == 0) return gfsm_automaton_closure(fsm, FALSE);
+ else if (n == 1) return gfsm_automaton_closure(fsm, TRUE);
+ else {
+ gfsm_automaton_n_concat(fsm, fsm, n-1);
+ }
+
+ return gfsm_automaton_closure(fsm, TRUE);
+}
+
+
+/*--------------------------------------------------------------
+ * complement()
+ */
+gfsmAutomaton *gfsm_automaton_complement(gfsmAutomaton *fsm)
+{
+ gfsmAlphabet *alph = gfsm_identity_alphabet_new();
+ gfsm_automaton_get_alphabet(fsm, gfsmLSLower, alph);
+ gfsm_automaton_complement_full(fsm,alph);
+ gfsm_alphabet_free(alph);
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * complement_full()
+ */
+gfsmAutomaton *gfsm_automaton_complement_full(gfsmAutomaton *fsm, gfsmAlphabet *alph)
+{
+ gfsmStateId id, sink_id;
+ gfsm_automaton_complete(fsm, alph, &sink_id);
+
+ //-- flip final states (no weights here)
+ for (id = 0; id < fsm->states->len; id++) {
+ gfsmState *s = gfsm_automaton_find_state(fsm,id);
+ if (!s || !s->is_valid) continue;
+ gfsm_automaton_set_final_state(fsm, id, !s->is_final);
+ }
+
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * complete()
+ */
+gfsmAutomaton *gfsm_automaton_complete(gfsmAutomaton *fsm, gfsmAlphabet *alph, gfsmStateId *sinkp)
+{
+ gfsmStateId id, sinkid;
+ GPtrArray *alabels;
+
+ if (!fsm->flags.is_deterministic) fsm = gfsm_automaton_determinize(fsm);
+ if (gfsm_acmask_nth(fsm->flags.sort_mode,0) != gfsmACLower) {
+ gfsm_automaton_arcsort(fsm,gfsmACLower);
+ }
+ //-- avoid "smart" arc insertion
+ fsm->flags.sort_mode = gfsmASMNone;
+
+ //-- add sink-id
+ sinkid = gfsm_automaton_add_state(fsm);
+ if (sinkp) *sinkp = sinkid;
+
+ //-- get alphabet label-vector
+ alabels = g_ptr_array_sized_new(gfsm_alphabet_size(alph));
+ gfsm_alphabet_labels_to_array(alph,alabels);
+
+ for (id = 0; id < fsm->states->len; id++) {
+ gfsmState *s = gfsm_automaton_find_state(fsm,id);
+ gfsmArcList *al;
+ gfsmArc *a;
+ guint labi;
+ if (!s || !s->is_valid) continue;
+
+ al = s->arcs;
+ a = gfsm_arclist_arc(al);
+ for (labi=0; labi < alabels->len; ) {
+ gfsmLabelVal lab = (gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(alabels,labi));
+
+ if (lab==gfsmEpsilon) {
+ ++labi;
+ }
+ else if (!a || a->lower > lab) {
+ //-- no arc for this label: route it to sink
+ gfsm_automaton_add_arc(fsm, id, sinkid, lab, lab, fsm->sr->one);
+ ++labi;
+ }
+ else if (a->lower == lab) {
+ ++labi;
+ }
+ else {
+ while (al != NULL && a->lower < lab) {
+ al = al->next;
+ a = gfsm_arclist_arc(al);
+ }
+ }
+ }
+ }
+
+ //-- mark fsm as (still) deterministic
+ fsm->flags.is_deterministic = TRUE;
+
+ //-- cleanup
+ //g_array_free(alabels,TRUE);
+ g_ptr_array_free(alabels,TRUE);
+
+ return fsm;
+}
+
+
+/*--------------------------------------------------------------
+ * compose()
+ */
+gfsmAutomaton *gfsm_automaton_compose(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsmAutomaton *fsm = gfsm_automaton_compose_full(fsm1,fsm2, NULL,NULL);
+ gfsm_automaton_swap(fsm1,fsm);
+ gfsm_automaton_free(fsm);
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * compose_visit_()
+ */
+//#define GFSM_DEBUG_COMPOSE_VISIT 1
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+# include <stdio.h>
+#endif
+gfsmStateId gfsm_automaton_compose_visit_(gfsmComposeState sp,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *fsm,
+ gfsmComposeStateEnum *spenum,
+ gfsmComposeFlags flags)
+{
+ gfsmState *q1, *q2;
+ gfsmStateId qid = gfsm_enum_lookup(spenum,&sp);
+ gfsmStateId qid2;
+ gfsmArcList *al1, *al2, *ai1, *ai2;
+ gfsmArcList *ai1_noneps, *ai2_noneps, *ai2_continue;
+ gfsmArc *a1,*a2;
+
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr, "compose(): visit : (q%u,f%u,q%u) => q%d\n", sp.id1, sp.idf, sp.id2,
+ (int)(qid==gfsmEnumNone ? -1 : qid));
+#endif
+
+ //-- ignore already-visited states
+ if (qid != gfsmEnumNone) return qid;
+
+ //-- get state pointers for input automata
+ q1 = gfsm_automaton_find_state(fsm1,sp.id1);
+ q2 = gfsm_automaton_find_state(fsm2,sp.id2);
+
+ //-- sanity check
+ if ( !(q1 && q2 && q1->is_valid && q2->is_valid) ) {
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr, "compose(): BAD : (q%u,f%u,q%u) XXXXX\n", sp.id1, sp.idf, sp.id2);
+#endif
+ return gfsmNoState;
+ }
+
+ //-- insert new state into output automaton
+ qid = gfsm_automaton_add_state(fsm);
+ gfsm_enum_insert_full(spenum,&sp,qid);
+
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr, "compose(): CREATE: (q%u,f%u,q%u) => q%u ***\n", sp.id1, sp.idf, sp.id2, qid);
+#endif
+
+ //-- check for final states
+ if (q1->is_final && q2->is_final) {
+ gfsm_automaton_set_final_state_full(fsm,qid,TRUE,
+ gfsm_sr_times(fsm->sr,
+ gfsm_automaton_get_final_weight(fsm1,sp.id1),
+ gfsm_automaton_get_final_weight(fsm2,sp.id2)));
+ }
+
+ //-------------------------------------------
+ // recurse on outgoing arcs
+
+ //--------------------------------
+ // recurse: arcs: sort
+
+ //-- arcs: sort arclists: fsm1
+ if (flags&gfsmCFEfsm1NeedsArcSort) {
+ gfsmArcCompData sortdata = { gfsmACUpper,NULL,NULL,NULL };
+ al1 = gfsm_arclist_sort(gfsm_arclist_clone(q1->arcs), &sortdata);
+ }
+ else { al1 = q1->arcs; }
+
+ //-- arcs: sort arclists: fsm2
+ if (flags&gfsmCFEfsm2NeedsArcSort) {
+ gfsmArcCompData sortdata = { gfsmACLower,NULL,NULL,NULL };
+ al2 = gfsm_arclist_sort(gfsm_arclist_clone(q2->arcs), &sortdata);
+ }
+ else { al2 = q2->arcs; }
+
+ //--------------------------------
+ // recusrse: arcs: handle epsilons
+ for (ai1_noneps=al1; ai1_noneps!=NULL && ai1_noneps->arc.upper==gfsmEpsilon; ai1_noneps=ai1_noneps->next) {;}
+ for (ai2_noneps=al2; ai2_noneps!=NULL && ai2_noneps->arc.lower==gfsmEpsilon; ai2_noneps=ai2_noneps->next) {;}
+
+ //-- (eps,NULL): case fsm1(q1 --a:eps(~eps2)--> q1b), filter:({0,2} --eps2:eps2--> 2), fsm2(q2 --(NULL~eps2:eps)--> q2)
+ if (sp.idf != 1) {
+ for (ai1=al1; ai1!=ai1_noneps; ai1=ai1->next) {
+ a1 = &(ai1->arc);
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr,
+ "compose(): MATCH[e,NULL]: (q%u --%d:eps(e2)--> q%u) ~ ({0,2}--(e2:e2)-->2) ~ (q%u --(NULL~e2:eps)--> q%u) ***\n",
+ sp.id1, a1->lower, a1->target,
+ sp.id2, sp.id2);
+#endif
+ qid2 = gfsm_automaton_compose_visit_((gfsmComposeState){a1->target, sp.id2, 2}, fsm1,fsm2,fsm, spenum,flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, a1->lower, gfsmEpsilon, a1->weight);
+ }
+ }
+ //-- (NULL,eps): case fsm1(q1 --(NULL~eps:eps1)--> q1), filter:({0,1} --eps1:eps1--> 1), fsm2(q2 --eps(~eps1):b--> q2b)
+ if (sp.idf != 2) {
+ for (ai2=al2; ai2!=ai2_noneps; ai2=ai2->next) {
+ a2 = &(ai2->arc);
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr,
+ "compose(): MATHC[NULL,e]: (q%u --(NULL~eps:e1)--> q%u) ~ ({0,1}--(e1:e1)-->1) ~ (q%u --eps(e1):%d--> q%u) ***\n",
+ sp.id1, sp.id1,
+ sp.id2, a2->upper, a2->target);
+#endif
+ qid2 = gfsm_automaton_compose_visit_((gfsmComposeState){sp.id1, a2->target, 1}, fsm1,fsm2,fsm, spenum,flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, gfsmEpsilon, a2->upper, a2->weight);
+ }
+ }
+ //-- (eps,eps): case fsm1(q1 --a:eps(~eps2)--> q1b), filter:({0} --eps2:eps1--> 0), fsm2(q2 --eps:b--> q2b)
+ if (sp.idf == 0) {
+ for (ai1=al1; ai1!=ai1_noneps; ai1=ai1->next) {
+ a1 = &(ai1->arc);
+ for (ai2=al2; ai2!=ai2_noneps; ai2=ai2->next) {
+ a2 = &(ai2->arc);
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr,
+ "compose(): MATCH[e,e]: (q%u --%d:eps(e2)--> q%u) ~ ({0}--(e2:e1)-->0) ~ (q%u --eps(e1):%d--> q%u) ***\n",
+ sp.id1, a1->lower, a1->target,
+ sp.id2, a2->upper, a2->target);
+#endif
+ qid2 = gfsm_automaton_compose_visit_((gfsmComposeState){a1->target, a2->target, 0},
+ fsm1,fsm2,fsm, spenum,flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, a1->lower, a2->upper,
+ gfsm_sr_times(fsm->sr, a1->weight, a2->weight));
+ }
+ }
+ }
+
+ //--------------------------------
+ // recurse: arcs: non-eps: iterate
+ for (ai1=ai1_noneps, ai2_continue=ai2_noneps; ai1!=NULL; ai1=ai1->next) {
+ a1 = &(ai1->arc);
+
+ for (ai2=ai2_continue; ai2!=NULL; ai2=ai2->next) {
+ a2 = &(ai2->arc);
+
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr,
+ "compose(): check[x,x]: (q%u --%d:%d--> q%u) ~ ({0,1,2}--(x:x)-->0) ~ (q%u --%d:%d--> q%u)\n",
+ sp.id1, a1->lower, a1->upper, a1->target,
+ sp.id2, a2->lower, a2->upper, a2->target);
+#endif
+
+ if (a2->lower < a1->upper) { ai2_continue=ai2->next; continue; }
+ else if (a2->lower > a1->upper) { break; }
+
+#ifdef GFSM_DEBUG_COMPOSE_VISIT
+ fprintf(stderr,
+ "compose(): MATCH[x,x]: (q%u --%d:%d--> q%u) ~ ({0,1,2}--(x:x)-->0) ~ (q%u --%d:%d--> q%u) ***\n",
+ sp.id1, a1->lower, a1->upper, a1->target,
+ sp.id2, a2->lower, a2->upper, a2->target);
+#endif
+
+ //-- non-eps: case fsm1:(q1 --a:b--> q1'), fsm2:(q2 --b:c--> q2')
+ qid2 = gfsm_automaton_compose_visit_((gfsmComposeState){a1->target,a2->target,0},
+ fsm1,fsm2,fsm, spenum,flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, a1->lower, a2->upper,
+ gfsm_sr_times(fsm1->sr, a1->weight, a2->weight));
+ }
+ }
+
+ //-- maybe cleanup temporary arc-lists
+ if (flags&gfsmCFEfsm1NeedsArcSort) gfsm_arclist_free(al1);
+ if (flags&gfsmCFEfsm2NeedsArcSort) gfsm_arclist_free(al2);
+
+ return qid;
+}
+
+/*--------------------------------------------------------------
+ * compose_full()
+ */
+//#define GFSM_DEBUG_COMPOSE
+#ifdef GFSM_DEBUG_COMPOSE
+# include <gfsmAutomatonIO.h>
+#endif
+gfsmAutomaton *gfsm_automaton_compose_full(gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *composition,
+ gfsmComposeStateEnum *spenum
+ )
+{
+ gboolean spenum_is_temp;
+ gfsmComposeState rootpair;
+ gfsmStateId rootid;
+ gfsmComposeFlags flags = 0;
+#ifdef GFSM_DEBUG_COMPOSE
+ gfsmError *err =NULL;
+#endif
+
+ //-- setup: output fsm
+ if (!composition) {
+ composition=gfsm_automaton_shadow(fsm1);
+ } else {
+ gfsm_automaton_clear(composition);
+ gfsm_automaton_copy_shallow(composition,fsm1);
+ }
+ composition->flags.sort_mode = gfsmASMNone;
+ composition->flags.is_transducer = 1;
+
+ //-- setup: ComposeStateEnum
+ if (spenum==NULL) {
+ spenum_is_temp=TRUE;
+ spenum = gfsm_compose_state_enum_new();
+ } else {
+ spenum_is_temp=FALSE;
+ gfsm_enum_clear(spenum);
+ }
+
+ //-- setup: flags
+ if (gfsm_acmask_nth(fsm1->flags.sort_mode,0) != gfsmACUpper) flags |= gfsmCFEfsm1NeedsArcSort;
+ if (gfsm_acmask_nth(fsm2->flags.sort_mode,0) != gfsmACLower) flags |= gfsmCFEfsm2NeedsArcSort;
+
+ //-- guts: recursively visit states depth-first from root
+ rootpair.id1 = fsm1->root_id;
+ rootpair.id2 = fsm2->root_id;
+ rootpair.idf = 0;
+ rootid = gfsm_automaton_compose_visit_(rootpair, fsm1, fsm2, composition, spenum, flags);
+
+ //-- finalize: set new root state
+ if (rootid != gfsmNoState) {
+ gfsm_automaton_set_root(composition, rootid);
+ } else {
+ composition->root_id = gfsmNoState;
+ }
+ //-- cleanup
+ if (spenum_is_temp) gfsm_enum_free(spenum);
+
+ return composition;
+}
+
+
+
+/*--------------------------------------------------------------
+ * concat_final_func()
+ * + called for each final @id of @fsm during concat(@fsm,@fsm2)
+ * + during the call @fsm1->root_id should be set to the translated root of @fsm2
+ */
+static
+gboolean gfsm_automaton_concat_final_func_(gfsmStateId id, gpointer pw, gfsmAutomaton *fsm)
+{
+ gfsmWeight w = gfsm_ptr2weight(pw);
+ gfsm_automaton_add_arc(fsm, id, fsm->root_id, gfsmEpsilon, gfsmEpsilon, w);
+ gfsm_automaton_find_state(fsm,id)->is_final = FALSE;
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * concat_final_func_1()
+ * + called for singleton final @id of @fsm during concat(@fsm,@fsm2)
+ * + BAD if singleton final of @fsm has outgoing arcs!
+ */
+#if 0
+struct gfsm_automaton_concat_1_final_data_ {
+ gfsmStateId *rootxp;
+ gfsmWeight *weightp;
+};
+static
+gboolean gfsm_automaton_concat_final_func_1_(gfsmStateId id,
+ gpointer pw,
+ struct gfsm_automaton_concat_1_final_data_ *data)
+{
+ *(data->rootxp) = id;
+ *(data->weightp) = gfsm_ptr2weight(pw);
+ return TRUE;
+}
+#endif
+
+/*--------------------------------------------------------------
+ * concat()
+ */
+gfsmAutomaton *gfsm_automaton_concat(gfsmAutomaton *fsm1, gfsmAutomaton *_fsm2)
+{
+ gfsmAutomaton *fsm2;
+ gfsmStateId offset;
+ gfsmStateId id2;
+ gfsmStateId size2;
+ gfsmStateId rootx;
+ gfsmWeightMap *finals2 = NULL;
+
+ //-- sanity check(s)
+ if (!_fsm2 || _fsm2->root_id == gfsmNoState) return fsm1;
+ if (_fsm2==fsm1) fsm2 = gfsm_automaton_clone(fsm1);
+ else fsm2 = _fsm2;
+
+ if (fsm1->finals == fsm2->finals) {
+ finals2 = gfsm_weightmap_new(gfsm_uint_compare);
+ gfsm_weightmap_copy(finals2, fsm2->finals);
+ }
+
+ offset = fsm1->states->len;
+ size2 = fsm2->states->len;
+ gfsm_automaton_reserve(fsm1, offset + size2);
+
+ //-- concatenative arcs
+ if (fsm1->root_id != gfsmNoState) {
+ //-- multiple final states: add epsilon arcs from old finals to mapped root2
+ gfsmStateId root_tmp = fsm1->root_id;
+ rootx = fsm2->root_id+offset;
+ fsm1->root_id = rootx;
+ gfsm_automaton_finals_foreach(fsm1, (GTraverseFunc)gfsm_automaton_concat_final_func_, fsm1);
+ fsm1->root_id = root_tmp;
+ } else /*if (fsm2->root_id != gfsmNoState)*/ {
+ fsm1->root_id = rootx = fsm2->root_id + offset;
+ }
+ gfsm_weightmap_clear(fsm1->finals);
+
+ //-- adopt states from fsm2 into fsm1
+ for (id2 = 0; id2 < size2; id2++) {
+ gfsmStateId id1;
+ const gfsmState *s2;
+ gfsmState *s1;
+ gfsmArcIter ai;
+ gfsmWeight s2fw;
+
+ s2 = gfsm_automaton_find_state_const(fsm2,id2);
+ id1 = id2+offset;
+ s1 = gfsm_automaton_find_state(fsm1, id1);
+
+ //-- sanity check(s)
+ if (!s1 || !s2 || !s2->is_valid) continue;
+
+ //-- copy state
+ gfsm_state_copy(s1,s2);
+
+ //-- translate targets for adopted arcs
+ for (gfsm_arciter_open_ptr(&ai,fsm1,s1); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai))
+ {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ a->target += offset;
+ }
+
+ //-- check for new final states: get weight & mark state is_final flag
+ if ( (finals2 && gfsm_weightmap_lookup(finals2, GUINT_TO_POINTER(id2), &s2fw))
+ ||
+ (!finals2 && gfsm_weightmap_lookup(fsm2->finals, GUINT_TO_POINTER(id2), &s2fw)) )
+ {
+ s1->is_final = TRUE;
+ gfsm_weightmap_insert(fsm1->finals, GUINT_TO_POINTER(id1), s2fw);
+ }
+ }
+
+ //-- mark as unsorted
+ fsm1->flags.sort_mode = gfsmASMNone;
+
+ //-- cleanup
+ if (finals2) gfsm_weightmap_free(finals2);
+ if (fsm2 != _fsm2) gfsm_automaton_free(fsm2);
+
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * n_concat()
+ */
+gfsmAutomaton *gfsm_automaton_n_concat(gfsmAutomaton *fsm1, gfsmAutomaton *_fsm2, guint n)
+{
+ gfsmAutomaton *fsm2 = _fsm2;
+
+ //-- sanity check(s)
+ if (!_fsm2 || _fsm2->root_id == gfsmNoState) return fsm1;
+ if (_fsm2==fsm1) fsm2 = gfsm_automaton_clone(fsm1);
+
+ for ( ; n > 0; n--) { gfsm_automaton_concat(fsm1, fsm2); }
+
+ if (fsm2 != _fsm2) gfsm_automaton_free(fsm2);
+
+ return fsm1;
+}
+
+
+/*--------------------------------------------------------------
+ * connect()
+ */
+gfsmAutomaton *gfsm_automaton_connect(gfsmAutomaton *fsm)
+{
+ gfsmBitVector *wanted;
+
+ //-- sanity check
+ if (!fsm) return fsm;
+
+ wanted = gfsm_bitvector_sized_new(fsm->states->len);
+ gfsm_automaton_connect_fw(fsm, wanted);
+
+ gfsm_bitvector_zero(wanted);
+ gfsm_automaton_connect_bw(fsm, NULL, wanted);
+
+ gfsm_bitvector_free(wanted);
+ return fsm;
+}
+
+
+/*--------------------------------------------------------------
+ * connect_fw_visit_state()
+ * + marks all states on a path from (id) in (visited)
+ */
+void gfsm_connect_fw_visit_state(gfsmAutomaton *fsm,
+ gfsmStateId id,
+ gfsmBitVector *visited)
+{
+ gfsmState *s;
+ gfsmArcIter ai;
+
+ //-- already visited
+ if (gfsm_bitvector_get(visited,id)) return;
+
+ s = gfsm_automaton_find_state(fsm,id);
+ if (!s || !s->is_valid) return; //-- ignore invalid states
+
+ //-- mark node as visited on this path
+ gfsm_bitvector_set(visited,id,1);
+
+ //-- visit targets of outgoing arcs
+ for (gfsm_arciter_open_ptr(&ai,fsm,s); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsm_connect_fw_visit_state(fsm, gfsm_arciter_arc(&ai)->target, visited);
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------
+ * connect_fw()
+ */
+gfsmAutomaton *gfsm_automaton_connect_fw(gfsmAutomaton *fsm, gfsmBitVector *visited)
+{
+ gboolean visited_is_temp = FALSE;
+
+ //-- sanity check
+ if (!fsm || fsm->root_id == gfsmNoState)
+ return gfsm_automaton_prune_states(fsm,NULL);
+
+ //-- traversal record
+ if (visited==NULL) {
+ visited = gfsm_bitvector_sized_new(fsm->states->len);
+ visited_is_temp = TRUE;
+ }
+
+ //-- traverse
+ gfsm_connect_fw_visit_state(fsm, fsm->root_id, visited);
+ gfsm_automaton_prune_states(fsm, visited);
+
+ //-- cleanup
+ if (visited_is_temp) gfsm_bitvector_free(visited);
+
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * connect_bw(): final_foreach()
+ */
+struct gfsm_connect_bw_data_ {
+ gfsmAutomaton *fsm;
+ GPtrArray *rarcs;
+ gfsmBitVector *finalizable;
+};
+
+gboolean gfsm_connect_bw_visit_state(gfsmStateId id,
+ gpointer pw,
+ struct gfsm_connect_bw_data_ *data)
+{
+ GSList *rl;
+
+ //-- already visited
+ if (gfsm_bitvector_get(data->finalizable,id) //-- already visited?
+ || !gfsm_automaton_has_state(data->fsm, id)) //-- bad state?
+ return FALSE; //-----> continue traversal
+
+ //-- mark state as finalizable
+ gfsm_bitvector_set(data->finalizable,id,1);
+
+ //-- visit sources of incoming arcs
+ for (rl=g_ptr_array_index(data->rarcs,id); rl != NULL; rl=rl->next) {
+ gfsmArc *arc = (gfsmArc*)rl->data;
+ gfsm_connect_bw_visit_state(arc->source,pw,data);
+ }
+
+ return FALSE; //-- continue traversal
+}
+
+/*--------------------------------------------------------------
+ * connect_bw()
+ */
+gfsmAutomaton *gfsm_automaton_connect_bw(gfsmAutomaton *fsm,
+ gfsmReverseArcIndex *rarcs,
+ gfsmBitVector *finalizable)
+{
+ gboolean rarcs_is_temp = FALSE;
+ gboolean finalizable_is_temp = FALSE;
+ struct gfsm_connect_bw_data_ data = {fsm,rarcs,finalizable};
+
+ //-- sanity check(s)
+ if (!fsm || gfsm_automaton_n_final_states(fsm)==0)
+ return gfsm_automaton_prune_states(fsm,NULL);
+
+ //-- reverse arc-index
+ if (rarcs==NULL) {
+ rarcs = data.rarcs = gfsm_automaton_reverse_arc_index(fsm,NULL);
+ rarcs_is_temp = TRUE;
+ }
+
+ //-- traversal record
+ if (finalizable==NULL) {
+ finalizable = data.finalizable = gfsm_bitvector_sized_new(fsm->states->len);
+ finalizable_is_temp = TRUE;
+ }
+
+ //-- traverse
+ gfsm_automaton_finals_foreach(fsm, (GTraverseFunc)gfsm_connect_bw_visit_state, &data);
+ gfsm_automaton_prune_states(fsm, finalizable);
+
+ //-- cleanup
+ if (finalizable_is_temp) gfsm_bitvector_free(finalizable);
+ if (rarcs_is_temp) gfsm_reverse_arc_index_free(rarcs,TRUE);
+
+ return fsm;
+}
+
+
+/*--------------------------------------------------------------
+ * prune_states()
+ */
+gfsmAutomaton *gfsm_automaton_prune_states(gfsmAutomaton *fsm, gfsmBitVector *wanted)
+{
+ gfsmStateId id, maxwanted=gfsmNoState;
+ gfsmArcIter ai;
+
+ for (id=0; id < fsm->states->len; id++) {
+ if (!wanted || !gfsm_bitvector_get(wanted,id)) {
+ //-- unwanted state: chuck it
+ gfsm_automaton_remove_state(fsm,id);
+ }
+ else {
+ maxwanted = id;
+ //-- prune outgoing arcs to any unwanted states, too
+ for (gfsm_arciter_open(&ai, fsm, id); gfsm_arciter_ok(&ai); ) {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+ if (!wanted || !gfsm_bitvector_get(wanted,arc->target)) {
+ gfsm_arciter_remove(&ai);
+ } else {
+ gfsm_arciter_next(&ai);
+ }
+ }
+ }
+ }
+
+ //-- update number of states
+ if (maxwanted != gfsmNoState) {
+ g_array_set_size(fsm->states, maxwanted+1);
+ } else {
+ g_array_set_size(fsm->states, 0);
+ }
+
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * determinize_lp2ec_foreach_func_()
+ */
+typedef struct {
+ gfsmAutomaton *nfa;
+ gfsmAutomaton *dfa;
+ gfsmStateId dfa_src_id;
+ gfsmEnum *ec2id;
+} gfsmLp2EcForeachData;
+
+static
+gboolean gfsm_determinize_lp2ec_foreach_func_(gfsmLabelPair lp,
+ gfsmWeightedStateSet *wss,
+ gfsmLp2EcForeachData *data)
+{
+ gfsmStateId ec2id_val;
+ gpointer ec2id_val_as_ptr;
+ gfsmStateSet *ec2id_key;
+
+ if ( gfsm_enum_lookup_extended(data->ec2id,
+ wss->set,
+ (gpointer)(&ec2id_key),
+ (gpointer)(&ec2id_val_as_ptr)) )
+ {
+ //-- target node-set is already present: just add an arc in @dfa
+ ec2id_val = GPOINTER_TO_UINT(ec2id_val_as_ptr);
+ gfsm_automaton_add_arc(data->dfa,
+ data->dfa_src_id,
+ ec2id_val,
+ gfsm_labelpair_lower(lp),
+ gfsm_labelpair_upper(lp),
+ wss->weight);
+
+ //-- ... and maybe free the embedded state set
+ if (wss->set != ec2id_key) gfsm_stateset_free(wss->set);
+ wss->set = NULL;
+ }
+ else
+ {
+ //-- image of equiv-class (wss->set) was not yet present: make a new one
+ ec2id_val = gfsm_automaton_ensure_state(data->dfa,
+ gfsm_enum_insert(data->ec2id, wss->set));
+
+ //-- ... add @dfa arc
+ gfsm_automaton_add_arc(data->dfa,
+ data->dfa_src_id,
+ ec2id_val,
+ gfsm_labelpair_lower(lp),
+ gfsm_labelpair_upper(lp),
+ wss->weight);
+
+ //-- ... and recurse
+ gfsm_determinize_visit_state_(data->nfa, data->dfa,
+ wss->set, ec2id_val,
+ data->ec2id);
+ }
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * determinize_visit_state_()
+ */
+void gfsm_determinize_visit_state_(gfsmAutomaton *nfa, gfsmAutomaton *dfa,
+ gfsmStateSet *nfa_ec, gfsmStateId dfa_id,
+ gfsmEnum *ec2id)
+{
+ GTree *lp2ecw; //-- maps label-pairs@nfa.src.ec => (eq-class@nfa.sink, sum(weight))
+ gfsmStateSetIter eci;
+ gfsmStateId ecid;
+ gfsmLp2EcForeachData lp2ec_foreach_data;
+ gfsmWeight fw;
+
+ //-- check for final state
+ if (gfsm_stateset_lookup_final_weight(nfa_ec,nfa,&fw)) {
+ gfsm_automaton_set_final_state_full(dfa, dfa_id, TRUE, fw);
+ }
+
+ //-- build label-pair => (sink-eqc, sum(weight)) mapping 'lp2ecw' for node-set nfa_ec
+ lp2ecw = g_tree_new_full(((GCompareDataFunc)
+ gfsm_labelpair_compare_with_data), //-- key_comp_func
+ NULL, //-- key_comp_data
+ NULL, //-- key_free_func
+ (GDestroyNotify)g_free); //-- val_free_func
+
+ for (eci=gfsm_stateset_iter_begin(nfa_ec);
+ (ecid=gfsm_stateset_iter_id(eci)) != gfsmNoState;
+ eci=gfsm_stateset_iter_next(nfa_ec,eci))
+ {
+ gfsmArcIter ai;
+ for (gfsm_arciter_open(&ai, nfa, ecid); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ gfsmLabelPair lp;
+ gfsmLabelPair *lp2ec_key;
+ gfsmWeightedStateSet *lp2ec_val;
+
+ //if (a->lower==gfsmEpsilon && a->upper==gfsmEpsilon) continue; //-- ignore eps arcs
+ lp = gfsm_labelpair_new(a->lower, a->upper);
+
+ //-- add equivalence class to local mapping
+ if ( g_tree_lookup_extended(lp2ecw,
+ GUINT_TO_POINTER(lp),
+ (gpointer)(&lp2ec_key),
+ (gpointer)(&lp2ec_val)) )
+ {
+ //-- already present: compute union and add new arc's weight
+ gfsm_stateset_insert(lp2ec_val->set, a->target);
+ lp2ec_val->weight = gfsm_sr_plus(nfa->sr, lp2ec_val->weight, a->weight);
+ }
+ else
+ {
+ //-- not yet present: insert new value
+ lp2ec_val = g_new(gfsmWeightedStateSet,1);
+ lp2ec_val->set = gfsm_stateset_new_singleton(a->target);
+ lp2ec_val->weight = a->weight;
+ g_tree_insert(lp2ecw, GUINT_TO_POINTER(lp), lp2ec_val);
+ }
+ }
+
+ //-- tmp-cleanup
+ gfsm_arciter_close(&ai);
+ }
+
+ //-- stateset-iter (eci) cleanup
+ //(none)
+
+ //-- insert computed arcs into @dfa
+ lp2ec_foreach_data.nfa = nfa;
+ lp2ec_foreach_data.dfa = dfa;
+ lp2ec_foreach_data.dfa_src_id = dfa_id;
+ lp2ec_foreach_data.ec2id = ec2id;
+ g_tree_foreach(lp2ecw,
+ (GTraverseFunc)gfsm_determinize_lp2ec_foreach_func_,
+ (gpointer)(&lp2ec_foreach_data));
+
+ //-- cleanup
+ g_tree_destroy(lp2ecw);
+}
+
+
+/*--------------------------------------------------------------
+ * determinize()
+ */
+gfsmAutomaton *gfsm_automaton_determinize(gfsmAutomaton *nfa)
+{
+ if (!nfa->flags.is_deterministic) {
+ gfsmAutomaton *dfa = gfsm_automaton_determinize_full(nfa,NULL);
+ gfsm_automaton_swap(nfa,dfa);
+ gfsm_automaton_free(dfa);
+ }
+ return nfa;
+}
+
+/*--------------------------------------------------------------
+ * determinize_full()
+ */
+gfsmAutomaton *gfsm_automaton_determinize_full(gfsmAutomaton *nfa, gfsmAutomaton *dfa)
+{
+ gfsmEnum *ec2id; //-- (global) maps literal(equiv-class@nfa) => node-id@dfa
+ gfsmStateSet *nfa_ec; //-- (temp) equiv-class@nfa
+ gfsmStateId dfa_id; //-- (temp) id @ dfa
+
+ //-- sanity check(s)
+ if (!nfa) return NULL;
+ else if (nfa->flags.is_deterministic) {
+ if (dfa) gfsm_automaton_copy(dfa,nfa);
+ else dfa = gfsm_automaton_clone(nfa);
+ return dfa;
+ }
+
+ //-- initialization: dfa
+ if (!dfa) {
+ dfa = gfsm_automaton_shadow(nfa);
+ } else {
+ gfsm_automaton_clear(dfa);
+ gfsm_automaton_copy_shallow(dfa,nfa);
+ }
+ //-- avoid "smart" arc-insertion
+ dfa->flags.sort_mode = gfsmASMNone;
+
+ //-- initialization: ec2id
+ ec2id = gfsm_enum_new_full(NULL /*(gfsmDupFunc)gfsm_stateset_clone*/ ,
+ (GHashFunc)gfsm_stateset_hash,
+ (GEqualFunc)gfsm_stateset_equal,
+ (GDestroyNotify)gfsm_stateset_free);
+
+ //-- initialization: nfa_ec
+ nfa_ec = gfsm_stateset_sized_new(32);
+ gfsm_stateset_insert(nfa_ec, nfa->root_id);
+
+ //-- set root in dfa
+ dfa_id = gfsm_automaton_ensure_state(dfa, gfsm_enum_insert(ec2id, nfa_ec));
+ gfsm_automaton_set_root(dfa, dfa_id);
+
+ //-- guts: determinize recursively outwards from root node
+ gfsm_determinize_visit_state_(nfa, dfa, nfa_ec, dfa_id, ec2id);
+
+ //-- set flag in dfa
+ dfa->flags.is_deterministic = TRUE;
+
+ //-- cleanup
+ //gfsm_stateset_free(nfa_ec); //-- this ought to be freed by gfsm_enum_free(ec2id)
+ gfsm_enum_free(ec2id);
+
+ return dfa;
+}
+
+
+
+/*--------------------------------------------------------------
+ * difference()
+ */
+gfsmAutomaton *gfsm_automaton_difference(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsmAutomaton *fsm = gfsm_automaton_difference_full(fsm1,fsm2,NULL);
+ gfsm_automaton_swap(fsm1,fsm);
+ gfsm_automaton_free(fsm);
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * difference_full()
+ */
+gfsmAutomaton *gfsm_automaton_difference_full(gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *diff)
+{
+ gfsmAutomaton *not_fsm2;
+ gfsmAlphabet *alph1 = gfsm_identity_alphabet_new();
+
+ gfsm_automaton_get_alphabet(fsm1, gfsmLSLower, alph1);
+ not_fsm2 = gfsm_automaton_clone(fsm2);
+ gfsm_automaton_complement_full(not_fsm2, alph1);
+ diff = gfsm_automaton_intersect_full(fsm1, not_fsm2, diff, NULL);
+
+ gfsm_automaton_free(not_fsm2);
+ gfsm_alphabet_free(alph1);
+
+ return diff;
+}
+
+
+
+/*--------------------------------------------------------------
+ * intersect()
+ */
+gfsmAutomaton *gfsm_automaton_intersect(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsmAutomaton *fsm = gfsm_automaton_intersect_full(fsm1,fsm2,NULL,NULL);
+ gfsm_automaton_swap(fsm1,fsm);
+ gfsm_automaton_free(fsm);
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * intersect_full()
+ */
+gfsmAutomaton *gfsm_automaton_intersect_full(gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *intersect,
+ gfsmStatePairEnum *spenum)
+{
+ gboolean spenum_is_temp;
+ gfsmStatePair rootpair;
+ gfsmStateId rootid;
+ gfsmComposeFlags flags = 0;
+
+ //-- setup: output fsm
+ if (!intersect) {
+ intersect=gfsm_automaton_shadow(fsm1);
+ } else {
+ gfsm_automaton_clear(intersect);
+ gfsm_automaton_copy_shallow(intersect,fsm1);
+ }
+ //-- avoid "smart" arc-insertion
+ intersect->flags.sort_mode = gfsmASMNone;
+ intersect->flags.is_transducer = 0;
+
+ //-- setup: StatePairEnum
+ if (spenum==NULL) {
+ spenum_is_temp=TRUE;
+ spenum = gfsm_statepair_enum_new();
+ } else {
+ spenum_is_temp=FALSE;
+ gfsm_enum_clear(spenum);
+ }
+
+ //-- setup: flags
+ if (gfsm_acmask_nth(fsm1->flags.sort_mode,0) != gfsmACLower) flags |= gfsmCFEfsm1NeedsArcSort;
+ if (gfsm_acmask_nth(fsm2->flags.sort_mode,0) != gfsmACLower) flags |= gfsmCFEfsm2NeedsArcSort;
+
+ //-- guts
+ rootpair.id1 = fsm1->root_id;
+ rootpair.id2 = fsm2->root_id;
+ rootid = gfsm_automaton_intersect_visit_(rootpair, fsm1, fsm2, intersect, spenum,flags);
+
+ //-- finalize: set root state
+ if (rootid != gfsmNoState) {
+ gfsm_automaton_set_root(intersect, rootid);
+ } else {
+ intersect->root_id = gfsmNoState;
+ }
+
+ //-- cleanup
+ if (spenum_is_temp) gfsm_enum_free(spenum);
+
+ return intersect;
+}
+
+/*--------------------------------------------------------------
+ * intersect_visit()
+ */
+gfsmStateId gfsm_automaton_intersect_visit_(gfsmStatePair sp,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *fsm,
+ gfsmStatePairEnum *spenum,
+ gfsmComposeFlags flags)
+{
+ gfsmState *q1, *q2;
+ gfsmStateId qid = gfsm_enum_lookup(spenum,&sp);
+ gfsmStateId qid2;
+ gfsmArcList *al1, *al2, *ai1, *ai2, *ai2eps;
+ gfsmArc *a1,*a2;
+
+ //-- ignore already-visited states
+ if (qid != gfsmEnumNone) return qid;
+
+ //-- get state pointers for input automata
+ q1 = gfsm_automaton_find_state(fsm1,sp.id1);
+ q2 = gfsm_automaton_find_state(fsm2,sp.id2);
+
+ //-- sanity check
+ if ( !(q1 && q2 && q1->is_valid && q2->is_valid) ) return gfsmNoState;
+
+ //-- insert new state into output automaton
+ qid = gfsm_automaton_add_state(fsm);
+ gfsm_enum_insert_full(spenum,&sp,qid);
+ //q = gfsm_automaton_get_state(fsm,qid);
+
+ //-- check for final states
+ if (q1->is_final && q2->is_final) {
+ gfsm_automaton_set_final_state_full(fsm,qid,TRUE,
+ gfsm_sr_times(fsm->sr,
+ gfsm_automaton_get_final_weight(fsm1,sp.id1),
+ gfsm_automaton_get_final_weight(fsm2,sp.id2)));
+ }
+
+ //-------------------------------------------
+ // recurse on outgoing arcs
+
+ //--------------------------------
+ // recurse: arcs: sort
+
+ //-- arcs: sort arclists: fsm1
+ if (flags&gfsmCFEfsm1NeedsArcSort) {
+ gfsmArcCompData sortdata = { (gfsmACLower|(gfsmACUpper<<gfsmACShift)),NULL,NULL,NULL };
+ al1 = gfsm_arclist_sort(gfsm_arclist_clone(q1->arcs), &sortdata);
+ }
+ else { al1 = q1->arcs; }
+
+ //-- arcs: sort arclists: fsm2
+ if (flags&gfsmCFEfsm2NeedsArcSort) {
+ gfsmArcCompData sortdata = { (gfsmACLower|(gfsmACUpper<<gfsmACShift)),NULL,NULL,NULL };
+ al2 = gfsm_arclist_sort(gfsm_arclist_clone(q2->arcs), &sortdata);
+ }
+ else { al2 = q2->arcs; }
+
+ //--------------------------------
+ // recurse: arcs: iterate
+ for (ai1=al1, ai2=al2; ai1 != NULL; ai1=ai1->next) {
+ a1 = &(ai1->arc);
+ if (a1->lower == gfsmEpsilon) {
+ //-- handle epsilon arcs
+
+ //-- eps: case fsm1:(q1 --eps--> q1'), fsm2:(q2)
+ qid2 = gfsm_automaton_intersect_visit_((gfsmStatePair){a1->target,sp.id2},
+ fsm1, fsm2, fsm, spenum, flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, gfsmEpsilon, gfsmEpsilon, a1->weight);
+
+ //-- eps: case fsm1:(q1 --eps--> q1'), fsm2:(q2 --eps--> q2')
+ for (ai2eps=al2; ai2eps != NULL; ai2eps=ai2eps->next) {
+ a2 = &(ai2eps->arc);
+ if (a2->lower != gfsmEpsilon) break;
+
+ qid2 = gfsm_automaton_intersect_visit_((gfsmStatePair){a1->target,a2->target},
+ fsm1, fsm2, fsm, spenum, flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, gfsmEpsilon, gfsmEpsilon,
+ gfsm_sr_times(fsm1->sr, a1->weight, a2->weight));
+ }
+ }
+ else {
+ //-- handle non-epsilon arcs
+ for ( ; ai2 != NULL; ai2=ai2->next) {
+ a2 = &(ai2->arc);
+
+ if (a2->lower < a1->lower) continue;
+ else if (a2->lower > a1->lower) break;
+
+ qid2 = gfsm_automaton_intersect_visit_((gfsmStatePair){a1->target,a2->target},
+ fsm1, fsm2, fsm, spenum, flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, a1->lower, a1->lower,
+ gfsm_sr_times(fsm1->sr, a1->weight, a2->weight));
+ }
+ }
+ }
+
+ //-- handle epsilon-arcs on fsm2
+ for (ai2=al2 ; ai2 != NULL; ai2=ai2->next) {
+ a2 = &(ai2->arc);
+ if (a2->lower != gfsmEpsilon) break;
+
+ //-- eps: case fsm1:(q1), fsm2:(q2 --eps--> q2')
+ qid2 = gfsm_automaton_intersect_visit_((gfsmStatePair){sp.id1,a2->target},
+ fsm1, fsm2, fsm, spenum, flags);
+ if (qid2 != gfsmNoState)
+ gfsm_automaton_add_arc(fsm, qid, qid2, gfsmEpsilon, gfsmEpsilon, a2->weight);
+ }
+
+ //-- cleanup
+ if (flags&gfsmCFEfsm1NeedsArcSort) gfsm_arclist_free(al1);
+ if (flags&gfsmCFEfsm2NeedsArcSort) gfsm_arclist_free(al2);
+
+ return qid;
+}
+
+
+/*--------------------------------------------------------------
+ * invert()
+ */
+gfsmAutomaton *gfsm_automaton_invert(gfsmAutomaton *fsm)
+{
+ gfsmStateId id;
+ gfsmArcIter ai;
+ gfsmArcCompMask acmask_old=fsm->flags.sort_mode, acmask_new=gfsmACNone;;
+ gint aci;
+
+ //-- invert arcs
+ for (id=0; id < fsm->states->len; id++) {
+ for (gfsm_arciter_open(&ai,fsm,id); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ gfsmLabelId tmp = a->lower;
+ a->lower = a->upper;
+ a->upper = tmp;
+ }
+ }
+
+ //-- adjust sort mask (translate "lower"<->"upper")
+ for (aci=0; aci < gfsmACMaxN; aci++) {
+ gfsmArcCompMask cmp = gfsm_acmask_nth(acmask_old,aci);
+ switch (cmp) {
+ case gfsmACLower: cmp=gfsmACUpper; break;
+ case gfsmACUpper: cmp=gfsmACLower; break;
+ case gfsmACLowerR: cmp=gfsmACUpperR; break;
+ case gfsmACUpperR: cmp=gfsmACLowerR; break;
+ default: break;
+ }
+ acmask_new |= gfsm_acmask_new(cmp,aci);
+ }
+ fsm->flags.sort_mode = acmask_new;
+
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * optional()
+ */
+gfsmAutomaton *gfsm_automaton_optional(gfsmAutomaton *fsm)
+{
+ if (!gfsm_automaton_is_final_state(fsm,fsm->root_id))
+ gfsm_automaton_set_final_state_full(fsm,fsm->root_id,TRUE,fsm->sr->one);
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * product() (single-destructive)
+ */
+gfsmAutomaton *gfsm_automaton_product(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsmAutomaton *fsm2_tmp = gfsm_automaton_clone(fsm2);
+ gfsm_automaton_product2(fsm1,fsm2_tmp);
+ gfsm_automaton_free(fsm2_tmp);
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * _product() (dual-destructive)
+ */
+gfsmAutomaton *gfsm_automaton_product2(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsmStateId qid;
+ gfsmState *qp;
+ gfsmArcIter ai;
+ gfsmArc *a;
+
+ //-- chuck out all upper-labels from fsm1
+ for (qid=0; qid < fsm1->states->len; qid++) {
+ qp = gfsm_automaton_find_state(fsm1,qid);
+ if (!qp || !qp->is_valid) continue;
+ for (gfsm_arciter_open_ptr(&ai,fsm1,qp); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ a = gfsm_arciter_arc(&ai);
+ a->upper = gfsmEpsilon;
+ }
+ }
+
+ //-- chuck out all upper-labels from fsm2
+ for (qid=0; qid < fsm2->states->len; qid++) {
+ qp = gfsm_automaton_find_state(fsm2,qid);
+ if (!qp || !qp->is_valid) continue;
+ for (gfsm_arciter_open_ptr(&ai,fsm2,qp); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ a = gfsm_arciter_arc(&ai);
+ a->lower = gfsmEpsilon;
+ }
+ }
+
+ //-- concatenate
+ gfsm_automaton_concat(fsm1,fsm2);
+
+ //-- mark output fsm as transducer
+ fsm1->flags.is_transducer = 1;
+
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * project()
+ */
+gfsmAutomaton *gfsm_automaton_project(gfsmAutomaton *fsm, gfsmLabelSide which)
+{
+ gfsmStateId id;
+ gfsmArcIter ai;
+ if (which==gfsmLSBoth) return fsm;
+
+ for (id=0; id < fsm->states->len; id++) {
+ for (gfsm_arciter_open(&ai,fsm,id); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ if (which==gfsmLSLower) a->upper = a->lower;
+ else a->lower = a->upper;
+ }
+ }
+ fsm->flags.is_transducer = FALSE;
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * replace()
+ */
+gfsmAutomaton *gfsm_automaton_replace(gfsmAutomaton *fsm1, gfsmLabelVal lo, gfsmLabelVal hi, gfsmAutomaton *fsm2)
+{
+ gfsmStateId id;
+ gfsmArcIter ai;
+ gfsmStateId nstates = fsm1->states->len;
+
+ for (id=0; id < nstates; id++) {
+ if (!gfsm_automaton_has_state(fsm1,id)) continue;
+ for (gfsm_arciter_open(&ai,fsm1,id), gfsm_arciter_seek_both(&ai,lo,hi);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_seek_both(&ai,lo,hi))
+ {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ gfsm_automaton_insert_automaton(fsm1, id, a->target, fsm2, a->weight);
+ gfsm_arciter_remove(&ai); //-- implies gfsm_arciter_next()
+ }
+ //gfsm_arciter_close(&ai);
+ }
+
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * insert_automaton()
+ */
+gfsmAutomaton *gfsm_automaton_insert_automaton(gfsmAutomaton *fsm1,
+ gfsmStateId q1from,
+ gfsmStateId q1to,
+ gfsmAutomaton *fsm2,
+ gfsmWeight w)
+{
+ gfsmStateId offset;
+ gfsmStateId size2;
+ gfsmStateId id2;
+ gfsmStateId id1;
+ const gfsmState *s2;
+ gfsmState *s1;
+ gfsmArcIter ai;
+ gfsmWeight s2fw;
+
+ //-- reserve size
+ offset = fsm1->states->len;
+ size2 = fsm2->states->len;
+ gfsm_automaton_reserve(fsm1, offset + size2);
+
+ //-- avoid "smart" arc-insertion
+ fsm1->flags.sort_mode = gfsmASMNone;
+
+ //-- adopt states from fsm2 into fsm1
+ for (id2 = 0; id2 < size2; id2++) {
+
+ s2 = gfsm_automaton_find_state_const(fsm2,id2);
+ id1 = id2+offset;
+ s1 = gfsm_automaton_find_state(fsm1, id1);
+
+ //-- sanity check(s)
+ if (!s1 || !s2 || !s2->is_valid) continue;
+
+ //-- copy state
+ gfsm_state_copy(s1,s2);
+
+ //-- translate targets for adopted arcs
+ for (gfsm_arciter_open_ptr(&ai,fsm1,s1); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai))
+ {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ a->target += offset;
+ }
+
+ //-- check for fsm2-final states: get weight & add arc to our sink state
+ if (gfsm_weightmap_lookup(fsm2->finals, GUINT_TO_POINTER(id2), &s2fw)) {
+ s1->is_final = FALSE;
+ gfsm_automaton_add_arc(fsm1,id1,q1to,gfsmEpsilon,gfsmEpsilon, s2fw);
+ }
+ }
+
+ //-- add arc to new state
+ gfsm_automaton_add_arc(fsm1, q1from, fsm2->root_id+offset, gfsmEpsilon, gfsmEpsilon, w);
+
+ return fsm1;
+}
+
+/*--------------------------------------------------------------
+ * rmepsilon_foreach_func()
+ */
+static
+void gfsm_automaton_rmeps_pass2_foreach_func_(gfsmStatePair *sp, gpointer pw, gfsmAutomaton *fsm)
+{
+ gfsmWeight w = gfsm_ptr2weight(pw);
+ gfsmWeight fw2;
+ gfsmArcIter ai;
+ gfsmArc *a;
+ if (sp->id1==sp->id2) return; //-- sanity check
+
+ //-- adopt final weights (plus)
+ if (gfsm_automaton_lookup_final(fsm, sp->id2, &fw2)) {
+ gfsm_automaton_set_final_state_full(fsm, sp->id1, TRUE,
+ gfsm_sr_plus(fsm->sr,
+ gfsm_automaton_get_final_weight(fsm, sp->id1),
+ gfsm_sr_times(fsm->sr, w, fw2)));
+ }
+
+ //-- adopt non-epsilon arcs
+ for (gfsm_arciter_open(&ai,fsm,sp->id2); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ a = gfsm_arciter_arc(&ai);
+ if (a->lower != gfsmEpsilon || a->upper != gfsmEpsilon) {
+ gfsm_automaton_add_arc(fsm, sp->id1, a->target, a->lower, a->upper,
+ gfsm_sr_times(fsm->sr, a->weight, w));
+ }
+ }
+}
+
+/*--------------------------------------------------------------
+ * rmepsilon()
+ */
+gfsmAutomaton *gfsm_automaton_rmepsilon(gfsmAutomaton *fsm)
+{
+ gfsmStatePair2WeightHash *sp2wh = gfsm_statepair2weighthash_new();
+ gfsmArcIter ai;
+ gfsmStateId qid;
+ gfsmArc *a;
+
+ //-- pass-1: populate sp2wh with epsilon-reachable states
+ for (qid=0; qid < fsm->states->len; qid++) {
+ gfsm_automaton_rmeps_visit_state_(fsm, qid, qid, fsm->sr->one, sp2wh);
+ }
+
+ //-- pass-2: adopt non-epsilon arcs & final weights from eps-reachable states
+ gfsm_weighthash_foreach(sp2wh, (GHFunc)gfsm_automaton_rmeps_pass2_foreach_func_, fsm);
+
+ //-- pass-3: actual removal of now-redundant epsilon arcs
+ for (qid=0; qid < fsm->states->len; qid++) {
+ for (gfsm_arciter_open(&ai,fsm,qid); gfsm_arciter_ok(&ai); ) {
+ a = gfsm_arciter_arc(&ai);
+ if (a->lower==gfsmEpsilon && a->upper==gfsmEpsilon) {
+ gfsm_arciter_remove(&ai);
+ } else {
+ gfsm_arciter_next(&ai);
+ }
+ }
+ }
+
+ //-- cleanup
+ gfsm_weighthash_free(sp2wh);
+
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * rmepsilon_visit_state()
+ */
+void gfsm_automaton_rmeps_visit_state_(gfsmAutomaton *fsm,
+ gfsmStateId qid_noeps, //-- state reachable by non-eps arcs
+ gfsmStateId qid_eps, //-- eps-reachable state from qid_noeps
+ gfsmWeight weight_eps, //-- total weight of followed eps-arcs
+ gfsmStatePair2WeightHash *sp2wh //-- maps (qid_noeps,qid_noeps)=>sum_weight_eps
+ )
+{
+ gfsmState *q_noeps, *q_eps;
+ gfsmStatePair sp = {qid_noeps,qid_eps};
+ gfsmArcIter ai;
+ gfsmArc *a;
+
+ //-- visited check, mark
+ if (!gfsm_weighthash_insert_sum_if_less(sp2wh, &sp, weight_eps, fsm->sr))
+ return; //-- no update required
+
+ //-- sanity check
+ q_noeps = gfsm_automaton_find_state(fsm,qid_noeps);
+ q_eps = gfsm_automaton_find_state(fsm,qid_eps);
+ if (!q_noeps || !q_noeps->is_valid || !q_eps || !q_eps->is_valid) return;
+
+ //-- visit epsilon-reachable states from q_eps
+ for (gfsm_arciter_open_ptr(&ai, fsm, q_eps), gfsm_arciter_seek_both(&ai,gfsmEpsilon,gfsmEpsilon);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_both(&ai,gfsmEpsilon,gfsmEpsilon))
+ {
+ a = gfsm_arciter_arc(&ai);
+ gfsm_automaton_rmeps_visit_state_(fsm, qid_noeps, a->target,
+ gfsm_sr_times(fsm->sr, weight_eps, a->weight),
+ sp2wh);
+ }
+}
+
+
+/*--------------------------------------------------------------
+ * reverse()
+ */
+gfsmAutomaton *gfsm_automaton_reverse(gfsmAutomaton *fsm)
+{
+ gfsmStateId new_root = gfsm_automaton_add_state(fsm);
+ gfsmStateId id;
+ gfsmState *s, *ts;
+ gfsmArcList *al, *al_next, *al_prev;
+ gfsmWeight w;
+ //gfsmArcSortMode sm = gfsm_automaton_sortmode(fsm);
+
+ //-- mark automaton as unsorted (avoid "smart" arc-insertion)
+ fsm->flags.sort_mode = gfsmASMNone;
+
+ //-- reverse arc directions, keeping old "source" and "target" values
+ // intact as sentinels
+ for (id = 0; id < new_root; id++) {
+ s = gfsm_automaton_find_state(fsm,id);
+ if (!s || !s->is_valid) continue;
+
+ //-- check for old final states
+ if (gfsm_automaton_lookup_final(fsm,id,&w)) {
+ s->is_final = FALSE;
+ gfsm_weightmap_remove(fsm->finals, GUINT_TO_POINTER(id));
+ gfsm_automaton_add_arc(fsm, new_root, id, gfsmEpsilon, gfsmEpsilon, w);
+ }
+
+ //-- reverse arcs
+ for (al_prev=NULL, al=s->arcs; al != NULL; al=al_next) {
+ gfsmArc *a = gfsm_arclist_arc(al);
+ al_next = al->next;
+ if (a->target==id) {
+ //-- already reversed (or a single-arc loop, which doesn't need reversal)
+ al_prev = al;
+ continue;
+ }
+
+ //-- steal arc
+ if (al_prev) al_prev->next = al->next;
+ else s->arcs = al->next;
+ al->next = NULL;
+
+ //-- move arc
+ ts = gfsm_automaton_find_state(fsm,a->target);
+ gfsm_automaton_add_arc_node(fsm, ts, al);
+ }
+ }
+
+ //-- sanitize: swap 'source' and 'target' fields
+ for (id=0; id < new_root; id++) {
+ gfsmArcIter ai;
+ for (gfsm_arciter_open(&ai,fsm,id); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ gfsmStateId tmp = a->target;
+ a->target = a->source;
+ a->source = tmp;
+ }
+ }
+
+ //-- root flop
+ gfsm_automaton_set_final_state_full(fsm,fsm->root_id,TRUE,fsm->sr->one);
+ fsm->root_id = new_root;
+
+ return fsm;
+}
+
+#if 0
+gfsmAutomaton *gfsm_automaton_reverse_old(gfsmAutomaton *fsm)
+{
+ gfsmStateId new_root = gfsm_automaton_add_state(fsm);
+ gfsmStateId id;
+ gfsmState *s, *ts;
+ gfsmArcList *al, *al_next, *al_prev;
+ gfsmWeight w;
+ //gfsmArcSortMode sm = gfsm_automaton_sortmode(fsm);
+
+ //-- mark automaton as unsorted (avoid "smart" arc-insertion)
+ fsm->flags.sort_mode = gfsmASMNone;
+
+ //-- reverse arc directions, assigning reversed arcs 'target' values as 'old_src+new_root'
+ for (id = 0; id < new_root; id++) {
+ s = gfsm_automaton_find_state(fsm,id);
+ if (!s || !s->is_valid) continue;
+
+ //-- check for old final states
+ if (gfsm_automaton_lookup_final(fsm,id,&w)) {
+ s->is_final = FALSE;
+ gfsm_weightmap_remove(fsm->finals, GUINT_TO_POINTER(id));
+ gfsm_automaton_add_arc(fsm, new_root, id, gfsmEpsilon, gfsmEpsilon, w);
+ }
+
+ //-- reverse arcs
+ for (al_prev=NULL, al=s->arcs; al != NULL; al=al_next) {
+ gfsmArc *a = gfsm_arclist_arc(al);
+ al_next = al->next;
+ if (a->target >= new_root) {
+ //-- already moved
+ al_prev = al;
+ continue;
+ }
+
+ //-- steal arc
+ if (al_prev) al_prev->next = al->next;
+ else s->arcs = al->next;
+ al->next = NULL;
+
+ //-- move arc
+ ts = gfsm_automaton_find_state(fsm,a->target);
+ gfsm_automaton_add_arc_link(fsm, ts, al);
+
+ //-- flag as reversed
+ a->target = id + new_root;
+ }
+ }
+
+ //-- sanitize
+ for (id=0; id < new_root; id++) {
+ gfsmArcIter ai;
+ for (gfsm_arciter_open(&ai,fsm,id); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ a->target -= new_root;
+ }
+ }
+
+ //-- root flop
+ gfsm_automaton_set_final_state_full(fsm,fsm->root_id,TRUE,fsm->sr->one);
+ fsm->root_id = new_root;
+
+ return fsm;
+}
+#endif
+
+/*--------------------------------------------------------------
+ * sigma()
+ */
+gboolean gfsm_automaton_sigma_foreach_func_(gfsmAlphabet *abet, gpointer key, gfsmLabelVal lab, gfsmAutomaton *fsm)
+{
+ gfsm_automaton_add_arc(fsm,0,1,lab,lab,fsm->sr->one);
+ return FALSE;
+}
+
+gfsmAutomaton *gfsm_automaton_sigma(gfsmAutomaton *fsm, gfsmAlphabet *abet)
+{
+ gfsm_automaton_clear(fsm);
+ fsm->flags.sort_mode = gfsmASMNone; //-- avoid "smart" arc-insertion
+ fsm->root_id = gfsm_automaton_add_state_full(fsm,0);
+ gfsm_automaton_add_state_full(fsm,1);
+ gfsm_automaton_set_final_state_full(fsm,1,TRUE,fsm->sr->one);
+ gfsm_alphabet_foreach(abet, (gfsmAlphabetForeachFunc)gfsm_automaton_sigma_foreach_func_, fsm);
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * union_()
+ */
+gfsmAutomaton *gfsm_automaton_union(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsmStateId offset;
+ gfsmStateId id2;
+ gfsmStateId oldroot1;
+ gfsmArcCompData sortdata = {0,0,0,0};
+
+ //-- sanity check
+ if (!fsm2 || fsm2->root_id==gfsmNoState) return fsm1;
+
+ offset = fsm1->states->len + 1;
+ gfsm_automaton_reserve(fsm1, offset + fsm2->states->len);
+
+
+ //-- add new root and eps-arc to old root for fsm1
+ oldroot1 = fsm1->root_id;
+ fsm1->root_id = gfsm_automaton_add_state(fsm1);
+ if (oldroot1 != gfsmNoState) {
+ gfsm_automaton_add_arc(fsm1, fsm1->root_id, oldroot1, gfsmEpsilon, gfsmEpsilon, fsm1->sr->one);
+ }
+
+ //-- avoid "smart" arc-insertion (temporary)
+ sortdata.mask = fsm1->flags.sort_mode;
+ sortdata.sr = fsm1->sr;
+ fsm1->flags.sort_mode = gfsmASMNone;
+
+ //-- adopt states from fsm2 into fsm1
+ for (id2 = 0; id2 < fsm2->states->len; id2++) {
+ const gfsmState *s2 = gfsm_automaton_find_state_const(fsm2,id2);
+ gfsmState *s1 = gfsm_automaton_find_state(fsm1,id2+offset);
+ gfsmArcIter ai;
+ gfsm_state_copy(s1,s2);
+ for (gfsm_arciter_open_ptr(&ai, fsm1, s1); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ a->target += offset;
+ }
+ //-- index final states from @fsm2
+ if (s2->is_final) {
+ gfsm_automaton_set_final_state_full(fsm1, id2+offset, TRUE, gfsm_automaton_get_final_weight(fsm2, id2));
+ }
+ //-- maybe sort new arcs
+ if (sortdata.mask != gfsmASMNone
+ && (fsm2->flags.sort_mode != sortdata.mask
+ || (sortdata.mask == gfsmASMWeight && fsm2->sr->type != fsm1->sr->type)))
+ {
+ s1->arcs = gfsm_arclist_sort(s1->arcs, &sortdata);
+ }
+ }
+
+ //-- re-instate "smart" arc-insertion
+ fsm1->flags.sort_mode = sortdata.mask;
+
+ //-- add epsilon arc to translated root(fsm2) in fsm1
+ gfsm_automaton_add_arc(fsm1,
+ fsm1->root_id,
+ offset + fsm2->root_id,
+ gfsmEpsilon,
+ gfsmEpsilon,
+ fsm1->sr->one);
+
+ return fsm1;
+}
+
+
+/*--------------------------------------------------------------
+ * dummy()
+ */
+gfsmAutomaton *gfsm_automaton_dummy(gfsmAutomaton *fsm)
+{
+ g_assert_not_reached(); /*-- NOT gfsm_assert_not_reached() ! */
+ return fsm;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAlgebra.h b/gfsm/gfsm/src/libgfsm/gfsmAlgebra.h
new file mode 100644
index 0000000..301bec1
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAlgebra.h
@@ -0,0 +1,559 @@
+
+/*=============================================================================*\
+ * File: gfsmAlgebra.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmAlgebra.h
+ * \brief Algebraic operations on automata
+ */
+
+#ifndef _GFSM_ALGEBRA_H
+#define _GFSM_ALGEBRA_H
+
+#include <gfsmStateSet.h>
+#include <gfsmCompound.h>
+#include <gfsmArcIter.h>
+#include <gfsmArcIndex.h>
+
+/*======================================================================
+ * Methods: algebra
+ */
+
+//------------------------------
+///\name Closure (self-concatenation)
+//@{
+/** Compute transitive or reflexive-\&-transitive
+ * closure of \a fsm.
+ * \note Destructively alters \a fsm .
+ *
+ * \param fsm Automaton
+ * \param is_plus Which type of closure to compute:
+ * \arg TRUE transitive closure
+ * \arg FALSE reflexive \& transitive closure
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_closure(gfsmAutomaton *fsm, gboolean is_plus);
+
+/* Final-state pre-traversal utility for \c closure(fsm). */
+//gboolean gfsm_automaton_closure_final_func_(gfsmStateId id, gpointer pw, gfsmAutomaton *fsm);
+
+/** Compute \a n-ary closure of \a fsm.
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Automaton
+ * \param n Number of repetitions
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_n_closure(gfsmAutomaton *fsm, guint n);
+//@}
+
+
+//------------------------------
+///\name Complementation and Completion
+//@{
+/**
+ * Compute the lower-side complement of \a fsm with respect to its own lower alphabet.
+ * \note Destructively alters \a fsm
+ *
+ * \param fsm Acceptor
+ * \returns \a fsm.
+ */
+gfsmAutomaton *gfsm_automaton_complement(gfsmAutomaton *fsm);
+
+/**
+ * Compute the lower-side complement of \a fsm with respect to the alphabet \a alph,
+ * which should contain all of the lower-labels from \a fsm.
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Acceptor
+ * \param alph Alphabet with respect to which to compute complement.
+ * \returns \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_complement_full(gfsmAutomaton *fsm, gfsmAlphabet *alph);
+
+/**
+ * Complete the lower side of automaton \a fsm with respect to the alphabet \a alph
+ * by directing "missing" arcs to the (new) state with id \a *sink.
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Acceptor
+ * \param alpha Alphabet with respect to which \a fsm is to be completed
+ * \param sinkp Pointer to a variable which on completion contains the Id of a (new) non-final sink state
+ * \returns \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_complete(gfsmAutomaton *fsm,
+ gfsmAlphabet *alph,
+ gfsmStateId *sinkp);
+//@}
+
+//------------------------------
+///\name Composition
+//@{
+
+/** Compute the composition of \a fsm1 with \a fsm2
+ * (upper-side of \a fsm1 intersection with lower-side of \a fsm2).
+ *
+ * \param fsm1 Lower-middle transducer
+ * \param fsm2 Middle-upper transducer
+ * \returns Altered \a fsm1
+ *
+ * \note
+ * \li Pseudo-destructive on \a fsm1.
+ * \li Runtime efficiency can be greatly improved if
+ * \a fsm1 is sorted on upper labels (::gfsmASMUpper)
+ * and \a fsm2 is sorted on lower labels (::gfsmASMLower).
+ *
+ * \sa gfsm_automaton_compose_full()
+ */
+gfsmAutomaton *gfsm_automaton_compose(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2);
+
+
+/** Compute the composition of two transducers \a fsm1 and \a fsm2
+ * into the transducer \a composition.
+ *
+ * \param fsm1 Lower-middle transducer
+ * \param fsm2 Middle-upper transducer
+ * \param composition Lower-upper transducer. May be passed as NULL to create a new automaton.
+ * \param spenum
+ * Mapping from (\a fsm1,\a fsm2,\a filter) ::gfsmComposeState s to \a composition (::gfsmStateId)s,
+ * if it is passed as \a NULL, a temporary enum will be created and freed.
+ *
+ * \sa Mohri, Pereira, and Riley (1996) "Weighted Automata in Text and Speech Processing",
+ * Proc. ECAI '96, John Wiley & Sons, Ltd.
+ *
+ * \returns \a composition
+ */
+gfsmAutomaton *gfsm_automaton_compose_full(gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *composition,
+ gfsmComposeStateEnum *spenum);
+
+typedef guint32 gfsmComposeFlags; /**< flags for gfsm_automaton_compose_visit_state_() */
+
+/** \brief Enum type for low-level flags to gfsm_automaton_compose_visit_state_() */
+typedef enum {
+ gfsmCFEfsm1NeedsArcSort = 0x1,
+ gfsmCFEfsm2NeedsArcSort = 0x2
+} gfsmComposeFlagsE;
+
+/** Guts for gfsm_automaton_compose() \returns (new) StateId for \a sp */
+gfsmStateId gfsm_automaton_compose_visit_(gfsmComposeState sp,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *fsm,
+ gfsmComposeStateEnum *spenum,
+ gfsmComposeFlags flags);
+//@}
+
+//------------------------------
+///\name Concatenation
+
+/** Append \a fsm2 onto the end of \a fsm1 \a n times.
+ * \note Destructively alters \a fsm1.
+ *
+ * \param fsm1 Automaton
+ * \param fsm2 Automaton
+ * \returns \a fsm1
+ */
+gfsmAutomaton *gfsm_automaton_n_concat(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2, guint n);
+
+/** Append \a _fsm2 onto the end of \a fsm1.
+ * \note Destructively alters \a fsm1.
+ *
+ * \param fsm1 Automaton
+ * \param fsm2 Automaton
+ * \returns \a fsm1
+ */
+gfsmAutomaton *gfsm_automaton_concat(gfsmAutomaton *fsm1, gfsmAutomaton *_fsm2);
+
+/* Final-state pre-traversal utility for \a concat(fsm,fsm2).
+ *
+ * \note Assumes \a fsm->root_id has been temporarily set to the translated gfsmStateId
+ * of \a fsm2->root_id.
+ *
+ * \param pw final ::gfsmWeight encoded as a gpointer (e.g. with gfsm_weight2ptr())
+ * \param fsm concatenation first argument / return value
+ * \returns FALSE
+ */
+//gboolean gfsm_automaton_concat_final_func_(gfsmStateId id, gpointer pw, gfsmAutomaton *fsm);
+
+//@}
+
+//------------------------------
+///\name Co-Accessibility & Pruning
+//@{
+
+/**
+ * Remove non-coaccessible states from \a fsm.
+ * Calls gfsm_automaton_connect_fw() and gfsm_automaton_connect_bw()
+ * \note Destructively alters \a fsm
+ *
+ * \param fsm Automaton
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_connect(gfsmAutomaton *fsm);
+
+//------------------------------
+/**
+ * Remove non root-accessible states from \a fsm.
+ * Called by gfsm_automaton_connect()
+ *
+ * \note Destructively alters \a fsm
+ *
+ * \param fsm Automaton
+ * \param visited
+ * Bit-vector for traversal. Should have all bits set to zero.
+ * If passed as NULL, a new bit-vector will be created and freed.
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_connect_fw(gfsmAutomaton *fsm, gfsmBitVector *visited);
+
+//------------------------------
+/**
+ * Remove non-finalizable states from \a fsm.
+ * Called by connect().
+ * \note Destructively alters \a fsm
+ *
+ * \param fsm Automaton
+ * \param rarcs
+ * Reverse arc-index as returned by gfsm_automaton_reverse_arc_index().
+ * If passed as NULL, gfsm_automaton_reverse_arc_index() will be called
+ * on a temporary arc index.
+ * \param finalizable
+ * Bit-vector for traversal. Should have all bits set to zero.
+ * If passed as NULL, a new bit-vector will be created and freed.
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_connect_bw(gfsmAutomaton *fsm,
+ gfsmReverseArcIndex *rarcs,
+ gfsmBitVector *finalizable);
+
+//------------------------------
+/**
+ * Utility for gfsm_automaton_connect_fw() and gfsm_automaton_connect_bw().
+ * Prunes states from \a fsm whose id bit is not set in \a want
+ *
+ * \param fsm Automaton
+ * \param wanted
+ * Bit-vector indexed by state id: bit \a id should be unset
+ * iff state \a id is to be removed.
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_prune_states(gfsmAutomaton *fsm, gfsmBitVector *wanted);
+
+//@}
+
+//------------------------------
+///\name Determinization
+//@{
+
+/** Utility for \a gfsm_automaton_determinize(). */
+void gfsm_determinize_visit_state_(gfsmAutomaton *nfa, gfsmAutomaton *dfa,
+ gfsmStateSet *nfa_ec, gfsmStateId dfa_id,
+ gfsmEnum *ec2id);
+
+/** Determinize acceptor \a fsm
+ *
+ * - Pseudo-destructive on \a fsm
+ * - Epsilon is treated like any other symbol.
+ * - Arc labels are treated as (input,output) pairs for purposes
+ * of state-equivalence-class construction: this may not be what you want.
+ * .
+ *
+ * \param fsm Automaton
+ * \returns altered \a fsm
+ *
+ * \sa gfsm_automaton_determinize_full()
+ */
+gfsmAutomaton *gfsm_automaton_determinize(gfsmAutomaton *fsm);
+
+/** Alias for gfsm_automaton_determinize() */
+#define gfsm_automaton_determinise(fsm) gfsm_automaton_determinize(fsm)
+
+/** Alias for gfsm_automaton_determinize_full() */
+#define gfsm_automaton_determinise_full(nfa,dfa) gfsm_automaton_determinize_full((nfa),(dfa))
+
+/** Determinize automaton \a nfa to \a dfa.
+ * - Epsilon is treated like any other symbol.
+ * - Arc labels are treated as (input,output) pairs.
+ * .
+ *
+ * \param nfa non-deterministic acceptor
+ * \param dfa deterministic acceptor to be constructed
+ * May be passed as \c NULL to create a new automaton.
+ * \returns \a dfa
+ */
+gfsmAutomaton *gfsm_automaton_determinize_full(gfsmAutomaton *nfa, gfsmAutomaton *dfa);
+
+//@}
+
+//------------------------------
+///\name Difference
+//@{
+
+/** Remove language of acceptor \a fsm2 from acceptor \a fsm1.
+ *
+ * - Pseudo-destructively alters \a fsm1.
+ * - Really just an alias for intersect_full(fsm1,fsm2,NULL)
+ * .
+ *
+ * \param fsm1 Acceptor
+ * \param fsm2 Acceptor
+ * \returns \a fsm1
+ */
+gfsmAutomaton *gfsm_automaton_difference(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2);
+
+/** Compute difference of acceptors (\a fsm1 - \a fsm2) into acceptor \a diff-
+ *
+ * \note Really just an alias for intersect_full(fsm1,complement(clone(fsm2)),diff).
+ *
+ * \param fsm1 Acceptor
+ * \param fsm2 Acceptor
+ * \param diff Output (difference) acceptor,
+ * may be passed as \c NULL to implicitly create a new automaton.
+ *
+ * \returns (possibly new) difference automaton \a diff
+ */
+gfsmAutomaton *gfsm_automaton_difference_full(gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *diff);
+
+//@}
+
+//------------------------------
+///\name Intersection
+//@{
+/** Compute the intersection of two acceptors \a fsm1 and \a fsm2 (lower-side intersection).
+ * \note Pseudo-destructive on \a fsm1.
+ *
+ * \param fsm1 Acceptor
+ * \param fsm2 Acceptor
+ * \returns \a fsm1.
+ */
+gfsmAutomaton *gfsm_automaton_intersect(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2);
+
+/** Compute the intersection of two acceptors \a fsm1 and \a fsm2
+ * into the acceptor \a intersect.
+ *
+ * \param fsm1 Acceptor
+ * \param fsm2 Acceptor
+ * \param intersect Output acceptor, may be \c NULL to create a new automaton.
+ * \param spenum Mapping from (\a fsm1,\a fsm2) (::gfsmStatePair)s to \a intersect (::gfsmStateId)s,
+ * may be NULL to use a temporary mapping.
+ * \returns \a intersect.
+ */
+gfsmAutomaton *gfsm_automaton_intersect_full(gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *intersect,
+ gfsmStatePairEnum *spenum);
+
+/** Guts for gfsm_automaton_intersect()
+ * \returns (new) ::gfsmStateId for \a sp
+ */
+gfsmStateId gfsm_automaton_intersect_visit_(gfsmStatePair sp,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2,
+ gfsmAutomaton *fsm,
+ gfsmStatePairEnum *spenum,
+ gfsmComposeFlags flags);
+//@}
+
+
+//------------------------------
+///\name Inversion & Projection
+//@{
+/** Invert upper and lower labels of an automaton.
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Transducer
+ * \returns \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_invert(gfsmAutomaton *fsm);
+
+//------------------------------
+/** Project one "side" (lower or upper) of \a fsm
+ * \note Destructively alters \a fsm
+ *
+ * \param fsm Transducer
+ * \param which Which label side to project.
+ * \arg gfsmLSLower project lower side
+ * \arg gfsmLSUpper project upper side (default)
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_project(gfsmAutomaton *fsm, gfsmLabelSide which);
+
+//@}
+
+//------------------------------
+///\name Optionality
+//@{
+/** Make \a fsm optional.
+ * \note Destructively alters \a fsm
+ *
+ * \param fsm Automaton
+ * \returns \a modified fsm
+ */
+gfsmAutomaton *gfsm_automaton_optional(gfsmAutomaton *fsm);
+
+//@}
+
+//------------------------------
+///\name Cartesian Product
+//@{
+/** Compute Cartesian product of acceptors \a fsm1 and \a fsm2.
+ * \note Destructively alters \a fsm1.
+ *
+ * \param fsm1 Acceptor (lower)
+ * \param fsm2 Acceptor (upper)
+ * \returns \a fsm1 (transducer)
+ *
+ * \sa gfsm_automaton_product2()
+ */
+gfsmAutomaton *gfsm_automaton_product(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2);
+
+/** Compute Cartesian product of acceptors \a fsm1 and \a fsm2.
+ * \note Destructively alters \a fsm1 \b and \a fsm2.
+ *
+ * \param fsm1 Acceptor (lower)
+ * \param fsm2 Acceptor (upper)
+ * \returns \a fsm1
+ */
+gfsmAutomaton *gfsm_automaton_product2(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2);
+
+/* Backwards-compatible alias for gfsm_automaton_product2() [DISABLED] */
+//#define _gfsm_automaton_product gfsm_automaton_product2
+
+//@}
+
+
+//------------------------------
+///\name Replacement
+//@{
+/** Replace label-pair \a (lo,hi) with \a fsm2 in \a fsm1 .
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm1 Automaton
+ * \param lo lower label or gfsmNoLabel to ignore lower labels
+ * \param hi upper label or gfsmNoLabel to ignore upper labels
+ * \returns modified \a fsm1
+ */
+gfsmAutomaton *gfsm_automaton_replace(gfsmAutomaton *fsm1, gfsmLabelVal lo, gfsmLabelVal hi, gfsmAutomaton *fsm2);
+
+/** Insert automaton \a fsm2 into \a fsm1 between states \a q1from and \a q1to with weight \a w.
+ * \note Destructively alters \a fsm1.
+ *
+ * \param fsm1 Automaton into which \a fsm2 is inserted
+ * \param fsm2 Automaton to be inserted
+ * \param q1from Source state for inserted automaton in \a fsm1
+ * \param q1to Final state for inserted automaton in \a fsm1
+ * \param w Weight to add to final arcs for translated \a fsm2 in \a fsm1
+ * \returns modified \a fsm1
+ */
+gfsmAutomaton *gfsm_automaton_insert_automaton(gfsmAutomaton *fsm1,
+ gfsmStateId q1from,
+ gfsmStateId q1to,
+ gfsmAutomaton *fsm2,
+ gfsmWeight w);
+
+//@}
+
+
+//------------------------------
+///\name Reversal
+//@{
+/** Reverse an automaton \a fsm.
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Automaton
+ * \returns \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_reverse(gfsmAutomaton *fsm);
+
+//@}
+
+//------------------------------
+///\name Epsilon Removal
+//@{
+/**
+ * Remove epsilon arcs from \a fsm.
+ * - Destructively alters \a fsm.
+ * - Multiple epsilon-paths between two states may not be weighted correctly in the output automaton.
+ * .
+ *
+ * \warning negative-cost epsilon cycles in \a fsm will cause infinite recursion!
+ *
+ * \param fsm Automaton
+ * \returns \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_rmepsilon(gfsmAutomaton *fsm);
+
+/** Pass-1 guts for gfsm_automaton_rmepsilon(): populates the mapping \a sp2wh
+ * with state-pairs (qid_noeps,qid_eps)=>weight for all
+ * \a qid_eps epsilon-reachable from \a qid_noeps in \a fsm
+ */
+void gfsm_automaton_rmeps_visit_state_(gfsmAutomaton *fsm,
+ gfsmStateId qid_noeps,
+ gfsmStateId qid_eps,
+ gfsmWeight weight_eps,
+ gfsmStatePair2WeightHash *sp2wh
+ );
+
+/* Pass-2 for gfsm_automaton_rmepsilon(): arc-adoption iterator */
+//void gfsm_automaton_rmeps_pass2_foreach_func_(gfsmStatePair *sp, gpointer pw, gfsmAutomaton *fsm);
+//@}
+
+//------------------------------
+///\name Alphabet Recognizer
+//@{
+/**
+ * Make \a fsm an identity-transducer for alphabet \a abet
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Automaton
+ * \returns \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_sigma(gfsmAutomaton *fsm, gfsmAlphabet *abet);
+//@}
+
+//------------------------------
+///\name Union
+//@{
+/** Add the language or relation of \a fsm2 to \a fsm1.
+ * \note Destructively alters \a fsm1
+ *
+ * \param fsm1 Automaton
+ * \param fsm2 Automaton
+ * \returns \a fsm1
+ */
+gfsmAutomaton *gfsm_automaton_union(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2);
+//@}
+
+/** \file gfsmAlgebra.h
+ * \todo sigma()
+ * \todo bestpath()
+ * \todo encode() ?
+ * \todo equiv() ?
+ * \todo minimize() ?
+ * \todo Regex compiler
+ * \todo deterministic union, tries
+ */
+
+#endif /* _GFSM_ALGEBRA_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAlphabet.c b/gfsm/gfsm/src/libgfsm/gfsmAlphabet.c
new file mode 100644
index 0000000..078f176
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAlphabet.c
@@ -0,0 +1,1026 @@
+/*=============================================================================*\
+ * File: gfsmAlphabet.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: alphabet
+ *
+ * Copyright (c) 2004-2008 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmAlphabet.h>
+#include <gfsmSet.h>
+#include <gfsmUtils.h>
+#include <gfsmError.h>
+
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*======================================================================
+ * Constants
+ */
+gfsmUserAlphabetMethods gfsmUserAlphabetDefaultMethods =
+ {
+ NULL, //-- key_lookup
+ NULL, //-- lab_lookup
+ NULL, //-- insert
+ //NULL, //-- key_remove
+ NULL, //-- lab_remove
+ NULL, //-- key_read
+ NULL //-- key_write
+ };
+
+/*======================================================================
+ * Methods: Constructors
+ */
+
+/*--------------------------------------------------------------
+ * new()
+ */
+gfsmAlphabet *gfsm_alphabet_new(gfsmAType type)
+{
+ gfsmAlphabet *a=NULL;
+ switch (type) {
+ case gfsmATIdentity:
+ a = (gfsmAlphabet*)g_new0(gfsmIdentityAlphabet,1);
+ break;
+ case gfsmATPointer:
+ a = (gfsmAlphabet*)g_new0(gfsmPointerAlphabet,1);
+ break;
+ case gfsmATUser:
+ a = (gfsmAlphabet*)g_new0(gfsmUserAlphabet,1);
+ break;
+ case gfsmATString:
+ a = (gfsmAlphabet*)g_new0(gfsmStringAlphabet,1);
+ break;
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ a = (gfsmAlphabet*)g_new0(gfsmRangeAlphabet,1);
+ break;
+ }
+ a->type = type;
+ a->lab_min = gfsmNoLabel;
+ a->lab_max = gfsmNoLabel;
+ return a;
+}
+
+/*--------------------------------------------------------------
+ * string_new()
+ */
+/*gfsmAlphabet *gfsm_string_alphabet_new(void)
+{
+ return gfsm_string_alphabet_init(g_new(gfsmStringAlphabet,1));
+ }
+*/
+
+/*--------------------------------------------------------------
+ * init()
+ */
+gfsmAlphabet *gfsm_alphabet_init(gfsmAlphabet *a)
+{
+ if (!a) return NULL;
+
+ a->lab_min = gfsmNoLabel;
+ a->lab_max = gfsmNoLabel;
+
+ switch (a->type) {
+ case gfsmATIdentity:
+ return gfsm_identity_alphabet_init((gfsmIdentityAlphabet*)a);
+ case gfsmATPointer:
+ return gfsm_pointer_alphabet_init((gfsmPointerAlphabet*)a,NULL,NULL,NULL,NULL);
+ case gfsmATUser:
+ return gfsm_user_alphabet_init((gfsmUserAlphabet*)a,NULL,NULL,NULL,NULL,
+ NULL,&gfsmUserAlphabetDefaultMethods);
+ case gfsmATString:
+ return gfsm_string_alphabet_init((gfsmStringAlphabet*)a,FALSE);
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ break;
+ }
+ return a;
+}
+
+/*--------------------------------------------------------------
+ * range_init()
+ */
+gfsmAlphabet *gfsm_range_alphabet_init (gfsmRangeAlphabet *a, gfsmLabelVal min, gfsmLabelVal max)
+{
+ a->lab_min = min;
+ a->lab_max = max;
+ return a;
+}
+
+/*--------------------------------------------------------------
+ * identity_init()
+ */
+gfsmAlphabet *gfsm_identity_alphabet_init (gfsmIdentityAlphabet *a)
+{
+ gfsm_range_alphabet_init((gfsmRangeAlphabet*)a, gfsmNoLabel, gfsmNoLabel);
+ if (!a->labels) a->labels = gfsm_set_new(gfsm_uint_compare);
+ gfsm_set_clear(a->labels);
+ return (gfsmAlphabet*)a;
+}
+
+/*--------------------------------------------------------------
+ * pointer_init()
+ */
+gfsmAlphabet *gfsm_pointer_alphabet_init(gfsmPointerAlphabet *a,
+ gfsmAlphabetKeyDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_free_func)
+{
+ gfsm_range_alphabet_init((gfsmRangeAlphabet*)a,gfsmNoLabel,gfsmNoLabel);
+
+ if (a->keys2labels) g_hash_table_destroy(a->keys2labels);
+ if (a->labels2keys) g_ptr_array_free(a->labels2keys,TRUE);
+
+ a->keys2labels = g_hash_table_new_full(key_hash_func, key_equal_func, key_free_func, NULL);
+ a->labels2keys = g_ptr_array_new();
+ a->key_dup_func = key_dup_func;
+
+ return (gfsmAlphabet*)a;
+}
+
+/*--------------------------------------------------------------
+ * string_init()
+ */
+gfsmAlphabet *gfsm_string_alphabet_init(gfsmStringAlphabet *a, gboolean do_copy)
+{
+ if (do_copy)
+ return gfsm_pointer_alphabet_init(a,
+ (gfsmAlphabetKeyDupFunc)gfsm_alphabet_strdup,
+ g_str_hash, g_str_equal, g_free);
+ return gfsm_pointer_alphabet_init(a, NULL, g_str_hash, g_str_equal, NULL);
+}
+
+/*--------------------------------------------------------------
+ * user_init()
+ */
+gfsmAlphabet *gfsm_user_alphabet_init(gfsmUserAlphabet *a,
+ gfsmAlphabetKeyDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func,
+ gpointer user_data,
+ gfsmUserAlphabetMethods *methods)
+{
+ gfsm_pointer_alphabet_init((gfsmPointerAlphabet*)a,
+ key_dup_func,
+ key_hash_func,
+ key_equal_func,
+ key_destroy_func);
+ a->data = user_data;
+ a->methods = methods ? (*methods) : gfsmUserAlphabetDefaultMethods;
+ return (gfsmAlphabet*)a;
+}
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+void gfsm_alphabet_clear(gfsmAlphabet *a)
+{
+ switch (a->type) {
+ case gfsmATUnknown:
+ case gfsmATRange:
+ break;
+ case gfsmATIdentity:
+ gfsm_set_clear(((gfsmIdentityAlphabet*)a)->labels);
+ break;
+ case gfsmATPointer:
+ case gfsmATString:
+ g_ptr_array_set_size(((gfsmPointerAlphabet*)a)->labels2keys,0);
+ g_hash_table_foreach_remove(((gfsmPointerAlphabet*)a)->keys2labels, gfsm_hash_clear_func, NULL);
+ break;
+ case gfsmATUser:
+ default:
+ gfsm_alphabet_foreach(a, gfsm_alphabet_foreach_remove_func, NULL);
+ g_ptr_array_set_size(((gfsmPointerAlphabet*)a)->labels2keys,0);
+ break;
+ }
+
+ a->lab_min = gfsmNoLabel;
+ a->lab_max = gfsmNoLabel;
+}
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_foreach_remove_func()
+ */
+gboolean gfsm_alphabet_foreach_remove_func(gfsmAlphabet *a,
+ gpointer key,
+ gfsmLabelVal lab,
+ gpointer data)
+{
+ gfsm_alphabet_remove_label(a,lab);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * free()
+ */
+void gfsm_alphabet_free(gfsmAlphabet *a)
+{
+ switch (a->type) {
+ case gfsmATIdentity:
+ gfsm_set_free(((gfsmIdentityAlphabet*)a)->labels);
+ g_free((gfsmIdentityAlphabet*)a);
+ return;
+ case gfsmATUser:
+ case gfsmATPointer:
+ case gfsmATString:
+ g_ptr_array_free(((gfsmPointerAlphabet*)a)->labels2keys,TRUE);
+ g_hash_table_destroy(((gfsmPointerAlphabet*)a)->keys2labels);
+ g_free((gfsmPointerAlphabet*)a);
+ return;
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ break;
+ }
+ g_free(a);
+};
+
+/*======================================================================
+ * Methods: Utilties
+ */
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_foreach()
+ */
+gboolean gfsm_alphabet_foreach (gfsmAlphabet *a,
+ gfsmAlphabetForeachFunc func,
+ gpointer data)
+{
+ gfsmLabelVal lab;
+ gpointer key;
+ gboolean rc=FALSE;
+ for (lab = a->lab_min; !rc && lab <= a->lab_max && lab < gfsmNoLabel; lab++) {
+ if ((key=gfsm_alphabet_find_key(a,lab))==gfsmNoKey) continue;
+ rc = (*func)(a,key,lab,data);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * strdup()
+ */
+gpointer gfsm_alphabet_strdup(gfsmAlphabet *a, const gchar *str)
+{ return g_strdup(str); }
+
+/*======================================================================
+ * Methods: Accessors
+ */
+
+/*--------------------------------------------------------------
+ * size()
+ */
+gfsmLabelVal gfsm_alphabet_size(gfsmAlphabet *a)
+{
+ guint n=0;
+ switch (a->type) {
+ case gfsmATIdentity:
+ return gfsm_set_size(((gfsmIdentityAlphabet*)a)->labels);
+ case gfsmATUser:
+ gfsm_alphabet_foreach(a, (gfsmAlphabetForeachFunc)gfsm_alphabet_foreach_size_func, &n);
+ return (gfsmLabelVal)n;
+ case gfsmATPointer:
+ case gfsmATString:
+ return ((gfsmPointerAlphabet*)a)->labels2keys->len;
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ return (a->lab_min != gfsmNoLabel && a->lab_max != gfsmNoLabel
+ ? (a->lab_max - a->lab_min)
+ : 0);
+ }
+ return n;
+}
+
+/*--------------------------------------------------------------
+ * foreach_size_func()
+ */
+gboolean gfsm_alphabet_foreach_size_func(gfsmAlphabet *a,
+ gpointer key,
+ gfsmLabelVal lab,
+ guint *np)
+{
+ if (key != gfsmNoKey && lab != gfsmNoLabel) ++(*np);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * insert()
+ */
+gfsmLabelVal gfsm_alphabet_insert(gfsmAlphabet *a, gpointer key, gfsmLabelVal label)
+{
+ switch (a->type) {
+
+ case gfsmATIdentity:
+ gfsm_set_insert(((gfsmIdentityAlphabet*)a)->labels, key);
+ label = (gfsmLabelVal) GPOINTER_TO_INT(key);
+ break;
+
+ case gfsmATUser:
+ if (((gfsmUserAlphabet*)a)->methods.insert) {
+ if (((gfsmPointerAlphabet*)a)->key_dup_func) {
+ key = (*(((gfsmPointerAlphabet*)a)->key_dup_func))(((gfsmPointerAlphabet*)a),key);
+ }
+ label = (*(((gfsmUserAlphabet*)a)->methods.insert))((gfsmUserAlphabet*)a, key, label);
+ break;
+ }
+
+ case gfsmATPointer:
+ case gfsmATString:
+ if (label==gfsmNoLabel)
+ label = ((gfsmPointerAlphabet*)a)->labels2keys->len;
+
+ if (label >= ((gfsmPointerAlphabet*)a)->labels2keys->len)
+ g_ptr_array_set_size(((gfsmPointerAlphabet*)a)->labels2keys, label+1);
+
+ if (((gfsmPointerAlphabet*)a)->key_dup_func)
+ key = (*(((gfsmPointerAlphabet*)a)->key_dup_func))(((gfsmPointerAlphabet*)a),key);
+
+ g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys, label) = key;
+ g_hash_table_insert(((gfsmPointerAlphabet*)a)->keys2labels, key, GUINT_TO_POINTER(label));
+ break;
+
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ break;
+ }
+
+ //-- range
+ if (label != gfsmNoLabel) {
+ if (a->lab_min==gfsmNoLabel || label < a->lab_min) a->lab_min = label;
+ if (a->lab_max==gfsmNoLabel || label > a->lab_max) a->lab_max = label;
+ }
+
+ return label;
+}
+
+/*--------------------------------------------------------------
+ * get_full()
+ */
+gfsmLabelVal gfsm_alphabet_get_full(gfsmAlphabet *a, gpointer key, gfsmLabelVal label)
+{
+ gfsmLabelVal l = gfsm_alphabet_find_label(a,key);
+ if (l != gfsmNoLabel) {
+ //-- old mapping exists
+ if (label == gfsmNoLabel) return l; //-- ... but no new mapping was requested
+ gfsm_alphabet_remove_label(a,l);
+ }
+ return gfsm_alphabet_insert(a,key,label);
+}
+
+/*--------------------------------------------------------------
+ * find_label()
+ */
+gfsmLabelVal gfsm_alphabet_find_label (gfsmAlphabet *a, gconstpointer key)
+{
+ gpointer k, l;
+
+ switch (a->type) {
+
+ case gfsmATIdentity:
+ if (gfsm_set_contains(((gfsmIdentityAlphabet*)a)->labels, key))
+ return (gfsmLabelVal)GPOINTER_TO_UINT(key);
+ break;
+
+ case gfsmATUser:
+ if (((gfsmUserAlphabet*)a)->methods.key_lookup)
+ return (*(((gfsmUserAlphabet*)a)->methods.key_lookup))((gfsmUserAlphabet*)a, key);
+
+ case gfsmATPointer:
+ case gfsmATString:
+ if ( g_hash_table_lookup_extended(((gfsmPointerAlphabet*)a)->keys2labels, key, &k, &l) )
+ return (gfsmLabelVal)GPOINTER_TO_UINT(l);
+ break;
+
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ return ( ((gfsmLabelVal)GPOINTER_TO_UINT(key)) >= a->lab_min
+ &&
+ ((gfsmLabelVal)GPOINTER_TO_UINT(key)) <= a->lab_max
+ ? ((gfsmLabelVal)GPOINTER_TO_UINT(key))
+ : gfsmNoLabel );
+ }
+
+ return gfsmNoLabel;
+}
+
+/*--------------------------------------------------------------
+ * find_key
+ */
+gpointer gfsm_alphabet_find_key(gfsmAlphabet *a, gfsmLabelVal label)
+{
+ switch (a->type) {
+
+ case gfsmATIdentity:
+ if ( gfsm_set_contains(((gfsmIdentityAlphabet*)a)->labels, GUINT_TO_POINTER(label)) )
+ return GUINT_TO_POINTER(label);
+ break;
+
+ case gfsmATUser:
+ if (((gfsmUserAlphabet*)a)->methods.lab_lookup)
+ return (*(((gfsmUserAlphabet*)a)->methods.lab_lookup))((gfsmUserAlphabet*)a, label);
+
+ case gfsmATPointer:
+ case gfsmATString:
+ if (label < ((gfsmPointerAlphabet*)a)->labels2keys->len)
+ return g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys,label);
+ break;
+
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ if (label >= a->lab_min && label <= a->lab_max)
+ return GUINT_TO_POINTER(label);
+ }
+
+ return gfsmNoKey;
+}
+
+/*--------------------------------------------------------------
+ * get_key()
+ */
+gpointer gfsm_alphabet_get_key(gfsmAlphabet *a, gfsmLabelVal label)
+{
+ gpointer key;
+ if (label == gfsmNoLabel) return gfsmNoKey;
+
+ key = gfsm_alphabet_find_key(a,label);
+ if (key != gfsmNoKey) return key;
+ gfsm_alphabet_get_full(a, gfsmNoKey, label);
+
+ return gfsmNoKey;
+}
+
+/*--------------------------------------------------------------
+ * remove_key()
+ */
+void gfsm_alphabet_remove_key(gfsmAlphabet *a, gconstpointer key)
+{
+ gfsmLabelVal label;
+
+ switch (a->type) {
+
+ case gfsmATIdentity:
+ gfsm_set_remove(((gfsmIdentityAlphabet*)a)->labels, key);
+ break;
+
+ case gfsmATUser:
+ if (((gfsmUserAlphabet*)a)->methods.lab_remove) {
+ label = gfsm_alphabet_find_label(a,key);
+ (*(((gfsmUserAlphabet*)a)->methods.lab_remove))((gfsmUserAlphabet*)a, label);
+ break;
+ }
+
+ case gfsmATPointer:
+ case gfsmATString:
+ label = gfsm_alphabet_find_label(a,key);
+ g_hash_table_remove(((gfsmPointerAlphabet*)a)->keys2labels,key);
+ if (label != gfsmNoLabel && label < ((gfsmPointerAlphabet*)a)->labels2keys->len) {
+ g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys, label) = NULL;
+ }
+ break;
+
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ break;
+ }
+
+ //-- ranges
+ //(missing)
+}
+
+/*--------------------------------------------------------------
+ * remove_label()
+ */
+void gfsm_alphabet_remove_label(gfsmAlphabet *a, gfsmLabelVal label)
+{
+ gpointer key;
+
+ switch (a->type) {
+ case gfsmATIdentity:
+ gfsm_set_remove(((gfsmIdentityAlphabet*)a)->labels, GUINT_TO_POINTER(label));
+ break;
+
+ case gfsmATUser:
+ if (((gfsmUserAlphabet*)a)->methods.lab_remove) {
+ (*(((gfsmUserAlphabet*)a)->methods.lab_remove))((gfsmUserAlphabet*)a, label);
+ break;
+ }
+
+ case gfsmATPointer:
+ case gfsmATString:
+ if (label < ((gfsmPointerAlphabet*)a)->labels2keys->len) {
+ key = g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys,label);
+ g_ptr_array_index(((gfsmPointerAlphabet*)a)->labels2keys,label) = NULL;
+ g_hash_table_remove(((gfsmPointerAlphabet*)a)->keys2labels,key);
+ }
+ break;
+
+ case gfsmATUnknown:
+ case gfsmATRange:
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------
+ * union()
+ */
+gfsmAlphabet *gfsm_alphabet_union(gfsmAlphabet *a1, gfsmAlphabet *a2)
+{
+ gfsm_alphabet_foreach(a2, (gfsmAlphabetForeachFunc)gfsm_alphabet_foreach_union_func, a1);
+ return a1;
+}
+
+/*--------------------------------------------------------------
+ * union_func()
+ */
+gboolean gfsm_alphabet_foreach_union_func(gfsmAlphabet *src,
+ gpointer src_key,
+ gfsmLabelVal src_id,
+ gfsmAlphabet *dst)
+{
+ gfsm_alphabet_get_label(dst,src_key);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_labels_to_array_func()
+ */
+gboolean gfsm_alphabet_labels_to_array_func(gfsmAlphabet *alph,
+ gpointer key,
+ gfsmLabelVal lab,
+ GPtrArray *ary)
+{
+ //g_array_append_val(ary, lab);
+ g_ptr_array_add(ary, GUINT_TO_POINTER(lab));
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_labels_to_array()
+ */
+void gfsm_alphabet_labels_to_array(gfsmAlphabet *alph, GPtrArray *ary)
+{
+ gfsm_alphabet_foreach(alph,
+ (gfsmAlphabetForeachFunc)gfsm_alphabet_labels_to_array_func,
+ ary);
+ //return ary;
+}
+
+/*======================================================================
+ * Methods: I/O
+ */
+
+/*--------------------------------------------------------------
+ * string2key()
+ */
+gpointer gfsm_alphabet_string2key(gfsmAlphabet *a, GString *gstr)
+{
+ gpointer key=NULL;
+
+ switch (a->type) {
+
+ case gfsmATUser:
+ if (((gfsmUserAlphabet*)a)->methods.key_read) {
+ key = (*(((gfsmUserAlphabet*)a)->methods.key_read))((gfsmUserAlphabet*)a, gstr);
+ break;
+ }
+
+ case gfsmATPointer:
+ case gfsmATString:
+ key = gstr->str;
+ break;
+
+ case gfsmATUnknown:
+ case gfsmATRange:
+ case gfsmATIdentity:
+ default:
+ key = (gpointer)strtol(gstr->str,NULL,10);
+ break;
+ }
+ return key;
+}
+
+/*--------------------------------------------------------------
+ * key2string()
+ */
+void gfsm_alphabet_key2string(gfsmAlphabet *a, gpointer key, GString *gstr)
+{
+ switch (a->type) {
+
+ case gfsmATUser:
+ if (((gfsmUserAlphabet*)a)->methods.key_write) {
+ (*(((gfsmUserAlphabet*)a)->methods.key_write))((gfsmUserAlphabet*)a, key, gstr);
+ break;
+ }
+
+ case gfsmATPointer:
+ //-- ?
+ case gfsmATString:
+ g_string_assign(gstr,key);
+ break;
+
+ case gfsmATUnknown:
+ case gfsmATRange:
+ case gfsmATIdentity:
+ default:
+ g_string_printf(gstr,"%u", GPOINTER_TO_UINT(key));
+ break;
+ }
+}
+
+/*--------------------------------------------------------------
+ * load_handle()
+ */
+gboolean gfsm_alphabet_load_handle (gfsmAlphabet *a, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ int c;
+ gpointer key;
+ gfsmLabelVal label;
+ GString *s_key = g_string_new("");
+ GString *s_lab = g_string_new("");
+
+ //if (!myname) myname = "gfsm_string_alphabet_load_file()";
+
+ do {
+ g_string_truncate(s_key,0);
+ g_string_truncate(s_lab,0);
+
+ //-- read data fields into temp strings
+ for (c=gfsmio_getc(ioh); !gfsmio_eof(ioh) && isspace((char)c); c=gfsmio_getc(ioh)) ;
+ if (gfsmio_eof(ioh)) break;
+
+ for (g_string_append_c(s_key,c), c=gfsmio_getc(ioh);
+ !gfsmio_eof(ioh) && !isspace((char)c);
+ c=gfsmio_getc(ioh))
+ {
+ g_string_append_c(s_key,c);
+ }
+
+ for ( ; !gfsmio_eof(ioh) && isspace((char)c); c=gfsmio_getc(ioh)) ;
+ if (gfsmio_eof(ioh)) break;
+
+ for (g_string_append_c(s_lab,c), c=gfsmio_getc(ioh);
+ !gfsmio_eof(ioh) && !isspace((char)c);
+ c=gfsmio_getc(ioh))
+ {
+ g_string_append_c(s_lab,c);
+ }
+
+ for ( ; (char)c != '\n' && !gfsmio_eof(ioh); c=gfsmio_getc(ioh) ) ;
+
+ //-- get actual key and label
+ key = gfsm_alphabet_string2key(a,s_key);
+ label = strtol(s_lab->str, NULL, 10);
+ if (gfsm_alphabet_find_label(a,key) != label) {
+ gfsm_alphabet_remove_key(a, key);
+ gfsm_alphabet_insert(a, key, label);
+ }
+ } while (!gfsmio_eof(ioh));
+
+ //-- cleanup
+ g_string_free(s_key,TRUE);
+ g_string_free(s_lab,TRUE);
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ * load_file()
+ */
+gboolean gfsm_alphabet_load_file (gfsmAlphabet *a, FILE *f, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_zfile(f,"rb",-1);
+ gboolean rc = gfsm_alphabet_load_handle(a, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * load_filename()
+ */
+gboolean gfsm_alphabet_load_filename (gfsmAlphabet *a, const gchar *filename, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename, "rb", -1, errp);
+ gboolean rc = ioh && !(*errp) && gfsm_alphabet_load_handle(a, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+
+
+/*--------------------------------------------------------------
+ * save_handle()
+ */
+gboolean gfsm_alphabet_save_handle(gfsmAlphabet *a, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmAlphabetSaveFileData sfdata;
+ gboolean rc;
+ sfdata.ioh = ioh;
+ sfdata.errp = errp;
+ sfdata.gstr = g_string_new("");
+ sfdata.field_sep = "\t";
+ sfdata.record_sep = "\n";
+
+ //-- guts
+ rc = gfsm_alphabet_foreach(a, (gfsmAlphabetForeachFunc)gfsm_alphabet_save_file_func, &sfdata);
+
+ //-- cleanup
+ g_string_free(sfdata.gstr,TRUE);
+
+ return !rc;
+}
+
+
+/*--------------------------------------------------------------
+ * save_file_full()
+ */
+gboolean gfsm_alphabet_save_file_full(gfsmAlphabet *a, FILE *f, int zlevel, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_zfile(f,"wb",zlevel);
+ gboolean rc = ioh && !(*errp) && gfsm_alphabet_save_handle(a, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_file()
+ */
+gboolean gfsm_alphabet_save_file(gfsmAlphabet *a, FILE *f, gfsmError **errp)
+{
+ return gfsm_alphabet_save_file_full(a,f,0,errp);
+}
+
+
+/*--------------------------------------------------------------
+ * save_filename_full()
+ */
+gboolean gfsm_alphabet_save_filename_full (gfsmAlphabet *a, const gchar *filename, int zlevel, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename,"wb",zlevel,errp);
+ gboolean rc = ioh && !(*errp) && gfsm_alphabet_save_handle(a, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_filename()
+ */
+gboolean gfsm_alphabet_save_filename (gfsmAlphabet *a, const gchar *filename, gfsmError **errp)
+{
+ return gfsm_alphabet_save_filename_full(a,filename,0,errp);
+}
+
+
+/*--------------------------------------------------------------
+ * save_file_func()
+ */
+gboolean gfsm_alphabet_save_file_func(gfsmAlphabet *a,
+ gpointer key,
+ gfsmLabelVal lab,
+ gfsmAlphabetSaveFileData *sfdata)
+{
+ gfsm_alphabet_key2string(a,key,sfdata->gstr);
+ gfsmio_printf(sfdata->ioh,
+ "%s%s%u%s",
+ sfdata->gstr->str, sfdata->field_sep, lab, sfdata->record_sep);
+ return (sfdata->errp && *(sfdata->errp));
+}
+
+
+
+/*======================================================================
+ * Methods: String Alphabet Utilities
+ */
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_string_to_labels()
+ */
+gfsmLabelVector *gfsm_alphabet_string_to_labels(gfsmAlphabet *abet,
+ const gchar *str,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined)
+{
+ gfsmLabelVal lab;
+ const gchar *s = str;
+ gchar cs[2] = {0,0};
+
+ //-- setup vector
+ if (vec==NULL) {
+ vec = g_ptr_array_sized_new(strlen(str));
+ } else {
+ g_ptr_array_set_size(vec, 0);
+ }
+
+ for (; *s; s++) {
+ cs[0] = *s;
+ lab = gfsm_alphabet_find_label(abet, cs);
+
+ //-- check for non-existant labels
+ if (lab==gfsmNoLabel) {
+ if (warn_on_undefined) {
+ gfsm_carp(g_error_new(g_quark_from_static_string("gfsm"), //--domain
+ g_quark_from_static_string("gfsm_alphabet_string_to_labels"), //-- code
+ "Warning: unknown character '%c' in string '%s' -- skipping.",
+ *s, str));
+ }
+ continue;
+ }
+
+ g_ptr_array_add(vec, GUINT_TO_POINTER(lab));
+ }
+
+ return vec;
+}
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_att_string_to_labels()
+ */
+gfsmLabelVector *gfsm_alphabet_att_string_to_labels(gfsmAlphabet *abet,
+ const gchar *str,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined)
+{
+ gfsmLabelVal lab;
+ const gchar *s = str;
+ GString *gs = g_string_sized_new(4);
+ gchar mode = 0;
+
+ //-- setup vector
+ if (vec==NULL) {
+ vec = g_ptr_array_sized_new(strlen(str));
+ } else {
+ g_ptr_array_set_size(vec, 0);
+ }
+
+ //-- loop(str): beginning of next symbol
+ for (; *s; s++) {
+ switch (mode) {
+ case '[':
+ //-- bracket-escape mode
+ if (*s==']') { mode=0; }
+ else { g_string_append_c(gs,*s); continue; }
+ break;
+
+ case '\\':
+ //-- backslash-escape mode
+ g_string_append_c(gs,*s);
+ mode = 0;
+ break;
+
+ default:
+ case 0:
+ //-- outer (unescaped) mode
+ if (*s == '[') { mode='['; continue; }
+ else if (*s == '\\') { mode='\\'; continue; }
+ else if (isspace(*s)) { continue; } //-- ignore spaces
+ //-- plain single-character symbol: set key-string
+ g_string_append_c(gs,*s);
+ break;
+ }
+
+ //-- lookup key
+ lab = gfsm_alphabet_find_label(abet, gs->str);
+
+ //-- check for non-existant labels
+ if (lab==gfsmNoLabel) {
+ if (warn_on_undefined) {
+ gfsm_carp(g_error_new(g_quark_from_static_string("gfsm"), //--domain
+ g_quark_from_static_string("gfsm_alphabet_att_string_to_labels"), //-- code
+ "Warning: unknown symbol [%s] in string '%s' -- skipping.",
+ gs->str, str));
+ }
+ g_string_truncate(gs,0);
+ continue;
+ }
+
+ //-- add to vector
+ g_ptr_array_add(vec, GUINT_TO_POINTER(lab));
+ g_string_truncate(gs,0);
+ }
+
+ //-- cleanup
+ g_string_free(gs,TRUE);
+
+ return vec;
+}
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_generic_string_to_labels()
+ */
+gfsmLabelVector *gfsm_alphabet_generic_string_to_labels(gfsmAlphabet *abet,
+ const gchar *str,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined,
+ gboolean att_mode)
+{
+ return (att_mode
+ ? gfsm_alphabet_att_string_to_labels(abet,str,vec,warn_on_undefined)
+ : gfsm_alphabet_string_to_labels(abet,str,vec,warn_on_undefined));
+}
+
+
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_labels_to_gstring()
+ */
+GString *gfsm_alphabet_labels_to_gstring(gfsmAlphabet *abet,
+ gfsmLabelVector *vec,
+ GString *gstr,
+ gboolean warn_on_undefined,
+ gboolean att_style)
+{
+ gfsmLabelVal lab;
+ const gchar *sym;
+ int i;
+
+ //-- setup GString
+ if (gstr==NULL) {
+ gstr = g_string_new_len("",vec->len);
+ }
+
+ //-- lookup & append symbols
+ for (i=0; i < vec->len; i++) {
+ lab = (gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(vec,i));
+ sym = (const gchar*)gfsm_alphabet_find_key(abet,lab);
+
+ //-- check for unknown labels
+ if (sym==NULL) {
+ if (warn_on_undefined) {
+ gfsm_carp(g_error_new(g_quark_from_static_string("gfsm"), //--domain
+ g_quark_from_static_string("gfsm_alphabet_labels_to_gstring"), //-- code
+ "Warning: unknown label '%d' -- skipping.",
+ lab));
+ }
+ continue;
+ }
+
+ //-- append the symbol to the output string
+ if (att_style) {
+ if (strlen(sym)==1) {
+ g_string_append_c(gstr,sym[0]);
+ }
+ else {
+ g_string_append_c(gstr,'[');
+ g_string_append(gstr,sym);
+ g_string_append_c(gstr,']');
+ }
+ } else { //-- !att_style
+ if (i != 0) g_string_append_c(gstr,' ');
+ g_string_append(gstr, sym);
+ }
+ }
+
+ return gstr;
+}
+
+/*--------------------------------------------------------------
+ * gfsm_alphabet_labels_to_string()
+ */
+char *gfsm_alphabet_labels_to_string(gfsmAlphabet *abet,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined,
+ gboolean att_style)
+{
+ GString *gstr = g_string_new("");
+ gfsm_alphabet_labels_to_gstring(abet,vec,gstr,warn_on_undefined,att_style);
+ char *str = gstr->str;
+ g_string_free(gstr,FALSE);
+ return str;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAlphabet.h b/gfsm/gfsm/src/libgfsm/gfsmAlphabet.h
new file mode 100644
index 0000000..5ae80cd
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAlphabet.h
@@ -0,0 +1,450 @@
+
+/*=============================================================================*\
+ * File: gfsmAlphabet.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: alphabet
+ *
+ * Copyright (c) 2004-2008 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmAlphabet.h
+ * \brief Map between gfsmLabelIds and external objects
+ */
+
+#ifndef _GFSM_ALPHABET_H
+#define _GFSM_ALPHABET_H
+
+#include <gfsmCommon.h>
+#include <gfsmSet.h>
+#include <gfsmIO.h>
+
+/*======================================================================
+ * Alphabet: Flags
+ */
+/** Enumeration of builtin alphabet types */
+typedef enum {
+ gfsmATUnknown = 0, ///< unknown alphabet type
+ gfsmATRange = 1, ///< alphabet type for label ranges
+ gfsmATIdentity = 2, ///< alphabet type for sparse identity alphabets
+ gfsmATPointer = 3, ///< pointer-hashing alphabet
+ gfsmATString = 4, ///< string alphabet
+ gfsmATUser = 256 ///< user-defined alphabet
+} gfsmAType;
+
+/*======================================================================
+ * Alphabet: Basic Types
+ */
+/// Generic alphabet structure
+typedef struct {
+ gfsmAType type; /**< alphabet type */
+ gfsmLabelVal lab_min; /**< minimum label */
+ gfsmLabelVal lab_max; /**< maximum label */
+} gfsmAlphabet;
+
+/// Ranged alphabet structure
+typedef gfsmAlphabet gfsmRangeAlphabet;
+
+/// Sparse identity alphabet structure
+typedef struct {
+ gfsmAlphabet a; /**< inheritance magic */
+ gfsmSet *labels; /**< known labels */
+} gfsmIdentityAlphabet;
+
+// Pointer-hashing alphabet structure (forward decl)
+struct gfsmPointerAlphabet_;
+
+// User-extendable alphabet structure (forward decl)
+struct gfsmUserAlphabet_;
+
+//@}
+
+/*======================================================================
+ * Alphabet: Function types
+ */
+///\name Alphabet: Function Types
+//@{
+/** Type for key-duplication functions */
+typedef gpointer (*gfsmAlphabetKeyDupFunc) (struct gfsmPointerAlphabet_ *a, gpointer key);
+
+/** Type for alphabet (key->label) lookup functions */
+typedef gfsmLabelVal (*gfsmAlphabetKeyLookupFunc) (struct gfsmUserAlphabet_ *a, gconstpointer key);
+
+/** Type for alphabet (label->key) lookup functions */
+typedef gpointer (*gfsmAlphabetLabLookupFunc) (struct gfsmUserAlphabet_ *a, gfsmLabelVal lab);
+
+/** Type for alphabet insertion functions */
+typedef gfsmLabelVal (*gfsmAlphabetInsertFunc) (struct gfsmUserAlphabet_ *a, gpointer key, gfsmLabelVal lab);
+
+/** Type for alphabet key removal functions (unused) */
+typedef void (*gfsmAlphabetKeyRemoveFunc) (struct gfsmUserAlphabet_ *a, gpointer key);
+
+/** Type for alphabet label removal functions */
+typedef void (*gfsmAlphabetLabRemoveFunc) (struct gfsmUserAlphabet_ *a, gfsmLabelVal lab);
+
+/** Type for alphabet string input functions (should return a static key) */
+typedef gpointer (*gfsmAlphabetKeyReadFunc) (struct gfsmUserAlphabet_ *a, GString *gstr);
+
+/** Type for alphabet string output functions (should write to @str) */
+typedef void (*gfsmAlphabetKeyWriteFunc) (struct gfsmUserAlphabet_ *a, gconstpointer key, GString *str);
+
+/// method table for user-defined alphabets
+typedef struct {
+ gfsmAlphabetKeyLookupFunc key_lookup; /**< key->label lookup function */
+ gfsmAlphabetLabLookupFunc lab_lookup; /**< label->key lookup function */
+ gfsmAlphabetInsertFunc insert; /**< insertion function: receives a newly copied key! */
+ gfsmAlphabetLabRemoveFunc lab_remove; /**< label removal function */
+ gfsmAlphabetKeyReadFunc key_read; /**< key input function */
+ gfsmAlphabetKeyWriteFunc key_write; /**< key output function */
+} gfsmUserAlphabetMethods;
+
+/// default methods for user-defined alphabets (dummy)
+extern gfsmUserAlphabetMethods gfsmUserAlphabetDefaultMethods;
+//@}
+
+/*======================================================================
+ * Alphabet: Extendible types
+ */
+///\name Alphabet: Extendible Types
+//@{
+/// Pointer-hashing alphabet structure
+typedef struct gfsmPointerAlphabet_ {
+ gfsmAlphabet a; /**< inheritance magic */
+ GPtrArray *labels2keys; /**< label->key lookup table */
+ GHashTable *keys2labels; /**< key->label lookup table */
+ gfsmAlphabetKeyDupFunc key_dup_func; /**< key duplication function */
+} gfsmPointerAlphabet;
+
+/// type for string alphabets
+typedef gfsmPointerAlphabet gfsmStringAlphabet;
+
+/// User-extendable alphabet structure
+typedef struct gfsmUserAlphabet_
+{
+ gfsmPointerAlphabet aa; /**< inheritance magic */
+ gpointer data; /**< user data */
+ gfsmUserAlphabetMethods methods; /**< method table */
+} gfsmUserAlphabet;
+//@}
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+/// \name Constructors etc.
+//@{
+
+/** Create a new alphabet. The alphabet will be uninitialized until you call
+ * one of the gfsm_*_alphabet_init() functions.
+ *
+ * \param type Type of alphabet to create.
+ */
+gfsmAlphabet *gfsm_alphabet_new(gfsmAType type);
+
+
+/** Create and initialize a new identity alphabet.
+ * You do not need to call an init() function for the returned alphabet.
+ */
+#define gfsm_identity_alphabet_new() \
+ gfsm_identity_alphabet_init((gfsmIdentityAlphabet*)gfsm_alphabet_new(gfsmATIdentity))
+
+/** Create and initialize a new string alphabet.
+ * You do not need to call an init() function for the returned alphabet.
+ */
+#define gfsm_string_alphabet_new_full(docopy) \
+ gfsm_string_alphabet_init((gfsmStringAlphabet*)gfsm_alphabet_new(gfsmATString),(docopy))
+
+/** Create and initialize a new string alphabet which copies keys.
+ * You do not need to call an init() function for the returned alphabet.
+ */
+#define gfsm_string_alphabet_new() gfsm_string_alphabet_new_full(TRUE)
+
+/** Create and initialize a new range alphabet.
+ * You do not need to call an init() function for the returned alphabet. */
+#define gfsm_range_alphabet_new() \
+ gfsm_range_alphabet_init((gfsmRangeAlphabet*)gfsm_alphabet_new(gfsmATRange), \
+ gfsmNoLabel, gfsmNoLabel)
+
+/** Create and initialize a new pointer alphabet.
+ * You do not need to call an init() function for the returned alphabet. */
+#define gfsm_pointer_alphabet_new(key_dup_f, key_hash_f, key_eq_f, key_free_f) \
+ gfsm_pointer_alphabet_init((gfsmPointerAlphabet*)gfsm_alphabet_new(gfsmATPointer),\
+ key_dup_f, key_hash_f, key_eq_f, key_free_f)
+
+
+/** Initialize a builtin alphabet (depending on \a a->type)
+ * This really only works well identity, range, and string alphabets,
+ * as well as for literal pointer alphabets (without copy and/or free)
+ * and for user alphabets using literal pointers.
+ */
+gfsmAlphabet *gfsm_alphabet_init(gfsmAlphabet *a);
+
+
+/** Initialize a range alphabet */
+gfsmAlphabet *gfsm_range_alphabet_init (gfsmRangeAlphabet *a, gfsmLabelVal min, gfsmLabelVal max);
+
+/** Initialize a sparse identity alphabet */
+gfsmAlphabet *gfsm_identity_alphabet_init (gfsmIdentityAlphabet *a);
+
+/** Initialize a pointer alphabet */
+gfsmAlphabet *gfsm_pointer_alphabet_init (gfsmPointerAlphabet *a,
+ gfsmAlphabetKeyDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func);
+
+/** Initialize a string alphabet */
+gfsmAlphabet *gfsm_string_alphabet_init (gfsmStringAlphabet *a, gboolean do_copy);
+
+
+/** Initialize a user alphabet */
+gfsmAlphabet *gfsm_user_alphabet_init(gfsmUserAlphabet *a,
+ gfsmAlphabetKeyDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func,
+ gpointer user_data,
+ gfsmUserAlphabetMethods *methods);
+
+/** Clear all labels and keys from a gfsmAlphabet */
+void gfsm_alphabet_clear(gfsmAlphabet *a);
+
+/** foreach utility function to clear user alphabets */
+gboolean gfsm_alphabet_foreach_remove_func (gfsmAlphabet *a,
+ gpointer key,
+ gfsmLabelVal lab,
+ gpointer data);
+
+/** Free all memory allocated by a gfsmAlphabet */
+void gfsm_alphabet_free(gfsmAlphabet *a);
+//@}
+
+/*======================================================================
+ * Methods: Utilties
+ */
+///\name Utilities
+//@{
+/** Type for alphabet iterator functions.
+ * Functions should return \a TRUE to stop the traversal
+ */
+typedef gboolean (*gfsmAlphabetForeachFunc) (gfsmAlphabet *a,
+ gpointer key,
+ gfsmLabelVal lab,
+ gpointer data);
+
+/** General iteration utility */
+gboolean gfsm_alphabet_foreach (gfsmAlphabet *a,
+ gfsmAlphabetForeachFunc func,
+ gpointer data);
+
+/** dup function for string alphabets */
+gpointer gfsm_alphabet_strdup(gfsmAlphabet *a, const gchar *str);
+//@}
+
+/*======================================================================
+ * Methods: Accessors
+ */
+/// \name Accessors
+///@{
+/** Get number of elements in the alphabet */
+gfsmLabelVal gfsm_alphabet_size(gfsmAlphabet *a);
+
+/** Utility for counting size of user alphabets (linear time) */
+gboolean gfsm_alphabet_foreach_size_func(gfsmAlphabet *a,
+ gpointer key,
+ gfsmLabelVal lab,
+ guint *np);
+
+/**
+ * Insert a \a (key,label) pair into the alphabet.
+ * If \a label is \a gfsmNoLabel, a new label will be assigned.
+ * \note No sanity checks are performed.
+ *
+ * \returns the new label for \a key
+ */
+gfsmLabelVal gfsm_alphabet_insert(gfsmAlphabet *a, gpointer key, gfsmLabelVal label);
+
+/** Get or assign a label for \a key.
+ * If \a label is gfsmNoLabel, a new label will be assigned for \a key if none exists.
+ * \returns label for \a key
+ */
+gfsmLabelVal gfsm_alphabet_get_full(gfsmAlphabet *a, gpointer key, gfsmLabelVal label);
+
+/** Get label for \a key or assign a new one if none exists.
+ * \returns label for \a key
+ */
+#define gfsm_alphabet_get_label(a,key) gfsm_alphabet_get_full(a,key,gfsmNoLabel)
+
+/** Lookup label for \a key.
+ * \returns label for \a key, or gfsmNoLabel if none is defined.
+ */
+gfsmLabelVal gfsm_alphabet_find_label(gfsmAlphabet *a, gconstpointer key);
+
+/** Lookup key for \a label
+ * \returns pointer to key for \a label, or \a NULL if no key is defined.
+ */
+gpointer gfsm_alphabet_find_key(gfsmAlphabet *a, gfsmLabelVal label);
+
+/** Get key for \a label or assign gfsmNoKey if none exists.
+ * \returns key for \a label
+ */
+gpointer gfsm_alphabet_get_key(gfsmAlphabet *a, gfsmLabelVal label);
+
+/** Remove mapping for \a key (and associated label, if any) */
+void gfsm_alphabet_remove_key(gfsmAlphabet *a, gconstpointer key);
+
+/** Remove mapping for \a label (and associated key, if any) */
+void gfsm_alphabet_remove_label(gfsmAlphabet *a, gfsmLabelVal label);
+
+/** Add all keys from alphabet \a a2 to \a a1. \returns \a a1 */
+gfsmAlphabet *gfsm_alphabet_union(gfsmAlphabet *a1, gfsmAlphabet *a2);
+
+/** foreach utility func for union() */
+gboolean gfsm_alphabet_foreach_union_func(gfsmAlphabet *src,
+ gpointer src_key,
+ gfsmLabelVal src_id,
+ gfsmAlphabet *dst);
+
+/** Append all defined labels to a GPtrArray of (gfsmLabelVal)s */
+void gfsm_alphabet_labels_to_array(gfsmAlphabet *alph, GPtrArray *ary);
+
+//@}
+
+/*======================================================================
+ * Methods: I/O
+ */
+///\name I/O
+//@{
+
+/** Convert a string to a temporary key, used by load().
+ * If you allocate anything here, you need to free it yourself.
+ */
+gpointer gfsm_alphabet_string2key(gfsmAlphabet *a, GString *gstr);
+
+/** Convert a key to a constant string, used by save() */
+void gfsm_alphabet_key2string(gfsmAlphabet *a, gpointer key, GString *gstr);
+
+
+/** Load a string alphabet from a stream. Returns true on success */
+gboolean gfsm_alphabet_load_handle (gfsmAlphabet *a, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Load a string alphabet from a stream. Returns true on success */
+gboolean gfsm_alphabet_load_file (gfsmAlphabet *a, FILE *f, gfsmError **errp);
+
+/** Load a string alphabet from a named file */
+gboolean gfsm_alphabet_load_filename (gfsmAlphabet *a, const gchar *filename, gfsmError **errp);
+
+
+/** Save a string alphabet to a gfsmIOHandle* */
+gboolean gfsm_alphabet_save_handle(gfsmAlphabet *a, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Save a string alphabet to a stream (uncompressed) */
+gboolean gfsm_alphabet_save_file (gfsmAlphabet *a, FILE *f, gfsmError **errp);
+
+/** Save a string alphabet to a (compressed) stream */
+gboolean gfsm_alphabet_save_file_full (gfsmAlphabet *a, FILE *f, int zlevel, gfsmError **errp);
+
+/** Save a string alphabet to a named file (uncompressed) */
+gboolean gfsm_alphabet_save_filename (gfsmAlphabet *a, const gchar *filename, gfsmError **errp);
+
+/** Save a string alphabet to a (compressed) named file */
+gboolean gfsm_alphabet_save_filename_full (gfsmAlphabet *a, const gchar *filename, int zlevel, gfsmError **errp);
+
+/// datatype used for save_file() iteration
+typedef struct {
+ gfsmIOHandle *ioh;
+ gfsmError **errp;
+ GString *gstr;
+ gchar *field_sep;
+ gchar *record_sep;
+} gfsmAlphabetSaveFileData;
+
+/** save_file iterator func */
+gboolean gfsm_alphabet_save_file_func(gfsmAlphabet *a,
+ gpointer key,
+ gfsmLabelVal lab,
+ gfsmAlphabetSaveFileData *sfdata);
+//@}
+
+/*======================================================================
+ * String Alphabet Utilties
+ */
+///\name String Alphabet Utilities
+//@{
+
+/** Convert an ASCII string character-wise to a vector of (gfsmLabel)s.
+ * \a vec is not cleared -- use g_ptr_array_set_size() for that.
+ * \returns \a vec if non-\a NULL, otherwise a new gfsmLabelVector.
+ * \a abet should be a gfsmStringAlphabet.
+ */
+gfsmLabelVector *gfsm_alphabet_string_to_labels(gfsmAlphabet *abet,
+ const gchar *str,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined);
+
+/** Convert an ASCII GString character-wise to a vector of (gfsmLabel)s.
+ * \a vec is not cleared -- use g_ptr_array_set_size() for that.
+ * \returns \a vec if non-\a NULL, otherwise a new gfsmLabelVector.
+ * \a abet should be a gfsmStringAlphabet.
+ */
+#define gfsm_alphabet_gstring_to_labels(abet,gstr,vec,warn) \
+ gfsm_alphabet_string_to_labels((abet),(gstr)->str,(vec),(warn))
+
+
+/** Convert an ASCII string in AT&T syntax to a vector of (gfsmLabel)s.
+ * \a vec is not cleared -- use g_ptr_array_set_size() for that.
+ * \returns \a vec if non-\a NULL, otherwise a new gfsmLabelVector.
+ * \a abet should be a gfsmStringAlphabet.
+ */
+gfsmLabelVector *gfsm_alphabet_att_string_to_labels(gfsmAlphabet *abet,
+ const gchar *str,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined);
+
+/** Convert an ASCII string to a vector of (gfsmLabel)s,
+ * using either ::gfsm_alphabet_string_to_labels() or ::gfsm_alphabet_att_string_to_labels().
+ * \param abet,str,vec,warn_undef as for ::gfsm_alphabet_string_to_labels().
+ * \param att_mode if true, \c str is parsed as att-syntax, otherwise character-wise
+ * \returns as for ::gfsm_alphabet_string_to_labels()
+ */
+gfsmLabelVector *gfsm_alphabet_generic_string_to_labels(gfsmAlphabet *abet,
+ const gchar *str,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined,
+ gboolean att_mode);
+
+/** Convert a gfsmLabelVector to a GString.
+ * \a gstr is not cleared.
+ * \returns \a gstr if non-\a NULL, otherwise a new GString*.
+ * \a abet should be a gfsmStringAlphabet.
+ */
+GString *gfsm_alphabet_labels_to_gstring(gfsmAlphabet *abet,
+ gfsmLabelVector *vec,
+ GString *gstr,
+ gboolean warn_on_undefined,
+ gboolean att_style);
+
+/** Convert a gfsmLabelVector to a new string.
+ * \a gstr is not cleared.
+ * \returns \a gstr if non-\a NULL, otherwise a new GString*.
+ * \a abet should be a gfsmStringAlphabet.
+ */
+char *gfsm_alphabet_labels_to_string(gfsmAlphabet *abet,
+ gfsmLabelVector *vec,
+ gboolean warn_on_undefined,
+ gboolean att_style);
+//@}
+
+#endif /*_GFSM_ALPHABET_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArc.c b/gfsm/gfsm/src/libgfsm/gfsmArc.c
new file mode 100644
index 0000000..6d88072
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArc.c
@@ -0,0 +1,192 @@
+/*=============================================================================*\
+ * File: gfsmArc.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arcs
+ *
+ * Copyright (c) 2004-2008 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmArc.h>
+#include <stdlib.h>
+
+#ifndef GFSM_INLINE_ENABLED
+//-- no inline definitions
+# include <gfsmArc.hi>
+#endif
+
+/*======================================================================
+ * Constants (none)
+ */
+
+/*======================================================================
+ * Methods: Arcs: Constructors etc.
+ */
+//--inline
+
+/*======================================================================
+ * Arc Comparisons (old)
+ */
+
+
+/*--------------------------------------------------------------
+ * sortmode_to_name()
+ */
+#if 0
+const gchar *gfsm_arc_sortmode_to_name(gfsmArcSortMode mode)
+{
+ switch (mode) {
+ case gfsmASMNone: return "none";
+ case gfsmASMLower: return "lower";
+ case gfsmASMUpper: return "upper";
+ case gfsmASMWeight: return "weight";
+ default: return "unknown";
+ }
+}
+#endif
+
+
+/*======================================================================
+ * Arc Comparisons (new)
+ */
+
+/*--------------------------------------------------------------
+ * acmask_from_chars()
+ */
+gfsmArcCompMask gfsm_acmask_from_chars(const char *maskchars)
+{
+ gfsmArcCompMask m = 0;
+ gint i;
+ gint nth=0;
+ for (i=0; maskchars && maskchars[i] && nth < gfsmACMaxN; i++) {
+ switch (maskchars[i]) {
+ case 'l' : m |= gfsm_acmask_new(gfsmACLower, nth++); break;
+ case 'L' : m |= gfsm_acmask_new(gfsmACLowerR,nth++); break;
+
+ case 'u' : m |= gfsm_acmask_new(gfsmACUpper, nth++); break;
+ case 'U' : m |= gfsm_acmask_new(gfsmACUpperR,nth++); break;
+
+ case 'w' : m |= gfsm_acmask_new(gfsmACWeight, nth++); break;
+ case 'W' : m |= gfsm_acmask_new(gfsmACWeightR,nth++); break;
+
+ case 's' : m |= gfsm_acmask_new(gfsmACSource, nth++); break;
+ case 'S' : m |= gfsm_acmask_new(gfsmACSourceR,nth++); break;
+
+ case 't' : m |= gfsm_acmask_new(gfsmACTarget, nth++); break;
+ case 'T' : m |= gfsm_acmask_new(gfsmACTargetR,nth++); break;
+
+ case 'x' : m |= gfsm_acmask_new(gfsmACUser, nth++); break;
+ case 'X' : m |= gfsm_acmask_new(gfsmACUserR,nth++); break;
+
+ //-- silently ignore these
+ case '_':
+ case '-':
+ case ',':
+ case ' ':
+ case '\t':
+ case '\n':
+ break;
+
+ default:
+ g_printerr("libgfsm: character '%c' is not in [stluwxSTLUWX_] in mode string '%s' - skipping\n",
+ maskchars[i], maskchars);
+ break;
+ }
+ }
+ return m;
+}
+
+/*--------------------------------------------------------------
+ * acmask_from_args()
+ */
+gfsmArcCompMask gfsm_acmask_from_args(gfsmArcComp cmp0, ...)
+{
+ gfsmArcCompMask m=0;
+ gfsmArcComp cmp;
+ gint nth=0;
+ va_list ap;
+
+ va_start(ap,cmp0);
+ for (cmp=cmp0; cmp!=0 && nth < gfsmACMaxN; nth++, cmp=va_arg(ap,gfsmArcComp)) {
+ m |= gfsm_acmask_new(cmp,nth);
+ }
+ va_end(ap);
+
+ return m;
+}
+
+/*--------------------------------------------------------------
+ * compare_bymask()
+ */
+gint gfsm_arc_compare_bymask(gfsmArc *a1, gfsmArc *a2, gfsmArcCompData *acdata)
+{ return gfsm_arc_compare_bymask_inline(a1,a2,acdata); }
+
+
+/*--------------------------------------------------------------
+ * acmask_to_chars()
+ */
+gchar *gfsm_acmask_to_chars(gfsmArcCompMask m, gchar *chars)
+{
+ gint nth;
+ if (!chars) { chars = g_new0(gchar,gfsmACMaxN+1); }
+ for (nth=0; nth < gfsmACMaxN; nth++) {
+ chars[nth] = gfsm_acmask_nth_char(m,nth);
+ }
+ chars[gfsmACMaxN] = '\0';
+ return chars;
+}
+
+/*--------------------------------------------------------------
+ * acmask_nth_string()
+ */
+const gchar *gfsm_acmask_nth_string(gfsmArcCompMask m, gint nth)
+{
+ switch (gfsm_acmask_nth(m,nth)) {
+ case gfsmACLower: return "lower";
+ case gfsmACUpper: return "upper";
+ case gfsmACWeight: return "weight";
+ case gfsmACSource: return "source";
+ case gfsmACTarget: return "target";
+ //
+ case gfsmACLowerR: return "reverse_lower";
+ case gfsmACUpperR: return "reverse_upper";
+ case gfsmACWeightR: return "reverse_weight";
+ case gfsmACSourceR: return "reverse_source";
+ case gfsmACTargetR: return "reverse_target";
+ //
+ case gfsmACUser: return "user";
+ case gfsmACUserR: return "reverse_user";
+ case gfsmACNone: return "none";
+ case gfsmACReverse: return "reverse_none";
+ default: return "?";
+ }
+ return "?";
+}
+
+/*--------------------------------------------------------------
+ * acmask_to_gstring()
+ */
+GString *gfsm_acmask_to_gstring(gfsmArcCompMask m, GString *gstr)
+{
+ gint nth;
+ if (!gstr) { gstr = g_string_sized_new(96); }
+ else { g_string_truncate(gstr,0); }
+ for (nth=0; nth < gfsmACMaxN; nth++) {
+ if (nth) { g_string_append(gstr, ", "); }
+ g_string_append(gstr, gfsm_acmask_nth_string(m,nth));
+ }
+ return gstr;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArc.h b/gfsm/gfsm/src/libgfsm/gfsmArc.h
new file mode 100644
index 0000000..3ea6e22
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArc.h
@@ -0,0 +1,305 @@
+/*=============================================================================*\
+ * File: gfsmArc.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arcs
+ *
+ * Copyright (c) 2004-2008 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmArc.h
+ * \brief Arc (transition) definitions & utilities
+ */
+
+#ifndef _GFSM_ARC_H
+#define _GFSM_ARC_H
+
+#include <gfsmSemiring.h>
+#include <stdarg.h>
+
+/// "Heavy" arc structure
+typedef struct {
+ gfsmStateId source; /**< ID of source node */
+ gfsmStateId target; /**< ID of target node */
+ gfsmLabelId lower; /**< Lower label */
+ gfsmLabelId upper; /**< Upper label */
+ gfsmWeight weight; /**< arc weight */
+} gfsmArc;
+
+/// Type for identifying arc-label "sides" in a transducer (lower vs. upper)
+typedef enum {
+ gfsmLSBoth = 0, ///< Both sides (lower and upper)
+ gfsmLSLower = 1, ///< Lower side only
+ gfsmLSUpper = 2 ///< Upper side only
+} gfsmLabelSide;
+
+//----------------------------------------------------------------------
+// arc sorting (new)
+
+/// Enum type for elementary builtin comparisons on ::gfsmArc
+/** \since v0.0.10 */
+typedef enum {
+ gfsmACNone = 0x0, /**< '_': no comparison at all */
+ //
+ //-- Forward (ascending)
+ gfsmACLower = 0x1, /**< 'l': compare lower labels (ascending order) */
+ gfsmACUpper = 0x2, /**< 'u': compare upper labels (ascending order) */
+ gfsmACWeight = 0x3, /**< 'w': compare semiring weights (ascending order) */
+ gfsmACSource = 0x4, /**< 's': compare source states (if supported and meaningful, ascending order) */
+ gfsmACTarget = 0x5, /**< 't': compare target states (if supported and meaningful, ascending order) */
+ gfsmACUser = 0x6, /**< 'x': pseudo-field indicating a user-defined comparison */
+ gfsmACUnused1 = 0x7, /**< unused */
+ //
+ //-- Reverse (descending)
+ gfsmACReverse = 0x8, /**< not really a comparison: the bit 0x8 is set for all "reverse" comparisons */
+ gfsmACLowerR = 0x9, /**< 'L': compare lower labels (descending order) */
+ gfsmACUpperR = 0xa, /**< 'U': compare upper labels (descending order) */
+ gfsmACWeightR = 0xb, /**< 'W': compare semiring weights (descending order) */
+ gfsmACSourceR = 0xc, /**< 'S': compare source states (if supported and meaningful, descending order) */
+ gfsmACTargetR = 0xd, /**< 'T': compare target states (if supported and meaningful, descending order) */
+ gfsmACUserR = 0xe, /**< 'X': pseudo-field for reversed user-defined comparisons, for symmetry */
+ //
+ //-- Pseudo-comparisons
+ gfsmACAll = 0xf /**< '*': pseudo-field for mask of all known elementary comparisons */
+} gfsmArcComp;
+
+/** \brief Prioritized list of up to 5 elementary arc comparisons packed as a guint32
+ * \detail
+ * The primary comparison is encoded as a ::gfsmArcComp in the least significant
+ * 4-bit nybble of the integer, the secondary comparison is left-shifted by 4 bits,
+ * and so on.
+ */
+typedef guint32 gfsmArcCompMask;
+
+/** Number of bits to left-shift ::gfsmArcCompMask for each arc sub-comparison using ::gfsmArcComp encoding */
+#define gfsmACShift 4
+
+/** Maximum number of ::gfsmArcComp fields supported by ::gfsmArcCompMask (pragmatic definition) */
+#define gfsmACMaxN 6
+
+/** Useful aliases for builtin arcsort modes, including backwards-compatible ::gfsmASMLower etc. */
+typedef enum {
+ gfsmASMNone = 0x0, /**< no sort */
+ gfsmASMLower = (gfsmACLower|(gfsmACUpper<<gfsmACShift)|(gfsmACTarget<<(2*gfsmACShift))), /**< (lower,upper,target) */
+ gfsmASMUpper = (gfsmACUpper|(gfsmACLower<<gfsmACShift)|(gfsmACTarget<<(2*gfsmACShift))), /**< (upper,lower,target) */
+ gfsmASMWeight = gfsmACWeight, /**< (weight) */
+ gfsmASMLowerWeight = (gfsmACLower|(gfsmACWeight<<gfsmACShift)), /**< (lower,weight) */
+ gfsmASMUpperWeight = (gfsmACUpper|(gfsmACWeight<<gfsmACShift)), /**< (upper,weight) */
+ gfsmASMUser = gfsmACUser, /**< user-defined sort */
+} gfsmArcSortModeE;
+
+/// Semi-compatible typedef for arc sort mode
+typedef gfsmArcCompMask gfsmArcSortMode;
+
+/// Data for new-style generic arc comparison
+typedef struct {
+ gfsmArcCompMask mask; /**< Comparison precedence */
+ gfsmSemiring *sr; /**< Semiring to use for weight comparisons (if any) */
+ GCompareDataFunc user_compare_func; /**< User comparison function (if any) */
+ gpointer user_data; /**< User data (for \c user_compare_func) */
+} gfsmArcCompData;
+
+/*======================================================================
+ * Methods: Arcs: Constructors etc.
+ */
+
+/// \name Arcs: Constructors etc.
+//@{
+/** Create and return a new (empty) ::gfsmArc */
+GFSM_INLINE
+gfsmArc *gfsm_arc_new(void);
+
+/** Initialize a ::gfsmArc
+ * \param a arc to initialize
+ * \param src ID of source state
+ * \param dst ID of target state
+ * \param lo ID of lower label
+ * \param hi ID of upper label
+ * \param w arc weight
+ * \returns initialized arc \a a
+ */
+GFSM_INLINE
+gfsmArc *gfsm_arc_init(gfsmArc *a,
+ gfsmStateId src,
+ gfsmStateId dst,
+ gfsmLabelId lo,
+ gfsmLabelId hi,
+ gfsmWeight wt);
+
+/** Convenience macro to simultaneously create and initialize a ::gfsmArc
+ * \param src ID of source state
+ * \param dst ID of target state
+ * \param lo ID of lower label
+ * \param hi ID of upper label
+ * \param w arc weight
+ * \returns newly allocated and initalized ::gfsmArc
+ */
+GFSM_INLINE
+gfsmArc *gfsm_arc_new_full(gfsmStateId src, gfsmStateId dst, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight wt);
+
+/** Create an exact copy of the ::gfsmArc \a src */
+GFSM_INLINE
+gfsmArc *gfsm_arc_clone(gfsmArc *src);
+
+/** Backwards-compatible convenience alias for gfsm_arc_clone() */
+#define gfsm_arc_copy(src) gfsm_arc_clone(src)
+
+/** Destroy a ::gfsmArc \a a */
+GFSM_INLINE
+void gfsm_arc_free(gfsmArc *a);
+//@}
+
+/*======================================================================
+ * Methods: Arc: Accessors
+ */
+///\name Arc Accessors
+//@{
+
+/** Get source node of an arc -- may be gfsmNoState */
+#define gfsm_arc_source(arcptr) ((arcptr)->source)
+
+/** Get target node of an arc -- may be gfsmNoState */
+#define gfsm_arc_target(arcptr) ((arcptr)->target)
+
+/** Get lower label of an arc -- may be gfsmNoLabel */
+#define gfsm_arc_lower(arcptr) ((arcptr)->lower)
+
+/** Get upper label of an arc -- may be gfsmNoLabel */
+#define gfsm_arc_upper(arcptr) ((arcptr)->upper)
+
+/** Get weight of an arc -- may be gfsmNoWeight */
+#define gfsm_arc_weight(arcptr) ((arcptr)->weight)
+
+//@}
+
+
+/*======================================================================
+ * Arc Comparison Utilities
+ */
+///\name Arc Comparison Utilities
+//@{
+
+/** Generic 3-way comparison on arcs (inline version)
+ * \param a1 first arc to compare
+ * \param a2 second arc to compare
+ * \param acdata specifies comparison priorities
+ * \returns
+ * negative, zero, or positive integer depending on whether
+ * \a a1 is less-than, equal-to, or greater-than \a a2 according to \a acdata.
+ */
+GFSM_INLINE
+gint gfsm_arc_compare_bymask_inline(gfsmArc *a1, gfsmArc *a2, gfsmArcCompData *acdata);
+
+/** Generic 3-way comparison on arcs (extern version)
+ * Really just a wrapper for gfsm_arc_compare_mask_inline()
+ */
+gint gfsm_arc_compare_bymask(gfsmArc *a1, gfsmArc *a2, gfsmArcCompData *acdata);
+
+/** Guts for gfsm_arc_compare_bymask_inline(): compare arcs w.r.t a single attribute \a cmp.
+ * \note gcc deems these calls "unlikely" and refuses to inline...
+ */
+GFSM_INLINE
+gint gfsm_arc_compare_bymask_1_(gfsmArc *a1, gfsmArc *a2, gfsmArcComp cmp, gfsmArcCompData *acdata);
+
+/** Parse a NUL-terminated string into a ::gfsmArcCompMask
+ * \param maskchars
+ * A NUL-terminated string representing the precedence among elementary comparisons.
+ * Each character represents a single elementary comparison.
+ * The primary comparison is the first character of the string.
+ * Correspondence of characters to comparisons is:
+ * \li 'l' ::gfsmACLower
+ * \li 'u' ::gfsmACUpper
+ * \li 'w' ::gfsmACWeight
+ * \li 's' ::gfsmACSource
+ * \li 't' ::gfsmACTarget
+ * \li 'x' ::gfsmACUser
+ * \li 'L' ::gfsmACLowerR
+ * \li 'U' ::gfsmACUpperR
+ * \li 'W' ::gfsmACWeightR
+ * \li 'S' ::gfsmACSourceR
+ * \li 'T' ::gfsmACTargetR
+ * \li 'X' ::gfsmACUserR
+ * \returns a ::gfsmArcCompMask for \a maskchars
+ */
+gfsmArcCompMask gfsm_acmask_from_chars(const char *maskchars);
+
+/** Create and return a ::gfsmArcCompMask from a variable argument list of ::gfsmArcComp
+ * The argument list must be terminated with a zero (e.g. ::gfsmACNone)
+ * \param cmp0 primary comparison
+ * \param ... secondary, tertiary, ... comparisons
+ * \returns ::gfsmArcCompMask for specified comparisons
+ */
+gfsmArcCompMask gfsm_acmask_from_args(gfsmArcComp cmp0, ...);
+
+/** Create a partial ::gfsmArcCompMask for \a cmp as the \a nth (sub-)comparison */
+GFSM_INLINE
+gfsmArcCompMask gfsm_acmask_new(gfsmArcComp cmp, gint nth);
+
+/** Get \a nth (sub-)comparison from a ::gfsmArcCompMask */
+GFSM_INLINE
+gfsmArcComp gfsm_acmask_nth(gfsmArcCompMask m, gint nth);
+
+/** Get basic \a nth basic (sub-)comparison from a ::gfsmArcCompMask, disregarding sort order */
+GFSM_INLINE
+gfsmArcComp gfsm_acmask_nth_comp(gfsmArcCompMask m, gint nth);
+
+/** Get sort order for \a nth (sub-)comparison of a ::gfsmArcCompMask.
+ * \returns a true value if \a nth sub-comparison is reversed (descending order), otherwise FALSE.
+ */
+GFSM_INLINE
+gboolean gfsm_acmask_nth_reverse(gfsmArcCompMask m, gint nth);
+
+/** Get single character representing the \a nth field of arc comparison mask \a m, as for gfsm_acmask_from_chars() */
+GFSM_INLINE
+gchar gfsm_acmask_nth_char(gfsmArcCompMask m, gint nth);
+
+/** Get a static human-readable string representing the \a nth field of arc comparison mask \a m */
+const gchar *gfsm_acmask_nth_string(gfsmArcCompMask m, gint nth);
+
+/** Populate a character string representing a ::gfsmArcCompMask.
+ * \param mask[in] mask to convert to a string
+ * \param chars[out] character string representing \a mask, in the format acepted by gfsm_acmask_from_chars(),
+ * or NULL to allocate a new string. If specified and non-NULL, \a chars should be
+ * long enough to hold ::gfsmACMaxN+1 characters, since a terminating NUL
+ * is implicitly added as the final character.
+ * \returns \a chars if specified, otherwise a newly allocated string.
+ * \note User is responsible for freeing the returned string with g_free() when it is no longer needed.
+ */
+gchar *gfsm_acmask_to_chars(gfsmArcCompMask m, gchar *chars);
+
+/** Populate a GString* with a human-readable representation of a ::gfsmArcCompMask.
+ * \param mask[in] mask to convert to a string
+ * \param gstr[out] GString representing \a mask, in human-readable format,
+ * or NULL to allocate a new GString*.
+* \returns \a gstr if specified, otherwise a newly allocated GString*.
+ * \note User is responsible for freeing the returned GString* with g_string_free() when it is no longer needed.
+ */
+GString *gfsm_acmask_to_gstring(gfsmArcCompMask m, GString *gstr);
+
+/** Backwards-compatible arc sort mode name resolution function
+ * \deprecated in favor of gfsm_acmask_nth_string(), gfsm_acmask_to_gstring(), gfsm_acmask_to_chars()
+ */
+GFSM_INLINE
+const gchar *gfsm_arc_sortmode_to_name(gfsmArcCompMask m);
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmArc.hi>
+#endif
+
+#endif /* _GFSM_ARC_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArc.hi b/gfsm/gfsm/src/libgfsm/gfsmArc.hi
new file mode 100644
index 0000000..fcd9d79
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArc.hi
@@ -0,0 +1,262 @@
+
+/*=============================================================================*\
+ * File: gfsmArc.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arcs: inline definitions
+ *
+ * Copyright (c) 2004-2008 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <stdlib.h>
+
+/*======================================================================
+ * Methods: Arcs: Constructors etc.
+ */
+
+/*--------------------------------------------------------------
+ * arc_new()
+ */
+GFSM_INLINE
+gfsmArc *gfsm_arc_new(void)
+{
+ return g_new0(gfsmArc,1);
+}
+
+/*--------------------------------------------------------------
+ * arc_init()
+ */
+GFSM_INLINE
+gfsmArc *gfsm_arc_init(gfsmArc *a,
+ gfsmStateId src,
+ gfsmStateId dst,
+ gfsmLabelId lo,
+ gfsmLabelId hi,
+ gfsmWeight wt)
+{
+ if (a) {
+ a->source = src;
+ a->target = dst;
+ a->lower = lo;
+ a->upper = hi;
+ a->weight = wt;
+ }
+ return a;
+}
+
+/*--------------------------------------------------------------
+ * arc_new_full()
+ */
+GFSM_INLINE
+gfsmArc *gfsm_arc_new_full(gfsmStateId src, gfsmStateId dst, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight wt)
+{
+ return gfsm_arc_init(g_new(gfsmArc,1),src,dst,lo,hi,wt);
+}
+
+/*--------------------------------------------------------------
+ * arc_clone()
+ */
+GFSM_INLINE
+gfsmArc *gfsm_arc_clone(gfsmArc *src)
+{
+ gfsmArc *dst = g_new(gfsmArc,1);
+ *dst = *src;
+ return dst;
+}
+
+/*--------------------------------------------------------------
+ * arc_free()
+ */
+GFSM_INLINE
+void gfsm_arc_free(gfsmArc *a)
+{ g_free(a); }
+
+
+/*======================================================================
+ * Methods: Arc Comparison (backwards-compatible)
+ */
+//-- none
+
+/*======================================================================
+ * Methods: arc comparison mask utilties
+ */
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmArcCompMask gfsm_acmask_new(gfsmArcComp cmp, gint nth)
+{
+ return
+#ifdef __cplusplus
+ //-- this kind of crap is the reason i hate c++ --moo
+ static_cast<gfsmArcCompMask>
+#endif
+ ( (cmp&gfsmACAll)<<(nth*gfsmACShift) );
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmArcComp gfsm_acmask_nth(gfsmArcCompMask m, gint nth)
+{
+ return
+#ifdef __cplusplus
+ //-- this kind of crap is the reason i hate c++ --moo
+ static_cast<gfsmArcComp>
+#endif
+ ( (m>>(nth*gfsmACShift))&gfsmACAll );
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmArcComp gfsm_acmask_nth_comp(gfsmArcCompMask m, gint nth)
+{
+ return
+#ifdef __cplusplus
+ //-- this kind of crap is the reason i hate c++ --moo
+ static_cast<gfsmArcComp>(
+ static_cast<gfsmArcCompMask>(gfsm_acmask_nth(m,nth))
+ &
+ ~static_cast<gfsmArcCompMask>(gfsmACReverse)
+ )
+#else
+ gfsm_acmask_nth(m,nth) & (~gfsmACReverse)
+#endif
+ ;
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gboolean gfsm_acmask_nth_reverse(gfsmArcCompMask m, gint nth)
+{ return (gfsm_acmask_nth(m,nth)&gfsmACReverse) ? TRUE : FALSE; }
+
+
+/*======================================================================
+ * Methods: Arc comparison: prioritized
+ */
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gint gfsm_arc_compare_bymask_1_(gfsmArc *a1, gfsmArc *a2, gfsmArcComp cmp, gfsmArcCompData *acdata)
+{
+ switch (cmp) {
+ //
+ //-- forward (ascending)
+ case gfsmACLower:
+ if (a1->lower < a2->lower) return -1;
+ if (a1->lower > a2->lower) return 1;
+ return 0;
+ case gfsmACUpper:
+ if (a1->upper < a2->upper) return -1;
+ if (a1->upper > a2->upper) return 1;
+ return 0;
+ case gfsmACWeight:
+ return acdata->sr ? gfsm_sr_compare(acdata->sr, a1->weight, a2->weight) : 0;
+ case gfsmACSource:
+ if (a1->source < a2->source) return -1;
+ if (a1->source > a2->source) return 1;
+ return 0;
+ case gfsmACTarget:
+ if (a1->target < a2->target) return -1;
+ if (a1->target > a2->target) return 1;
+ return 0;
+ //
+ //-- reverse (descending)
+ case gfsmACLowerR:
+ if (a1->lower < a2->lower) return 1;
+ if (a1->lower > a2->lower) return -1;
+ return 0;
+ case gfsmACUpperR:
+ if (a1->upper < a2->upper) return 1;
+ if (a1->upper > a2->upper) return -1;
+ return 0;
+ case gfsmACWeightR:
+ return acdata->sr ? gfsm_sr_compare(acdata->sr, a2->weight, a1->weight) : 0;
+ case gfsmACSourceR:
+ if (a1->source < a2->source) return 1;
+ if (a1->source > a2->source) return -1;
+ return 0;
+ case gfsmACTargetR:
+ if (a1->target < a2->target) return 1;
+ if (a1->target > a2->target) return -1;
+ return 0;
+ //
+ //-- user
+ case gfsmACUser:
+ if (acdata->user_compare_func) {
+ return (*(acdata->user_compare_func))(a1,a2,acdata->user_data);
+ }
+ //
+ //-- default
+ case gfsmACNone:
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gint gfsm_arc_compare_bymask_inline(gfsmArc *a1, gfsmArc *a2, gfsmArcCompData *acdata)
+{
+ gint rc=0;
+ //-- NULL check
+ if (!a1) {
+ if (!a2) return 0;
+ return 1;
+ }
+ if (!a2) return -1;
+ //
+ if ( (rc=gfsm_arc_compare_bymask_1_(a1,a2,gfsm_acmask_nth(acdata->mask,0),acdata)) ) return rc;
+ if ( (rc=gfsm_arc_compare_bymask_1_(a1,a2,gfsm_acmask_nth(acdata->mask,1),acdata)) ) return rc;
+ if ( (rc=gfsm_arc_compare_bymask_1_(a1,a2,gfsm_acmask_nth(acdata->mask,2),acdata)) ) return rc;
+ if ( (rc=gfsm_arc_compare_bymask_1_(a1,a2,gfsm_acmask_nth(acdata->mask,3),acdata)) ) return rc;
+ if ( (rc=gfsm_arc_compare_bymask_1_(a1,a2,gfsm_acmask_nth(acdata->mask,4),acdata)) ) return rc;
+ if ( (rc=gfsm_arc_compare_bymask_1_(a1,a2,gfsm_acmask_nth(acdata->mask,5),acdata)) ) return rc;
+ return 0;
+}
+
+
+/*======================================================================
+ * Methods: String utilities
+ */
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gchar gfsm_acmask_nth_char(gfsmArcCompMask m, gint nth)
+{
+ switch (gfsm_acmask_nth(m,nth)) {
+ case gfsmACLower: return 'l';
+ case gfsmACUpper: return 'u';
+ case gfsmACWeight: return 'w';
+ case gfsmACSource: return 's';
+ case gfsmACTarget: return 't';
+ //
+ case gfsmACLowerR: return 'L';
+ case gfsmACUpperR: return 'U';
+ case gfsmACWeightR: return 'W';
+ case gfsmACSourceR: return 'S';
+ case gfsmACTargetR: return 'T';
+ //
+ case gfsmACUser: return 'x';
+ case gfsmACNone: return '_';
+ default: return '?';
+ }
+ return '?';
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+const gchar *gfsm_arc_sortmode_to_name(gfsmArcCompMask m)
+{ return gfsm_acmask_nth_string(m,0); }
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcIndex.c b/gfsm/gfsm/src/libgfsm/gfsmArcIndex.c
new file mode 100644
index 0000000..3df0760
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcIndex.c
@@ -0,0 +1,498 @@
+
+/*=============================================================================*\
+ * File: gfsmArcIndex.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc indices
+ *
+ * Copyright (c) 2006-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmArcIndex.h>
+#include <gfsmArcIter.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmArcIndex.hi>
+#endif
+
+/*======================================================================
+ * gfsmReverseArcIndex
+ */
+
+/*--------------------------------------------------------------
+ * automaton_reverse_arc_index()
+ */
+gfsmReverseArcIndex *gfsm_automaton_to_reverse_arc_index(gfsmAutomaton *fsm, gfsmReverseArcIndex *rarcs)
+{
+ gfsmStateId idfrom;
+ gfsmArcIter ai;
+ gfsmArc *arc;
+
+ if (!rarcs) {
+ rarcs = gfsm_reverse_arc_index_sized_new(fsm->states->len);
+ }
+ g_ptr_array_set_size(rarcs,fsm->states->len);
+
+ for (idfrom=0; idfrom < fsm->states->len; idfrom++) {
+ for (gfsm_arciter_open(&ai,fsm,idfrom); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ arc = gfsm_arciter_arc(&ai);
+ g_ptr_array_index(rarcs,arc->target)
+ //= gfsm_arclist_prepend(g_ptr_array_index(rarcs,arc->target), arc);
+ = g_slist_prepend(g_ptr_array_index(rarcs,arc->target),arc);
+ }
+ gfsm_arciter_close(&ai);
+ }
+
+ return rarcs;
+}
+
+/*--------------------------------------------------------------
+ * reverse_arc_index_free()
+ */
+void gfsm_reverse_arc_index_free(gfsmReverseArcIndex *rarcs, gboolean free_lists)
+{
+ guint i;
+ if (free_lists) {
+ //-- +free_lists, -free_arcs
+ for (i=0; i < rarcs->len; i++) { g_slist_free(g_ptr_array_index(rarcs,i)); }
+ }
+
+ //-- free index array
+ g_ptr_array_free(rarcs,TRUE);
+}
+
+
+
+/*======================================================================
+ * gfsmWeightVector
+ */
+
+/*--------------------------------------------------------------
+ * automaton_to_weight_vector()
+ */
+gfsmWeightVector *gfsm_automaton_to_final_weight_vector(gfsmAutomaton *fsm, gfsmWeightVector *wv)
+{
+ gfsmStateId qid;
+ guint n_states = gfsm_automaton_n_states(fsm);
+ gfsmWeight *wp;
+
+ if (wv==NULL) {
+ wv = gfsm_weight_vector_sized_new(n_states);
+ } else {
+ gfsm_weight_vector_resize(wv,n_states);
+ }
+ wv->len = n_states;
+
+ for (qid=0,wp=(gfsmWeight*)wv->data; qid < n_states; qid++,wp++) {
+ gfsm_automaton_lookup_final(fsm,qid,wp);
+ }
+
+ return wv;
+}
+
+/*--------------------------------------------------------------
+ * weight_vector_write_bin_handle()
+ */
+gboolean gfsm_weight_vector_write_bin_handle(gfsmWeightVector *wv, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ guint32 len = wv->len;
+ if (!gfsmio_write(ioh,&len,sizeof(guint32))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("weight_vector_write_bin_handle:len"), //-- code
+ "could not store weight vector length");
+ return FALSE;
+ }
+ if (!gfsmio_write(ioh,wv->data,wv->len*sizeof(gfsmWeight))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("weight_vector_write_bin_handle:weights"), //-- code
+ "could not store weight vector data");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*--------------------------------------------------------------
+ * weight_vector_read_bin_handle()
+ */
+gboolean gfsm_weight_vector_read_bin_handle(gfsmWeightVector *wv, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ guint32 len;
+ if (!gfsmio_read(ioh, &len, sizeof(guint32))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("weight_vector_read_bin_handle:len"), //-- code
+ "could not read weight vector length");
+ return FALSE;
+ }
+ gfsm_weight_vector_resize(wv,len);
+ if (!gfsmio_read(ioh, wv->data, len*sizeof(gfsmWeight))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("weight_vector_read_bin_handle:data"), //-- code
+ "could not read weight vector data");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*======================================================================
+ * gfsmArcTable
+ */
+
+/*--------------------------------------------------------------
+ * automaton_to_arc_table()
+ */
+gfsmArcTable *gfsm_automaton_to_arc_table(gfsmAutomaton *fsm, gfsmArcTable *tab)
+{
+ gfsmStateId qid, n_states=gfsm_automaton_n_states(fsm);
+ guint n_arcs=gfsm_automaton_n_arcs(fsm);
+ gfsmArcIter ai;
+ gfsmArc *arcp;
+
+ //-- maybe allocate
+ if (!tab) {
+ tab = gfsm_arc_table_sized_new(n_arcs);
+ } else {
+ gfsm_arc_table_resize(tab, n_arcs);
+ }
+ tab->len = n_arcs;
+
+ //-- populate arcs
+ for (qid=0,arcp=(gfsmArc*)tab->data; qid < n_states; qid++) {
+ if (!gfsm_automaton_has_state(fsm,qid)) continue;
+ for (gfsm_arciter_open(&ai,fsm,qid); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ *(arcp++) = *a;
+ }
+ gfsm_arciter_close(&ai);
+ }
+
+ //-- return
+ return tab;
+}
+
+/*--------------------------------------------------------------
+ * arc_table_write_bin_handle()
+ */
+gboolean gfsm_arc_table_write_bin_handle(gfsmArcTable *tab, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ guint32 len = tab->len;
+ if (!gfsmio_write(ioh, &len, sizeof(guint32))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_write_bin_handle:len"),
+ "could not write arc table length");
+ return FALSE;
+ }
+ if (!gfsmio_write(ioh, tab->data, len*sizeof(gfsmArc))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_write_bin_handle:data"),
+ "could not write arc table data");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*--------------------------------------------------------------
+ * arc_table_read_bin_handle()
+ */
+gboolean gfsm_arc_table_read_bin_handle(gfsmArcTable *tab, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ guint32 len;
+ if (!gfsmio_read(ioh, &len, sizeof(guint32))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_read_bin_handle:len"),
+ "could not read arc table length");
+ return FALSE;
+ }
+ gfsm_arc_table_resize(tab,len);
+ if (!gfsmio_read(ioh, tab->data, len*sizeof(gfsmArc))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_read_bin_handle:data"),
+ "could not read arc table data");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+/*======================================================================
+ * gfsmArcTableIndex
+ */
+
+/*--------------------------------------------------------------
+ * arc_table_index_copy()
+ */
+gfsmArcTableIndex *gfsm_arc_table_index_copy(gfsmArcTableIndex *dst, gfsmArcTableIndex *src)
+{
+ gfsmStateId i;
+ gfsm_arc_table_copy (dst->tab, src->tab);
+ g_ptr_array_set_size(dst->first, src->first->len);
+
+ for (i=0; i < src->first->len; i++) {
+ gint offset = (gfsmArc*)g_ptr_array_index(src->first,i) - (gfsmArc*)src->tab->data;
+ g_ptr_array_index(dst->first,i) = (gfsmArc*)dst->tab->data + offset;
+ }
+
+ return dst;
+}
+
+
+/*--------------------------------------------------------------
+ * automaton_to_arc_table_index()
+ */
+gfsmArcTableIndex *gfsm_automaton_to_arc_table_index(gfsmAutomaton *fsm, gfsmArcTableIndex *tabx)
+{
+ gfsmStateId qid, n_states=gfsm_automaton_n_states(fsm);
+ guint n_arcs=gfsm_automaton_n_arcs(fsm);
+ gfsmArc *arcp, *arcp_max;
+ gfsmArc **firstp;
+
+ //-- maybe allocate
+ if (!tabx) {
+ tabx = gfsm_arc_table_index_sized_new(n_states, n_arcs);
+ } else {
+ gfsm_arc_table_index_resize(tabx, n_states, n_arcs);
+ }
+
+ //-- populate tabx->arcs
+ gfsm_automaton_to_arc_table(fsm,tabx->tab);
+
+ //-- populate tabx->first
+ arcp = (gfsmArc*)tabx->tab->data;
+ arcp_max = arcp + n_arcs;
+ for (qid=0,firstp=(gfsmArc**)tabx->first->pdata; qid<n_states; qid++,firstp++) {
+ *firstp = arcp;
+ for ( ; arcp<arcp_max && arcp->source==qid; arcp++) { ; }
+ }
+ *firstp = arcp_max;
+
+ //-- return
+ return tabx;
+}
+
+/*--------------------------------------------------------------
+ * arc_table_index_sort_with_data()
+ */
+void gfsm_arc_table_index_sort_with_data(gfsmArcTableIndex *tabx, GCompareDataFunc compare_func, gpointer data)
+{
+ gfsmArc **firstp = (gfsmArc**)tabx->first->pdata;
+ gfsmArc **firstp_max = firstp + tabx->first->len - 1;
+ for ( ; firstp < firstp_max; firstp++) {
+ gfsmArc *min = *firstp;
+ gfsmArc *max = *(firstp+1);
+ g_qsort_with_data(min, max-min, sizeof(gfsmArc), compare_func, data);
+ }
+}
+
+/*--------------------------------------------------------------
+ * arc_table_index_write_bin_handle()
+ */
+gboolean gfsm_arc_table_index_write_bin_handle(gfsmArcTableIndex *tabx, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmStateId first_len=tabx->first->len, qid;
+ if (!gfsm_arc_table_write_bin_handle(tabx->tab, ioh, errp)) return FALSE;
+
+ if (!gfsmio_write(ioh, &first_len, sizeof(gfsmStateId))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_index_write_bin_handle:len"),
+ "could not write arc table index 'first' length");
+ return FALSE;
+ }
+ for (qid=0; qid < first_len; qid++) {
+ gfsmArc *a = (gfsmArc*)g_ptr_array_index(tabx->first,qid);
+ guint32 offset = a - ((gfsmArc*)tabx->tab->data);
+ if (!gfsmio_write(ioh, &offset, sizeof(guint32))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_index_write_bin_handle:data"),
+ "could not write state arc offset for state '%u'", qid);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*--------------------------------------------------------------
+ * arc_table_index_read_bin_handle()
+ */
+gboolean gfsm_arc_table_index_read_bin_handle(gfsmArcTableIndex *tabx, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmStateId first_len, qid;
+ if (!gfsm_arc_table_read_bin_handle(tabx->tab, ioh, errp)) return FALSE;
+
+ if (!gfsmio_read(ioh, &first_len, sizeof(gfsmStateId))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_index_read_bin_handle:len"),
+ "could not read arc table index 'first' length");
+ return FALSE;
+ }
+ g_ptr_array_set_size(tabx->first,first_len);
+ for (qid=0; qid < first_len; qid++) {
+ guint32 offset;
+ if (!gfsmio_read(ioh, &offset, sizeof(guint32))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("arc_table_index_write_bin_handle:data"),
+ "could not read state arc offset for state '%u'", qid);
+ return FALSE;
+ }
+ g_ptr_array_index(tabx->first,qid) = &g_array_index(tabx->tab,gfsmArc,offset);
+ }
+ return TRUE;
+}
+
+
+/*======================================================================
+ * gfsmArcLabelIndex [GONE]
+ */
+//--------------------------------------------------------------
+// arc_label_index_compare_arcs()
+/*
+gint gfsm_arc_label_index_compare_arcs(gfsmArc *a1, gfsmArc *a2, gfsmArcLabelIndexSortData *sdata)
+{ return gfsm_arc_label_index_compare_arcs_inline(a1,a2,sdata); }
+*/
+
+
+/*======================================================================
+ * gfsmArcRange
+ */
+
+#undef GFSM_ARCRANGE_ENABLE_BSEARCH
+#undef GFSM_ARCRANGE_ENABLE_SEEK
+
+#ifdef GFSM_ARCRANGE_ENABLE_BSEARCH
+/*--------------------------------------------------------------
+ * arc_range_bsearch_*()
+ * + NOT WORTH IT (tested for out_degree {1,2,4,8,16,32,64,128,256,512})
+ */
+void gfsm_arcrange_bsearch_source(gfsmArcRange *range, gfsmStateId find)
+{
+ gfsmArc *min=range->min, *max=range->max;
+ while (min < max) {
+ gfsmArc *mid = min + (max-min)/2;
+ if (mid->source < find) { min = mid+1; }
+ else { max = mid; }
+ }
+ range->min = min;
+}
+
+//--------------------------------------------------------------
+void gfsm_arcrange_bsearch_target(gfsmArcRange *range, gfsmStateId find)
+{
+ gfsmArc *min=range->min, *max=range->max;
+ while (min < max) {
+ gfsmArc *mid = min + (max-min)/2;
+ if (mid->target < find) { min = mid+1; }
+ else { max = mid; }
+ }
+ range->min = min;
+}
+
+//--------------------------------------------------------------
+void gfsm_arcrange_bsearch_lower(gfsmArcRange *range, gfsmLabelId find)
+{
+ gfsmArc *min=range->min, *max=range->max;
+ while (min < max) {
+ gfsmArc *mid = min + (max-min)/2;
+ if (mid->lower < find) { min = mid+1; }
+ else { max = mid; }
+ }
+ range->min = min;
+}
+
+//--------------------------------------------------------------
+void gfsm_arcrange_bsearch_upper(gfsmArcRange *range, gfsmLabelId find)
+{
+ gfsmArc *min=range->min, *max=range->max;
+ while (min < max) {
+ gfsmArc *mid = min + (max-min)/2;
+ if (mid->upper < find) { min = mid+1; }
+ else { max = mid; }
+ }
+ range->min = min;
+}
+
+//--------------------------------------------------------------
+void gfsm_arcrange_bsearch_weight(gfsmArcRange *range, gfsmWeight find, gfsmSemiring *sr)
+{
+ gfsmArc *min=range->min, *max=range->max;
+ while (min < max) {
+ gfsmArc *mid = min + (max-min)/2;
+ if (gfsm_sr_compare(sr,mid->weight,find) < 0) { range->min = mid+1; }
+ else { range->max = mid; }
+ }
+ range->min = min;
+}
+#endif /* GFSM_ARCRANGE_ENABLE_BSEARCH */
+
+#ifdef GFSM_ARCRANGE_ENABLE_SEEK
+//--------------------------------------------------------------
+// arcrange_seek_X()
+// -- also not worth it
+
+//----------------------------------------------
+GFSM_INLINE
+void gfsm_arcrange_seek_source(gfsmArcRange *range, gfsmStateId find)
+{
+ gfsm_assert(range != NULL);
+ while (gfsm_arcrange_ok(range) && gfsm_arcrange_arc(range)->source < find)
+ gfsm_arcrange_next(range);
+}
+
+//----------------------------------------------
+GFSM_INLINE
+void gfsm_arcrange_seek_target(gfsmArcRange *range, gfsmStateId find)
+{
+ gfsm_assert(range != NULL);
+ while (gfsm_arcrange_ok(range) && gfsm_arcrange_arc(range)->target < find)
+ gfsm_arcrange_next(range);
+}
+
+//----------------------------------------------
+GFSM_INLINE
+void gfsm_arcrange_seek_lower(gfsmArcRange *range, gfsmLabelId find)
+{
+ gfsm_assert(range != NULL);
+ while (gfsm_arcrange_ok(range) && gfsm_arcrange_arc(range)->lower < find)
+ gfsm_arcrange_next(range);
+}
+
+//----------------------------------------------
+GFSM_INLINE
+void gfsm_arcrange_seek_upper(gfsmArcRange *range, gfsmLabelId find)
+{
+ gfsm_assert(range != NULL);
+ while (gfsm_arcrange_ok(range) && gfsm_arcrange_arc(range)->upper < find)
+ gfsm_arcrange_next(range);
+}
+
+//----------------------------------------------
+GFSM_INLINE
+void gfsm_arcrange_seek_weight(gfsmArcRange *range, gfsmWeight find, gfsmSemiring *sr)
+{
+ gfsm_assert(range != NULL);
+ while (gfsm_arcrange_ok(range) && gfsm_sr_compare(sr,gfsm_arcrange_arc(range)->weight,find) < 0)
+ gfsm_arcrange_next(range);
+}
+#endif /* GFSM_ARCRANGE_ENABLE_SEEK */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcIndex.h b/gfsm/gfsm/src/libgfsm/gfsmArcIndex.h
new file mode 100644
index 0000000..db3f19b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcIndex.h
@@ -0,0 +1,360 @@
+
+/*=============================================================================*\
+ * File: gfsmArcIndex.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc indices
+ *
+ * Copyright (c) 2006-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmArcIndex.h
+ * \brief Arc (transition) index utilities
+ */
+
+#ifndef _GFSM_ARCINDEX_H
+#define _GFSM_ARCINDEX_H
+
+#include <gfsmAutomaton.h>
+#include <gfsmIO.h>
+
+/*======================================================================
+ * ReverseArcIndex
+ */
+///\name gfsmReverseArcIndex
+//@{
+
+/// Reverse arc-index type
+/** \a element at \a qto is a GSList*
+ * which contains a data element \a gfsmArc* \a arc={qfrom,qto,lo,hi,w}
+ * whenever source \a fsm contains an arc \a arc={qfrom,qto,lo,hi,w}
+ * from \a qfrom.
+ *
+ * \note
+ * arc data pointed to is shared by source automaton
+ * and the ::gfsmReverseArcIndex!
+ */
+typedef GPtrArray gfsmReverseArcIndex;
+
+/** Create and return a new ::gfsmReverseArcIndex
+ * \note
+ * Caller is responsible for freeing the returned index when it is no longer needed.
+ */
+GFSM_INLINE
+gfsmReverseArcIndex *gfsm_reverse_arc_index_new(void);
+
+/** Create a new ::gfsmReverseArcIndex, given number of states to be indexed
+ * \note
+ * Caller is responsible for freeing the returned index when it is no longer needed.
+ */
+GFSM_INLINE
+gfsmReverseArcIndex *gfsm_reverse_arc_index_sized_new(gfsmStateId n_states);
+
+/** Populate a reversed arc index for \a fsm.
+ * \param fsm source automaton
+ * \param rarcs
+ * Reverse arc index.
+ * May be passed as NULL to create a new arc index.
+ * \returns
+ * \a rarcs if non-NULL, otherwise a new reverse arc index for \a fsm.
+ * \note
+ * Caller is responsible for freeing the returned index when it is no longer needed.
+ */
+gfsmReverseArcIndex *gfsm_automaton_to_reverse_arc_index(gfsmAutomaton *fsm, gfsmReverseArcIndex *rarcs);
+
+/** Backwards-compatible alias for gfsm_automaton_to_reverse_arc_inde() */
+#define gfsm_automaton_reverse_arc_index gfsm_automaton_to_reverse_arc_index
+
+/** Free a ::gfsmReverseArcIndex
+ * \param rarcs
+ * reverse arc-index to be freed
+ * \param free_lists
+ * If true, associated arc-lists will be freed.
+ */
+void gfsm_reverse_arc_index_free(gfsmReverseArcIndex *rarcs, gboolean free_lists);
+
+//@}
+
+
+/*======================================================================
+ * gfsmFinalWeightIndex
+ */
+///\name gfsmFinalWeightIndex
+//@{
+
+/** GArray of ::gfsmWeight, indexed e.g. by ::gfsmStateId */
+typedef GArray gfsmWeightVector;
+
+/** Create a new (empty) ::gfsmWeightVector
+ * \note
+ * Caller is responsible for freeing \a wv when it is no longer needed.
+ */
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_new(void);
+
+/** Create a new (empty) ::gfsmWeightVector, specifying initial size
+ * \note
+ * Caller is responsible for freeing the returned index when it is no longer needed.
+ */
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_sized_new(guint size);
+
+/** Copy a ::gfsmWeightVector \a src to \a dst. \returns \a dst */
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_copy(gfsmWeightVector *dst, gfsmWeightVector *src);
+
+/** Create and return an exact clone of a ::gfsmWeightVector */
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_clone(gfsmWeightVector *src);
+
+
+/** Set size of a ::gfsmWeightVector */
+GFSM_INLINE
+void gfsm_weight_vector_resize(gfsmWeightVector *wv, guint size);
+
+/** Populate a ::gfsmWeightVector of state final weights in a ::gfsmAutomaton
+ * \param fsm source automaton
+ * \param wv
+ * Final weight index
+ * May be passed as NULL to create a new index.
+ * \returns \a wv if non-NULL, otherwise a new final weight index for \a fsm.
+ */
+gfsmWeightVector *gfsm_automaton_to_final_weight_vector(gfsmAutomaton *fsm, gfsmWeightVector *wv);
+
+/** Free a ::gfsmWeightVector */
+GFSM_INLINE
+void gfsm_weight_vector_free(gfsmWeightVector *wv);
+
+/** Write the contents of a ::gfsmWeightVector to a (binary) ::gfsmIOHandle.
+ * \param wv weight vector to write
+ * \param ioh handle to which data is to be written
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_weight_vector_write_bin_handle(gfsmWeightVector *wv, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Read the contents of a ::gfsmWeightVector from a (binary) ::gfsmIOHandle.
+ * \param wv weight vector into which data is to be read
+ * \param ioh handle from which data is to be read
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_weight_vector_read_bin_handle(gfsmWeightVector *wv, gfsmIOHandle *ioh, gfsmError **errp);
+
+//@}
+
+/*======================================================================
+ * gfsmArcTable
+ */
+///\name gfsmArcTable
+//@{
+
+/// Type for dedicated block-wise storage of ::gfsmArc data: GArray of ::gfsmArc
+typedef GArray gfsmArcTable;
+
+/** Create and return a new (empty) ::gfsmArcTable */
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_new(void);
+
+/** Create and return a new (empty) ::gfsmArcTable, specifying size */
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_sized_new(guint n_arcs);
+
+/** Resize a ::gfsmArcTable */
+GFSM_INLINE
+void gfsm_arc_table_resize(gfsmArcTable *tab, guint n_arcs);
+
+/** Copy a ::gfsmArcTable \a src to \a dst. \returns \a dst. */
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_copy(gfsmArcTable *dst, gfsmArcTable *src);
+
+/** Create and return an exact copy of a ::gfsmArcTable \a src */
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_clone(gfsmArcTable *src);
+
+/** Free a ::gfsmArcTable */
+GFSM_INLINE
+void gfsm_arc_table_free(gfsmArcTable *tab);
+
+/** Populate a :gfsmArcTable by copying arcs from \a fsm
+ * \param fsm source automaton
+ * \param tab
+ * arc table to populate.
+ * May be passed as NULL to create a new arc table.
+ * \returns
+ * \a tab if non-NULL, otherwise a new ::gfsmArcTable for \a fsm.
+ * \note
+ * Caller is responsible for freeing \a tab when it is no longer needed.
+ */
+gfsmArcTable *gfsm_automaton_to_arc_table(gfsmAutomaton *fsm, gfsmArcTable *tab);
+
+/** Sort all arcs in a ::gfsmArcTable using a user-specified comparison function */
+GFSM_INLINE
+void gfsm_arc_table_sort_with_data(gfsmArcTable *tab, GCompareDataFunc compare_func, gpointer data);
+
+/** Sort arcs by comparison priority in a ::gfsmArcTable */
+GFSM_INLINE
+void gfsm_arc_table_sort_bymask(gfsmArcTable *tab, gfsmArcCompMask m, gfsmSemiring *sr);
+
+/** Write the contents of a ::gfsmArcTable to a (binary) ::gfsmIOHandle.
+ * \param tab table to write
+ * \param ioh handle to which data is to be written
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_arc_table_write_bin_handle(gfsmArcTable *tab, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Read the contents of a ::gfsmArcTable from a (binary) ::gfsmIOHandle.
+ * \param tab table into which data is to be read
+ * \param ioh handle from which data is to be read
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_arc_table_read_bin_handle(gfsmArcTable *tab, gfsmIOHandle *ioh, gfsmError **errp);
+
+//@}
+
+/*======================================================================
+ * gfsmArcTableIndex
+ */
+///\name gfsmArcTableIndex
+//@{
+
+/// Basic type for dedicated arc storage state-based arc index
+typedef struct {
+ gfsmArcTable *tab; /**< arc table, sorted by (source,...) */
+ GPtrArray *first; /**< \a first[q] is address of first element of \a arcs->data for state \a q (a ::gfsmArc*) */
+} gfsmArcTableIndex;
+
+/** Create and return a new (empty) ::gfsmArcTableIndex */
+GFSM_INLINE
+gfsmArcTableIndex *gfsm_arc_table_index_new(void);
+
+/** Create and return a new (empty) ::gfsmArcTableIndex, specifying sizes */
+GFSM_INLINE
+gfsmArcTableIndex *gfsm_arc_table_index_sized_new(gfsmStateId n_states, guint n_arcs);
+
+/** Resize a ::gfsmArcTableIndex */
+GFSM_INLINE
+void gfsm_arc_table_index_resize(gfsmArcTableIndex *tab, gfsmStateId n_states, guint n_arcs);
+
+/** Get number of states allocated for a ::gfsmArcTableIndex */
+GFSM_INLINE
+gfsmStateId gfsm_arc_table_index_n_states(gfsmArcTableIndex *tabx);
+
+/** Get number of arcs allocated for a ::gfsmArcTableIndex */
+GFSM_INLINE
+guint gfsm_arc_table_index_n_arcs(gfsmArcTableIndex *tabx);
+
+/** Copy a ::gfsmArcTableIndex \a src to \a dst. \returns \a dst. */
+gfsmArcTableIndex *gfsm_arc_table_index_copy(gfsmArcTableIndex *dst, gfsmArcTableIndex *src);
+
+/** Create and return an exact copy of a ::gfsmArcTableIndex \a src */
+GFSM_INLINE
+gfsmArcTableIndex *gfsm_arc_table_index_clone(gfsmArcTableIndex *src);
+
+/** Free a ::gfsmArcTableIndex */
+GFSM_INLINE
+void gfsm_arc_table_index_free(gfsmArcTableIndex *tabx);
+
+/** Populate a ::gfsmArcTableIndex by indexing outgoing arcs from each state in \a fsm.
+ * \param fsm source automaton
+ * \param tabx
+ * Indexed arc table to populate.
+ * May be passed as NULL to create a new indexed arc table.
+ * \returns
+ * \a tabx if non-NULL, otherwise a new index for \a fsm.
+ * \note
+ * \li Caller is responsible for freeing \a tabx when it is no longer needed.
+ */
+gfsmArcTableIndex *gfsm_automaton_to_arc_table_index(gfsmAutomaton *fsm, gfsmArcTableIndex *tabx);
+
+/** Sort arcs state-wise in a ::gfsmArcTableIndex */
+void gfsm_arc_table_index_sort_with_data(gfsmArcTableIndex *tabx, GCompareDataFunc compare_func, gpointer data);
+
+/** Sort arcs state-wise by field priority in a ::gfsmArcTableIndex.
+ * Really just a wrapper for gfsm_arc_table_index_sort_with_data()
+ */
+GFSM_INLINE
+void gfsm_arc_table_index_sort_bymask(gfsmArcTableIndex *tabx, gfsmArcCompMask m, gfsmSemiring *sr);
+
+/** Get number of outgoing arcs from state \a qid in \a tabx */
+GFSM_INLINE
+guint gfsm_arc_table_index_out_degree(gfsmArcTableIndex *tabx, gfsmStateId qid);
+
+/** Write the contents of a ::gfsmArcTableIndex to a (binary) ::gfsmIOHandle.
+ * \param tabx index to write
+ * \param ioh handle to which data is to be written
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_arc_table_index_write_bin_handle(gfsmArcTableIndex *tabx, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Read the contents of a ::gfsmArcTableIndex from a (binary) ::gfsmIOHandle.
+ * \param tabx table into which data is to be read
+ * \param ioh handle from which data is to be read
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_arc_table_index_read_bin_handle(gfsmArcTableIndex *tabx, gfsmIOHandle *ioh, gfsmError **errp);
+
+//@}
+
+/*======================================================================
+ * gfsmArcRange
+ */
+///\name gfsmArcRange
+//@{
+
+/// Type for searching and iterating over arcs in a ::gfsmArcTable
+typedef struct {
+ gfsmArc *min; /**< First (current) arc in range */
+ gfsmArc *max; /**< First arc \b not in range */
+} gfsmArcRange;
+
+/** Open a ::gfsmArcRange for all outgoing arcs from state \a qid in \a tabx */
+GFSM_INLINE
+void gfsm_arcrange_open_table_index(gfsmArcRange *range, gfsmArcTableIndex *tabx, gfsmStateId qid);
+
+/** Close a ::gfsmArcRange (currently does nothing really useful) */
+GFSM_INLINE
+void gfsm_arcrange_close(gfsmArcRange *range);
+
+/** Check validity of a ::gfsmArcRange */
+GFSM_INLINE
+gboolean gfsm_arcrange_ok(gfsmArcRange *range);
+
+/** Get current arc from a ::gfsmArcRange, which is assumed to be valid */
+GFSM_INLINE
+gfsmArc *gfsm_arcrange_arc(gfsmArcRange *range);
+
+/** Increment current arc of a ::gfsmArcRange */
+GFSM_INLINE
+void gfsm_arcrange_next(gfsmArcRange *range);
+
+//@}
+
+/*======================================================================
+ * inline definitions
+ */
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmArcIndex.hi>
+#endif
+
+/*======================================================================
+ * END
+ */
+#endif /* _GFSM_ARCINDEX_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcIndex.hi b/gfsm/gfsm/src/libgfsm/gfsmArcIndex.hi
new file mode 100644
index 0000000..3cd7b49
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcIndex.hi
@@ -0,0 +1,325 @@
+
+/*=============================================================================*\
+ * File: gfsmArcIndex.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc indices: inline definitions
+ *
+ * Copyright (c) 2006-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmAssert.h>
+
+/*======================================================================
+ * ReverseArcIndex
+ */
+
+//--------------------------------------------------------------
+// reverse_arc_index_new()
+GFSM_INLINE
+gfsmReverseArcIndex *gfsm_reverse_arc_index_new(void)
+{ return g_ptr_array_new(); }
+
+//--------------------------------------------------------------
+// reverse_arc_index_sized_new()
+GFSM_INLINE
+gfsmReverseArcIndex *gfsm_reverse_arc_index_sized_new(gfsmStateId n_states)
+{ return g_ptr_array_sized_new(n_states); }
+
+//--------------------------------------------------------------
+// automaton_to_reverse_arc_index()
+//--extern
+
+//--------------------------------------------------------------
+// reverse_arc_index_free()
+//--extern
+
+//@}
+
+/*======================================================================
+ * gfsmWeightVector
+ */
+
+//--------------------------------------------------------------
+// weight_vector_new()
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_new(void)
+{ return g_array_new(FALSE,FALSE,sizeof(gfsmWeight)); }
+
+//--------------------------------------------------------------
+// weight_vector_sized_new()
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_sized_new(gfsmStateId n_states)
+{ return g_array_sized_new(FALSE,FALSE,sizeof(gfsmWeight),n_states); }
+
+//--------------------------------------------------------------
+// weight_vector_copy()
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_copy(gfsmWeightVector *dst, gfsmWeightVector *src)
+{
+ g_array_set_size(dst, src->len);
+ dst->len = 0;
+ g_array_append_vals(dst, src->data, src->len);
+ return dst;
+}
+
+//--------------------------------------------------------------
+// weight_vector_clone()
+GFSM_INLINE
+gfsmWeightVector *gfsm_weight_vector_clone(gfsmWeightVector *src)
+{
+ return gfsm_weight_vector_copy(gfsm_weight_vector_sized_new(src->len), src);
+}
+
+
+//--------------------------------------------------------------
+// weight_vector_resize()
+GFSM_INLINE
+void gfsm_weight_vector_resize(gfsmWeightVector *wv, gfsmStateId n_states)
+{
+ g_array_set_size(wv,n_states);
+ wv->len = n_states;
+}
+
+//--------------------------------------------------------------
+// weight_vector_free()
+GFSM_INLINE
+void gfsm_weight_vector_free(gfsmWeightVector *wv)
+{ g_array_free(wv,TRUE); }
+
+//--------------------------------------------------------------
+// automaton_weight_vector()
+//-- extern
+
+
+/*======================================================================
+ * gfsmArcTable
+ */
+
+//--------------------------------------------------------------
+// arc_table_new()
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_new(void)
+{ return g_array_new(FALSE,FALSE,sizeof(gfsmArc)); }
+
+//--------------------------------------------------------------
+// arc_table_sized_new()
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_sized_new(guint n_arcs)
+{ return g_array_sized_new(FALSE,FALSE,sizeof(gfsmArc),n_arcs); }
+
+//--------------------------------------------------------------
+// arc_table_resize()
+GFSM_INLINE
+void gfsm_arc_table_resize(gfsmArcTable *tab, guint n_arcs)
+{
+ g_array_set_size(tab,n_arcs);
+ tab->len = n_arcs;
+}
+
+//--------------------------------------------------------------
+// arc_table_copy()
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_copy(gfsmArcTable *dst, gfsmArcTable *src)
+{
+ g_array_set_size(dst, src->len);
+ dst->len = 0;
+ g_array_append_vals(dst, src->data, src->len);
+ return dst;
+}
+
+//--------------------------------------------------------------
+// arc_table_clone()
+GFSM_INLINE
+gfsmArcTable *gfsm_arc_table_clone(gfsmArcTable *src)
+{
+ return gfsm_arc_table_copy(gfsm_arc_table_sized_new(src->len), src);
+}
+
+//--------------------------------------------------------------
+// arc_table_free()
+GFSM_INLINE
+void gfsm_arc_table_free(gfsmArcTable *tab)
+{ g_array_free(tab,TRUE); }
+
+//--------------------------------------------------------------
+// arc_table_sort_with_data()
+GFSM_INLINE
+void gfsm_arc_table_sort_with_data(gfsmArcTable *tab, GCompareDataFunc compare_func, gpointer data)
+{ g_array_sort_with_data(tab,compare_func,data); }
+
+//--------------------------------------------------------------
+// arc_table_sort_bymask()
+GFSM_INLINE
+void gfsm_arc_table_sort_bymask(gfsmArcTable *tab, gfsmArcCompMask m, gfsmSemiring *sr)
+{
+ gfsmArcCompData acdata = { m,sr,NULL,NULL };
+ gfsm_arc_table_sort_with_data(tab, (GCompareDataFunc)gfsm_arc_compare_bymask, &acdata);
+}
+
+
+/*======================================================================
+ * gfsmArcTableIndex
+ */
+
+//--------------------------------------------------------------
+// arc_table_index_new()
+GFSM_INLINE
+gfsmArcTableIndex *gfsm_arc_table_index_new(void)
+{
+ gfsmArcTableIndex *tabx = g_new(gfsmArcTableIndex,1);
+ tabx->tab = gfsm_arc_table_new();
+ tabx->first = g_ptr_array_new();
+ return tabx;
+}
+
+//--------------------------------------------------------------
+// arc_table_index_init() [UNDECLARED]
+GFSM_INLINE
+void gfsm_arc_table_index_init(gfsmArcTableIndex *tabx, gfsmStateId n_states, guint n_arcs)
+{
+ tabx->tab = gfsm_arc_table_sized_new(n_arcs);
+ tabx->first = g_ptr_array_sized_new(n_states+1);
+}
+
+//--------------------------------------------------------------
+// arc_table_index_sized_new()
+GFSM_INLINE
+gfsmArcTableIndex *gfsm_arc_table_index_sized_new(gfsmStateId n_states, guint n_arcs)
+{
+ gfsmArcTableIndex *tabx = g_new(gfsmArcTableIndex,1);
+ gfsm_arc_table_index_init(tabx, n_states, n_arcs);
+ return tabx;
+}
+
+//--------------------------------------------------------------
+// arc_table_index_resize()
+GFSM_INLINE
+void gfsm_arc_table_index_resize(gfsmArcTableIndex *tabx, gfsmStateId n_states, guint n_arcs)
+{
+ gfsm_arc_table_resize(tabx->tab, n_arcs);
+ g_ptr_array_set_size(tabx->first, n_states+1);
+ tabx->first->len = n_states+1;
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmStateId gfsm_arc_table_index_n_states(gfsmArcTableIndex *tabx)
+{ return tabx->first->len - 1; }
+
+//--------------------------------------------------------------
+GFSM_INLINE
+guint gfsm_arc_table_index_n_arcs(gfsmArcTableIndex *tabx)
+{ return tabx->tab->len; }
+
+
+//--------------------------------------------------------------
+// arc_table_index_clone()
+GFSM_INLINE
+gfsmArcTableIndex *gfsm_arc_table_index_clone(gfsmArcTableIndex *src)
+{
+ return gfsm_arc_table_index_copy(gfsm_arc_table_index_sized_new(gfsm_arc_table_index_n_states(src),
+ gfsm_arc_table_index_n_arcs(src)),
+ src);
+}
+
+
+//--------------------------------------------------------------
+// arc_table_index_free()
+GFSM_INLINE
+void gfsm_arc_table_index_free(gfsmArcTableIndex *tabx)
+{
+ if (!tabx) return;
+ if (tabx->tab) gfsm_arc_table_free(tabx->tab);
+ if (tabx->first) g_ptr_array_free(tabx->first, TRUE);
+ g_free(tabx);
+}
+
+//--------------------------------------------------------------
+// arc_table_index_sort_bymask()
+GFSM_INLINE
+void gfsm_arc_table_index_sort_bymask(gfsmArcTableIndex *tabx, gfsmArcCompMask m, gfsmSemiring *sr)
+{
+ gfsmArcCompData acdata = { m,sr,NULL,NULL };
+ gfsm_arc_table_index_sort_with_data(tabx, (GCompareDataFunc)gfsm_arc_compare_bymask, &acdata);
+}
+
+//--------------------------------------------------------------
+// arc_table_index_out_degree()
+GFSM_INLINE
+guint gfsm_arc_table_index_out_degree(gfsmArcTableIndex *tabx, gfsmStateId qid)
+{
+ //if (qid+1 >= tabx->first->len) return 0;
+ gfsm_assert( (qid+1) < tabx->first->len );
+ return ((gfsmArc*)g_ptr_array_index(tabx->first,qid+1)) - ((gfsmArc*)g_ptr_array_index(tabx->first,qid));
+}
+
+
+
+/*======================================================================
+ * gfsmArcRange
+ */
+
+//--------------------------------------------------------------
+// arcrange_open_table_index()
+GFSM_INLINE
+void gfsm_arcrange_open_table_index(gfsmArcRange *range, gfsmArcTableIndex *tabx, gfsmStateId qid)
+{
+ gfsm_assert(range!=NULL);
+ gfsm_assert(qid < tabx->first->len-1);
+ range->min = (gfsmArc*)g_ptr_array_index(tabx->first, qid );
+ range->max = (gfsmArc*)g_ptr_array_index(tabx->first, qid+1);
+}
+
+//--------------------------------------------------------------
+// arcrange_close()
+GFSM_INLINE
+void gfsm_arcrange_close(gfsmArcRange *range)
+{
+ gfsm_assert(range!=NULL);
+ range->min = range->max = NULL;
+}
+
+//--------------------------------------------------------------
+// arcrange_ok()
+GFSM_INLINE
+gboolean gfsm_arcrange_ok(gfsmArcRange *range)
+{
+ gfsm_assert(range!=NULL);
+ return range->min < range->max;
+}
+
+//--------------------------------------------------------------
+// arcrange_arc()
+GFSM_INLINE
+gfsmArc *gfsm_arcrange_arc(gfsmArcRange *range)
+{
+ gfsm_assert(range!=NULL);
+ return range->min;
+}
+
+//--------------------------------------------------------------
+// arcrange_next()
+GFSM_INLINE
+void gfsm_arcrange_next(gfsmArcRange *range)
+{
+ gfsm_assert(range!=NULL);
+ range->min++;
+}
+
+/*======================================================================
+ * END
+ */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcIter.c b/gfsm/gfsm/src/libgfsm/gfsmArcIter.c
new file mode 100644
index 0000000..6a6d51e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcIter.c
@@ -0,0 +1,78 @@
+
+/*=============================================================================*\
+ * File: gfsmArcIter.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc iterators
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmArcIter.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmArcIter.hi>
+#endif
+
+/*======================================================================
+ * Methods: Arc iterators: open/close
+ */
+
+/*======================================================================
+ * Methods: Arc iterators: Accessors
+ */
+
+
+//--------------------------------------------------------------
+// seek_lower()
+void gfsm_arciter_seek_lower(gfsmArcIter *aip, gfsmLabelVal lo)
+{
+ for ( ; gfsm_arciter_ok(aip); gfsm_arciter_next(aip)) {
+ if (gfsm_arciter_arc(aip)->lower == lo) break;
+ }
+}
+
+//--------------------------------------------------------------
+// seek_upper()
+void gfsm_arciter_seek_upper(gfsmArcIter *aip, gfsmLabelVal hi)
+{
+ for ( ; gfsm_arciter_ok(aip); gfsm_arciter_next(aip)) {
+ if (gfsm_arciter_arc(aip)->upper == hi) break;
+ }
+}
+
+//--------------------------------------------------------------
+// seek_both()
+void gfsm_arciter_seek_both(gfsmArcIter *aip, gfsmLabelVal lo, gfsmLabelVal hi)
+{
+ for ( ; gfsm_arciter_ok(aip); gfsm_arciter_next(aip)) {
+ gfsmArc *a = gfsm_arciter_arc(aip);
+ if ((lo==gfsmNoLabel || a->lower==lo) && (hi==gfsmNoLabel || a->upper==hi)) break;
+ }
+}
+
+
+//--------------------------------------------------------------
+// seek_user()
+void gfsm_arciter_seek_user(gfsmArcIter *aip,
+ gfsmArcIterSeekFunc seekfunc,
+ gpointer data)
+{
+ for ( ; gfsm_arciter_ok(aip); gfsm_arciter_next(aip)) {
+ if ((*seekfunc)(aip,data)) break;
+ }
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcIter.h b/gfsm/gfsm/src/libgfsm/gfsmArcIter.h
new file mode 100644
index 0000000..ff96994
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcIter.h
@@ -0,0 +1,202 @@
+
+/*=============================================================================*\
+ * File: gfsmArcIter.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc iterators
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmArcIter.h
+ * \brief Iterate over outgoing arcs of an automaton state.
+ */
+
+#ifndef _GFSM_ARCITER_H
+#define _GFSM_ARCITER_H
+
+#include <gfsmAutomaton.h>
+
+/*======================================================================
+ * Types: Arc iterators
+ */
+/// Abstract type for arc iterators
+typedef struct {
+ gfsmAutomaton *fsm; /**< fsm holding these arcs */
+ gfsmState *state; /**< state holding these arcs */
+ gfsmArcList *arcs; /**< pointer to node for current arc */
+} gfsmArcIter;
+
+/*======================================================================
+ * Methods: Arc iterators: open/close
+ */
+///\name Arc Iterators: Constructors etc.
+//@{
+/** Open a ::gfsmArcIter \a aip for the outgoing arcs from state with ID \a qid in the automaton \a fsm.
+ * \param aip Pointer to the ::gfsmArcIter to be opened; assumed to be already allocated
+ * \param fsm Automaton containing the state whose outgoing arcs are to be opened
+ * \param qid ID of the state whose outgoing arcs are to be opened
+ *
+ * \note
+ * \li Arc iterators may be silently invalidated by destructive operations
+ * \li The arc iterator should be closed with gfsm_arciter_close() when it is no longer needed.
+ * \li Caller is responsible for allocation and freeing of \a *aip.
+ */
+GFSM_INLINE
+void gfsm_arciter_open(gfsmArcIter *aip, gfsmAutomaton *fsm, gfsmStateId stateid);
+
+/** "Open" an arc iterator for the outgoing arcs from a state pointer into \a fsm
+ * \deprecated prefer gfsm_arciter_open()
+ */
+GFSM_INLINE
+void gfsm_arciter_open_ptr(gfsmArcIter *aip, gfsmAutomaton *fsm, gfsmState *stateptr);
+
+/** Close a ::gfsmArcIter \a aip if already opened, otherwise does nothing.
+ * \param aip The ::gfsmArcIter to be closed.
+ * \note
+ * \li If multiple copies of a ::gfsmArcIter exist, only one needs to be closed.
+ * \li Currently does nothing useful; in future versions this function may
+ * be required to free temporary allocations, etc.
+ */
+GFSM_INLINE
+void gfsm_arciter_close(gfsmArcIter *aip);
+
+/** Copy positional data from \a src to \a dst.
+ * \param src The ::gfsmArcIter from which to copy positional data
+ * \param dst The ::gfsmArcIter to which positional data is to be written
+ * \note
+ * \li Only the position pointed to should be copied by this method,
+ * and not the underlying data.
+ * \li If you use this method to copy ::gfsmArcIter positions,
+ * you should subsequently call gfsm_arciter_close() on only
+ * \e one of them!
+ */
+GFSM_INLINE
+gfsmArcIter *gfsm_arciter_copy(gfsmArcIter *dst, const gfsmArcIter *src);
+
+/* Create and return a new (shallow) copy of a ::gfsmArcIter.
+ * \param src The ::gfsmArcIter whose positional data is to be duplicated.
+ * \note
+ * \li Only the position pointed to should be copied by this method,
+ * and not the underlying data.
+ * \li If you use this method to copy ::gfsmArcIter positions,
+ * you should subsequently call gfsm_arciter_close() on only
+ * \e one of them!
+ */
+GFSM_INLINE
+gfsmArcIter *gfsm_arciter_clone(const gfsmArcIter *src);
+
+//@}
+
+/*======================================================================
+ * Methods: Arc iterators: Accessors
+ */
+///\name Arc Iterators: Accessors
+//@{
+
+/** Check validity of a ::gfsmArcIter* \a aip.
+ * \param aip The ::gfsmArcIter whose status is to be queried.
+ * \returns a true value if \a aip is considered valid, FALSE otherwise.
+ */
+GFSM_INLINE
+gboolean gfsm_arciter_ok(const gfsmArcIter *aip);
+
+/** Position the ::gfsmArcIter \a aip to the next available outgoing arc for which it was opened.
+ * \param aip The ::gfsmArcIter to be incremented.
+ */
+GFSM_INLINE
+void gfsm_arciter_next(gfsmArcIter *aip);
+
+/** Reset an arc iterator to the first outgoing arc for which it was initially opened.
+ * \param aip the ::gfsmArcIter to be reset
+ */
+GFSM_INLINE
+void gfsm_arciter_reset(gfsmArcIter *aip);
+
+/** Get current arc associated with a :gfsmArcIter, or NULL if none is available.
+ * \param aip The ::gfsmArcIter to be 'dereferenced'.
+ * \returns A pointer to the current ::gfsmArc 'pointed to' by \a aip, or NULL if
+ * no more arcs are available.
+ * \note
+ * \li In future versions, a ::gfsmAutomaton implementation will be free to return
+ * a dynamically generated arc here: there is no general
+ * guarantee that modifications to the ::gfsmArc returned by this
+ * function will be propagated to the underlying ::gfsmAutomaton.
+ * \li It is expected to remain the case that for the default automaton implementation class,
+ * the arcs returned by this function should be modifiable in-place.
+ */
+GFSM_INLINE
+gfsmArc *gfsm_arciter_arc(const gfsmArcIter *aip);
+
+/** Remove the arc referred to by a ::gfsmArcIter \a aip from the associated ::gfsmAutomaton,
+ * and position \aip to the next available arc, if any.
+ * \param aip The ::gfsmArcIter whose 'current' arc is to be removed.
+ */
+GFSM_INLINE
+void gfsm_arciter_remove(gfsmArcIter *aip);
+
+
+/** Position an arc-iterator to the current or next arc with lower label \a lo.
+ * \param aip The ::gfsmArcIter to reposition
+ * \param lo Lower arc label to seek
+ * \note
+ * Currently just wraps gfsm_arciter_ok(), gfsm_arciter_next() and gfsm_arciter_arc()
+ * in a linear search from the current position.
+ */
+void gfsm_arciter_seek_lower(gfsmArcIter *aip, gfsmLabelVal lo);
+
+/** Position an arc-iterator to the current or next arc with upper label \a hi.
+ * \param aip The ::gfsmArcIter to reposition
+ * \param lo Upper arc label to seek
+ * \note
+ * Currently just wraps gfsm_arciter_ok(), gfsm_arciter_next() and gfsm_arciter_arc()
+ * in a linear search from the current position.
+ */
+void gfsm_arciter_seek_upper(gfsmArcIter *aip, gfsmLabelVal hi);
+
+/** Position an arc-iterator to the current or next arc with lower label \a lo and upper label \a hi.
+ * If either \a lo or \a hi is ::gfsmNoLabel, no matching will be performed on the corresponding arc label(s).
+ * \param aip The ::gfsmArcIter to reposition
+ * \param lo Lower arc label to seek, or ::gfsmNoLabel to ignore lower labels
+ * \param hi Upper arc label to seek, or ::gfsmNoLabel to ignore upper labels
+ * \note
+ * Default implementation wraps gfsm_arciter_ok(), gfsm_arciter_next() and gfsm_arciter_arc()
+ * in a linear search from the current position.
+ */
+void gfsm_arciter_seek_both(gfsmArcIter *aip, gfsmLabelVal lo, gfsmLabelVal hi);
+
+/// Typedef for user-seek functions
+typedef gboolean (*gfsmArcIterSeekFunc) (gfsmArcIter *aip, gpointer data);
+
+/** Position an arc-iterator to the next arc for which (*seekfunc)(arciter,data) returns TRUE.
+ * \note
+ * Just wraps gfsm_arciter_ok() and gfsm_arciter_next()
+ * in a linear search from the current position.
+ */
+void gfsm_arciter_seek_user(gfsmArcIter *aip,
+ gfsmArcIterSeekFunc seekfunc,
+ gpointer data);
+
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmArcIter.hi>
+#endif
+
+#endif /* _GFSM_ARCITER_H */
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcIter.hi b/gfsm/gfsm/src/libgfsm/gfsmArcIter.hi
new file mode 100644
index 0000000..bb8268e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcIter.hi
@@ -0,0 +1,126 @@
+
+/*=============================================================================*\
+ * File: gfsmArcIter.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc iterators: inline definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/*======================================================================
+ * Methods: Arc iterators: open/close
+ */
+
+//--------------------------------------------------------------
+// open()
+GFSM_INLINE
+void gfsm_arciter_open(gfsmArcIter *aip, gfsmAutomaton *fsm, gfsmStateId stateid)
+{
+ aip->fsm = fsm;
+ aip->state = gfsm_automaton_find_state(fsm,stateid);
+ aip->arcs = NULL;
+ gfsm_arciter_reset(aip);
+}
+
+//--------------------------------------------------------------
+// open_ptr()
+GFSM_INLINE
+void gfsm_arciter_open_ptr(gfsmArcIter *aip, gfsmAutomaton *fsm, gfsmState *stateptr)
+{
+ aip->fsm = fsm;
+ aip->state = stateptr;
+ aip->arcs = NULL;
+ gfsm_arciter_reset(aip);
+}
+
+//--------------------------------------------------------------
+// reset()
+GFSM_INLINE
+void gfsm_arciter_reset(gfsmArcIter *aip) {
+ if (aip->state && gfsm_state_is_ok(aip->state)) {
+ aip->arcs = aip->state->arcs;
+ } else {
+ aip->arcs = NULL;
+ }
+}
+
+//--------------------------------------------------------------
+// close()
+GFSM_INLINE
+void gfsm_arciter_close(gfsmArcIter *aip) {
+ if (!aip) return;
+ aip->fsm = NULL;
+ aip->state = NULL;
+ aip->arcs = NULL;
+}
+
+//--------------------------------------------------------------
+// copy()
+GFSM_INLINE
+gfsmArcIter *gfsm_arciter_copy(gfsmArcIter *dst, const gfsmArcIter *src) {
+ *dst = *src;
+ return dst;
+}
+
+//--------------------------------------------------------------
+// clone()
+GFSM_INLINE
+gfsmArcIter *gfsm_arciter_clone(const gfsmArcIter *src) {
+ return (gfsmArcIter*)gfsm_mem_dup_n(src,sizeof(gfsmArcIter));
+}
+
+/*======================================================================
+ * Methods: Arc iterators: Accessors
+ */
+
+//--------------------------------------------------------------
+// arc()
+GFSM_INLINE
+gfsmArc *gfsm_arciter_arc(const gfsmArcIter *aip)
+{
+ //return aip->arcs ? ((gfsmArc*)aip->arcs->data) : NULL;
+ return aip->arcs ? (&(aip->arcs->arc)) : NULL;
+}
+
+//--------------------------------------------------------------
+// ok()
+GFSM_INLINE
+gboolean gfsm_arciter_ok(const gfsmArcIter *aip)
+{ return (aip != NULL && aip->arcs != NULL); }
+
+//--------------------------------------------------------------
+// next()
+GFSM_INLINE
+void gfsm_arciter_next(gfsmArcIter *aip)
+{ if (aip && aip->arcs) aip->arcs = aip->arcs->next; }
+
+
+//--------------------------------------------------------------
+// seek_X()
+//--EXTERN
+
+//--------------------------------------------------------------
+// remove()
+GFSM_INLINE
+void gfsm_arciter_remove(gfsmArcIter *aip)
+{
+ if (aip && aip->arcs) {
+ gfsmArcList *next = aip->arcs->next;
+ aip->state->arcs = gfsm_arclist_delete_node(aip->state->arcs, aip->arcs);
+ aip->arcs = next;
+ }
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcList.c b/gfsm/gfsm/src/libgfsm/gfsmArcList.c
new file mode 100644
index 0000000..8a2e381
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcList.c
@@ -0,0 +1,226 @@
+
+/*=============================================================================*\
+ * File: gfsmArclist.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc lists
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmArcList.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmArcList.hi>
+#endif
+
+/*======================================================================
+ * Methods: Arc lists
+ */
+
+/*--------------------------------------------------------------
+ * arclist_insert_node_sorted()
+ */
+gfsmArcList *gfsm_arclist_insert_node_sorted(gfsmArcList *al, gfsmArcList *nod, gfsmArcCompData *acdata)
+{
+ gfsmArcList *al_first=al;
+ gfsmArcList *al_prev=NULL;
+
+ for (; al != NULL; al_prev=al, al=al->next) {
+ if (gfsm_arc_compare_bymask_inline(&(nod->arc), &(al->arc), acdata) <= 0) break;
+ }
+ if (al_prev == NULL) return gfsm_arclist_prepend_node(al,nod);
+ al_prev->next = gfsm_arclist_prepend_node(al,nod);
+
+ return al_first;
+}
+
+/*--------------------------------------------------------------
+ * arclist_clone()
+ */
+gfsmArcList *gfsm_arclist_clone(gfsmArcList *src)
+{
+ gfsmArcList *dst = NULL, *prev=NULL;
+ while (src != NULL) {
+ gfsmArcList *nod = gfsm_arclist_new_full(src->arc.source,
+ src->arc.target,
+ src->arc.lower,
+ src->arc.upper,
+ src->arc.weight,
+ NULL);
+ if (prev==NULL) {
+ dst = nod;
+ } else {
+ prev->next = nod;
+ }
+ prev = nod;
+ src = src->next;
+ }
+ return dst;
+}
+
+/*--------------------------------------------------------------
+ * arclist_concat()
+ */
+gfsmArcList *gfsm_arclist_concat(gfsmArcList *al1, gfsmArcList *al2)
+{
+ if (al1==NULL) { return al2; }
+ else {
+ gfsmArcList *nod=al1;
+ while (nod->next != NULL) { nod=nod->next; }
+ nod->next = al2;
+ }
+ return al1;
+}
+
+/*--------------------------------------------------------------
+ * arclist_length()
+ */
+guint gfsm_arclist_length(gfsmArcList *al)
+{
+ guint len=0;
+ while (al != NULL) { ++len; al=al->next; }
+ return len;
+}
+
+/*--------------------------------------------------------------
+ * arclist_free()
+ */
+void gfsm_arclist_free(gfsmArcList *al)
+{
+ while (al != NULL) {
+ gfsmArcList *nxt = al->next;
+ g_free(al);
+ al = nxt;
+ }
+}
+
+/*--------------------------------------------------------------
+ * arclist_sort_with_data() & friends
+ * + adapted from code in GLib glib/gslist.c:
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald,
+ * Modified by the GLib Team and others 1997-2000.
+ */
+static
+gfsmArcList *gfsm_arclist_sort_merge (gfsmArcList *l1,
+ gfsmArcList *l2,
+ GFunc compare_func,
+ gpointer user_data)
+{
+ gfsmArcList list, *l;
+ gint cmp;
+
+ l=&list;
+
+ while (l1 && l2)
+ {
+ cmp = ((GCompareDataFunc) compare_func) (&(l1->arc), (&l2->arc), user_data);
+
+ if (cmp <= 0)
+ {
+ l=l->next=l1;
+ l1=l1->next;
+ }
+ else
+ {
+ l=l->next=l2;
+ l2=l2->next;
+ }
+ }
+ l->next= l1 ? l1 : l2;
+
+ return list.next;
+}
+
+
+gfsmArcList *gfsm_arclist_sort_real (gfsmArcList *list,
+ GFunc compare_func,
+ gpointer user_data)
+{
+ gfsmArcList *l1, *l2;
+
+ if (!list)
+ return NULL;
+ if (!list->next)
+ return list;
+
+ l1 = list;
+ l2 = list->next;
+
+ while ((l2 = l2->next) != NULL)
+ {
+ if ((l2 = l2->next) == NULL)
+ break;
+ l1=l1->next;
+ }
+ l2 = l1->next;
+ l1->next = NULL;
+
+ return gfsm_arclist_sort_merge (gfsm_arclist_sort_real (list, compare_func, user_data),
+ gfsm_arclist_sort_real (l2, compare_func, user_data),
+ compare_func,
+ user_data);
+}
+
+
+/*--------------------------------------------------------------
+ * arclist_remove_node()
+ * + adapted from _g_slist_remove_link()
+ */
+gfsmArcList *gfsm_arclist_remove_node(gfsmArcList *al, gfsmArcList *nod)
+{
+ gfsmArcList *tmp;
+ gfsmArcList *prev;
+
+ prev = NULL;
+ tmp = al;
+
+ while (tmp)
+ {
+ if (tmp == nod)
+ {
+ if (prev)
+ prev->next = tmp->next;
+ if (al == tmp)
+ al = al->next;
+
+ tmp->next = NULL;
+ break;
+ }
+
+ prev = tmp;
+ tmp = tmp->next;
+ }
+
+ return al;
+}
+
+
+/*--------------------------------------------------------------
+ * arclist_reverse()
+ */
+gfsmArcList* gfsm_arclist_reverse(gfsmArcList *al)
+{
+ gfsmArcList *prev=NULL;
+ while (al) {
+ gfsmArcList *next = al->next;
+ al->next = prev;
+ prev = al;
+ al = next;
+ }
+ return prev;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcList.h b/gfsm/gfsm/src/libgfsm/gfsmArcList.h
new file mode 100644
index 0000000..23ae0ad
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcList.h
@@ -0,0 +1,207 @@
+
+/*=============================================================================*\
+ * File: gfsmArcList.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc lists
+ * + formerly defined in gfsmArc.h
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmArcList.h
+ * \brief Definitions & utilities for arc lists, <b>Deprecated</b>
+ * \detail
+ * \deprecated
+ * in favor of gfsm_automaton_add_arc() and ::gfsmArcIter interface
+ * \see gfsmAutomaton.h, gfsmArcIter.h
+ */
+
+#ifndef _GFSM_ARC_LIST_H
+#define _GFSM_ARC_LIST_H
+
+#include <gfsmArc.h>
+
+/// "Heavy" arc-list structure, no longer using GSList
+typedef struct gfsmArcListNode_ {
+ gfsmArc arc; /**< current arc */
+ struct gfsmArcListNode_ *next; /**< next node in the list */
+} gfsmArcListNode;
+
+/// Alias for gfsmArcListNode
+typedef gfsmArcListNode gfsmArcList;
+
+
+/*======================================================================
+ * Methods: Arc List: Constructors etc.
+ */
+/// \name Arc List: Constructors etc.
+//@{
+
+/** Prepend the node \a nod to the ::gfsmArcList \a al
+ * \returns a pointer to the new 1st element of the arclist
+ * \deprecated in favor of gfsm_automaton_add_arc(), gfsm_arciter_insert()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_prepend_node(gfsmArcList *al, gfsmArcList *nod);
+
+/** Allocate and return a new arc-list node */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_new_full(gfsmStateId src,
+ gfsmStateId dst,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gfsmWeight wt,
+ gfsmArcList *nxt);
+
+
+/** Insert an arc into a (possibly sorted) arclist.
+ * \param al ::gfsmArcList into which a new arc is to be inserted
+ * \param src source state id for the new arc
+ * \param dst target state id for the new arc
+ * \param lo lower label for the new arc
+ * \param hi upper label for the new arc
+ * \parm wt weight for the new arc
+ * \param acdata comparison data for 'smart' sorted insertion
+ * \returns a pointer to the (possibly new) 1st node of the arc list
+ * \deprecated in favor of gfsm_automaton_add_arc(), gfsm_arciter_insert()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_insert(gfsmArcList *al,
+ gfsmStateId src,
+ gfsmStateId dst,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gfsmWeight wt,
+ gfsmArcCompData *acdata);
+
+
+/** Insert a single arc-link into a (possibly sorted) arclist.
+ * \param al arc list into which \a link is to be inserted
+ * \param link arc list node to insert
+ * \param acdata sort data for 'smart' sorted insertion
+ * \returns a pointer to the (possibly new) 1st element of the arclist
+ * \deprecated in favor of gfsm_automaton_add_arc(), gfsm_arciter_insert()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_insert_node(gfsmArcList *al, gfsmArcList *nod, gfsmArcCompData *acdata);
+
+/** Low-level guts for gfsm_arclist_insert(), gfsm_arclist_insert_node() */
+gfsmArcList *gfsm_arclist_insert_node_sorted(gfsmArcList *al, gfsmArcList *link, gfsmArcCompData *acdata);
+
+/** Create and return a (deep) copy of an existing arc-list */
+gfsmArcList *gfsm_arclist_clone(gfsmArcList *src);
+
+
+/** Destroy an arc-list node and all subsequent nodes */
+void gfsm_arclist_free(gfsmArcList *al);
+
+/* Free a single node of an arc-list */
+//void gfsm_arclist_free_node(gfsmArcList *nod);
+
+//@}
+
+/*======================================================================
+ * Methods: Arc List: Accessors
+ */
+///\name Arc List: Access & Manipulation
+//@{
+
+/** Get the arc pointer for an arclist -- may be \c NULL
+ * \deprecated in favor of ::gfsmArcIter interface
+ * \see gfsmArcIter.h
+ */
+#define gfsm_arclist_arc(al) \
+ ((al) ? (&(al->arc)) : NULL)
+
+// ((al) ? ((gfsmArc*)((al)->data)) : NULL)
+
+/** Concatenate 2 arc-lists
+ * \param al1 initial sublist
+ * \param al2 final sublist
+ * \returns pointer to head of the concatenated list
+ */
+gfsmArcList *gfsm_arclist_concat(gfsmArcList *al1, gfsmArcList *al2);
+
+/** Splice a single node out from a ::gfsmArcList.
+ * \param al arc list
+ * \param nod node to extract
+ * \returns pointer to head of the new arc list, without \a nod
+ * \warning removed \a nod is not freed!
+ * \see gfsm_arclist_delte_node()
+ */
+gfsmArcList *gfsm_arclist_remove_node(gfsmArcList *al, gfsmArcList *nod);
+
+/** Remove and free a single node from a ::gfsmArcList.
+ * \param al arc list
+ * \param nod node to extract
+ * \returns pointer to head of the new arc list, without \a nod
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_delete_node(gfsmArcList *al, gfsmArcList *nod);
+
+/** Reverse a ::gfsmArcList
+ * \param al arc list to reverse
+ * \returns pointer to head of the reversed arc list
+ */
+gfsmArcList *gfsm_arclist_reverse(gfsmArcList *al);
+
+//@}
+
+
+/*======================================================================
+ * Methods: Arc List: Utilities
+ */
+///\name Arc List: Utilities
+//@{
+
+/** Get length of an arc-list \a al (linear time) */
+guint gfsm_arclist_length(gfsmArcList *al);
+ // Signature: <tt>guint gfsm_arclist_length(gfsmArcList *al)</tt>
+//#define gfsm_arclist_length g_slist_length
+
+/** Sort an arclist \a al using one of the builtin sort modes as specified by \a acdata.
+ * \param al arc list to sort
+ * \param acdata sort data for builtin comparison
+ * \returns pointer to the new head of the sorted arc list
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_sort(gfsmArcList *al, gfsmArcCompData *acdata);
+
+/** Sort an arclist \a al using a user-defined arc comparison function.
+ * \param al arc list to sort
+ * \param cmpfunc 3-way comparison function on ::gfsmArc* for sorting
+ * \param data additional data for \a cmpfunc
+ * \returns pointer to the new head of the sorted arc list
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_sort_with_data(gfsmArcList *al, GCompareDataFunc cmpfunc, gpointer data);
+
+/** Alias for gfsm_arclist_sort_with_data() */
+#define gfsm_arclist_sort_full gfsm_arclist_sort_with_data
+
+/** low-level guts for gfsm_arclist_sort() */
+gfsmArcList *gfsm_arclist_sort_real (gfsmArcList *list, GFunc compare_func, gpointer user_data);
+
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmArcList.hi>
+#endif
+
+#endif /* _GFSM_ARC_LIST_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArcList.hi b/gfsm/gfsm/src/libgfsm/gfsmArcList.hi
new file mode 100644
index 0000000..9426f26
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArcList.hi
@@ -0,0 +1,124 @@
+
+/*=============================================================================*\
+ * File: gfsmArclist.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc lists: inline definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <stdlib.h>
+
+/*======================================================================
+ * Methods: Arc lists
+ */
+
+/*--------------------------------------------------------------
+ * arclist_prepend_node()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_prepend_node(gfsmArcList *al, gfsmArcList *nod)
+{
+ nod->next = al;
+ return nod;
+}
+
+/*--------------------------------------------------------------
+ * arclist_new_full()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_new_full(gfsmStateId src,
+ gfsmStateId dst,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gfsmWeight wt,
+ gfsmArcList *nxt)
+{
+ gfsmArcList *nod = g_new(gfsmArcList,1);
+ nod->arc.source = src;
+ nod->arc.target = dst;
+ nod->arc.lower = lo;
+ nod->arc.upper = hi;
+ nod->arc.weight = wt;
+ nod->next = nxt;
+ return nod;
+}
+
+/*--------------------------------------------------------------
+ * arclist_delete_node()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_delete_node(gfsmArcList *al, gfsmArcList *nod)
+{
+ al = gfsm_arclist_remove_node(al,nod);
+ g_free(nod);
+ return al;
+}
+
+/*--------------------------------------------------------------
+ * arclist_insert()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_insert(gfsmArcList *al,
+ gfsmStateId src,
+ gfsmStateId dst,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gfsmWeight wt,
+ gfsmArcCompData *acdata)
+{
+ gfsmArcList *nod = gfsm_arclist_new_full(src,dst,lo,hi,wt,NULL);
+ if (!acdata || acdata->mask == gfsmASMNone) {
+ nod->next = al;
+ return nod;
+ }
+ return gfsm_arclist_insert_node_sorted(al,nod,acdata);
+}
+
+/*--------------------------------------------------------------
+ * arclist_insert_node()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_insert_node(gfsmArcList *al,
+ gfsmArcList *nod,
+ gfsmArcCompData *acdata)
+{
+ if (!acdata || acdata->mask == gfsmASMNone) return gfsm_arclist_prepend_node(al,nod);
+ return gfsm_arclist_insert_node_sorted(al,nod,acdata);
+}
+
+/*--------------------------------------------------------------
+ * arclist_sort_with_data()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_sort_with_data (gfsmArcList *al,
+ GCompareDataFunc compare_func,
+ gpointer user_data)
+{
+ return gfsm_arclist_sort_real (al, (GFunc)compare_func, user_data);
+}
+
+
+
+/*--------------------------------------------------------------
+ * arclist_sort()
+ */
+GFSM_INLINE
+gfsmArcList *gfsm_arclist_sort(gfsmArcList *al, gfsmArcCompData *acdata)
+{
+ return gfsm_arclist_sort_real(al, (GFunc)gfsm_arc_compare_bymask, acdata);
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArith.c b/gfsm/gfsm/src/libgfsm/gfsmArith.c
new file mode 100644
index 0000000..f9ccf11
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArith.c
@@ -0,0 +1,199 @@
+/*=============================================================================*\
+ * File: gfsmArith.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <math.h>
+#include <glib.h>
+#include <gfsmArith.h>
+#include <gfsmArcIter.h>
+
+
+/*======================================================================
+ * Methods: arithmetic: Generic
+ */
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_automaton_arith(gfsmAutomaton *fsm,
+ gfsmArithOp op,
+ gfsmWeight arg,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gboolean do_arcs,
+ gboolean do_final,
+ gboolean do_zero)
+{
+ if (op == gfsmAONone) return fsm; //-- dummy operation
+
+ //-- arc weights
+ if (do_arcs) {
+ gfsmStateId qid;
+
+ if (fsm->flags.sort_mode == gfsmASMWeight)
+ fsm->flags.sort_mode = gfsmASMNone; //-- arc-weights may be destructively altered
+
+ for (qid=0; qid < fsm->states->len; qid++) {
+ gfsmArcIter ai;
+ for (gfsm_arciter_open(&ai,fsm,qid), gfsm_arciter_seek_both(&ai,lo,hi);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_both(&ai,lo,hi))
+ {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+ arc->weight = gfsm_weight_arith(fsm->sr, op, arc->weight, arg, do_zero);
+ }
+ }
+ }
+
+ //-- final weights
+ if (do_final) gfsm_automaton_arith_final(fsm, op, arg, do_zero);
+
+ return fsm;
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_automaton_arith_state(gfsmAutomaton *fsm,
+ gfsmStateId qid,
+ gfsmArithOp op,
+ gfsmWeight arg,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gboolean do_arcs,
+ gboolean do_final,
+ gboolean do_zero)
+{
+ if (qid==gfsmNoState) return gfsm_automaton_arith(fsm,op,arg,lo,hi,do_arcs,do_final,do_zero);
+
+ //-- arc weights
+ if (do_arcs) {
+ gfsmArcIter ai;
+
+ if (fsm->flags.sort_mode == gfsmASMWeight)
+ fsm->flags.sort_mode = gfsmASMNone; //-- arc-weights may be destructively altered
+
+ for (gfsm_arciter_open(&ai,fsm,qid), gfsm_arciter_seek_both(&ai,lo,hi);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_both(&ai,lo,hi))
+ {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+ arc->weight = gfsm_weight_arith(fsm->sr, op, arc->weight, arg, do_zero);
+ }
+ }
+
+ //-- final weight
+ if (do_final) {
+ gfsm_automaton_set_final_state_full(fsm,
+ qid,
+ gfsm_automaton_is_final_state(fsm, qid),
+ gfsm_weight_arith(fsm->sr,
+ op,
+ gfsm_automaton_get_final_weight(fsm, qid),
+ arg,
+ do_zero));
+ }
+
+ return fsm;
+}
+
+//--------------------------------------------------------------
+gfsmWeight gfsm_weight_arith(gfsmSemiring *sr,
+ gfsmArithOp op,
+ gfsmWeight w1,
+ gfsmWeight w2,
+ gboolean do_zero)
+{
+ if (!do_zero && w1==sr->zero) return w1;
+
+ switch (op) {
+
+ case gfsmAOExp: ///< Exponentiate
+ return expf(w1);
+ break;
+
+ case gfsmAOLog: ///< Logarithm
+ return logf(w1);
+ break;
+
+ case gfsmAONoNeg: ///< Real force-positive
+ return (w1 < 0 ? (-w1) : w1);
+ break;
+
+ case gfsmAOAdd: ///< Real Addition
+ return w1+w2;
+ break;
+
+ case gfsmAOMult: ///< Real Multiplication
+ return w1*w2;
+ break;
+
+ case gfsmAOSRNoNeg: ///< Semiring Force positive
+ return (gfsm_sr_less(sr,sr->zero,w1) ? sr->zero : w1);
+ break;
+
+ case gfsmAOSRPlus: ///< Semiring Addition
+ return gfsm_sr_plus(sr,w1,w2);
+ break;
+
+ case gfsmAOSRTimes: ///< Semiring Multiplication
+ return gfsm_sr_times(sr,w1,w2);
+ break;
+
+ case gfsmAONone: ///< No operation
+ default:
+ return w1;
+ }
+ return w1; //-- should never happen
+}
+
+
+
+/*======================================================================
+ * Methods: arithmetic: final
+ */
+
+//--------------------------------------------------------------
+gboolean _gfsm_automaton_arith_final_foreach_func(gfsmStateId id,
+ gpointer pw,
+ gfsmArithParams *params)
+{
+ gfsmWeight w = gfsm_ptr2weight(pw);
+ gfsm_weightmap_insert(params->fsm->finals,
+ GUINT_TO_POINTER(id),
+ gfsm_weight_arith(params->fsm->sr,
+ params->op,
+ w,
+ params->arg,
+ params->do_zero));
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_automaton_arith_final(gfsmAutomaton *fsm,
+ gfsmArithOp op,
+ gfsmWeight arg,
+ gboolean do_zero)
+{
+ gfsmArithParams params = { fsm, op, arg, do_zero };
+ g_tree_foreach(fsm->finals,
+ (GTraverseFunc)_gfsm_automaton_arith_final_foreach_func,
+ &params);
+ return fsm;
+}
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArith.h b/gfsm/gfsm/src/libgfsm/gfsmArith.h
new file mode 100644
index 0000000..c9ee40b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmArith.h
@@ -0,0 +1,137 @@
+
+/*=============================================================================*\
+ * File: gfsmArith.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#ifndef _GFSM_ARITH_H
+#define _GFSM_ARITH_H
+
+#include <gfsmAutomaton.h>
+
+/** \file gfsmArith.h
+ * \brief Arithmetic operations on automata
+ */
+
+/*======================================================================
+ * Types
+ */
+/** Type representing an elementary arithmetic operation */
+typedef enum {
+ //-- real ops
+ gfsmAONone, ///< No operation: \a w=w
+ gfsmAOExp, ///< Real Exponentiation: \a w=exp(w)
+ gfsmAOLog, ///< Real Logarithm: \a w=log(w)
+ gfsmAONoNeg, ///< Real Force-positive: \a w=(w < 0 ? -w : w)
+ gfsmAOAdd, ///< Real Addition: \a w=w+arg
+ gfsmAOMult, ///< Real Multiplication: \a w=w*arg
+ //-- semiring ops
+ gfsmAOSRNoNeg, ///< Semiring Force-positve: \a w=(sr_less(sr_zero,w) ? sr_zero : w)
+ gfsmAOSRPlus, ///< Semiring Addition: \a w=sr_plus(w,arg)
+ gfsmAOSRTimes ///< Semiring Multiplication: \a w=sr_times(w,arg)
+} gfsmArithOp;
+
+/** \brief Type representing all parameters for a generic automaton arithmetic operation */
+typedef struct {
+ gfsmAutomaton *fsm; ///< Automaton
+ gfsmArithOp op; ///< Operation
+ gfsmWeight arg; ///< 2nd operation argument (if any)
+ gboolean do_zero; ///< operate on semiring-zeroes?
+} gfsmArithParams;
+
+
+/*======================================================================
+ * Methods: arithmetic: generic
+ */
+///\name Arithmetic (Generic)
+//@{
+
+//------------------------------
+/** Perform a generic arithmetic operation on \a fsm.
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Automaton
+ * \param op Operation
+ * \parma arg Argument of operation (if any)
+ * \param lo Perform only for arcs with lower label \a lo (gfsmNoLabel for any label)
+ * \param hi Perform only for arcs with upper label \a hi (gfsmNoLabel for any label)
+ * \param do_arcs Perform operation on arc weights
+ * \param do_final Perform operation on final weights
+ * \param do_zero Perform operation on zero weights
+ *
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_arith(gfsmAutomaton *fsm,
+ gfsmArithOp op,
+ gfsmWeight arg,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gboolean do_arcs,
+ gboolean do_final,
+ gboolean do_zero);
+
+//------------------------------
+/** Perform a generic arithmetic operation on state \a qid in \a fsm.
+ * \note Destructively alters \a fsm.
+ *
+ * \param fsm Automaton
+ * \param qid State-id in \a fsm, or gfsmNoState for all states
+ * \param op Operation
+ * \parma arg Argument of operation (if any)
+ * \param lo Perform only for arcs with lower label \a lo (gfsmNoLabel for any label)
+ * \param hi Perform only for arcs with upper label \a hi (gfsmNoLabel for any label)
+ * \param do_arcs Perform operation on arc weights
+ * \param do_final Perform operation on final weights
+ * \param do_zero Perform operation on zero weights
+ *
+ * \returns modified \a fsm
+ */
+gfsmAutomaton *gfsm_automaton_arith_state(gfsmAutomaton *fsm,
+ gfsmStateId qid,
+ gfsmArithOp op,
+ gfsmWeight arg,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi,
+ gboolean do_arcs,
+ gboolean do_final,
+ gboolean do_zero);
+
+
+//------------------------------
+/** Perform a generic arithmetic operation on final weights
+ * \returns params->fsm
+ */
+gfsmAutomaton *gfsm_automaton_arith_final(gfsmAutomaton *fsm,
+ gfsmArithOp op,
+ gfsmWeight arg,
+ gboolean do_zero);
+
+//------------------------------
+/** Perform a generic arithmetic operation on a gfsmWeight.
+ * \returns result of operation
+ */
+gfsmWeight gfsm_weight_arith(gfsmSemiring *sr,
+ gfsmArithOp op,
+ gfsmWeight w1,
+ gfsmWeight w2,
+ gboolean do_zero);
+
+//@}
+#endif /* _GFSM_ARITH_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAssert.h b/gfsm/gfsm/src/libgfsm/gfsmAssert.h
new file mode 100644
index 0000000..baae9d4
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAssert.h
@@ -0,0 +1,51 @@
+
+/*=============================================================================*\
+ * File: gfsmAssert.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: assertions
+ *
+ * Copyright (c) 2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmAssert.h
+ * \brief Assertions
+ */
+
+#ifndef _GFSM_ASSERT_H
+#define _GFSM_ASSERT_H
+
+#include <glib.h>
+
+/**
+ * \def gfsm_assert_not_reached()
+ * \detail If ever actually evaluated, aborts with an error message.
+ * Only available if libgfsm was configured with debugging enabled.
+ *
+ * \def gfsm_assert(expr)
+ * \detail If \a expr does not evaluate to a true value, aborts with an error message.
+ * Only available if libgfsm was configured with debugging enabled.
+ */
+
+#ifdef GFSM_DEBUG_ENABLED
+# define gfsm_assert_not_reached() g_assert_not_reached()
+# define gfsm_assert(expr) g_assert(expr)
+#else
+# define gfsm_assert_not_reached()
+# define gfsm_assert(expr)
+#endif
+
+#endif /* _GFSM_ASSERT_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAutomaton.c b/gfsm/gfsm/src/libgfsm/gfsmAutomaton.c
new file mode 100644
index 0000000..17f7a37
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAutomaton.c
@@ -0,0 +1,338 @@
+/*=============================================================================*\
+ * File: gfsmAutomaton.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmAutomaton.h>
+#include <gfsmArcIter.h>
+#include <gfsmUtils.h>
+#include <gfsmBitVector.h>
+#include <stdlib.h>
+
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmAutomaton.hi>
+#endif
+
+/*======================================================================
+ * Constants
+ */
+const gfsmStateId gfsmAutomatonDefaultSize = 128;
+
+const gfsmAutomatonFlags gfsmAutomatonDefaultFlags =
+ {
+ TRUE, //-- is_transducer:1
+ TRUE, //-- is_weighted:1
+ //0, //-- sort_mode_old__:4
+ FALSE, //-- is_deterministic:1
+ 0, //-- unused:29 (was: 25)
+ gfsmASMNone //-- sort_mode
+ };
+
+//const gfsmSRType gfsmAutomatonDefaultSRType = gfsmSRTReal;
+const gfsmSRType gfsmAutomatonDefaultSRType = gfsmSRTTropical;
+
+//======================================================================
+// API: Constructors etc.
+
+/*--------------------------------------------------------------
+ * copy()
+ */
+gfsmAutomaton *gfsm_automaton_copy(gfsmAutomaton *dst, gfsmAutomaton *src)
+{
+ gfsmStateId qid;
+ gfsm_automaton_clear(dst);
+ gfsm_automaton_copy_shallow(dst,src);
+ dst->root_id = src->root_id; //-- since copy_shallow() no longer does this!
+ gfsm_automaton_reserve(dst,src->states->len);
+ gfsm_weightmap_copy(dst->finals, src->finals);
+ //
+ for (qid=0; qid < src->states->len; qid++) {
+ const gfsmState *src_s = gfsm_automaton_find_state_const(src,qid);
+ gfsmState *dst_s = gfsm_automaton_find_state(dst,qid);
+ gfsm_state_copy(dst_s, src_s);
+ }
+ return dst;
+}
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+void gfsm_automaton_clear(gfsmAutomaton *fsm)
+{
+ gfsmStateId i;
+ if (!fsm) return;
+ for (i=0; fsm->states && i < fsm->states->len; i++) {
+ gfsmState *st = gfsm_automaton_find_state(fsm,i);
+ if (!st || !st->is_valid) continue;
+ gfsm_state_clear(st);
+ }
+ if (fsm->states) g_array_set_size(fsm->states,0);
+ if (fsm->finals) gfsm_set_clear(fsm->finals);
+ fsm->root_id = gfsmNoState;
+ return;
+}
+
+
+//======================================================================
+// API: Automaton Semiring
+
+//======================================================================
+// API: Automaton Properties
+
+/*--------------------------------------------------------------
+ * n_arcs_full()
+ */
+guint gfsm_automaton_n_arcs_full(gfsmAutomaton *fsm,
+ guint *n_lo_epsilon,
+ guint *n_hi_epsilon,
+ guint *n_both_epsilon)
+{
+ guint i, total=0;
+ guint n_lo_eps=0, n_hi_eps=0, n_both_eps=0;
+ gfsmStateId n_states = gfsm_automaton_n_states(fsm);
+
+ for (i=0; i < n_states; i++) {
+ gfsmArcIter ai;
+ for (gfsm_arciter_open(&ai, fsm, i); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ ++total;
+ if (a->lower==gfsmEpsilon) {
+ ++n_lo_eps;
+ if (a->upper==gfsmEpsilon) {
+ ++n_hi_eps;
+ ++n_both_eps;
+ }
+ }
+ else if (a->upper==gfsmEpsilon) {
+ ++n_hi_eps;
+ }
+ }
+ gfsm_arciter_close(&ai);
+ }
+ if (n_lo_epsilon) *n_lo_epsilon = n_lo_eps;
+ if (n_hi_epsilon) *n_hi_epsilon = n_hi_eps;
+ if (n_both_epsilon) *n_both_epsilon = n_both_eps;
+ return total;
+}
+
+
+/*--------------------------------------------------------------
+ * is_cyclic_state()
+ */
+gboolean gfsm_automaton_is_cyclic_state(gfsmAutomaton *fsm,
+ gfsmStateId id,
+ gfsmBitVector *visited,
+ gfsmBitVector *completed)
+{
+ gfsmState *s;
+ gfsmArcIter ai;
+ //
+ if (gfsm_bitvector_get(visited,id)) {
+ if (gfsm_bitvector_get(completed,id)) return FALSE;
+ return TRUE;
+ }
+ //
+ s = gfsm_automaton_find_state(fsm,id);
+ if (!s || !s->is_valid) return FALSE; //-- invalid states don't count as cyclic
+ //
+ //-- mark node as visited (& not completed)
+ gfsm_bitvector_set(visited,id,1);
+ gfsm_bitvector_set(completed,id,0);
+ //
+ //-- visit outgoing arcs
+ for (gfsm_arciter_open_ptr(&ai,fsm,s); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ if (gfsm_automaton_is_cyclic_state(fsm, gfsm_arciter_arc(&ai)->target, visited, completed)) {
+ gfsm_arciter_close(&ai);
+ return TRUE;
+ }
+ }
+ gfsm_arciter_close(&ai);
+ //
+ //-- mark node as completed
+ gfsm_bitvector_set(completed,id,1);
+ //
+ //-- finished traversal; this state isn't cyclic
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * is_cyclic()
+ */
+gboolean gfsm_automaton_is_cyclic(gfsmAutomaton *fsm)
+{
+ gfsmBitVector *visited; //-- records which states we've visited
+ gfsmBitVector *completed; //-- records which states we've completed
+ gboolean rc; //-- return value
+
+ if (fsm->root_id==gfsmNoState || fsm->states->len==0) return FALSE; //-- sanity check(s)
+
+ visited = gfsm_bitvector_sized_new(fsm->states->len);
+ completed = gfsm_bitvector_sized_new(fsm->states->len);
+ rc = gfsm_automaton_is_cyclic_state(fsm, fsm->root_id, visited, completed);
+
+ //-- cleanup
+ gfsm_bitvector_free(visited);
+ gfsm_bitvector_free(completed);
+
+ return rc;
+}
+
+
+/*--------------------------------------------------------------
+ * get_alphabet()
+ */
+gfsmAlphabet *gfsm_automaton_get_alphabet(gfsmAutomaton *fsm, gfsmLabelSide which, gfsmAlphabet *alph)
+{
+ gfsmStateId id;
+ //-- ensure alphabet
+ if (!alph) alph = gfsm_range_alphabet_new();
+
+ for (id=0; id < fsm->states->len; id++) {
+ gfsmArcIter ai;
+ for (gfsm_arciter_open(&ai,fsm,id); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+
+ if (which != gfsmLSUpper)
+ gfsm_alphabet_insert(alph, GUINT_TO_POINTER((guint)(a->lower)), a->lower);
+
+ if (which != gfsmLSLower)
+ gfsm_alphabet_insert(alph, GUINT_TO_POINTER((guint)(a->upper)), a->upper);
+ }
+ gfsm_arciter_close(&ai);
+ }
+ return alph;
+}
+
+/*======================================================================
+ * Methods: Accessors: Automaton States
+ */
+
+/*--------------------------------------------------------------
+ * renumber_states()
+ */
+void gfsm_automaton_renumber_states(gfsmAutomaton *fsm)
+{
+ gfsmStateId oldid, newid;
+ GArray *old2new = NULL;
+
+ //-- always set root state to zero -- even add one
+ if (fsm->root_id == gfsmNoState) fsm->root_id = gfsm_automaton_add_state(fsm);
+
+ //-- get old-to-new id map
+ old2new = g_array_sized_new(FALSE,FALSE,sizeof(gfsmStateId),fsm->states->len);
+ g_array_index(old2new,gfsmStateId,fsm->root_id) = 0;
+ for (oldid=0, newid=0; oldid < fsm->states->len; oldid++) {
+ if (oldid==fsm->root_id) continue;
+ if (gfsm_automaton_has_state(fsm,oldid)) {
+ g_array_index(old2new,gfsmStateId,oldid) = ++newid;
+ } else {
+ g_array_index(old2new,gfsmStateId,oldid) = gfsmNoState;
+ }
+ }
+
+ //-- perform actual renumbering
+ gfsm_automaton_renumber_states_full(fsm, old2new, newid+1);
+
+ //-- cleanup
+ g_array_free(old2new,TRUE);
+}
+
+/*--------------------------------------------------------------
+ * renumber_states_full()
+ */
+void gfsm_automaton_renumber_states_full(gfsmAutomaton *fsm, GArray *old2new, gfsmStateId n_new_states)
+{
+ gfsmStateId oldid, newid;
+ gfsmState *s_old, *s_new;
+ gfsmWeightMap *new_finals = gfsm_weightmap_new(gfsm_uint_compare);
+ GArray *new_states = NULL;
+
+ //-- get new number of states
+ if (n_new_states==0) {
+ for (oldid=0; oldid < fsm->states->len; oldid++) {
+ if (!gfsm_automaton_has_state(fsm,oldid)) continue;
+ newid = g_array_index(old2new,gfsmStateId,oldid);
+ if (newid != gfsmNoState && newid >= n_new_states) { n_new_states=newid+1; }
+ }
+ }
+
+ //-- allocate new state-vector
+ new_states = g_array_sized_new(FALSE,TRUE,sizeof(gfsmState),n_new_states);
+
+ //-- renumber states
+ for (oldid=0; oldid < fsm->states->len; oldid++) {
+ gfsmArcIter ai;
+ newid = g_array_index(old2new,gfsmStateId,oldid);
+
+ if (newid==gfsmNoState || !gfsm_automaton_has_state(fsm,oldid)) continue; //-- ignore bad states
+
+ //-- copy state data
+ s_old = gfsm_automaton_find_state(fsm, oldid);
+ s_new = &(g_array_index(new_states,gfsmState,newid));
+ *s_new = *s_old;
+
+ //-- check for final state
+ if (s_new->is_final) {
+ gfsmWeight fw =0; //-- hack to convince gcc not to complain about unitialized fw
+ gfsm_weightmap_lookup(fsm->finals, GUINT_TO_POINTER(oldid), &fw);
+ gfsm_weightmap_insert(new_finals, GUINT_TO_POINTER(newid), fw);
+ }
+
+ //-- renumber sources & targets of outgoing arcs
+ for (gfsm_arciter_open_ptr(&ai, fsm, s_new); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai))
+ {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ a->source = newid;
+ a->target = g_array_index(old2new,gfsmStateId,a->target);
+ }
+ gfsm_arciter_close(&ai);
+ }
+
+ //-- set new root-id
+ fsm->root_id = g_array_index(old2new,gfsmStateId,fsm->root_id);
+
+ //-- set new final weights
+ gfsm_weightmap_free(fsm->finals);
+ fsm->finals = new_finals;
+
+ //-- set new state vector
+ g_array_free(fsm->states,TRUE);
+ fsm->states = new_states;
+ fsm->states->len = n_new_states;
+}
+
+
+/*======================================================================
+ * Methods: Accessors: Automaton Arcs
+ */
+
+/*--------------------------------------------------------------
+ * arcsort_full()
+ */
+void gfsm_automaton_arcsort_full(gfsmAutomaton *fsm, GCompareDataFunc cmpfunc, gpointer data)
+{
+ gfsmStateId qid;
+ for (qid=0; qid < fsm->states->len; qid++) {
+ gfsmState *qp = gfsm_automaton_find_state(fsm,qid);
+ if (!qp || !qp->is_valid) continue;
+ qp->arcs = gfsm_arclist_sort_full(qp->arcs, cmpfunc, data);
+ }
+ fsm->flags.sort_mode = gfsmACUser;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAutomaton.h b/gfsm/gfsm/src/libgfsm/gfsmAutomaton.h
new file mode 100644
index 0000000..6cb4927
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAutomaton.h
@@ -0,0 +1,557 @@
+
+/*=============================================================================*\
+ * File: gfsmAutomaton.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmAutomaton.h
+ * \brief Automaton definitions and low-level access
+ */
+
+#ifndef _GFSM_AUTOMATON_H
+#define _GFSM_AUTOMATON_H
+
+#include <gfsmAlphabet.h>
+#include <gfsmState.h>
+#include <gfsmWeightMap.h>
+#include <gfsmBitVector.h>
+
+/*======================================================================
+ * Types
+ */
+
+/** \brief Automaton status flags
+ * \detail
+ * \todo convert ::gfsmAutomatonFlags flags to 3-valued domain: unknown,true,false
+ * \todo add better checking & access for automaton status flags
+ */
+typedef struct {
+ guint32 is_transducer : 1; /**< whether this automaton is a transducer */
+ guint32 is_weighted : 1; /**< whether this automaton is weighted */
+ guint32 is_deterministic : 1; /**< whether fsm is known to be deterministic */
+ guint32 sort_mode : 24; /**< new-style sort mode (a ::gfsmArcCompMask) */
+ guint32 unused : 5; /**< reserved */
+} gfsmAutomatonFlags;
+
+/** \brief "Heavy" automaton type
+ *
+ * All automata are stored as weighted transducers.
+ */
+typedef struct {
+ //-- basic data
+ gfsmAutomatonFlags flags; /**< automaton flags */
+ gfsmSemiring *sr; /**< semiring used for arc weight computations */
+ GArray *states; /**< vector of automaton states */
+ gfsmWeightMap *finals; /**< map from final state-Ids to final weights */
+ gfsmStateId root_id; /**< ID of root node, or gfsmNoState if not defined */
+} gfsmAutomaton;
+
+/*======================================================================
+ * Constants
+ */
+/** Default initial automaton size (number of states) */
+extern const gfsmStateId gfsmAutomatonDefaultSize;
+
+/** Default initial automaton flags */
+extern const gfsmAutomatonFlags gfsmAutomatonDefaultFlags;
+
+/** Default semiring for automaton arc weights */
+extern const gfsmSRType gfsmAutomatonDefaultSRType;
+
+/*======================================================================*/
+/// \name API: Constructors etc.
+//@{
+
+/** Create a new ::gfsmAutomaton, preallocating \a n_states states */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_new_full(gfsmAutomatonFlags flags, gfsmSRType srtype, gfsmStateId n_states);
+
+/** Create and return a new ::gfsmAutomaton, using default flags, semiring type and size */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_new(void);
+
+/** Create a new gfsmAutomaton as a deep exact copy of \a fsm.
+ * \param fsm automaton to be cloned
+ * \returns new deep copy of \a src
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_clone(gfsmAutomaton *fsm);
+
+/** Assign non-structural contents (flags, semiring) of \a src to \a dst,
+ * without altering \a dst's topology.
+ * \param dst target automaton
+ * \param src source automaton
+ * \returns modified \a dst
+ * \warning Earlier versions of this function also set the root state of \a dst
+ * to that of \a src, but you should no longer rely on this being the case!
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_copy_shallow(gfsmAutomaton *dst, gfsmAutomaton *src);
+
+/** Assign the contents of fsm \a src to fsm \a dst \returns \a dst */
+gfsmAutomaton *gfsm_automaton_copy(gfsmAutomaton *dst, gfsmAutomaton *src);
+
+/** Create a new ::gfsmAutomaton whose non-structural contents match those of \a fsm.
+ * \param fsm source automaton
+ * \returns new automaton whose non-structural fields match those of \a fsm
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_shadow(gfsmAutomaton *fsm);
+
+/** Swap the contents of automata \a fsm1 and \a fsm2 */
+GFSM_INLINE
+void gfsm_automaton_swap(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2);
+
+/** Clear an automaton */
+void gfsm_automaton_clear(gfsmAutomaton *fsm);
+
+/** Destroy an automaton: all associated states and arcs will be freed. */
+GFSM_INLINE
+void gfsm_automaton_free(gfsmAutomaton *fsm);
+//@}
+
+
+/*======================================================================*/
+/// \name API: Automaton Semiring
+//@{
+
+/** Get pointer to the semiring associated with this automaton */
+GFSM_INLINE
+gfsmSemiring *gfsm_automaton_get_semiring(gfsmAutomaton *fsm);
+
+/** Set the semiring associated with this automaton
+ * \param fsm automaton to modify
+ * \param sr semiring to be copied into \a fsm->sr
+ * \returns pointer to the (new) semiring for \a fsm
+ * \note
+ * \li Implicitly frees the semiring previously associated with \a fsm, if any.
+ * \warning
+ * Prior to libgfsm-v0.0.9 this function returned the parameter \a sr itself
+ */
+GFSM_INLINE
+gfsmSemiring *gfsm_automaton_set_semiring(gfsmAutomaton *fsm, gfsmSemiring *sr);
+
+/** Set the semiring associated with this automaton by type.
+ * \param fsm automaton whose semiring is to be set
+ * \param srtype type of new semiring
+ * \note
+ * \li If \a fsm's semiring is already of type \a srtype, this function does nothing.
+ * \li If \a srtype is ::gfsmSRTUser, \a fsm's new semiring will be unitialized
+ * \li Implicitly frees the semiring previously associated with \a fsm, if any.
+ */
+GFSM_INLINE
+void gfsm_automaton_set_semiring_type(gfsmAutomaton *fsm, gfsmSRType srtype);
+
+//@}
+
+/*======================================================================*/
+///\name API: Automaton Structure
+//@{
+
+/** Reserve space for at least \a n_states states (may do nothing)
+ * \param fsm automaton to modify
+ * \param n_states number of states to reserve, if supported by implementation
+ */
+GFSM_INLINE
+void gfsm_automaton_reserve_states(gfsmAutomaton *fsm, gfsmStateId n_states);
+
+/** Backwards-compatible alias for gfsm_automaton_reserve_states()
+ * \deprecated in favor of gfsm_automaton_reserve_states()
+ */
+#define gfsm_automaton_reserve(fsm,n_states) gfsm_automaton_reserve_states((fsm),(n_states))
+
+
+/** Reserve space for at least \a n_arcs arcs
+ * \param fsm automaton to modify
+ * \param n_arcs number of arcs to reserve
+ * \note
+ * Currently does nothing.
+ */
+GFSM_INLINE
+void gfsm_automaton_reserve_arcs(gfsmAutomaton *fsm, guint n_arcs);
+
+/** Get the number of states in an automaton (modulo 'gaps' in state ID numbering).
+ * \param fsm automaton to examine
+ * \returns
+ * The least ::gfsmStateId \b q such that for all <b>r >= q</b>,
+ * \a fsm has no state with ID \b r.
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_n_states(gfsmAutomaton *fsm);
+
+/** Get number of final states in \a fsm */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_n_final_states(gfsmAutomaton *fsm);
+
+/** Get total number of arcs in \a fsm.
+ * \note
+ * Currently just a wrapper for gfsm_automaton_n_arcs_full(), so time is <em>O(n_arcs)</em>
+ */
+GFSM_INLINE
+guint gfsm_automaton_n_arcs(gfsmAutomaton *fsm);
+
+/** Get ID of root state, or ::gfsmNoState if undefined */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_get_root(gfsmAutomaton *fsm);
+
+/** Set ID of root state, creating state if necessary.
+ * \param fsm automaton whose root state is to be set
+ * \param new_root_id ID of new root state
+ * \li If \a new_root_id is ::gfsmNoState, \a fsm is marked as 'unrooted'
+ * \li otherwise, a new state with ID \a new_root_id is implicitly created if none already existed
+ */
+GFSM_INLINE
+void gfsm_automaton_set_root(gfsmAutomaton *fsm, gfsmStateId new_root_id);
+
+/** Call a user-defined function \a func for each final state of \a fsm.
+ * \param fsm automaton whose final states are to be traversed
+ * \param func \c GTraverseFunc for final states, as for \c g_tree_foreach()
+ * \param data user data for \a func
+ * \warning
+ * \a func may \e not directly alter any final weights of \a fsm.
+ * See GLib documentaion of g_tree_foreach() for details and a workaround.
+ * \note
+ * \a func will be called as <tt>(*func)(gpointer final_stateid, gpointer final_weight, gpointer data)</tt>;
+ * that is, both the ::gfsmStateId \a final_stateid and the final weight \a final_weight will be encoded
+ * as (gpointers). They can be decoded with GPOINTER_TO_UINT() and gfsm_ptr2weight(), respectively, e.g.
+\code
+gboolean my_final_func(gpointer id_p, gpointer fw_p, gpointer data) {
+ gfsmStateId final_id = GPOINTER_TO_UINT(id_p); //-- decode state id
+ gfsmWeight final_weight = gfsm_ptr2weight(fw_p); //-- decode final weight
+ do_something_interesting(); //-- ... whatever ...
+ return FALSE; //-- continue traversal
+}
+\endcode
+* \see gfsm_automaton_finals_to_array()
+ */
+GFSM_INLINE
+void gfsm_automaton_finals_foreach(gfsmAutomaton *fsm, GTraverseFunc func, gpointer data);
+
+/** Get a GArray of ::gfsmStateWeightPair values for final states of \a fsm.
+ * \param fsm automaton from which to extract final states
+ * \param array array to be populated, or NULL to allocate a new array
+ * \returns new \a array, or a newly allocated ::gfsmStateWeightPairArray
+ * \note
+ * Caller is responsible for freeing the array returned when it is no longer needed.
+ */
+GFSM_INLINE
+gfsmStateWeightPairArray* gfsm_automaton_finals_to_array(gfsmAutomaton *fsm, gfsmStateWeightPairArray *array);
+
+//@}
+
+/*======================================================================*/
+/** \name API: Automaton Properties
+ * Currently quite sketchy; better tracking and checking of automaton flags should be implemented.
+ */
+//@{
+
+/** True iff automaton is a transducer */
+#define gfsm_automaton_is_transducer(fsm) ((fsm)->flags.is_transducer)
+
+/** True iff automaton is weighted */
+#define gfsm_automaton_is_weighted(fsm) ((fsm)->flags.is_weighted)
+
+/** Get current automaton arc-sort mode (primary sort) */
+#define gfsm_automaton_sortmode(fsm) \
+ ((gfsmArcSortMode)(gfsm_acmask_nth((fsm)->flags.sort_mode,0)))
+
+// ((gfsmArcSortMode)((fsm)->flags.sort_mode))
+
+/** Get verbose summary arc information (linear time w/ number of arcs)
+ * \param[in] fsm automaton to examine
+ * \param[out] n_lo_epsilon on return holds number of arcs with lower label ::gfsmEpsilon, or NULL
+ * \param[out] n_hi_epsilon on return holds number of arcs with upper label ::gfsmEpsilon, or NULL
+ * \param[out] n_both_epsilon on return holds number of arcs with both lower and upper labels ::gfsmEpsilon, or NULL
+ * \returns total number of arcs
+ */
+guint gfsm_automaton_n_arcs_full(gfsmAutomaton *fsm,
+ guint *n_lo_epsilon,
+ guint *n_hi_epsilon,
+ guint *n_both_epsilon);
+
+/** Low-level utility function for gfsm_automaton_is_cyclic() */
+gboolean gfsm_automaton_is_cyclic_state(gfsmAutomaton *fsm,
+ gfsmStateId qid,
+ gfsmBitVector *visited,
+ gfsmBitVector *completed);
+
+/** Test whether automaton is cyclic */
+gboolean gfsm_automaton_is_cyclic(gfsmAutomaton *fsm);
+
+/** Test whether automaton is acyclic */
+#define gfsm_automaton_is_acyclic(fsm) (!gfsm_automaton_is_cyclic(fsm))
+
+/** Extract automaton-internal labels to \a alph. If \a alph is NULL,
+ * a new default alphabet will be created and returned (you will need to
+ * free it yourself).
+ *
+ * The alphabet should be able to match literal label values to themselves
+ * (so don't pass a string alphabet)
+ *
+ * \param[in] fsm automaton to examine
+ * \param[in] which determines which label side(s) to extract
+ * \param[out] alph alphabet to which labels are extracted, or NULL to create a new alphabet
+ *
+ * \returns \a alph, or a newly allocated and populated alphabet
+ */
+gfsmAlphabet *gfsm_automaton_get_alphabet(gfsmAutomaton *fsm,
+ gfsmLabelSide which,
+ gfsmAlphabet *alph);
+
+
+/** Renumber states of the automaton \a fsm.
+ * Destructively alters \c fsm.
+ * On return, \a fsm should have no 'gaps' in its state enumeration function, and its
+ * root state should have the ID 0 (zero).
+ */
+void gfsm_automaton_renumber_states(gfsmAutomaton *fsm);
+
+/** Renumber states of an FSM using user-specified state-ID map \a old2new.
+ * Destructively alters \c fsm.
+ * \param fsm
+ * Automaton whose states are to be renumbered
+ * \param old2new
+ * GArray of ::gfsmStateId such that <tt>qid_new=old2new[qid_old]</tt>.
+ * \a qid_new may be ::gfsmNoState to ignore the corresponding \a qid_old
+ * \param n_new_states
+ * Maximum \a qid_new ::gfsmStateId value in \a old2new, or 0 (zero) to auto-compute.
+ */
+void gfsm_automaton_renumber_states_full(gfsmAutomaton *fsm, GArray *old2new, gfsmStateId n_new_states);
+
+//@}
+
+/*======================================================================*/
+///\name API: gfsmState
+//@{
+
+/** Open and return a pointer to a ::gfsmState struct for ::gfsmStateId \a qid in \a fsm.
+ * \warning
+ * The pointer returned should be closed with gfsm_automaton_close_state()
+ * \param fsm automaton from which to draw state information
+ * \param qid ID of state to be opened
+ * \returns ::gfsmState* for state with ID \a qid in \a fsm, or NULL if no such state exists.
+ * \deprecated
+ * prefer gfsm_automaton_has_state(), gfsm_automaton_state_is_final(), gfsm_arciter_open() etc.
+ */
+GFSM_INLINE
+gfsmState *gfsm_automaton_open_state(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Open and return a pointer to a ::gfsmState struct for ::gfsmStateId \a qid in \a fsm,
+ * creating state if it does not already exists.
+ * \warning
+ * The pointer returned should be closed with gfsm_automaton_close_state().
+ * \param fsm automaton from which to draw state information
+ * \param qid ID of state to be opened
+ * \returns ::gfsmState* for (possibly new) state with ID \a qid in \a fsm
+ * \deprecated
+ * prefer gfsm_automaton_has_state(), gfsm_automaton_state_is_final(), gfsm_arciter_open() etc.
+ */
+GFSM_INLINE
+gfsmState *gfsm_automaton_open_state_force(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Close a pointer to a ::gfsmState opened with gfsm_automaton_open_state() for \a fsm.
+ * \param fsm automaton from which state was opened.
+ * \param qp pointer as returned by gfsm_automaton_open_state()
+ * \note Currently does nothing.
+ */
+GFSM_INLINE
+void gfsm_automaton_close_state(gfsmAutomaton *fsm, gfsmState *qp);
+
+/** Backwards-compatible alias for gfsm_automaton_open_state().
+ * This alias is expected to disappear when calling gfsm_automaton_close_state() becomes mandatory.
+ */
+#define gfsm_automaton_find_state(fsm,qid) gfsm_automaton_open_state((fsm),(qid))
+
+/** Backwards-compatible alias for gfsm_automaton_open_state().
+ * This alias is expected to disappear when calling gfsm_automaton_close_state() becomes mandatory.
+ */
+#define gfsm_automaton_find_state_const(fsm,qid) ((const gfsmState*)(gfsm_automaton_open_state((fsm),(qid))))
+
+/** Backwards-compatible alias for gfsm_automaton_open_state_force()
+ * This alias is expected to disappear when calling gfsm_automaton_close_state() becomes mandatory.
+ */
+#define gfsm_automaton_get_state(fsm,qid) gfsm_automaton_open_state_force((fsm),(qid))
+
+//@}
+
+/*======================================================================*/
+/// \name API: Automaton States
+//@{
+
+/*--------------------------------------------------------------
+ * has_state()
+ */
+GFSM_INLINE
+gboolean gfsm_automaton_has_state(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Add a new state, specifying state ID.
+ * \param fsm automaton to modify
+ * \param qid ID of new state, or ::gfsmNoState to use the first available state ID.
+ * \returns Id of the (new) state
+ * \note
+ * \li Implicitly sets \a fsm's root state if \a fsm was previously unrooted.
+ * \li Does nothing if \a fsm already has a state with ID \a qid.
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_add_state_full(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Ensures that state \a id exists \returns \a qid
+ * Really just an alias for gfsm_automaton_add_state_full().
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_ensure_state(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Add a new state to \a fsm.
+ * Really just an alias for \code gfsm_automaton_add_state_full(fsm,gfsmNoState) \endcode
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_add_state(gfsmAutomaton *fsm);
+
+/** Remove the state with id \a qid, if any.
+ * \param fsm automaton from which to remove a state
+ * \param qid ID of the state to be removed
+ * \note
+ * Any incoming arcs for state \a qid are NOT removed,
+ * although any outgoing arcs are removed and freed.
+ */
+GFSM_INLINE
+void gfsm_automaton_remove_state(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Lookup final weight for state with ID \a qid in automaton \a fsm.
+ * \param fsm automaton to examine
+ * \param qid ID of state to examine
+ * \param wp output parameter for final weight
+ * \returns
+ * TRUE if state \a qid is final, FALSE otherwise
+ */
+GFSM_INLINE
+gboolean gfsm_automaton_lookup_final(gfsmAutomaton *fsm, gfsmStateId qid, gfsmWeight *wp);
+
+/** Check whether the state with ID \a qid is final in \a fsm.
+ * Really just a wrapper for gfsm_automaton_lookup_final().
+ * \param fsm automaton to examine
+ * \param qid ID of state to check for finality
+ * \returns TRUE if \a qid is final in \a fsm, FALSE otherwise.
+ */
+GFSM_INLINE
+gboolean gfsm_automaton_state_is_final(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Backwards-compatible alias for gfsm_automaton_state_is_final() */
+#define gfsm_automaton_is_final_state(fsm,qid) gfsm_automaton_state_is_final((fsm),(qid))
+
+/** Get final weight. \returns final weight if state \a qid is final, else \a fsm->sr->zero */
+GFSM_INLINE
+gfsmWeight gfsm_automaton_get_final_weight(gfsmAutomaton *fsm, gfsmStateId qid);
+
+/** Set final-weight and/or final-states membership flag for state with ID \a qid in \a fsm.
+ * \param fsm automaton to modify
+ * \param qid ID of state to modified
+ * \param is_final whether state should be considered final
+ * \param final_weight
+ * If \a is_final is true, final weight for state.
+ * Otherwise, final weight is implicitly <tt>fsm->sr->zero</tt>
+ */
+GFSM_INLINE
+void gfsm_automaton_set_final_state_full(gfsmAutomaton *fsm,
+ gfsmStateId qid,
+ gboolean is_final,
+ gfsmWeight final_weight);
+
+/** Backwards-compatble wrapper for <code>gfsm_automaton_set_final_state_fulll(fsm,qid,is_final,fsm->sr->one)</code>
+ * \see gfsm_automaton_set_final_state_full()
+ */
+GFSM_INLINE
+void gfsm_automaton_set_final_state(gfsmAutomaton *fsm, gfsmStateId qid, gboolean is_final);
+
+/** Get number of outgoing arcs from \a qid in \a fsm */
+GFSM_INLINE
+guint gfsm_automaton_out_degree(gfsmAutomaton *fsm, gfsmStateId qid);
+
+//@}
+
+/*======================================================================*/
+/// \name Accessors: Automaton Arcs
+//@{
+
+/** Add an arc from state with ID \a qid1 to state with ID \a qid2
+ * on labels (\a lo,\a hi) with weight \a w.
+ * Missing states should be implicitly created.
+ * \param fsm Automaton to modify
+ * \param qid1 ID of source state
+ * \param qid2 ID of target state
+ * \param lo Lower label
+ * \param hi Upper label
+ * \param w Arc weight
+ */
+GFSM_INLINE
+void gfsm_automaton_add_arc(gfsmAutomaton *fsm,
+ gfsmStateId qid1,
+ gfsmStateId qid2,
+ gfsmLabelId lo,
+ gfsmLabelId hi,
+ gfsmWeight w);
+
+/** Add an arc given pointers \a sp to the state and \a link to a
+ * single-element arclist to be added.
+ * No states are implicitly created.
+ *
+ * \deprecated prefer gfsm_automaton_add_arc()
+ */
+GFSM_INLINE
+void gfsm_automaton_add_arc_node(gfsmAutomaton *fsm,
+ gfsmState *sp,
+ gfsmArcList *node);
+
+
+/** Sort all arcs in an automaton by one of the built-in comparison functions.
+ * \param fsm Automaton to modify
+ * \param mode Specifies built-in arc comparison priorities
+ * \returns modified \a fsm
+ * \note
+ * \li Does nothing if \code (mode==gfsmASMNone || mode==fsm->flags.sort_mode) \endcode
+ * \li Really just a wrapper for gfsm_automaton_arcsort_full()
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_arcsort(gfsmAutomaton *fsm, gfsmArcCompMask mode);
+
+/** Sort all arcs in an automaton by a user-specified comparison function.
+ * \param fsm
+ * Automaton to modify
+ * \param cmpfunc
+ * 3-way comparison function, called as \a (*cmpfunc)(gfsmArc *a1, gfsmArc *a2, gpointer data)
+ * to compare arcs \a a1 and \a a2.
+ * \param data
+ * User data for \a cmpfunc
+ * \returns
+ * Modified \a fsm
+ */
+void gfsm_automaton_arcsort_full(gfsmAutomaton *fsm, GCompareDataFunc cmpfunc, gpointer data);
+
+/** Alias for gfsm_automaton_arcsort_full() */
+#define gfsm_automaton_arcsort_with_data(fsm,cmpfunc,data) gfsm_automaton_arcsort_full((fsm),(cmpfunc),(data))
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmAutomaton.hi>
+#endif
+
+#endif /* _GFSM_AUTOMATON_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAutomaton.hi b/gfsm/gfsm/src/libgfsm/gfsmAutomaton.hi
new file mode 100644
index 0000000..b99f441
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAutomaton.hi
@@ -0,0 +1,530 @@
+/*=============================================================================*\
+ * File: gfsmAutomaton.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata: inline definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmUtils.h>
+#include <gfsmBitVector.h>
+#include <stdlib.h>
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+
+/*--------------------------------------------------------------
+ * new_full()
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_new_full(gfsmAutomatonFlags flags, gfsmSRType srtype, gfsmStateId size)
+{
+ gfsmAutomaton *fsm = (gfsmAutomaton*)g_new0(gfsmAutomaton,1);
+ fsm->flags = flags;
+ fsm->sr = gfsm_semiring_new(srtype);
+ fsm->states = g_array_sized_new(FALSE, TRUE, sizeof(gfsmState), size);
+ fsm->finals = gfsm_set_new(gfsm_uint_compare);
+ fsm->root_id = gfsmNoState;
+ return fsm;
+}
+
+/*--------------------------------------------------------------
+ * new()
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_new(void)
+{
+ return gfsm_automaton_new_full(gfsmAutomatonDefaultFlags,
+ gfsmAutomatonDefaultSRType,
+ gfsmAutomatonDefaultSize);
+}
+
+
+/*--------------------------------------------------------------
+ * copy_shallow()
+ */
+//#define GFSM_SHALLOW_ROOT 1
+#undef GFSM_SHALLOW_ROOT //-- for local testing
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_copy_shallow(gfsmAutomaton *dst, gfsmAutomaton *src)
+{
+ dst->flags = src->flags;
+#ifdef GFSM_SHALLOW_ROOT
+ dst->root_id = src->root_id; //-- pre v0.0.9: DANGEROUS! (assumed by clone() ?!)
+#endif
+ //
+ //-- copy semiring
+ if (dst->sr && dst->sr->type != src->sr->type) {
+ gfsm_semiring_free(dst->sr);
+ dst->sr = gfsm_semiring_copy(src->sr);
+ }
+ return dst;
+}
+
+/*--------------------------------------------------------------
+ * copy()
+ */
+//--extern
+
+/*--------------------------------------------------------------
+ * clone()
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_clone(gfsmAutomaton *fsm)
+{
+ return gfsm_automaton_copy(gfsm_automaton_new_full(gfsmAutomatonDefaultFlags,fsm->sr->type,0),fsm);
+}
+
+/*--------------------------------------------------------------
+ * shadow()
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_shadow(gfsmAutomaton *fsm)
+{
+ return gfsm_automaton_copy_shallow(gfsm_automaton_new(), fsm);
+}
+
+/*--------------------------------------------------------------
+ * swap()
+ */
+GFSM_INLINE
+void gfsm_automaton_swap(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ if (fsm1 != fsm2) {
+ gfsmAutomaton *tmp = g_new0(gfsmAutomaton,1);
+ *tmp = *fsm2;
+ *fsm2 = *fsm1;
+ *fsm1 = *tmp;
+ g_free(tmp);
+ }
+}
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+//--extern
+
+/*--------------------------------------------------------------
+ * free()
+ */
+GFSM_INLINE
+void gfsm_automaton_free(gfsmAutomaton *fsm)
+{
+ if (!fsm) return;
+ gfsm_automaton_clear(fsm); //-- implicitly frees indices
+ if (fsm->sr) gfsm_semiring_free(fsm->sr);
+ if (fsm->states) g_array_free(fsm->states,TRUE);
+ if (fsm->finals) gfsm_weightmap_free(fsm->finals);
+ g_free(fsm);
+}
+
+/*======================================================================
+ * Methods: Accessors: Semiring
+ */
+
+/*--------------------------------------------------------------
+ * get_semiring()
+ */
+GFSM_INLINE
+gfsmSemiring *gfsm_automaton_get_semiring(gfsmAutomaton *fsm) { return fsm->sr; }
+
+/*--------------------------------------------------------------
+ * set_semiring()
+ */
+GFSM_INLINE
+gfsmSemiring *gfsm_automaton_set_semiring(gfsmAutomaton *fsm, gfsmSemiring *sr)
+{
+ if (fsm->sr) gfsm_semiring_free(fsm->sr);
+ fsm->sr = gfsm_semiring_copy(sr);
+ return fsm->sr; //-- WARNING: in gfsm < v0.0.9, returned literal 'sr' parameter!
+}
+
+/*--------------------------------------------------------------
+ * set_semiring_type()
+ */
+GFSM_INLINE
+void gfsm_automaton_set_semiring_type(gfsmAutomaton *fsm, gfsmSRType srtype)
+{
+ if (!fsm->sr) fsm->sr = gfsm_semiring_new(srtype);
+ else if (fsm->sr->type != srtype) {
+ gfsm_semiring_free(fsm->sr);
+ fsm->sr = gfsm_semiring_new(srtype);
+ }
+}
+
+/*======================================================================*/
+///\name API: Automaton Structure
+
+/*--------------------------------------------------------------
+ * reserve_states()
+ */
+GFSM_INLINE
+void gfsm_automaton_reserve_states(gfsmAutomaton *fsm, gfsmStateId n_states)
+{
+ if (n_states != gfsmNoState && n_states > fsm->states->len)
+ g_array_set_size(fsm->states, n_states);
+}
+
+/*--------------------------------------------------------------
+ * reserve_arcs()
+ */
+GFSM_INLINE
+void gfsm_automaton_reserve_arcs(gfsmAutomaton *fsm, guint n_arcs)
+{
+ return;
+}
+
+/*--------------------------------------------------------------
+ * n_states()
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_n_states(gfsmAutomaton *fsm)
+{
+ return fsm->states->len;
+}
+
+/*--------------------------------------------------------------
+ * n_arcs()
+ */
+GFSM_INLINE
+guint gfsm_automaton_n_arcs(gfsmAutomaton *fsm)
+{
+ return gfsm_automaton_n_arcs_full(fsm,NULL,NULL,NULL);
+}
+
+/*--------------------------------------------------------------
+ * n_final_states()
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_n_final_states(gfsmAutomaton *fsm)
+{
+ return gfsm_weightmap_size(fsm->finals);
+}
+
+/*--------------------------------------------------------------
+ * finals_foreach
+ */
+GFSM_INLINE
+void gfsm_automaton_finals_foreach(gfsmAutomaton *fsm, GTraverseFunc func, gpointer data)
+{
+ gfsm_weightmap_foreach(fsm->finals,func,data);
+ return;
+}
+
+/*--------------------------------------------------------------
+ * finals_to_array
+ */
+GFSM_INLINE
+gfsmStateWeightPairArray* gfsm_automaton_finals_to_array(gfsmAutomaton *fsm, gfsmStateWeightPairArray *array)
+{
+ return gfsm_weightmap_to_array(fsm->finals,array);
+}
+
+/*--------------------------------------------------------------
+ * get_root()
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_get_root(gfsmAutomaton *fsm)
+{
+ return fsm->root_id;
+}
+
+/*--------------------------------------------------------------
+ * set_root()
+ */
+GFSM_INLINE
+void gfsm_automaton_set_root(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ if (qid!=gfsmNoState) qid = gfsm_automaton_ensure_state(fsm,qid);
+ fsm->root_id = qid;
+}
+
+
+/*======================================================================
+ * API: Automaton Properties
+ */
+
+/*--------------------------------------------------------------
+ * is_cyclic_state()
+ */
+//--EXTERN
+
+/*--------------------------------------------------------------
+ * is_cyclic()
+ */
+//--extern
+
+/*--------------------------------------------------------------
+ * get_alphabet()
+ */
+//--EXTERN
+
+/*======================================================================
+ * API: Automaton States: gfsmState*
+ */
+
+/*--------------------------------------------------------------
+ * open_state() [aka find_state()]
+ */
+GFSM_INLINE
+gfsmState *gfsm_automaton_open_state(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ return (qid < fsm->states->len
+ ? (((gfsmState*)fsm->states->data)+qid)
+ : NULL);
+}
+
+/*--------------------------------------------------------------
+ * add_state_full()
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_add_state_full(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ gfsmState *st;
+ if (qid == gfsmNoState) qid = fsm->states->len;
+ if (qid >= fsm->states->len) gfsm_automaton_reserve(fsm,qid+1);
+ st = gfsm_automaton_open_state(fsm,qid);
+ st->is_valid = TRUE;
+ return qid;
+}
+
+/*--------------------------------------------------------------
+ * ensure_state()
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_ensure_state(gfsmAutomaton *fsm, gfsmStateId qid)
+{ return gfsm_automaton_add_state_full(fsm,qid); }
+
+/*--------------------------------------------------------------
+ * open_state_force() [aka get_state()]
+ */
+GFSM_INLINE
+gfsmState *gfsm_automaton_open_state_force(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ return ((gfsmState*)fsm->states->data) + gfsm_automaton_ensure_state(fsm,qid);
+}
+
+/*--------------------------------------------------------------
+ * close_state()
+ */
+GFSM_INLINE
+void gfsm_automaton_close_state(gfsmAutomaton *fsm, gfsmState *qp)
+{
+ //gfsm_state_close(qp);
+ return;
+}
+
+/*======================================================================
+ * API: Automaton States
+ */
+
+/*--------------------------------------------------------------
+ * has_state()
+ */
+GFSM_INLINE
+gboolean gfsm_automaton_has_state(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ return qid < fsm->states->len && ((gfsmState*)fsm->states->data)[qid].is_valid;
+}
+
+/*--------------------------------------------------------------
+ * state_is_final()
+ */
+GFSM_INLINE
+gboolean gfsm_automaton_state_is_final(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ gfsmState *qp = gfsm_automaton_find_state(fsm,qid);
+ return qp!=NULL && qp->is_valid && qp->is_final;
+}
+
+/*--------------------------------------------------------------
+ * add_state()
+ */
+GFSM_INLINE
+gfsmStateId gfsm_automaton_add_state(gfsmAutomaton *fsm)
+{
+ return gfsm_automaton_add_state_full(fsm,gfsmNoState);
+}
+
+
+/*--------------------------------------------------------------
+ * remove_state()
+ */
+GFSM_INLINE
+void gfsm_automaton_remove_state(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ gfsmState *s = gfsm_automaton_find_state(fsm,qid);
+ if (!s || !s->is_valid) return;
+ //
+ if (s->is_final) gfsm_weightmap_remove(fsm->finals,GUINT_TO_POINTER(qid));
+ if (qid==fsm->root_id) fsm->root_id = gfsmNoState;
+ //
+ gfsm_arclist_free(s->arcs);
+ s->arcs = NULL;
+ s->is_valid = FALSE;
+}
+
+/*--------------------------------------------------------------
+ * lookup_final()
+ */
+GFSM_INLINE
+gboolean gfsm_automaton_lookup_final(gfsmAutomaton *fsm, gfsmStateId qid, gfsmWeight *wp)
+{
+ gfsmState *qp = gfsm_automaton_find_state(fsm,qid);
+ if (!qp || !qp->is_valid || !qp->is_final) {
+ *wp = fsm->sr->zero;
+ return FALSE;
+ }
+ return gfsm_weightmap_lookup(fsm->finals, GUINT_TO_POINTER(qid), wp);
+}
+
+/*--------------------------------------------------------------
+ * get_final_weight
+ */
+GFSM_INLINE
+gfsmWeight gfsm_automaton_get_final_weight(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ gfsmWeight w =0; //-- convince gcc not to complain about uninitialized 'w'
+#if 0
+ //-- old implementation: direct weightmap lookup
+ if (gfsm_weightmap_lookup(fsm->finals, GUINT_TO_POINTER(id), &w)) return w;
+ return fsm->sr->zero;
+#else
+ gfsm_automaton_lookup_final(fsm,qid,&w);
+ return w;
+#endif
+}
+
+/*--------------------------------------------------------------
+ * set_final_state_full
+ */
+GFSM_INLINE
+void gfsm_automaton_set_final_state_full(gfsmAutomaton *fsm,
+ gfsmStateId qid,
+ gboolean is_final,
+ gfsmWeight final_weight)
+{
+ gfsm_state_set_final(gfsm_automaton_get_state(fsm,qid),is_final);
+ if (is_final) {
+ gfsm_weightmap_insert(fsm->finals, GUINT_TO_POINTER(qid), final_weight);
+ } else {
+ gfsm_weightmap_remove(fsm->finals, GUINT_TO_POINTER(qid));
+ }
+}
+
+/*--------------------------------------------------------------
+ * set_final_state()
+ */
+GFSM_INLINE
+void gfsm_automaton_set_final_state(gfsmAutomaton *fsm, gfsmStateId qid, gboolean is_final)
+{
+ gfsm_automaton_set_final_state_full(fsm,qid,is_final,fsm->sr->one);
+}
+
+
+/*--------------------------------------------------------------
+ * out_degree()
+ */
+GFSM_INLINE
+guint gfsm_automaton_out_degree(gfsmAutomaton *fsm, gfsmStateId qid)
+{
+ gfsmState *qp = gfsm_automaton_open_state(fsm,qid);
+ if (!qp || !qp->is_valid) return 0;
+ return gfsm_state_out_degree(qp);
+}
+
+/*--------------------------------------------------------------
+ * renumber_states()
+ */
+//--EXTERN
+
+/*--------------------------------------------------------------
+ * renumber_states_full()
+ */
+//--EXTERN
+
+
+/*======================================================================
+ * Methods: Accessors: Automaton Arcs
+ */
+
+/*--------------------------------------------------------------
+ * add_arc_link()
+ */
+GFSM_INLINE
+void gfsm_automaton_add_arc_node(gfsmAutomaton *fsm,
+ gfsmState *sp,
+ gfsmArcList *node)
+{
+ //-- possibly sorted
+ gfsmArcCompData acdata = { fsm->flags.sort_mode, fsm->sr, NULL, NULL };
+ sp->arcs = gfsm_arclist_insert_node(sp->arcs, node, &acdata);
+
+ //-- always unmark 'deterministic' flag -- better: check
+ fsm->flags.is_deterministic = FALSE;
+
+ //-- always mark arcs "dirty"
+ /*fsm->flags.arcs_dirty=1;
+ */
+
+ //- always mark 'unsorted'
+ /*
+ alp->next = sp->arcs;
+ sp->arcs = alp;
+ fsm->flags.sort_mode = gfsmASMNone;
+ */
+}
+
+/*--------------------------------------------------------------
+ * add_arc()
+ */
+GFSM_INLINE
+void gfsm_automaton_add_arc(gfsmAutomaton *fsm,
+ gfsmStateId qid1,
+ gfsmStateId qid2,
+ gfsmLabelId lo,
+ gfsmLabelId hi,
+ gfsmWeight w)
+{
+ gfsmState *qp1;
+ gfsm_automaton_ensure_state(fsm,qid2);
+ qp1 = gfsm_automaton_get_state(fsm,qid1);
+ gfsm_automaton_add_arc_node(fsm,
+ qp1,
+ gfsm_arclist_new_full(qid1,qid2,lo,hi,w,NULL));
+}
+
+
+/*--------------------------------------------------------------
+ * arcsort_full()
+ */
+//-- EXTERN
+
+/*--------------------------------------------------------------
+ * arcsort()
+ */
+GFSM_INLINE
+gfsmAutomaton *gfsm_automaton_arcsort(gfsmAutomaton *fsm, gfsmArcCompMask mode)
+{
+ if (mode != fsm->flags.sort_mode && mode != gfsmASMNone) {
+ gfsmArcCompData acdata = { mode, fsm->sr, NULL, NULL };
+ gfsm_automaton_arcsort_full(fsm, (GCompareDataFunc)gfsm_arc_compare_bymask, &acdata);
+ }
+ fsm->flags.sort_mode = mode;
+ return fsm;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.c b/gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.c
new file mode 100644
index 0000000..234dec1
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.c
@@ -0,0 +1,897 @@
+
+/*=============================================================================*\
+ * File: gfsmAutomatonIO.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata: I/O
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmAutomatonIO.h>
+#include <gfsmArcIter.h>
+#include <gfsmUtils.h>
+//#include <gfsmCompat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+
+
+/*======================================================================
+ * Constants: Binary I/O
+ */
+const gfsmVersionInfo gfsm_version_bincompat_min_store =
+ {
+ 0, // major
+ 0, // minor
+ 10 // micro //--8
+ };
+
+const gfsmVersionInfo gfsm_version_bincompat_min_check =
+ {
+ 0, // major
+ 0, // minor
+ 2 // micro
+ };
+
+const gchar gfsm_header_magic[16] = "gfsm_automaton\0";
+
+/*======================================================================
+ * Methods: Binary I/O: load()
+ */
+
+/*--------------------------------------------------------------
+ * gfsmAutomatonFlags_009
+ */
+typedef struct {
+ guint32 is_transducer : 1; /**< whether this automaton is a transducer */
+ guint32 is_weighted : 1; /**< whether this automaton is weighted */
+ guint32 sort_mode_009 : 4; /**< old-style sort-mode (cast to ::gfsmArcSortMode_009) */
+ guint32 is_deterministic_009 : 1; /**< whether fsm is known to be deterministic */
+ guint32 unused_009 : 25; /**< reserved */
+} gfsmAutomatonFlags_009;
+
+/*--------------------------------------------------------------
+ * gfsmArcSortMode_009
+ */
+typedef enum {
+ gfsmASMNone_009,
+ gfsmASMLower_009,
+ gfsmASMUpper_009,
+ gfsmASMWeight_009
+} gfsmArcSortMode_009;
+
+/*--------------------------------------------------------------
+ * load_bin_header()
+ */
+gboolean gfsm_automaton_load_bin_header(gfsmAutomatonHeader *hdr, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ if (!gfsmio_read(ioh, hdr, sizeof(gfsmAutomatonHeader))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin_header:size"), //-- code
+ "could not read header");
+ return FALSE;
+ }
+ else if (strcmp(hdr->magic, gfsm_header_magic) != 0) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin_header:magic"), //-- code
+ "bad magic");
+ return FALSE;
+ }
+ else if (gfsm_version_compare(hdr->version, gfsm_version_bincompat_min_check) < 0) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin_header:version"), //-- code
+ "stored format v%u.%u.%u is obsolete - need at least v%u.%u.%u",
+ hdr->version.major,
+ hdr->version.minor,
+ hdr->version.micro,
+ gfsm_version_bincompat_min_check.major,
+ gfsm_version_bincompat_min_check.minor,
+ gfsm_version_bincompat_min_check.micro);
+ return FALSE;
+ }
+ else if (gfsm_version_compare(gfsm_version, hdr->version_min) < 0) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin_header:version"), //-- code
+ "libgfsm v%u.%u.%u is obsolete - stored automaton needs at least v%u.%u.%u",
+ gfsm_version.major,
+ gfsm_version.minor,
+ gfsm_version.micro,
+ hdr->version_min.major,
+ hdr->version_min.minor,
+ hdr->version_min.micro);
+ return FALSE;
+ }
+ if (gfsm_version_less(hdr->version, ((gfsmVersionInfo){0,0,10}))) {
+ //-- flags compatibility hack
+ gpointer flags_009p = &(hdr->flags);
+ gfsmAutomatonFlags_009 flags_009 = *((gfsmAutomatonFlags_009*)flags_009p);
+ hdr->flags.is_transducer = flags_009.is_transducer;
+ hdr->flags.is_weighted = flags_009.is_weighted;
+ hdr->flags.is_deterministic = flags_009.is_deterministic_009;
+ hdr->flags.unused = flags_009.unused_009;
+ switch (flags_009.sort_mode_009) {
+ case gfsmASMLower_009: hdr->flags.sort_mode = gfsmASMLower; break;
+ case gfsmASMUpper_009: hdr->flags.sort_mode = gfsmASMUpper; break;
+ case gfsmASMWeight_009: hdr->flags.sort_mode = gfsmASMWeight; break;
+ default:
+ hdr->flags.sort_mode = flags_009.sort_mode_009;
+ }
+ }
+ if (hdr->srtype == gfsmSRTUnknown || hdr->srtype >= gfsmSRTUser) {
+ //-- compatibility hack
+ hdr->srtype = gfsmAutomatonDefaultSRType;
+ }
+
+ return TRUE;
+}
+
+/*--------------------------------------------------------------
+ * load_bin_handle_0_0_8()
+ * + supports stored file versions v0.0.8 -- CURRENT
+ */
+gboolean gfsm_automaton_load_bin_handle_0_0_8(gfsmAutomatonHeader *hdr, gfsmAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmStateId id;
+ guint arci;
+ gfsmStoredArc s_arc;
+ gfsmStoredState s_state;
+ gfsmState *st;
+ gboolean rc = TRUE;
+ gfsmWeight w;
+
+ //-- allocate states
+ gfsm_automaton_reserve(fsm, hdr->n_states);
+
+ //-- set automaton-global properties
+ fsm->flags = hdr->flags;
+ gfsm_automaton_set_semiring_type(fsm, hdr->srtype);
+ fsm->root_id = hdr->root_id;
+
+ //------ load states (one-by-one)
+ for (id=0; rc && id < hdr->n_states; id++) {
+ if (!gfsmio_read(ioh, &s_state, sizeof(gfsmStoredState))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin:state"), //-- code
+ "could not read stored state %d", id);
+ rc = FALSE;
+ break;
+ }
+
+ if (!s_state.is_valid) continue;
+
+ st = gfsm_automaton_find_state(fsm,id);
+ st->is_valid = TRUE;
+
+ if (s_state.is_final) {
+ //-- read final weight
+ if (!gfsmio_read(ioh, &w, sizeof(gfsmWeight))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin:state:final_weight"), //-- code
+ "could not read final weight for stored state %d", id);
+ rc = FALSE;
+ break;
+ }
+
+ //-- set final weight
+ st->is_final = TRUE;
+ gfsm_weightmap_insert(fsm->finals,GINT_TO_POINTER(id),w);
+ } else {
+ st->is_final = FALSE;
+ }
+
+
+ //-- read arcs (one-by-one)
+ st->arcs = NULL;
+ for (arci=0; arci < s_state.n_arcs; arci++) {
+ if (!gfsmio_read(ioh, &s_arc, sizeof(gfsmStoredArc))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin:state:arc"), //-- code
+ "could not read stored arcs for state %d", id);
+ rc=FALSE;
+ break;
+ }
+ if (!rc) break;
+
+ st->arcs = gfsm_arclist_new_full(id,
+ s_arc.target,
+ s_arc.lower,
+ s_arc.upper,
+ s_arc.weight,
+ st->arcs);
+ }
+
+ //-- reverse arc-list for sorted automata
+ if (fsm->flags.sort_mode != gfsmASMNone) st->arcs = gfsm_arclist_reverse(st->arcs);
+ }
+
+ return rc;
+}
+
+
+/*--------------------------------------------------------------
+ * load_bin_handle_0_0_7()
+ * + supports stored file versions 0.0.2 -- 0.0.7
+ */
+/// Type for a stored state (v0.0.2 .. v0.0.7)
+typedef struct {
+ gboolean is_valid : 1; /**< valid flag */
+ gboolean is_final : 1; /**< final flag */
+ guint n_arcs; /**< number of stored arcs */
+ guint min_arc; /**< index of stored minimum arc (not really necessary) */
+} gfsmStoredState_007;
+
+gboolean gfsm_automaton_load_bin_handle_0_0_7(gfsmAutomatonHeader *hdr, gfsmAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmStateId id;
+ guint arci, n_arcs;
+ gfsmStoredArc s_arc;
+ gfsmStoredState_007 s_state;
+ gfsmState *st;
+ gboolean rc = TRUE;
+
+ //-- allocate states
+ gfsm_automaton_reserve(fsm, hdr->n_states);
+
+ //-- set automaton-global properties
+ fsm->flags = hdr->flags;
+ gfsm_semiring_init(fsm->sr, hdr->srtype);
+ fsm->root_id = hdr->root_id;
+
+ //------ load states (one-by-one)
+ for (id=0; rc && id < hdr->n_states; id++) {
+ if (!gfsmio_read(ioh, &s_state, sizeof(gfsmStoredState_007))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin:state"), //-- code
+ "could not read stored state %d", id);
+ rc = FALSE;
+ break;
+ }
+
+ if (!s_state.is_valid) continue;
+
+ st = gfsm_automaton_find_state(fsm,id);
+ st->is_valid = TRUE;
+
+ if (s_state.is_final) {
+ st->is_final = TRUE;
+ gfsm_weightmap_insert(fsm->finals, GUINT_TO_POINTER(id), fsm->sr->one);
+ } else {
+ st->is_final = FALSE;
+ }
+
+ //-- HACK: remember number of arcs!
+ st->arcs = (gfsmArcList*) GUINT_TO_POINTER(s_state.n_arcs);
+ }
+
+ //------ load arcs (state-by-state)
+ for (id=0; rc && id < hdr->n_states; id++) {
+ //-- get state
+ st = gfsm_automaton_find_state(fsm,id);
+ if (!st || !st->is_valid) continue;
+
+ //-- read in arcs (one-by-one)
+ n_arcs = GPOINTER_TO_UINT(st->arcs);
+ st->arcs = NULL;
+ for (arci=0; arci < n_arcs; arci++) {
+ if (!gfsmio_read(ioh, &s_arc, sizeof(gfsmStoredArc))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_load_bin:arc"), //-- code
+ "could not read stored arcs for state %d", id);
+ rc=FALSE;
+ break;
+ }
+
+ st->arcs = gfsm_arclist_new_full(id,
+ s_arc.target,
+ s_arc.lower,
+ s_arc.upper,
+ s_arc.weight,
+ st->arcs);
+ }
+
+ //-- reverse arc-list for sorted automata
+ if (fsm->flags.sort_mode != gfsmASMNone) st->arcs = gfsm_arclist_reverse(st->arcs);
+ }
+
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * load_bin_handle()
+ * + dispatch
+ */
+gboolean gfsm_automaton_load_bin_handle(gfsmAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmAutomatonHeader hdr;
+
+ gfsm_automaton_clear(fsm);
+
+ //-- load header
+ if (!gfsm_automaton_load_bin_header(&hdr,ioh,errp)) return FALSE;
+
+ if (gfsm_version_ge(hdr.version,((gfsmVersionInfo){0,0,8}))) {
+ //-- v0.0.8 .. CURRENT
+ return gfsm_automaton_load_bin_handle_0_0_8(&hdr,fsm,ioh,errp);
+ }
+ else {
+ //-- v0.0.2 .. v0.0.7
+ return gfsm_automaton_load_bin_handle_0_0_7(&hdr,fsm,ioh,errp);
+ }
+}
+
+/*--------------------------------------------------------------
+ * load_bin_file()
+ */
+gboolean gfsm_automaton_load_bin_file(gfsmAutomaton *fsm, FILE *f, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_zfile(f,"rb",-1);
+ gboolean rc = gfsm_automaton_load_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * load_bin_filename()
+ */
+gboolean gfsm_automaton_load_bin_filename(gfsmAutomaton *fsm, const gchar *filename, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename, "rb", -1, errp);
+ gboolean rc = ioh && !(*errp) && gfsm_automaton_load_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * load_bin_gstring()
+ */
+gboolean gfsm_automaton_load_bin_gstring(gfsmAutomaton *fsm, GString *gs, gfsmError **errp)
+{
+ gfsmPosGString pgs = { gs, 0 };
+ gfsmIOHandle *ioh = gfsmio_new_gstring(&pgs);
+ gboolean rc = ioh && !(*errp) && gfsm_automaton_load_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+
+/*======================================================================
+ * Methods: Binary I/O: save()
+ */
+
+/*--------------------------------------------------------------
+ * save_bin_handle()
+ */
+gboolean gfsm_automaton_save_bin_handle(gfsmAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmAutomatonHeader hdr;
+ gfsmStateId id;
+ gfsmState *st;
+ gfsmStoredState sst;
+ gfsmStoredArc sa;
+ gfsmWeight w;
+ gfsmArcIter ai;
+ gboolean rc = TRUE;
+
+ //-- create header
+ memset(&hdr, 0, sizeof(gfsmAutomatonHeader));
+ strcpy(hdr.magic, gfsm_header_magic);
+ hdr.version = gfsm_version;
+ hdr.version_min = gfsm_version_bincompat_min_store;
+ hdr.flags = fsm->flags;
+ hdr.root_id = fsm->root_id;
+ hdr.n_states = gfsm_automaton_n_states(fsm);
+ //hdr.n_arcs_007= gfsm_automaton_n_arcs(fsm);
+ hdr.srtype = gfsm_automaton_get_semiring(fsm)->type;
+
+ //-- write header
+ if (!gfsmio_write(ioh, &hdr, sizeof(gfsmAutomatonHeader))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_save_bin:header"), //-- code
+ "could not store header");
+ return FALSE;
+ }
+
+ //-- zero stored state (allow zlib compression to work better for any 'unused' members)
+ memset(&sst, 0, sizeof(gfsmStoredState));
+
+ //-- write states
+ for (id=0; rc && id < hdr.n_states; id++) {
+ //-- store basic state information
+ st = &g_array_index(fsm->states, gfsmState, id);
+ sst.is_valid = st->is_valid;
+ sst.is_final = sst.is_valid ? st->is_final : FALSE;
+ sst.n_arcs = sst.is_valid ? gfsm_state_out_degree(st) : 0;
+ if (!gfsmio_write(ioh, &sst, sizeof(sst))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_save_bin:state"), //-- code
+ "could not store state %d", id);
+ rc = FALSE;
+ }
+
+ //-- store final weight (maybe)
+ if (rc && sst.is_final) {
+ w = gfsm_automaton_get_final_weight(fsm,id);
+ if (!gfsmio_write(ioh, &w, sizeof(gfsmWeight))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_save_bin:state:final_weight"), //-- code
+ "could not store final weight for state %d", id);
+ rc = FALSE;
+ }
+ }
+
+ //-- store arcs
+ if (sst.is_valid) {
+ for (gfsm_arciter_open_ptr(&ai,fsm,st); rc && gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ sa.target = a->target;
+ sa.lower = a->lower;
+ sa.upper = a->upper;
+ sa.weight = a->weight;
+ if (!gfsmio_write(ioh, &sa, sizeof(sa))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("automaton_save_bin:state:arc"), //-- code
+ "could not store arcs for state %d", id);
+ rc = FALSE;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_file()
+ */
+gboolean gfsm_automaton_save_bin_file(gfsmAutomaton *fsm, FILE *f, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_file(f);
+ gboolean rc = ioh && !(*errp) && gfsm_automaton_save_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ //gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_filename_nc()
+ */
+gboolean gfsm_automaton_save_bin_filename_nc(gfsmAutomaton *fsm, const gchar *filename, gfsmError **errp)
+{
+ FILE *f;
+ gboolean rc;
+ if (!(f=gfsm_open_filename(filename,"wb",errp))) return FALSE;
+ rc = gfsm_automaton_save_bin_file(fsm, f, errp);
+ if (f != stdout) fclose(f);
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_filename()
+ */
+gboolean gfsm_automaton_save_bin_filename(gfsmAutomaton *fsm, const gchar *filename, int zlevel, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename, "wb", zlevel, errp);
+ gboolean rc = ioh && !(*errp) && gfsm_automaton_save_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_gstring()
+ */
+gboolean gfsm_automaton_save_bin_gstring(gfsmAutomaton *fsm, GString *gs, gfsmError **errp)
+{
+ gfsmPosGString pgs = { gs, gs->len };
+ gfsmIOHandle *ioh = gfsmio_new_gstring(&pgs);
+ gboolean rc = ioh && !(*errp) && gfsm_automaton_save_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+
+/*======================================================================
+ * Methods: Text I/O: compile()
+ */
+
+/*--------------------------------------------------------------
+ * compile_handle()
+ */
+gboolean gfsm_automaton_compile_handle (gfsmAutomaton *fsm,
+ gfsmIOHandle *ioh,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ gfsmStateId q1, q2;
+ gfsmLabelId lo, hi;
+ gfsmWeight w;
+ char *buf = NULL;
+ size_t buflen = 0;
+ guint lineno = 1;
+ char *b1, *b2, *b3, *b4, *b5, *end;
+ GString *gs = g_string_new("");
+ gpointer key;
+ gboolean rc = TRUE;
+
+ /*extern int getline(char **, size_t *, FILE *);*/
+ for (lineno=1; rc && gfsmio_getline(ioh,&buf,&buflen) > 0; ++lineno) {
+ b1 = b2 = b3 = b4 = b5 = end = NULL;
+ short int nfields = 0;
+
+ //-- get pointers to initial elements of the line
+ for (b1 = buf; b1 && *b1 && isspace(*b1); b1++) { *b1 = '\0'; }
+
+ for (b2 = b1 ; b2 && *b2 && !isspace(*b2); b2++) ;
+ for ( ; b2 && *b2 && isspace(*b2); b2++) { *b2 = '\0'; }
+ if (b2 != b1) nfields = 1;
+ else {
+ //-- empty line
+ continue;
+ }
+
+ for (b3 = b2 ; b3 && *b3 && !isspace(*b3); b3++) ;
+ for ( ; b3 && *b3 && isspace(*b3); b3++) { *b3 = '\0'; }
+ if (b3 != b2) nfields = 2;
+
+ for (b4 = b3 ; b4 && *b4 && !isspace(*b4); b4++) ;
+ for ( ; b4 && *b4 && isspace(*b4); b4++) { *b4 = '\0'; }
+ if (b4 != b3) nfields = 3;
+
+ for (b5 = b4 ; b5 && *b5 && !isspace(*b5); b5++) ;
+ for ( ; b5 && *b5 && isspace(*b5); b5++) { *b5 = '\0'; }
+ if (b5 != b4) nfields = 4;
+
+ for (end = b5; end && *end && !isspace(*end); end++) ;
+ if (end) *end = '\0';
+ if (end != b5) nfields = 5;
+
+ //---- q1: source state
+ if (state_alphabet) {
+ g_string_assign(gs,b1);
+ key = gfsm_alphabet_string2key(state_alphabet, gs);
+ if ((q1 = gfsm_alphabet_find_label(state_alphabet,key)) == gfsmNoLabel)
+ q1 = gfsm_alphabet_get_label(state_alphabet, key);
+ } else q1 = strtol(b1,NULL,10);
+ if (fsm->root_id == gfsmNoState) fsm->root_id = q1;
+
+ //-- weightless final state?
+ if (nfields == 1) {
+ gfsm_automaton_set_final_state(fsm,q1,TRUE);
+ continue;
+ }
+ //-- weighted final state?
+ else if (nfields == 2) {
+ w = strtod(b2,NULL);
+ gfsm_automaton_set_final_state_full(fsm,q1,TRUE,w);
+ continue;
+ }
+
+ //---- q2: sink state
+ if (state_alphabet) {
+ g_string_assign(gs,b2);
+ key = gfsm_alphabet_string2key(state_alphabet, gs);
+ if ((q2 = gfsm_alphabet_find_label(state_alphabet,key)) == gfsmNoLabel)
+ q2 = gfsm_alphabet_get_label(state_alphabet, key);
+ } else q2 = strtol(b2,NULL,10);
+
+ //---- lo: lower label
+ if (lo_alphabet) {
+ g_string_assign(gs,b3);
+ key = gfsm_alphabet_string2key(lo_alphabet, gs);
+ if ((lo = gfsm_alphabet_find_label(lo_alphabet,key)) == gfsmNoLabel)
+ lo = gfsm_alphabet_get_label(lo_alphabet, key);
+ } else lo = strtol(b3,NULL,10);
+
+ //---- hi: upper label
+ if (fsm->flags.is_transducer) {
+ if (nfields > 3) {
+ if (hi_alphabet) {
+ g_string_assign(gs,b4);
+ key = gfsm_alphabet_string2key(hi_alphabet, gs);
+ if ((hi = gfsm_alphabet_find_label(hi_alphabet,key)) == gfsmNoLabel)
+ hi = gfsm_alphabet_get_label(hi_alphabet, key);
+ }
+ else hi = strtol(b4,NULL,10);
+ }
+ else {
+ g_printerr("gfsm: Warning: no upper label given for transducer at line %u - using lower label\n",
+ lineno);
+ hi = lo;
+ }
+ }
+ else {
+ //-- not a transducer
+ hi = lo;
+ if (nfields > 4) {
+ g_printerr("gfsm: Warning: ignoring extra fields in acceptor file at line %u\n", lineno);
+ }
+ }
+
+ //-- w: arc weight
+ if ( fsm->flags.is_transducer && nfields >= 5) { w = strtod(b5,NULL); }
+ else if (!fsm->flags.is_transducer && nfields >= 4) { w = strtod(b4,NULL); }
+ else { w = fsm->sr->one; }
+
+ gfsm_automaton_add_arc(fsm,q1,q2,lo,hi,w);
+ }
+
+ if (buf) free(buf);
+ g_string_free(gs,TRUE);
+
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * compile_file_full()
+ */
+gboolean gfsm_automaton_compile_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_zfile(f,"rb",-1);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_automaton_compile_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * compile_filename_full()
+ */
+gboolean gfsm_automaton_compile_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename,"rb",-1,errp);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_automaton_compile_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * compile_gstring_full()
+ */
+gboolean gfsm_automaton_compile_gstring_full (gfsmAutomaton *fsm,
+ GString *gs,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ gfsmPosGString pgs = { gs, 0 };
+ gfsmIOHandle *ioh = gfsmio_new_gstring(&pgs);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_automaton_compile_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+
+/*======================================================================
+ * Methods: Text I/O: print()
+ */
+
+/*--------------------------------------------------------------
+ * print_handle()
+ */
+gboolean gfsm_automaton_print_handle (gfsmAutomaton *fsm,
+ gfsmIOHandle *ioh,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ guint i;
+ GString *gs = g_string_new("");
+ gboolean rc = TRUE;
+
+ //-- sanity check
+ if (fsm->root_id == gfsmNoState) {
+ g_printerr("gfsm: Warning: cowardly refusing to print() unrooted automaton\n");
+ return TRUE;
+ }
+
+ for (i=0; rc && i < fsm->states->len; i++) {
+ guint id = (fsm->root_id + i) % fsm->states->len;
+ gfsmState *st = gfsm_automaton_find_state(fsm,id);
+ gfsmArcIter ai;
+ gpointer key;
+ if (!st || !st->is_valid) continue;
+
+ for (gfsm_arciter_open_ptr(&ai,fsm,st); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+
+ //-- source state
+ if (state_alphabet && (key=gfsm_alphabet_find_key(state_alphabet,id)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(state_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", id);
+ gfsmio_printf(ioh, "%u", id);
+ }
+ gfsmio_putc(ioh, '\t');
+
+ //-- sink state
+ if (state_alphabet && (key=gfsm_alphabet_find_key(state_alphabet,a->target)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(state_alphabet,key,gs);
+ gfsmio_puts(ioh,gs->str);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", a->target);
+ gfsmio_printf(ioh, "%u", a->target);
+ }
+ gfsmio_putc(ioh,'\t');
+
+ //-- lower label
+ if (lo_alphabet && (key=gfsm_alphabet_find_key(lo_alphabet,a->lower)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(lo_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ if (lo_alphabet) g_printerr("Warning: no lower label defined for Id '%u'!\n", a->lower);
+ gfsmio_printf(ioh, "%u", a->lower);
+ }
+
+ //-- upper label
+ if (fsm->flags.is_transducer) {
+ gfsmio_putc(ioh, '\t');
+ if (hi_alphabet && (key=gfsm_alphabet_find_key(hi_alphabet,a->upper)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(hi_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ if (hi_alphabet) g_printerr("Warning: no upper label defined for Id '%u'!\n", a->upper);
+ gfsmio_printf(ioh, "%u", a->upper);
+ }
+ }
+
+ //-- weight
+ if (fsm->flags.is_weighted) { // && a->weight != fsm->sr->one
+ gfsmio_printf(ioh, "\t%g", a->weight);
+ }
+
+ gfsmio_putc(ioh, '\n');
+ }
+
+ //-- final?
+ if (gfsm_state_is_final(st)) {
+ if (state_alphabet && (key=gfsm_alphabet_find_key(state_alphabet,id)) != NULL) {
+ gfsm_alphabet_key2string(state_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ gfsmio_printf(ioh, "%u", id);
+ }
+ if (fsm->flags.is_weighted) {
+ gfsmio_printf(ioh, "\t%g", gfsm_automaton_get_final_weight(fsm,id));
+ }
+ gfsmio_putc(ioh, '\n');
+ }
+ }
+
+ //-- cleanup
+ g_string_free(gs,TRUE);
+
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * print_file_full()
+ */
+gboolean gfsm_automaton_print_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_zfile(f,"wb",zlevel);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_automaton_print_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * print_filename()
+ */
+gboolean gfsm_automaton_print_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename,"wb",zlevel,errp);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_automaton_print_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+/*--------------------------------------------------------------
+ * print_gstring_full()
+ */
+gboolean gfsm_automaton_print_gstring_full (gfsmAutomaton *fsm,
+ GString *gs,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ gfsmPosGString pgs = { gs, gs->len };
+ gfsmIOHandle *ioh = gfsmio_new_gstring(&pgs);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_automaton_print_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.h b/gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.h
new file mode 100644
index 0000000..be9848c
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.h
@@ -0,0 +1,225 @@
+
+/*=============================================================================*\
+ * File: gfsmAutomatonIO.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata: I/O
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmAutomatonIO.h
+ * \brief Librarian routines for automata.
+ */
+
+#ifndef _GFSM_AUTOMATON_IO_H
+#define _GFSM_AUTOMATON_IO_H
+
+#include <gfsmAutomaton.h>
+#include <gfsmVersion.h>
+
+/*======================================================================
+ * Types
+ */
+/// Header info for binary files
+typedef struct {
+ gchar magic[16]; /**< magic header string "gfsm_automaton" */
+ gfsmVersionInfo version; /**< gfsm version which created the stored file */
+ gfsmVersionInfo version_min; /**< minimum gfsm version required to load the file */
+ gfsmAutomatonFlags flags; /**< automaton flags */
+ gfsmStateId root_id; /**< Id of root node */
+ gfsmStateId n_states; /**< number of stored states */
+ gfsmStateId n_arcs_007; /**< number of stored arcs (v0.0.2 .. v0.0.7) */
+ guint32 srtype; /**< semiring type (cast to gfsmSRType) */
+ guint32 unused1; /**< reserved */
+ guint32 unused2; /**< reserved */
+ guint32 unused3; /**< reserved */
+} gfsmAutomatonHeader;
+
+/// Type for a stored state
+typedef struct {
+ guint32 is_valid : 1; /**< valid flag */
+ guint32 is_final : 1; /**< final flag */
+ guint32 unused : 30; /**< reserved */
+ guint32 n_arcs; /**< number of stored arcs for this state */
+} gfsmStoredState;
+
+
+/// Type for a stored arc (no 'source' field)
+//typedef gfsmArc gfsmStoredArc;
+typedef struct {
+ gfsmStateId target; /**< ID of target node */
+ gfsmLabelId lower; /**< Lower label */
+ gfsmLabelId upper; /**< Upper label */
+ gfsmWeight weight; /**< arc weight */
+} gfsmStoredArc;
+
+/*======================================================================
+ * Constants
+ */
+/* Scanner config for gfsm_automaton_compile() */
+//extern const GScannerConfig gfsm_automaton_scanner_config;
+
+/** Magic header string for stored gfsm files */
+extern const gchar gfsm_header_magic[16];
+
+/** Minimum libgfsm version required for loading files stored by this version of libgfsm */
+extern const gfsmVersionInfo gfsm_version_bincompat_min_store;
+
+/** Minimum libgfsm version whose binary files this version of libgfsm can read */
+extern const gfsmVersionInfo gfsm_version_bincompat_min_check;
+
+/*======================================================================
+ * Methods: Binary I/O
+ */
+/// \name Automaton Methods: Binary I/O
+//@{
+/** Load an automaton header from a stored binary file.
+ * Returns TRUE iff the header looks valid. */
+gboolean gfsm_automaton_load_header(gfsmAutomatonHeader *hdr, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Load an automaton from a named binary file (implicitly clear()s \a fsm) */
+gboolean gfsm_automaton_load_bin_handle(gfsmAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Load an automaton from a stored binary file (implicitly clear()s \a fsm) */
+gboolean gfsm_automaton_load_bin_file(gfsmAutomaton *fsm, FILE *f, gfsmError **errp);
+
+/** Load an automaton from a named binary file (implicitly clear()s \a fsm) */
+gboolean gfsm_automaton_load_bin_filename(gfsmAutomaton *fsm, const gchar *filename, gfsmError **errp);
+
+/** Load an automaton from an in-memory buffer */
+gboolean gfsm_automaton_load_bin_gstring(gfsmAutomaton *fsm, GString *gs, gfsmError **errp);
+
+
+/** Store an automaton in binary form to a gfsmIOHandle* */
+gboolean gfsm_automaton_save_bin_handle(gfsmAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Store an automaton in binary form to a file */
+gboolean gfsm_automaton_save_bin_file(gfsmAutomaton *fsm, FILE *f, gfsmError **errp);
+
+/** Store an automaton to a named binary file (no compression) */
+gboolean gfsm_automaton_save_bin_filename_nc(gfsmAutomaton *fsm, const gchar *filename, gfsmError **errp);
+
+/** Store an automaton to a named binary file, possibly compressing.
+ * Set \a zlevel=-1 for default compression, and
+ * set \a zlevel=0 for no compression, otherwise should be as for zlib (1 <= zlevel <= 9)
+ */
+gboolean gfsm_automaton_save_bin_filename(gfsmAutomaton *fsm, const gchar *filename, int zlevel, gfsmError **errp);
+
+/** Append an uncompressed binary automaton to an in-memory buffer */
+gboolean gfsm_automaton_save_bin_gstring(gfsmAutomaton *fsm, GString *gs, gfsmError **errp);
+
+//@}
+
+/*======================================================================
+ * Automaton Methods: Text I/O
+ */
+/// \name Automaton Methods: Text I/O
+//@{
+
+/** Load an automaton in Ma-Bell-compatible text-format from a gfsmIOHandle* */
+gboolean gfsm_automaton_compile_handle (gfsmAutomaton *fsm,
+ gfsmIOHandle *ioh,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+
+/** Load an automaton in Ma-Bell-compatible text-format from a FILE* */
+gboolean gfsm_automaton_compile_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+/** Convenience macro for compiling all-numeric-id text streams */
+#define gfsm_automaton_compile_file(fsm,filep,errp) \
+ gfsm_automaton_compile_file_full((fsm),(filep),NULL,NULL,NULL,(errp))
+
+/** Load an automaton in Ma-Bell-compatible text-format from a named file, possibly compressed. */
+gboolean gfsm_automaton_compile_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+/** Convenience macro for compiling all-numeric-id named text files */
+#define gfsm_automaton_compile_filename(fsm,filename,errp) \
+ gfsm_automaton_compile_filename_full((fsm),(filename),NULL,NULL,NULL,(errp))
+
+/** Load an automaton in Ma-Bell-compatible text-format from an in-memory buffer */
+gboolean gfsm_automaton_compile_gstring_full (gfsmAutomaton *fsm,
+ GString *gs,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+
+/*-----------------------*/
+
+/** Print an automaton in Ma-Bell-compatible text-format to a gfsmIOHandle* */
+gboolean gfsm_automaton_print_handle (gfsmAutomaton *fsm,
+ gfsmIOHandle *ioh,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+
+/** Print an automaton in Ma-Bell-compatible text-format to a FILE* */
+gboolean gfsm_automaton_print_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp);
+
+/** Convenience macro for printing to uncompresed all-numeric-id text streams */
+#define gfsm_automaton_print_file(fsm,filep,errp) \
+ gfsm_automaton_print_file_full((fsm),(filep),NULL,NULL,NULL,0,(errp))
+
+/** Print an automaton in Ma-Bell-compatible text-format to a named file */
+gboolean gfsm_automaton_print_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp);
+
+/** Convenience macro for printing to uncompressed all-numeric-id named text files */
+#define gfsm_automaton_print_filename(fsm,filep,errp) \
+ gfsm_automaton_print_filename_full((fsm),(filep),NULL,NULL,NULL,0,(errp))
+
+/** Print an automaton in Ma-Bell-compatible text-format to an in-memory buffer */
+gboolean gfsm_automaton_print_gstring_full (gfsmAutomaton *fsm,
+ GString *gs,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+//@}
+
+#endif /* _GFSM_AUTOMATON_IO_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmBitVector.c b/gfsm/gfsm/src/libgfsm/gfsmBitVector.c
new file mode 100644
index 0000000..e7ab34d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmBitVector.c
@@ -0,0 +1,80 @@
+
+/*=============================================================================*\
+ * File: gfsmBitVector.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: bit vectors: extern functions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmConfig.h>
+#include <gfsmBitVector.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmBitVector.hi>
+#endif
+
+/*======================================================================
+ * I/O
+ */
+
+//--------------------------------------------------------------
+// bitvector_write_bin_handle()
+gboolean gfsm_bitvector_write_bin_handle(gfsmBitVector *bv, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ guint32 len = bv->len;
+ if (!gfsmio_write(ioh,&len,sizeof(guint32))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("bitvector_write_bin_handle:len"),
+ "could not store bit vector length ");
+ return FALSE;
+ }
+ if (!gfsmio_write(ioh, bv->data, bv->len)) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("bitvector_write_bin_handle:weights"),
+ "could not store bit vector data");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+//--------------------------------------------------------------
+// bitvector_read_bin_handle()
+gboolean gfsm_bitvector_read_bin_handle(gfsmBitVector *bv, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ guint32 len;
+ if (!gfsmio_read(ioh, &len, sizeof(guint32))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("bitvector_read_bin_handle:len"),
+ "could not read bit vector length");
+ return FALSE;
+ }
+ gfsm_bitvector_resize(bv,len);
+ if (!gfsmio_read(ioh, bv->data, len)) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("bitvector_read_bin_handle:data"),
+ "could not read bit vector data");
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmBitVector.h b/gfsm/gfsm/src/libgfsm/gfsmBitVector.h
new file mode 100644
index 0000000..6c9b999
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmBitVector.h
@@ -0,0 +1,141 @@
+
+/*=============================================================================*\
+ * File: gfsmBitVector.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmBitVector.h
+ * \brief Bit vector utilities using GArray
+ */
+
+#ifndef _GFSM_BITVECTOR_H
+#define _GFSM_BITVECTOR_H
+
+#include <gfsmIO.h>
+
+/*======================================================================
+ * Types
+ */
+/// bit vector type: really just a wrapper for GArray
+typedef GArray gfsmBitVector;
+
+/*======================================================================
+ * Utilities
+ */
+///\name Utilities
+//@{
+/** Low-level utility to convert bit-indices to byte-indices (starting from 0) */
+GFSM_INLINE
+guint gfsm_bitvector_bits2bytes_(guint nbits);
+
+/** Low-level utility to convert byte-sizes to bit-sizes */
+GFSM_INLINE
+guint gfsm_bitvector_bytes2bits_(guint nbytes);
+
+//@}
+
+/*======================================================================
+ * Constructors etc.
+ */
+///\name Constructors etc.
+//@{
+
+/** Create a new bit vector of length 0 */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_new(void);
+
+/** Create a new bit vector of length 0 with reserved space for at least \a nbits bits */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_sized_new(guint nbits);
+
+/** Resize a bit vector \a bv to at least \a nbits bits (rounded to next byte boundary) */
+GFSM_INLINE
+void gfsm_bitvector_resize(gfsmBitVector *bv, guint nbits);
+
+/** Get current size (in bits) of a bit vector \a bv */
+GFSM_INLINE
+guint gfsm_bitvector_size(gfsmBitVector *bv);
+
+/** Clear a bit vector */
+GFSM_INLINE
+void gfsm_bitvector_clear(gfsmBitVector *bv);
+
+/** Set all bits to zero. \returns altered bv */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_zero(gfsmBitVector *bv);
+
+/** Set all bits to one. \returns altered bv */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_one(gfsmBitVector *bv);
+
+/** Destroy a bit vector */
+GFSM_INLINE
+void gfsm_bitvector_free(gfsmBitVector *bv);
+//@}
+
+/*======================================================================
+ * Accessors
+ */
+///\name Accessors
+//@{
+
+/** Get the value (0 or 1) of the bit at index \a i in vector \a bv.
+ */
+GFSM_INLINE
+gboolean gfsm_bitvector_get(gfsmBitVector *bv, guint i);
+
+/** Set the value (0 or 1) of the bit at index \a i to boolean value \a v in vector \a bv.
+ * Formerly implemented as a macro which evaluates its arguments multiple times.
+ */
+GFSM_INLINE
+void gfsm_bitvector_set(gfsmBitVector *bv, guint i, gboolean v);
+
+//@}
+
+/*======================================================================
+ * I/O
+ */
+///\name I/O
+//@{
+
+/** Write the contents of a ::gfsmBitVector to a (binary) ::gfsmIOHandle.
+ * \param bv bit-vector to write
+ * \param ioh handle to which data is to be written
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_bitvector_write_bin_handle(gfsmBitVector *bv, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Read the contents of a ::gfsmBitVector from a (binary) ::gfsmIOHandle.
+ * \param bv bit-vector into which data is to be read
+ * \param ioh handle from which data is to be read
+ * \param errp if an error occurs, \a *errp will hold an error message
+ * \returns true on success
+ */
+gboolean gfsm_bitvector_read_bin_handle(gfsmBitVector *bv, gfsmIOHandle *ioh, gfsmError **errp);
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmBitVector.hi>
+#endif
+
+#endif /* _GFSM_BITVECTOR_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmBitVector.hi b/gfsm/gfsm/src/libgfsm/gfsmBitVector.hi
new file mode 100644
index 0000000..cfcc4dd
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmBitVector.hi
@@ -0,0 +1,133 @@
+
+/*=============================================================================*\
+ * File: gfsmBitVector.def
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: bit vectors: inline definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <stdlib.h>
+#include <string.h>
+
+/*======================================================================
+ * Utilities
+ */
+
+//--------------------------------------------------------------
+// bits2bytes()
+GFSM_INLINE
+guint gfsm_bitvector_bits2bytes_(guint nbits)
+{ return nbits/8; }
+
+//--------------------------------------------------------------
+// bytes2bits()
+GFSM_INLINE
+guint gfsm_bitvector_bytes2bits_(guint nbytes)
+{ return nbytes*8; }
+
+/*--------------------------------------------------------------
+ * size()
+ */
+GFSM_INLINE
+guint gfsm_bitvector_size(gfsmBitVector *bv)
+{ return gfsm_bitvector_bytes2bits_(bv->len); }
+
+/*--------------------------------------------------------------
+ * get()
+ */
+GFSM_INLINE
+gboolean gfsm_bitvector_get(gfsmBitVector *bv, guint i)
+{
+ if (i < gfsm_bitvector_size(bv)) {
+ return g_array_index(bv, guint8, gfsm_bitvector_bits2bytes_(i)) & (1<<(i%8)) ? TRUE : FALSE;
+ }
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * resize()
+ */
+GFSM_INLINE
+void gfsm_bitvector_resize(gfsmBitVector *bv, guint nbits)
+{ g_array_set_size(bv, gfsm_bitvector_bits2bytes_(nbits)+1); }
+
+/*--------------------------------------------------------------
+ * set()
+ */
+GFSM_INLINE
+void gfsm_bitvector_set(gfsmBitVector *bv, guint i, gboolean v)
+{
+ if (i >= gfsm_bitvector_size(bv)) { gfsm_bitvector_resize(bv,i); }
+ if (v) { g_array_index(bv, guint8, gfsm_bitvector_bits2bytes_(i)) |= (1<<(i%8)); }
+ else { g_array_index(bv, guint8, gfsm_bitvector_bits2bytes_(i)) &= ~(1<<(i%8)); }
+}
+
+/*--------------------------------------------------------------
+ * new()
+ */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_new(void)
+{ return g_array_new(FALSE,TRUE,1); }
+
+/*--------------------------------------------------------------
+ * sized_new()
+ */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_sized_new(guint nbits)
+{
+ gfsmBitVector *bv = g_array_sized_new(FALSE,TRUE,1, gfsm_bitvector_bits2bytes_(nbits)+1);
+ gfsm_bitvector_set(bv, nbits-1, 0);
+ return bv;
+}
+
+/*--------------------------------------------------------------
+ * free()
+ */
+GFSM_INLINE
+void gfsm_bitvector_free(gfsmBitVector *bv)
+{ g_array_free(bv,TRUE); }
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+GFSM_INLINE
+void gfsm_bitvector_clear(gfsmBitVector *bv)
+{ g_array_set_size(bv,0); }
+
+/*--------------------------------------------------------------
+ * zero()
+ */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_zero(gfsmBitVector *bv)
+{
+ memset(bv->data, 0, bv->len);
+ return bv;
+}
+
+/*--------------------------------------------------------------
+ * one()
+ */
+GFSM_INLINE
+gfsmBitVector *gfsm_bitvector_one(gfsmBitVector *bv)
+{
+ memset(bv->data, 255, bv->len);
+ return bv;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmCommon.c b/gfsm/gfsm/src/libgfsm/gfsmCommon.c
new file mode 100644
index 0000000..1135277
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmCommon.c
@@ -0,0 +1,42 @@
+/*=============================================================================*\
+ * File: gfsmCommon.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: common definitions
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmCommon.h>
+#include <stdlib.h>
+
+/*======================================================================
+ * Constants
+ */
+const gfsmLabelId gfsmEpsilon = 0;
+
+const gpointer gfsmNoKey = NULL;
+
+const gfsmLabelId gfsmNoLabel = (gfsmLabelId)-1;
+
+const gfsmLabelId gfsmEpsilon1 = (gfsmLabelId)-2;
+
+const gfsmLabelId gfsmEpsilon2 = (gfsmLabelId)-3;
+
+const gfsmStateId gfsmNoState = (gfsmStateId)-1;
+
+const gfsmWeight gfsmNoWeight = 0;
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmCommon.h b/gfsm/gfsm/src/libgfsm/gfsmCommon.h
new file mode 100644
index 0000000..b27910e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmCommon.h
@@ -0,0 +1,88 @@
+
+/*=============================================================================*\
+ * File: gfsmCommon.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: common definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmCommon.h
+ * \brief Commonly use typedefs and constants
+ */
+
+#ifndef _GFSM_COMMON_H
+#define _GFSM_COMMON_H
+
+#include <gfsmConfig.h>
+#include <glib.h>
+
+/*======================================================================
+ * Basic Types
+ */
+/** Type for elementary arc-labels */
+typedef guint16 gfsmLabelId;
+
+/** Type for extended arc-labels (parameters and return values) */
+typedef guint32 gfsmLabelVal;
+
+/** Type for elementary state identifiers */
+typedef guint32 gfsmStateId;
+
+/** Alias for state identifiers */
+typedef gfsmStateId gfsmNodeId;
+
+/** Type for arc weights */
+typedef gfloat gfsmWeight;
+
+/*======================================================================
+ * Vector types
+ */
+/** Type for sequence of (gfsmLabelVal)s */
+typedef GPtrArray gfsmLabelVector;
+
+/** Type for a sequence of (gfsmStateId)s */
+typedef GPtrArray gfsmStateIdVector;
+
+
+/*======================================================================
+ * Constants
+ */
+/** Constant epsilon label */
+extern const gfsmLabelId gfsmEpsilon;
+
+/** Constant label for pseudo-epsilon moves in 1st argument to compose() */
+extern const gfsmLabelId gfsmEpsilon1;
+
+/** Constant label for pseudo-epsilon moves in 2nd argument to compose() */
+extern const gfsmLabelId gfsmEpsilon2;
+
+/** Constant indicating missing alphabet key */
+extern const gpointer gfsmNoKey;
+
+/** Constant indicating missing label */
+extern const gfsmLabelId gfsmNoLabel;
+
+/** Constant indicating missing state */
+extern const gfsmStateId gfsmNoState;
+
+/** Constant indicating missing weight
+ * \warning Deprecated: prefer gfsm_sr_one()
+ */
+extern const gfsmWeight gfsmNoWeight;
+
+#endif /* _GFSM_COMMON_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmCompound.c b/gfsm/gfsm/src/libgfsm/gfsmCompound.c
new file mode 100644
index 0000000..ec54502
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmCompound.c
@@ -0,0 +1,154 @@
+/*=============================================================================*\
+ * File: gfsmCompound.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: compound states
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmCompound.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmCompound.hi>
+#endif
+
+/*======================================================================
+ * Label Pair: Methods
+ */
+
+/*--------------------------------------------------------------
+ * labelpair_compare()
+ */
+gint gfsm_labelpair_compare(gfsmLabelPair lp1, gfsmLabelPair lp2)
+{ return gfsm_labelpair_compare_inline(lp1,lp2); }
+
+/*--------------------------------------------------------------
+ * labelpair_compare_with_data()
+ */
+gint gfsm_labelpair_compare_with_data(gfsmLabelPair lp1, gfsmLabelPair lp2, gpointer data)
+{ return gfsm_labelpair_compare_inline(lp1,lp2); }
+
+
+/*======================================================================
+ * Methods: gfsmStatePair
+ */
+
+/*--------------------------------------------------------------
+ * statepair_hash()
+ */
+guint gfsm_statepair_hash(gfsmStatePair *sp)
+{
+ //return 7*sp->id1 + sp->id2;
+ //return 5039*sp->id1 + sp->id2;
+ return 7949*sp->id1 + sp->id2;
+}
+
+
+/*--------------------------------------------------------------
+ * statepair_compare()
+ */
+gint gfsm_statepair_compare(const gfsmStatePair *sp1, const gfsmStatePair *sp2)
+{
+ return (sp1->id1 < sp2->id1 ? -1
+ : (sp1->id1 > sp2->id1 ? 1
+ : (sp1->id2 < sp2->id2 ? -1
+ : (sp1->id2 > sp2->id2 ? 1
+ : 0))));
+}
+
+/*--------------------------------------------------------------
+ * statepair_equal()
+ */
+gboolean gfsm_statepair_equal(const gfsmStatePair *sp1, const gfsmStatePair *sp2)
+{
+ return sp1->id1==sp2->id1 && sp1->id2==sp2->id2;
+}
+
+
+
+/*======================================================================
+ * Methods: gfsmComposeState
+ */
+
+/*--------------------------------------------------------------
+ * compose_state_hash()
+ */
+guint gfsm_compose_state_hash(gfsmComposeState *sp)
+{
+ return 7949*sp->id1 + sp->id2 + 7963*sp->idf;
+}
+
+
+/*--------------------------------------------------------------
+ * compose_state_compare()
+ */
+gint gfsm_compose_state_compare(const gfsmComposeState *sp1, const gfsmComposeState *sp2)
+{
+ return (sp1->id1 < sp2->id1 ? -1
+ : (sp1->id1 > sp2->id1 ? 1
+ : (sp1->id2 < sp2->id2 ? -1
+ : (sp1->id2 > sp2->id2 ? 1
+ : (sp1->idf < sp2->idf ? -1
+ : (sp1->idf > sp2->idf ? 1
+ : 0))))));
+}
+
+/*--------------------------------------------------------------
+ * compose_state_equal()
+ */
+gboolean gfsm_compose_state_equal(const gfsmComposeState *sp1, const gfsmComposeState *sp2)
+{
+ return sp1->id1==sp2->id1 && sp1->id2==sp2->id2 && sp1->idf==sp2->idf;
+}
+
+
+
+/*======================================================================
+ * Methods: gfsmStateWeightPair
+ */
+
+//--------------------------------------------------------------
+guint gfsm_state_weight_pair_hash(gfsmStateWeightPair *swp)
+{
+ return swp->id;
+}
+
+//--------------------------------------------------------------
+gint gfsm_state_weight_pair_compare(const gfsmStateWeightPair *swp1, const gfsmStateWeightPair *swp2, gfsmSemiring *sr)
+{
+ return (swp1->id < swp2->id ? -1
+ : (swp1->id > swp2->id ? 1
+ : gfsm_sr_compare(sr,swp1->w,swp2->w)));
+}
+
+//--------------------------------------------------------------
+gboolean gfsm_state_weight_pair_equal(const gfsmStateWeightPair *swp1, const gfsmStateWeightPair *swp2)
+{
+ return swp1->id==swp2->id && swp1->w==swp2->w;
+}
+
+
+/*======================================================================
+ * Methods: gfsmStatePairEnum
+ */
+
+
+/*======================================================================
+ * Methods: gfsmComposeStateEnum
+ */
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmCompound.h b/gfsm/gfsm/src/libgfsm/gfsmCompound.h
new file mode 100644
index 0000000..d492cc7
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmCompound.h
@@ -0,0 +1,266 @@
+
+/*=============================================================================*\
+ * File: gfsmCompound.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: basic compound types
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmCompound.h
+ * \brief Utilities for "compound" states and labels
+ */
+
+#ifndef _GFSM_COMPOUND_H
+#define _GFSM_COMPOUND_H
+
+#include <gfsmEnum.h>
+#include <gfsmWeightMap.h>
+
+/*======================================================================
+ * Compound Types
+ */
+/// Typedef for (lower,upper) label pairs: really just a wrapper for some bit operations
+typedef guint32 gfsmLabelPair;
+
+/// Matched pair of state-ids (used for automaton intersection)
+typedef struct {
+ gfsmStateId id1; /**< Id of first component */
+ gfsmStateId id2; /**< Id of second component */
+} gfsmStatePair;
+
+/// Typedef for composition filter states
+/**
+ * as described in Morhi, Pereira, & Riley (1996) "Weighted Automata in Text and Speech Processing",
+ * Proc. ECAI 96, John Wiley & Sons.
+ */
+typedef guint8 gfsmComposeFilterState;
+
+/// Matched pair of (::gfsmStateId)s with an additional filter state (used for transducer composition)
+/**
+ * for details, see
+ * Morhi, Pereira, & Riley (1996) "Weighted Automata in Text and Speech Processing",
+ * Proc. ECAI 96, John Wiley & Sons.
+ */
+typedef struct {
+ gfsmStateId id1; /**< Id of first component */
+ gfsmStateId id2; /**< Id of second component */
+ gfsmComposeFilterState idf; /**< Filter state (0|1|2) */
+} gfsmComposeState;
+
+/// Type for a (::gfsmStateId,::gfsmWeight) pair (used by algebraic operations)
+typedef struct {
+ gfsmStateId id; /**< state-id */
+ gfsmWeight w; /**< weight */
+} gfsmStateWeightPair;
+
+/// Typedef for mapping (::gfsmStatePair)s to single (::gfsmStateId)s,
+/// used by gfsm_automaton_intersection()
+typedef gfsmEnum gfsmStatePairEnum;
+
+/// Typedef for mapping (::gfsmComposeState)s to single (::gfsmStateId)s,
+/// used by gfsm_automaton_compose()
+typedef gfsmEnum gfsmComposeStateEnum;
+
+/// Typedef for mapping (::gfsmStatePair)s to single (::gfsmWeight)s,
+/// used by gfsm_automaton_rmepsilon()
+typedef gfsmWeightHash gfsmStatePair2WeightHash;
+
+
+/*======================================================================
+ * LabelPair: Methods
+ */
+///\name gfsmLabelPair Methods
+//@{
+
+/** Create a "new" gsfmLabelPair */
+GFSM_INLINE
+gfsmLabelPair gfsm_labelpair_new(guint32 lo, guint32 hi);
+
+/** Get lower label of of a label-pair */
+GFSM_INLINE
+gfsmLabelId gfsm_labelpair_lower(gfsmLabelPair lp);
+
+/** Get upper label of of a label-pair */
+GFSM_INLINE
+gfsmLabelId gfsm_labelpair_upper(gfsmLabelPair lp);
+
+/** Hash function alias for ::gfsmLabelPair */
+#define gfsm_labelpair_hash g_direct_hash
+
+/** Equal function alias for ::gfsmLabelPair */
+#define gfsm_labelpair_equal g_direct_equal
+
+/** Comparison function for ::gfsmLabelPair */
+gint gfsm_labelpair_compare(gfsmLabelPair lp1, gfsmLabelPair lp2);
+
+/** Dummy data-comparison function for gfsmLabelPair */
+gint gfsm_labelpair_compare_with_data(gfsmLabelPair lp1, gfsmLabelPair lp2, gpointer data);
+//@}
+
+/*======================================================================
+ * Methods: gfsmStatePair
+ */
+///\name gfsmStatePair Methods
+//@{
+
+/** Create a new ::gfsmStatePair */
+GFSM_INLINE
+gfsmStatePair *gfsm_statepair_new(gfsmStateId id1, gfsmStateId id2);
+
+/** Clone an existing ::gfsmStatePair */
+GFSM_INLINE
+gfsmStatePair *gfsm_statepair_clone(gfsmStatePair *sp);
+
+/** Free a ::gfsmStatePair:
+ * \code void gfsm_statepair_free(gfsmStatePair *sp); \endcode
+ */
+#define gfsm_statepair_free g_free
+
+/** Get a more or less sensible hash value from a state pair */
+guint gfsm_statepair_hash(gfsmStatePair *sp);
+
+/** Comparison function for ::gfsmStatePair */
+gint gfsm_statepair_compare(const gfsmStatePair *sp1, const gfsmStatePair *sp2);
+
+/** Equality predicate for ::gfsmStatePair */
+gboolean gfsm_statepair_equal(const gfsmStatePair *sp1, const gfsmStatePair *sp2);
+
+//@}
+
+/*======================================================================
+ * Methods: gfsmComposeState
+ */
+///\name gfsmComposeState Methods
+//@{
+
+/** Create a new ::gfsmComposeState */
+GFSM_INLINE
+gfsmComposeState *gfsm_compose_state_new(gfsmStateId id1, gfsmStateId id2, gfsmComposeFilterState idf);
+
+/** Clone an existing ::gfsmComposeState */
+GFSM_INLINE
+gfsmComposeState *gfsm_compose_state_clone(gfsmComposeState *sp);
+
+/** Free a ::gfsmComposeState:
+ * \code void gfsm_compose_state_free(gfsmComposeState *csp); \endcode
+*/
+#define gfsm_compose_state_free g_free
+
+/** Get a (more or less sensible) hash value from a ::gfsmComposeState */
+guint gfsm_compose_state_hash(gfsmComposeState *sp);
+
+/** Comparison function for gfsmComposeState */
+gint gfsm_compose_state_compare(const gfsmComposeState *sp1, const gfsmComposeState *sp2);
+
+/** Equality predicate for ::gfsmComposeState */
+gboolean gfsm_compose_state_equal(const gfsmComposeState *sp1, const gfsmComposeState *sp2);
+
+//@}
+
+
+/*======================================================================
+ * Methods: gfsmStateWeightPair
+ */
+///\name gfsmStateWeightPair Methods
+//@{
+
+/** Create a new ::gfsmStateWeightPair */
+GFSM_INLINE
+gfsmStateWeightPair *gfsm_state_weight_pair_new(gfsmStateId id, gfsmWeight w);
+
+/** Clone an existing ::gfsmStateWeightPair */
+GFSM_INLINE
+gfsmStateWeightPair *gfsm_state_weight_pair_clone(const gfsmStateWeightPair *swp);
+
+/** Free a ::gfsmStateWeightPair
+ * \code void gfsm_state_weight_pair_free(gfsmStateWeightPair *swp); \endcode
+ */
+#define gfsm_state_weight_pair_free g_free
+
+/** Get a (more or less sensible) hash value from a ::gfsmStateWeightPair (really just hashes id) */
+guint gfsm_state_weight_pair_hash(gfsmStateWeightPair *sp);
+
+/** Comparison function for ::gfsmStateWeightPair (id << w) */
+gint gfsm_state_weight_pair_compare(const gfsmStateWeightPair *swp1, const gfsmStateWeightPair *swp2, gfsmSemiring *sr);
+
+/** Equality predicate for ::gfsmStateWeightPair */
+gboolean gfsm_state_weight_pair_equal(const gfsmStateWeightPair *swp1, const gfsmStateWeightPair *swp2);
+
+//@}
+
+/*======================================================================
+ * Methods: gfsmStatePairEnum
+ */
+///\name gfsmStatePairEnum Methods
+//@{
+
+/** create a new ::gfsmStatePairEnum (copies & frees keys)
+ * \see gfsmEnum
+ */
+GFSM_INLINE
+gfsmStatePairEnum *gfsm_statepair_enum_new(void);
+
+/** Alias \see gfsm_enum_clear() */
+#define gfsm_statepair_enum_clear gfsm_enum_clear
+
+/** Alias; \see gfsm_enum_free() */
+#define gfsm_statepair_enum_free gfsm_enum_free
+
+//@}
+
+/*======================================================================
+ * Methods: gfsmComposeStateEnum
+ */
+///\name gfsmComposeStateEnum Methods
+//@{
+
+/** create a new ::gfsmComposeStateEnum (copies & frees keys)
+ * \see gfsmEnum
+ */
+GFSM_INLINE
+gfsmComposeStateEnum *gfsm_compose_state_enum_new(void);
+
+/** Alias; \see gfsm_enum_clear() */
+#define gfsm_compose_state_enum_clear gfsm_enum_clear
+
+/** Alias; \see gfsm_enum_clear() */
+#define gfsm_compose_state_enum_free gfsm_enum_free
+
+//@}
+
+
+/*======================================================================
+ * Methods: gfsmStatePair2WeightHash
+ */
+///\name gfsmStatePair2WeightHash Methods
+//@{
+
+/** create a new ::gfsmStatePair2WeightHash (copies & frees keys)
+ * \see gfsmWeightHash
+ */
+GFSM_INLINE
+gfsmStatePair2WeightHash *gfsm_statepair2weighthash_new(void);
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmCompound.hi>
+#endif
+
+#endif /* _GFSM_COMPOUND_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmCompound.hi b/gfsm/gfsm/src/libgfsm/gfsmCompound.hi
new file mode 100644
index 0000000..cf0f006
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmCompound.hi
@@ -0,0 +1,217 @@
+/*=============================================================================*\
+ * File: gfsmCompound.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: compound states: inline definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmMem.h>
+#include <stdlib.h>
+#include <gfsmUtils.h>
+
+
+/*======================================================================
+ * Label Pair: Methods
+ */
+
+//--------------------------------------------------------------
+// labelpair_new()
+GFSM_INLINE
+gfsmLabelPair gfsm_labelpair_new(guint32 lo, guint32 hi)
+{
+ return ((hi<<16)|lo);
+}
+
+//--------------------------------------------------------------
+// labelpair_lower()
+GFSM_INLINE
+gfsmLabelId gfsm_labelpair_lower(gfsmLabelPair lp)
+{ return (lp & 0xffff); }
+
+//--------------------------------------------------------------
+// labelpair_upper()
+GFSM_INLINE
+gfsmLabelId gfsm_labelpair_upper(gfsmLabelPair lp)
+{ return ((lp>>16) & 0xffff); }
+
+
+/*--------------------------------------------------------------
+ * labelpair_compare()
+ */
+GFSM_INLINE
+gint gfsm_labelpair_compare_inline(gfsmLabelPair lp1, gfsmLabelPair lp2)
+{
+ gfsmLabelId
+ lo1 = gfsm_labelpair_lower(lp1),
+ lo2 = gfsm_labelpair_lower(lp2),
+ hi1 = gfsm_labelpair_upper(lp1),
+ hi2 = gfsm_labelpair_upper(lp2);
+ return (lo1 < lo2 ? -1
+ : (lo1 > lo2 ? 1
+ : (hi1 < hi2 ? -1
+ : (hi1 > hi2 ? 1
+ : 0))));
+}
+
+
+/*======================================================================
+ * Methods: gfsmStatePair
+ */
+
+/*--------------------------------------------------------------
+ * statepair_new()
+ */
+GFSM_INLINE
+gfsmStatePair *gfsm_statepair_new(gfsmStateId id1, gfsmStateId id2)
+{
+ gfsmStatePair *sp = g_new(gfsmStatePair,1);
+ sp->id1 = id1;
+ sp->id2 = id2;
+ return sp;
+}
+
+/*--------------------------------------------------------------
+ * statepair_clone()
+ */
+GFSM_INLINE
+gfsmStatePair *gfsm_statepair_clone(gfsmStatePair *sp)
+{
+ return (gfsmStatePair*)gfsm_mem_dup_n(sp, sizeof(gfsmStatePair));
+}
+
+/*--------------------------------------------------------------
+ * statepair_free()
+ */
+#if 0
+GFSM_INLINE
+void gfsm_statepair_free(gfsmStatePair *sp)
+{ g_free(sp); }
+#endif
+
+
+
+/*======================================================================
+ * Methods: gfsmComposeState
+ */
+
+/*--------------------------------------------------------------
+ * compose_state_new()
+ */
+GFSM_INLINE
+gfsmComposeState *gfsm_compose_state_new(gfsmStateId id1, gfsmStateId id2, gfsmComposeFilterState idf)
+{
+ gfsmComposeState *sp = g_new(gfsmComposeState,1);
+ sp->id1 = id1;
+ sp->id2 = id2;
+ sp->idf = idf;
+ return sp;
+}
+
+/*--------------------------------------------------------------
+ * compose_state_clone()
+ */
+GFSM_INLINE
+gfsmComposeState *gfsm_compose_state_clone(gfsmComposeState *sp)
+{
+ return (gfsmComposeState*)gfsm_mem_dup_n(sp, sizeof(gfsmComposeState));
+}
+
+/*--------------------------------------------------------------
+ * compose_state_free()
+ */
+#if 0
+GFSM_INLINE
+void gfsm_compose_state_free(gfsmComposeState *sp)
+{ g_free(sp); }
+#endif
+
+
+
+/*======================================================================
+ * Methods: gfsmStateWeightPair
+ */
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmStateWeightPair *gfsm_state_weight_pair_new(gfsmStateId id, gfsmWeight w)
+{
+ gfsmStateWeightPair *swp = g_new(gfsmStateWeightPair,1);
+ swp->id = id;
+ swp->w = w;
+ return swp;
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmStateWeightPair *gfsm_state_weight_pair_clone(const gfsmStateWeightPair *swp)
+{
+ return gfsm_state_weight_pair_new(swp->id,swp->w);
+}
+
+//--------------------------------------------------------------
+#if 0
+GFSM_INLINE
+void gfsm_state_weight_pair_free(gfsmStateWeightPair *swp)
+{ g_free(swp); }
+#endif
+
+
+/*======================================================================
+ * Methods: gfsmStatePairEnum
+ */
+
+/*--------------------------------------------------------------
+ * statepair_enum_new()
+ */
+GFSM_INLINE
+gfsmStatePairEnum *gfsm_statepair_enum_new(void)
+{
+ return gfsm_enum_new_full((gfsmDupFunc)gfsm_statepair_clone,
+ (GHashFunc)gfsm_statepair_hash,
+ (GEqualFunc)gfsm_statepair_equal,
+ (GDestroyNotify)g_free);
+}
+
+
+/*======================================================================
+ * Methods: gfsmComposeStateEnum
+ */
+
+/*--------------------------------------------------------------
+ * compose_state_enum_new()
+ */
+GFSM_INLINE
+gfsmComposeStateEnum *gfsm_compose_state_enum_new(void)
+{
+ return gfsm_enum_new_full((gfsmDupFunc)gfsm_compose_state_clone,
+ (GHashFunc)gfsm_compose_state_hash,
+ (GEqualFunc)gfsm_compose_state_equal,
+ (GDestroyNotify)g_free);
+}
+
+/*======================================================================
+ * Methods: StatePair2WeightHash
+ */
+GFSM_INLINE
+gfsmStatePair2WeightHash *gfsm_statepair2weighthash_new(void)
+{
+ return gfsm_weighthash_new_full((gfsmDupFunc)gfsm_statepair_clone,
+ (GHashFunc)gfsm_statepair_hash,
+ (GEqualFunc)gfsm_statepair_equal,
+ (GDestroyNotify)g_free);
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmConfig.h b/gfsm/gfsm/src/libgfsm/gfsmConfig.h
new file mode 100644
index 0000000..ccb9cb4
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmConfig.h
@@ -0,0 +1,64 @@
+/*=============================================================================*\
+ * File: gfsmConfig.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: autoconf configuration hack
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/**
+ * \file gfsmConfig.h
+ * \brief safely include autoheader preprocessor defines
+ *
+ * \file gfsmConfigNoAuto.h
+ * \brief Undefine any autoheader preprocessor defines
+ *
+ * \file gfsmConfigAuto.h
+ * \brief autoheader-generated preprocessor defines
+ */
+
+/*
+ * Putting autoheader files within the #ifndef/#endif idiom (below)
+ * is potentially a BAD IDEA, since we might need to (re-)define
+ * the autoheader-generated preprocessor symbols (e.g. after
+ * (#include)ing in some config.h from another autoheader package
+ */
+#include <gfsmConfigNoAuto.h>
+#include <gfsmConfigAuto.h>
+
+/*
+ * Define a sentinel preprocessor symbol _GFSM_CONFIG_H, just
+ * in case someone wants to check whether we've already
+ * (#include)d this file ....
+ */
+#ifndef _GFSM_CONFIG_H
+#define _GFSM_CONFIG_H
+
+#ifdef GFSM_INLINE_ENABLED
+# ifdef __cplusplus
+/** Macro for declaring small functions inline (inlining enabled, C++-style) */
+# define GFSM_INLINE inline
+# else
+/** Macro for declaring small functions inline (inlining enabled, C98-style) */
+# define GFSM_INLINE static inline
+# endif /* __cplusplus */
+#else
+/** Macro for declaring small functions inline (inlining disabled) */
+# define GFSM_INLINE
+#endif /* GFSM_INLINE_ENABLED */
+
+#endif /* _GFSM_CONFIG_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmConfigAuto.h.in b/gfsm/gfsm/src/libgfsm/gfsmConfigAuto.h.in
new file mode 100644
index 0000000..ba4b089
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmConfigAuto.h.in
@@ -0,0 +1,185 @@
+/* src/libgfsm/gfsmConfigAuto.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define as good substitute value for EOVERFLOW. */
+#undef EOVERFLOW
+
+/* Define this to enable debugging code */
+#undef GFSM_DEBUG_ENABLED
+
+/* Define this to enable inline functions */
+#undef GFSM_INLINE_ENABLED
+
+/* Major gfsm version */
+#undef GFSM_VERSION_MAJOR
+
+/* Micro gfsm version */
+#undef GFSM_VERSION_MICRO
+
+/* Minor gfsm version */
+#undef GFSM_VERSION_MINOR
+
+/* Define this to enable zlib compression support */
+#undef GFSM_ZLIB_ENABLED
+
+/* Define to 1 if you have `alloca' after including <alloca.h>, a header that
+ may be supplied by this distribution. */
+#undef HAVE_ALLOCA
+
+/* Define HAVE_ALLOCA_H for backward compatibility with older code that
+ includes <alloca.h> only if HAVE_ALLOCA_H is defined. */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the declaration of `getdelim', and to 0 if you
+ don't. */
+#undef HAVE_DECL_GETDELIM
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `flockfile' function. */
+#undef HAVE_FLOCKFILE
+
+/* Define to 1 if you have the `funlockfile' function. */
+#undef HAVE_FUNLOCKFILE
+
+/* Define to 1 if you have the `getdelim' function. */
+#undef HAVE_GETDELIM
+
+/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
+#undef HAVE_INTMAX_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
+ declares uintmax_t. */
+#undef HAVE_INTTYPES_H_WITH_UINTMAX
+
+/* Define if you have the 'long double' type. */
+#undef HAVE_LONG_DOUBLE
+
+/* Define if you have the 'long long' type. */
+#undef HAVE_LONG_LONG
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if the system has the type `ptrdiff_t'. */
+#undef HAVE_PTRDIFF_T
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
+ uintmax_t. */
+#undef HAVE_STDINT_H_WITH_UINTMAX
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define this if you have the strdup() function */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vasnprintf' function. */
+#undef HAVE_VASNPRINTF
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the `vfprintf' function. */
+#undef HAVE_VFPRINTF
+
+/* Define if you have the 'wchar_t' type. */
+#undef HAVE_WCHAR_T
+
+/* Define to 1 if you have the `wcslen' function. */
+#undef HAVE_WCSLEN
+
+/* Define if you have the 'wint_t' type. */
+#undef HAVE_WINT_T
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the maximum value of type 'size_t', if the system doesn't define
+ it. */
+#undef SIZE_MAX
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to long or long long if <stdint.h> and <inttypes.h> don't define. */
+#undef intmax_t
+
+/* Define to empty if the C compiler doesn't support this keyword. */
+#undef signed
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/gfsm/gfsm/src/libgfsm/gfsmDebug.c b/gfsm/gfsm/src/libgfsm/gfsmDebug.c
new file mode 100644
index 0000000..463e28a
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmDebug.c
@@ -0,0 +1,35 @@
+#include <gfsmDebug.h>
+#include <gfsmMem.h>
+#include <gfsmConfig.h>
+
+#ifdef GFSM_DEBUG_ENABLED
+# define GFSM_MEM_DEBUG
+# define GFSM_ALLOC_DEBUG
+#endif /* GFSM_DEBUG_ENABLED */
+
+void gfsm_debug_init(void) {
+#if defined(GFSM_MEM_DEBUG)
+ g_mem_set_vtable(glib_mem_profiler_table);
+# if defined(GFSM_ALLOC_DEBUG)
+ gfsm_allocators_enable();
+# endif /* GFSM_ALLOC_DEBUG */
+#endif /* GFSM_MEM_DEBUG */
+ return;
+}
+
+void gfsm_debug_finish(void) {
+#if defined(GFSM_MEM_DEBUG)
+ g_blow_chunks();
+# if defined(GFSM_ALLOC_DEBUG)
+ gfsm_allocators_free();
+# endif /* GFSM_ALLOC_DEBUG */
+#endif /* GFSM_MEM_DEBUG */
+ return;
+}
+
+void gfsm_debug_print(void) {
+#if defined(GFSM_MEM_DEBUG)
+ g_mem_profile();
+#endif /* GFSM_MEM_DEBUG */
+ return;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmDebug.h b/gfsm/gfsm/src/libgfsm/gfsmDebug.h
new file mode 100644
index 0000000..73fa741
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmDebug.h
@@ -0,0 +1,46 @@
+
+/*=============================================================================*\
+ * File: gfsmDebug.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: debugging
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmDebug.h
+ * \brief Debugging utilities
+ */
+
+#ifndef _GFSM_DEBUG_H
+#define _GFSM_DEBUG_H
+
+#include <glib.h>
+
+/* Define these to enable verbose memory debugging */
+/*#define GFSM_MEM_DEBUG*/
+/*#define GFSM_ALLOC_DEBUG*/
+
+/** Initialize debugging -- should be called before any other gfsm operations */
+void gfsm_debug_init(void);
+
+/** Finish debugging -- be nice and clean up after ourselves */
+void gfsm_debug_finish(void);
+
+/** Print memory debugging trace information */
+void gfsm_debug_print(void);
+
+#endif /* _GFSM_DEBUG_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmDraw.c b/gfsm/gfsm/src/libgfsm/gfsmDraw.c
new file mode 100644
index 0000000..3c10991
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmDraw.c
@@ -0,0 +1,293 @@
+
+/*=============================================================================*\
+ * File: gfsmDraw.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata: visualization
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmDraw.h>
+#include <gfsmArcIter.h>
+#include <gfsmUtils.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*======================================================================
+ * Methods: Text I/O: vcg
+ */
+
+/*--------------------------------------------------------------
+ * draw_vcg_file()
+ */
+gboolean gfsm_automaton_draw_vcg_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ int xspace, // ?
+ int yspace, // ?
+ const gchar *orientation, // "(top|bottom|left|right)_to_(ditto)"
+ const gchar *state_shape,
+ const gchar *state_color,
+ const gchar *final_color,
+ gfsmError **errp)
+{
+ gfsmStateId id;
+ GString *gstr = g_string_new("");
+
+ fprintf(f, "graph: {\n");
+ fprintf(f, " title: \"%s\"\n", (title ? title : "(gfsm)"));
+ fprintf(f, " display_edge_labels:yes\n");
+ fprintf(f, " splines:yes\n");
+ fprintf(f, " color:white\n");
+ fprintf(f, " xspace:%d\n", (xspace ? xspace : 40));
+ fprintf(f, " yspace:%d\n", (yspace ? yspace : 20));
+ fprintf(f, " orientation:%s\n", (orientation ? orientation : "left_to_right"));
+ fprintf(f, " node.shape:%s\n", (state_shape ? state_shape : "ellipse"));
+ fprintf(f, " node.color:%s\n", (state_color ? state_color : "white"));
+ fprintf(f, " node.borderwidth:1\n");
+
+ //-- ye olde iterationne
+ for (id = 0; id < fsm->states->len; id++) {
+ gfsmState *s = gfsm_automaton_find_state(fsm,id);
+ gfsmArcIter ai;
+ gchar *sym;
+ if (!s || !s->is_valid) continue;
+
+ //-- source state
+ fprintf(f, " node: {title:\"%u\" label:\"", id);
+ if (state_alphabet && (sym=gfsm_alphabet_find_key(state_alphabet,id)) != NULL) {
+ gfsm_alphabet_key2string(state_alphabet, sym, gstr);
+ fprintf(f, "%s", gstr->str);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", id);
+ fprintf(f, "%u", id);
+ }
+ if (fsm->flags.is_weighted) {
+ fprintf(f, "/%g", gfsm_automaton_get_final_weight(fsm,id));
+ }
+ fprintf(f, "\"");
+
+ if (s->is_final) {
+ fprintf(f, " color:%s", (final_color ? final_color : "lightgrey"));
+ }
+ if (id == fsm->root_id) fputs(" borderwidth:3", f);
+ fputs("}\n", f);
+
+ for (gfsm_arciter_open_ptr(&ai,fsm,s); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ fprintf(f, " edge: {sourcename:\"%u\" targetname:\"%u\" label:\"", id, a->target);
+
+ if (lo_alphabet && (sym=gfsm_alphabet_find_key(lo_alphabet,a->lower)) != NULL) {
+ gfsm_alphabet_key2string(lo_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (lo_alphabet)
+ g_printerr("Warning: no label defined for lower label '%u'!\n", a->lower);
+ fprintf(f, "%u", a->lower);
+ }
+
+ if (fsm->flags.is_transducer) {
+ fputc(':', f);
+ if (hi_alphabet && (sym=gfsm_alphabet_find_key(hi_alphabet,a->upper)) != NULL) {
+ gfsm_alphabet_key2string(hi_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (hi_alphabet)
+ g_printerr("Warning: no label defined for upper label '%u'!\n", a->upper);
+ fprintf(f, "%u", a->upper);
+ }
+ }
+
+ if (fsm->flags.is_weighted) fprintf(f, "/%g", a->weight);
+ fprintf(f, "\"}\n");
+ }
+ }
+ fputs("}\n", f);
+
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ * draw_vcg_filename()
+ */
+gboolean gfsm_automaton_draw_vcg_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ int xspace,
+ int yspace,
+ const gchar *orientation,
+ const gchar *state_shape,
+ const gchar *state_color,
+ const gchar *final_color,
+ gfsmError **errp)
+{
+ FILE *f;
+ gboolean rc;
+ if (!(f=gfsm_open_filename(filename, "w", errp))) return FALSE;
+ rc = gfsm_automaton_draw_vcg_file_full(fsm, f, lo_alphabet, hi_alphabet, state_alphabet,
+ title, xspace, yspace, orientation,
+ state_shape, state_color, final_color,
+ errp);
+ if (f != stdout) fclose(f);
+ return rc;
+}
+
+
+/*======================================================================
+ * Methods: Draw: dot
+ */
+
+/*--------------------------------------------------------------
+ * draw_dot_file()
+ */
+gboolean gfsm_automaton_draw_dot_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ float width,
+ float height,
+ int fontsize,
+ const gchar *fontname,
+ gboolean portrait,
+ gboolean vertical,
+ float nodesep,
+ float ranksep,
+ gfsmError **errp)
+{
+ gfsmStateId id;
+ GString *gstr = g_string_new("");
+
+ fprintf(f, "digraph GFSM {\n");
+ fprintf(f, " rankdir = %s;\n", vertical ? "TB" : "LR");
+ if (width>0 && height>0) {
+ fprintf(f, " size = \"%g,\%g\";\n", (width ? width : 8.5), (height ? height : 11));
+ }
+ fprintf(f, " label = \"%s\";\n", (title ? title : "(gfsm)"));
+ fprintf(f, " center = 1;\n");
+ fprintf(f, " nodesep = \"%f\";\n", (nodesep ? nodesep : 0.25));
+ fprintf(f, " ranksep = \"%f\";\n", (ranksep ? ranksep : 0.4));
+ if (!portrait) {
+ //fprintf(f, " orientation = \"Landscape\";\n");
+ fprintf(f, " rotate = 90;\n");
+ }
+
+ //-- ye olde iterationne
+ for (id = 0; id < fsm->states->len; id++) {
+ gfsmState *s = gfsm_automaton_find_state(fsm,id);
+ gfsmArcIter ai;
+ gchar *sym;
+ if (!s || !s->is_valid) continue;
+
+ //-- source state
+ fprintf(f, "%u [label=\"", id);
+ if (state_alphabet && (sym=gfsm_alphabet_find_key(state_alphabet,id)) != NULL) {
+ gfsm_alphabet_key2string(state_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", id);
+ fprintf(f, "%u", id);
+ }
+ if (fsm->flags.is_weighted && s->is_final) {
+ fprintf(f, "/%g", gfsm_automaton_get_final_weight(fsm,id));
+ }
+ fprintf(f, "\", shape=%s, style=%s, fontsize=%d",
+ (s->is_final ? "doublecircle" : "circle"),
+ (id == fsm->root_id ? "bold" : "solid"),
+ (fontsize ? fontsize : 14));
+ if (fontname && *fontname) fprintf(f, ", fontname=\"%s\"", fontname);
+ fprintf(f, "]\n");
+
+ for (gfsm_arciter_open_ptr(&ai,fsm,s); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ fprintf(f, " %u -> %u \[label=\"", id, a->target);
+
+ if (lo_alphabet && (sym=gfsm_alphabet_find_key(lo_alphabet,a->lower)) != NULL) {
+ gfsm_alphabet_key2string(lo_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (lo_alphabet)
+ g_printerr("Warning: no label defined for lower label '%u'!\n", a->lower);
+ fprintf(f, "%u", a->lower);
+ }
+
+ if (fsm->flags.is_transducer) {
+ fputc(':', f);
+ if (hi_alphabet && (sym=gfsm_alphabet_find_key(hi_alphabet,a->upper)) != NULL) {
+ gfsm_alphabet_key2string(hi_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (hi_alphabet)
+ g_printerr("Warning: no label defined for upper label '%u'!\n", a->upper);
+ fprintf(f, "%u", a->upper);
+ }
+ }
+
+ if (fsm->flags.is_weighted) fprintf(f, "/%g", a->weight);
+
+ fprintf(f, "\", fontsize=%d", (fontsize ? fontsize : 14));
+ if (fontname && *fontname) fprintf(f, ", fontname=\"%s\"", fontname);
+ fprintf(f, "];\n");
+ }
+ }
+ fputs("}\n", f);
+
+ //--cleanup
+ g_string_free(gstr,TRUE);
+
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ * draw_dot_filename()
+ */
+gboolean gfsm_automaton_draw_dot_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ float width,
+ float height,
+ int fontsize,
+ const gchar *fontname,
+ gboolean portrait,
+ gboolean vertical,
+ float nodesep,
+ float ranksep,
+ gfsmError **errp)
+{
+ FILE *f;
+ gboolean rc;
+ if (!(f=gfsm_open_filename(filename, "w", errp))) return FALSE;
+ rc = gfsm_automaton_draw_dot_file_full(fsm, f, lo_alphabet, hi_alphabet, state_alphabet,
+ title, width, height, fontsize, fontname,
+ portrait, vertical, nodesep, ranksep,
+ errp);
+ if (f != stdout) fclose(f);
+ return rc;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmDraw.h b/gfsm/gfsm/src/libgfsm/gfsmDraw.h
new file mode 100644
index 0000000..793c821
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmDraw.h
@@ -0,0 +1,113 @@
+
+/*=============================================================================*\
+ * File: gfsmDraw.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata: visualization
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmDraw.h
+ * \brief Automaton visualization utilities
+ */
+
+#ifndef _GFSM_DRAW_H
+#define _GFSM_DRAW_H
+
+#include <gfsmAutomaton.h>
+
+/*======================================================================
+ * Automaton Methods: Visualization: vcg
+ */
+/// \name Automaton Methods: Visualization: vcg
+//@{
+
+/** Draw an automaton in VCG format to a FILE* */
+gboolean gfsm_automaton_draw_vcg_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ int xspace, // ?
+ int yspace, // ?
+ const gchar *orientation, // "(top|bottom|left|right)_to_(ditto)"
+ const gchar *state_shape,
+ const gchar *state_color,
+ const gchar *final_color,
+ gfsmError **errp);
+
+/** Draw an automaton in VCG format to a named file */
+gboolean gfsm_automaton_draw_vcg_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ int xspace, // ?
+ int yspace, // ?
+ const gchar *orientation, // "(top|bottom|left|right)_to_(ditto)"
+ const gchar *state_shape,
+ const gchar *state_color,
+ const gchar *final_color,
+ gfsmError **errp);
+//@}
+
+
+/*======================================================================
+ * Automaton Methods: Visualization: dot
+ */
+///\name Automaton Methods: Visualization: dot
+//@{
+
+/** Draw an automaton in Ma-Bell .dot format to a FILE* */
+gboolean gfsm_automaton_draw_dot_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ float width,
+ float height,
+ int fontsize,
+ const gchar *fontname,
+ gboolean portrait,
+ gboolean vertical,
+ float nodesep,
+ float ranksep,
+ gfsmError **errp);
+
+/** Draw an automaton in Ma-Bell .dot format to a named file */
+gboolean gfsm_automaton_draw_dot_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ float width,
+ float height,
+ int fontsize,
+ const gchar *fontname,
+ gboolean portrait,
+ gboolean vertical,
+ float nodesep,
+ float ranksep,
+ gfsmError **errp);
+//@}
+
+
+#endif /* _GFSM_DRAW_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmEnum.c b/gfsm/gfsm/src/libgfsm/gfsmEnum.c
new file mode 100644
index 0000000..828aeb5
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmEnum.c
@@ -0,0 +1,39 @@
+/*=============================================================================*\
+ * File: gfsmEnum.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmEnum.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmEnum.hi>
+#endif
+
+/*======================================================================
+ * Constants
+ */
+const guint gfsmEnumNone = ((guint)(-1));
+
+/*======================================================================
+ * Methods:
+ */
+//-- all inlined
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmEnum.h b/gfsm/gfsm/src/libgfsm/gfsmEnum.h
new file mode 100644
index 0000000..96ccdb7
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmEnum.h
@@ -0,0 +1,129 @@
+
+/*=============================================================================*\
+ * File: gfsmEnum.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmEnum.h
+ * \brief Abstract utilities for run-time value enumerations
+ */
+
+#ifndef _GFSM_ENUM_H
+#define _GFSM_ENUM_H
+
+#include <gfsmMem.h>
+#include <gfsmCommon.h>
+
+/*======================================================================
+ * Types
+ */
+///\name Types and constants
+//@{
+
+/// Structure for mapping symbolic names to numeric IDs
+typedef struct {
+ GHashTable *table; ///< hash table which does the dirty work
+ guint nxtval; ///< next id to assign
+ gfsmDupFunc key_dup; ///< key copying function
+} gfsmEnum;
+
+/// Enumeration of StateIds
+typedef gfsmEnum gfsmDirectEnum;
+
+/** Constant indicating failed gfsmEnum value-lookup */
+extern const guint gfsmEnumNone;
+
+//@}
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+/// \name Constructors etc.
+//@{
+
+/** create a new gfsmEnum (full version) */
+GFSM_INLINE
+gfsmEnum *gfsm_enum_new_full(gfsmDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func);
+
+/** create a new gfsmEnum (no copying) */
+#define gfsm_enum_new(key_hash_f) gfsm_enum_new_full(NULL,key_hash_f,NULL,NULL)
+
+/** create a new gfsmDirectEnum */
+#define gfsm_direct_enum_new() gfsm_enum_new(g_direct_hash)
+
+/** Clear a gfsmEnum */
+GFSM_INLINE
+void gfsm_enum_clear(gfsmEnum *en);
+
+/** Free a gfsmEnum */
+GFSM_INLINE
+void gfsm_enum_free(gfsmEnum *en);
+//@}
+
+/*======================================================================
+ * Methods: Accessors
+ */
+/// \name Accessors
+//@{
+
+/** Get next available value */
+#define gfsm_enum_next_value(en) ((en)->nxtval)
+
+/** Lookup the numeric value associated with \a lookup_key.
+ * On return, *\a stored_key points to the original (stored) key, if any;
+ * and *\a stored_value points to the stored value.
+ * \returns true iff a value for \a key was already stored
+ */
+GFSM_INLINE
+gboolean gfsm_enum_lookup_extended(gfsmEnum *en,
+ gconstpointer lookup_key,
+ gpointer *stored_key,
+ gpointer *stored_val);
+
+/** Lookup the numeric value associated with \a key.
+ * \returns the value associated with \a key, or gfsmEnumNone
+ * if no such value was found
+ */
+GFSM_INLINE
+guint gfsm_enum_lookup(gfsmEnum *en, gconstpointer key);
+
+
+/** Insert or overwrite new value \a val for \a key.
+ * If \a val is gfsmEnumNone, the next available value will be used.
+ * \returns new value for \a key
+ */
+GFSM_INLINE
+guint gfsm_enum_insert_full(gfsmEnum *en, gpointer key, guint val);
+
+/** Insert a (possibly new) value \a val for \a key */
+#define gfsm_enum_insert(en,key) gfsm_enum_insert_full(en,key,gfsmEnumNone)
+
+/** Really just an alias for gfsm_enum_insert(en,key) */
+#define gfsm_enum_get(en,key) gfsm_enum_insert(en,key)
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmEnum.hi>
+#endif
+
+#endif /* _GFSM_ENUM_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmEnum.hi b/gfsm/gfsm/src/libgfsm/gfsmEnum.hi
new file mode 100644
index 0000000..f7ae20e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmEnum.hi
@@ -0,0 +1,126 @@
+/*=============================================================================*\
+ * File: gfsmEnum.def
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: enumerations: inline definitions
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <glib.h>
+#include <gfsmUtils.h>
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+
+/*--------------------------------------------------------------
+ * new_full()
+ */
+GFSM_INLINE
+gfsmEnum *gfsm_enum_new_full(gfsmDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func)
+{
+ gfsmEnum *en = g_new(gfsmEnum,1);
+ en->table = g_hash_table_new_full(key_hash_func,
+ key_equal_func,
+ key_destroy_func,
+ NULL);
+ en->nxtval = 0;
+ en->key_dup = key_dup_func;
+ return en;
+}
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+GFSM_INLINE
+void gfsm_enum_clear(gfsmEnum *en)
+{
+ g_hash_table_foreach_remove(en->table, gfsm_hash_clear_func, NULL);
+ en->nxtval = 0;
+}
+
+/*--------------------------------------------------------------
+ * free()
+ */
+GFSM_INLINE
+void gfsm_enum_free(gfsmEnum *en)
+{
+ g_hash_table_destroy(en->table);
+ g_free(en);
+}
+
+
+/*======================================================================
+ * Methods: Accessors
+ */
+
+/*--------------------------------------------------------------
+ * lookup_extended()
+ */
+GFSM_INLINE
+gboolean gfsm_enum_lookup_extended(gfsmEnum *en,
+ gconstpointer lookup_key,
+ gpointer *stored_key,
+ gpointer *stored_val)
+{
+ return g_hash_table_lookup_extended(en->table, lookup_key, stored_key, stored_val);
+}
+
+/*--------------------------------------------------------------
+ * lookup()
+ */
+GFSM_INLINE
+guint gfsm_enum_lookup(gfsmEnum *en, gconstpointer key)
+{
+ gpointer s_val;
+ if (g_hash_table_lookup_extended(en->table, key, NULL, &s_val)) return GPOINTER_TO_UINT(s_val);
+ return gfsmEnumNone;
+}
+
+
+/*--------------------------------------------------------------
+ * insert_full()
+ */
+GFSM_INLINE
+guint gfsm_enum_insert_full(gfsmEnum *en, gpointer key, guint val)
+{
+ gpointer s_key, s_val;
+ if (g_hash_table_lookup_extended(en->table, key, &s_key, &s_val)) {
+ //-- already present: steal it & replace
+ if (val == gfsmEnumNone) {
+ val = GPOINTER_TO_UINT(s_val);
+ } else {
+ g_hash_table_steal(en->table, s_key);
+ g_hash_table_insert(en->table, s_key, GUINT_TO_POINTER(val));
+ }
+ }
+ else {
+ //-- no key already present: insert a new one
+ if (en->key_dup) s_key = (*(en->key_dup))(key);
+ else s_key = key;
+ if (val == gfsmEnumNone) val = en->nxtval;
+ g_hash_table_insert(en->table, s_key, GUINT_TO_POINTER(val));
+ }
+
+ //-- keep track of available values
+ if (val >= en->nxtval) en->nxtval = val+1;
+
+ return val;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmError.c b/gfsm/gfsm/src/libgfsm/gfsmError.c
new file mode 100644
index 0000000..88b8ac0
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmError.c
@@ -0,0 +1,46 @@
+/*=============================================================================*\
+ * File: gfsmError.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmError.h>
+#include <stdlib.h>
+
+/*======================================================================
+ * Error Utilties
+ */
+/*--------------------------------------------------------------
+ * carp_named()
+ */
+void gfsm_carp_named(gfsmError *error, const gchar *myname)
+{
+ if (!error) return;
+ g_printerr("%s: %s\n", (myname ? myname : "gfsm"), error->message);
+}
+
+/*--------------------------------------------------------------
+ * die_named()
+ */
+void gfsm_die_named(gfsmError *error, const gchar *myname)
+{
+ if (!error) return;
+ g_printerr("%s: %s\n", (myname ? myname : "gfsm"), error->message);
+ exit(error->code);
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmError.h b/gfsm/gfsm/src/libgfsm/gfsmError.h
new file mode 100644
index 0000000..d1b2a5f
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmError.h
@@ -0,0 +1,63 @@
+
+/*=============================================================================*\
+ * File: gfsmError.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmError.h
+ * \brief Error utilities
+ */
+
+#ifndef _GFSM_ERROR_H
+#define _GFSM_ERROR_H
+
+#include <glib.h>
+
+/*======================================================================
+ * Types
+ */
+/// struct for errors
+typedef GError gfsmError;
+
+/*======================================================================
+ * Constants
+ */
+/** Constant indicating no error condition */
+#define gfsmErrorNone NULL
+
+/*======================================================================
+ * Error Methods
+ */
+/** Report a warning and continue; does nothing if error==NULL */
+void gfsm_carp_named(gfsmError *error, const gchar *myname);
+
+/** Report a warning and continue; does nothing if error==NULL */
+#define gfsm_carp(e) gfsm_carp_named(e,NULL)
+
+/** carp and exit with code error->code ; does nothing if error==NULL */
+void gfsm_die_named(gfsmError *error, const gchar *myname);
+
+/** die using default diagnostic name "gfsm"; does nothing if error==NULL */
+#define gfsm_die(e) gfsm_die_named(e,NULL)
+
+/** do or die */
+#define gfsm_do_or_die(e) gfsm_die_named(e,NULL)
+
+#endif /* _GFSM_UTILS_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIO.c b/gfsm/gfsm/src/libgfsm/gfsmIO.c
new file mode 100644
index 0000000..f5e637d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIO.c
@@ -0,0 +1,558 @@
+/*=============================================================================*\
+ * File: gfsmIO.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: I/O
+ *
+ * Copyright (c) 2006-2008 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmConfig.h>
+
+#include <glib.h>
+#include <gfsmIO.h>
+//#include <gfsmCompat.h>
+#include <gfsmUtils.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#if 0
+#include <fcntl.h>
+#endif
+#include <errno.h>
+
+#ifdef GFSM_ZLIB_ENABLED
+# include <zlib.h>
+# define GFSM_DEFAULT_COMPRESSION Z_DEFAULT_COMPRESSION
+#endif
+
+#include "vasprintf.h"
+#include "getdelim.h"
+
+/*======================================================================
+ * Protos: I/O: Handles: Methods: Instatiations: C FILE*
+ */
+void gfsmio_close_cfile(FILE *f);
+void gfsmio_flush_cfile(FILE *f);
+gboolean gfsmio_eof_cfile(FILE *f);
+gboolean gfsmio_read_cfile(FILE *f, void *buf, size_t nbytes);
+ssize_t gfsmio_getdelim_cfile(FILE *f, char **lineptr, size_t *n, int delim);
+gboolean gfsmio_write_cfile(FILE *f, const void *buf, size_t nbytes);
+#ifdef HAVE_VFPRINTF
+int gfsmio_vprintf_cfile(FILE *f, const char *fmt, va_list *app);
+#endif
+
+/*======================================================================
+ * Protos: I/O: Handles: Methods: Instatiations: gzFile
+ */
+#ifdef GFSM_ZLIB_ENABLED
+void gfsmio_close_zfile(gzFile zf);
+void gfsmio_flush_zfile(gzFile zf);
+gboolean gfsmio_eof_zfile(gzFile zf);
+gboolean gfsmio_read_zfile(gzFile zf, void *buf, size_t nbytes);
+gboolean gfsmio_write_zfile(gzFile zf, const void *buf, size_t nbytes);
+#endif
+
+/*======================================================================
+ * Protos: I/O: Handles: Methods: Instatiations: GString*
+ */
+void gfsmio_close_gstring(gfsmPosGString *pgs);
+gboolean gfsmio_eof_gstring(gfsmPosGString *pgs);
+gboolean gfsmio_read_gstring(gfsmPosGString *pgs, void *buf, size_t nbytes);
+gboolean gfsmio_write_gstring(gfsmPosGString *pgs, const void *buf, size_t nbytes);
+
+/*======================================================================
+ * I/O: Handles: Constructors etc.
+ */
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_handle_new(gfsmIOHandleType typ, void *handle_data)
+{
+ gfsmIOHandle *ioh = g_new0(gfsmIOHandle,1);
+ ioh->iotype = typ;
+ ioh->handle = handle_data;
+
+ switch (typ) {
+ //--------------------------------
+ case gfsmIOTCFile:
+#ifndef GFSM_ZLIB_ENABLED
+ case gfsmIOTZFile:
+#endif
+ ioh->read_func = (gfsmIOReadFunc)gfsmio_read_cfile;
+ ioh->getdelim_func= (gfsmIOGetdelimFunc)gfsmio_getdelim_cfile;
+
+ ioh->write_func = (gfsmIOWriteFunc)gfsmio_write_cfile;
+#ifdef HAVE_VFPRINTF
+ ioh->vprintf_func = (gfsmIOVprintfFunc)gfsmio_vprintf_cfile;
+#endif
+
+ ioh->flush_func = (gfsmIOFlushFunc)gfsmio_flush_cfile;
+ ioh->close_func = (gfsmIOCloseFunc)gfsmio_close_cfile;
+ ioh->eof_func = (gfsmIOEofFunc)gfsmio_eof_cfile;
+ break;
+
+#ifdef GFSM_ZLIB_ENABLED
+ //--------------------------------
+ case gfsmIOTZFile:
+ ioh->read_func = (gfsmIOReadFunc)gfsmio_read_zfile;
+ //ioh->getdelim_func= (gfsmIOReadFunc)gfsmio_getdelim_zfile;
+
+ ioh->write_func = (gfsmIOWriteFunc)gfsmio_write_zfile;
+ //ioh->vprintf_func = (gfsmIOReadFunc)gfsmio_vprintf_zfile;
+
+ ioh->flush_func = (gfsmIOFlushFunc)gfsmio_flush_zfile;
+ ioh->close_func = (gfsmIOCloseFunc)gfsmio_close_zfile;
+ ioh->eof_func = (gfsmIOEofFunc)gfsmio_eof_zfile;
+ break;
+#endif
+
+ //--------------------------------
+ case gfsmIOTGString:
+ ioh->read_func = (gfsmIOReadFunc)gfsmio_read_gstring;
+ //ioh->getdelim_func= gfsmio_getdelim_gstring;
+
+ ioh->write_func = (gfsmIOWriteFunc)gfsmio_write_gstring;
+ //ioh->vprintf_func = gfsmio_vprintf_gstring;
+
+ //ioh->flush_func = gfsmio_flush_gstring;
+ ioh->close_func = (gfsmIOCloseFunc)gfsmio_close_gstring;
+ ioh->eof_func = (gfsmIOEofFunc)gfsmio_eof_gstring;
+ break;
+
+ //--------------------------------
+ case gfsmIOTUser:
+ default:
+ break;
+ }
+
+ return ioh;
+}
+
+/*--------------------------------------------------------------*/
+void gfsmio_handle_free(gfsmIOHandle *ioh)
+{
+ g_free(ioh);
+}
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_new_file(FILE *f)
+{
+ return gfsmio_handle_new(gfsmIOTCFile, f);
+}
+
+/*--------------------------------------------------------------*/
+#undef GFSM_ZFILE_USE_FCNTL
+gfsmIOHandle *gfsmio_new_zfile(FILE *f, const char *mode, int compress_level)
+{
+#ifdef GFSM_ZLIB_ENABLED
+# ifdef GFSM_ZFILE_USE_FCNTL
+ int fd = fileno(f);
+ int flags = fcntl(fd, F_GETFL);
+ gzFile zf;
+# if 0 /* DEBUG */
+ //-- DEBUG
+ const int o_rdwr = O_RDWR;
+ const int o_rdonly = O_RDONLY;
+ const int o_wronly = O_WRONLY;
+ //-- /DEBUG
+# endif /* DEBUG */
+ if ( (flags&O_RDWR) == O_RDWR ) {
+ zf = gzdopen(dup(fd),"rwb");
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+ else
+ if ( (flags&O_WRONLY) == O_WRONLY ) {
+ zf = gzdopen(fd,"wb");
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+ else { // if ( (flags&O_RDONLY) == O_RDONLY )
+ zf = gzdopen(fd,"rb");
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+ return gfsmio_handle_new(gfsmIOTZFile, zf);
+
+# else /* !defined(GFSM_ZFILE_USE_FCNTL) */
+
+ if (compress_level != 0) {
+ //-- use compression
+ gzFile zf = gzdopen(fileno(f), mode);
+ if (strchr(mode,'w')) gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ return gfsmio_handle_new(gfsmIOTZFile, zf);
+ } else {
+ return gfsmio_new_file( fdopen(dup(fileno(f)), mode) );
+ }
+
+# endif /* GFSM_ZFILE_USE_FCNTL */
+
+#else /* !defined(GFSM_ZLIB_ENABLED) */
+
+ return gfsmio_new_file( fdopen(dup(fileno(f)), mode) );
+#endif
+}
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_new_filename(const char *filename, const char *mode, int compress_level, gfsmError **errp)
+{
+#ifdef GFSM_ZLIB_ENABLED
+ if (compress_level != 0) {
+ gzFile zf;
+ if (strcmp(filename,"-")==0) {
+ if (strchr(mode,'w')) zf = gzdopen(dup(fileno(stdout)), mode);
+ else zf = gzdopen(dup(fileno(stdin)), mode);
+ }
+ else if (!(zf = gzopen(filename,mode))) {
+ int errnum;
+ const char *zerror = gzerror(zf,&errnum);
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("gzopen"), //-- code
+ "gzopen() failed for file '%s': %s",
+ filename,
+ errnum==Z_ERRNO ? strerror(errno) : zerror);
+ return NULL;
+ }
+
+ //-- set compression level
+ if (compress_level < 0) compress_level = GFSM_DEFAULT_COMPRESSION;
+ if (strchr(mode,'w')) {
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+
+ return gfsmio_handle_new(gfsmIOTZFile,zf);
+ }
+ else {
+#endif
+ FILE *f;
+ if (strcmp(filename,"-")==0) {
+ if (strchr(mode,'w')) f = stdout;
+ else f = stdin;
+ }
+ else if (!(f = fopen(filename,mode))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("fopen"), //-- code
+ "open failed for file '%s': %s",
+ filename, strerror(errno));
+ }
+ return gfsmio_new_file(f);
+#ifdef GFSM_ZLIB_ENABLED
+ }
+#endif
+}
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_new_gstring(gfsmPosGString *pgs)
+{
+ return gfsmio_handle_new(gfsmIOTGString, pgs);
+}
+
+
+/*======================================================================
+ * I/O: Handles: Methods: Basic
+ */
+
+/*--------------------------------------------------------------*/
+/** flush all data to an output handle (calls \a flush_func) */
+void gfsmio_close(gfsmIOHandle *ioh)
+{
+ if (ioh->close_func) (*ioh->close_func)(ioh->handle);
+}
+
+/*--------------------------------------------------------------*/
+/** flush all data to an output handle (calls \a flush_func) */
+void gfsmio_flush(gfsmIOHandle *ioh)
+{
+ if (ioh->flush_func) (*ioh->flush_func)(ioh->handle);
+}
+
+/*--------------------------------------------------------------*/
+/** returns true if \a h is at EOF, false otherwise or if no \a eof_func is defined */
+gboolean gfsmio_eof(gfsmIOHandle *ioh)
+{
+ if (ioh->eof_func) return (*ioh->eof_func)(ioh->handle);
+ return FALSE;
+}
+
+
+
+/*======================================================================
+ * I/O: Handles: Methods: Read
+ */
+
+/*--------------------------------------------------------------*/
+int gfsmio_getc(gfsmIOHandle *ioh)
+{
+ if (gfsmio_eof(ioh)) return GFSMIO_EOF;
+ else {
+ //-- getc() --> read()
+ unsigned char c = 0;
+ if (gfsmio_read(ioh, &c, 1)) return (int)c;
+ }
+ return GFSMIO_EOF;
+}
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_read(gfsmIOHandle *ioh, void *buf, size_t nbytes)
+{
+ if (ioh->read_func) return (*ioh->read_func)(ioh->handle, buf, nbytes);
+
+ g_printerr("gfsmio_read(): no method defined for handle of type %d\n", ioh->iotype);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------*/
+ssize_t gfsmio_getline(gfsmIOHandle *ioh, char **lineptr, size_t *n)
+{
+ return gfsmio_getdelim(ioh, lineptr, n, '\n');
+}
+
+/*--------------------------------------------------------------*/
+ssize_t gfsmio_getdelim(gfsmIOHandle *ioh, char **lineptr, size_t *n, int delim)
+{
+ if (ioh->getdelim_func) {
+ return (*ioh->getdelim_func)(ioh->handle, lineptr, n, delim);
+ }
+ else {
+ //-- getdelim() --> getc()
+ ssize_t i = 0;
+ int c = -2;
+ GString *gs=NULL;
+
+ while ( *n > 0 && i < (*n-1) && (c=gfsmio_getc(ioh)) != GFSMIO_EOF ) {
+ (*lineptr)[i++] = c;
+#ifdef GFSM_DEBUG_GETDELIM
+ fprintf(stderr, "---> getdelim(i=%d) got char %d ~ '%c' to linebuf\n", i, (char)c, c);//--DEBUG
+#endif
+ if ((char)c == (char)delim) {
+ (*lineptr)[i] = '\0';
+ return i;
+ }
+ }
+ if (c == GFSMIO_EOF) {
+#ifdef GFSM_DEBUG_GETDELIM
+ fprintf(stderr, "---> getdelim(i=%d) got EOF reading to linebuf\n", i);//--DEBUG
+#endif
+ (*lineptr)[i] = '\0';
+ return i == 0 ? GFSMIO_EOF : i;
+ }
+
+ //-- oops: buffer overflow
+ gs = g_string_new_len((i>0 ? *lineptr : ""), i);
+ while ( (c=gfsmio_getc(ioh)) != GFSMIO_EOF ) {
+ g_string_append_c(gs,c);
+ i++;
+#ifdef GFSM_DEBUG_GETDELIM
+ fprintf(stderr, "---> getdelim(i=%d) got char %d ~ '%c' to GString*\n", i, (char)c, c);//--DEBUG
+#endif
+ if ((char)c == (char)delim) break;
+ }
+
+#ifdef GFSM_DEBUG_GETDELIM
+ if (c==GFSMIO_EOF) { fprintf(stderr, "---> getdelim(i=%d) got EOF reading to GString*\n", i); }//--DEBUG
+#endif
+
+ //-- maybe free old line buffer
+ if (*lineptr) free(*lineptr);
+
+ //-- set up new buffer
+ g_string_append_c(gs,0); //-- this shouldn't be necessary, but weird things happen otherwise (bug?)
+
+ //-- the following code breaks in Perl on OpenSuSE 11.0 [maybe GString doesn't use malloc ?!], --moocow 2008-10-31
+ /*
+ *lineptr = gs->str; //-- copy literal GString data buffer
+ *n = gs->allocated_len; //-- ... and its length
+ g_string_free(gs,FALSE); //-- ... and only free GString wrapper struct; not the data buffer
+ */
+ //-- ...so we do this instead (ugly but functional):
+ *lineptr = (char *)malloc(gs->allocated_len); //-- malloc a copy of GString data buffer
+ memcpy(*lineptr, gs->str, gs->allocated_len); //-- ... and copy the data
+ *n = gs->allocated_len; //-- ... and its length
+ g_string_free(gs,TRUE); //-- ... and free the whole GString and its data buffer
+
+ return i==0 && c==GFSMIO_EOF ? GFSMIO_EOF : i;
+ }
+ return GFSMIO_EOF;
+}
+
+/*======================================================================
+ * I/O: Handles: Methods: Write
+ */
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_putc(gfsmIOHandle *ioh, int c)
+{
+ return gfsmio_write(ioh, &c, 1);
+}
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_puts(gfsmIOHandle *ioh, const char *s)
+{
+ return gfsmio_write(ioh, s, strlen(s));
+}
+
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_write(gfsmIOHandle *ioh, const void *buf, size_t nbytes)
+{
+ if (ioh->write_func) return (*ioh->write_func)(ioh->handle, buf, nbytes);
+
+ g_printerr("gfsmio_read(): no method defined for handle of type %d\n", ioh->iotype);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------*/
+int gfsmio_printf(gfsmIOHandle *io, const char *fmt, ...)
+{
+ int len;
+ va_list ap;
+
+ va_start(ap,fmt);
+ len = gfsmio_vprintf(io, fmt, &ap);
+ va_end(ap);
+
+ return len;
+}
+
+/*--------------------------------------------------------------*/
+int gfsmio_vprintf(gfsmIOHandle *io, const char *fmt, va_list *app)
+{
+ char *obuf = NULL;
+ size_t len = 0;
+ gboolean rc;
+ len = vasprintf(&obuf, fmt, *app);
+ rc = gfsmio_write(io, obuf, len);
+ if (obuf) free(obuf);
+ return rc ? len : 0;
+}
+
+
+/*======================================================================
+ * I/O: Handles: Methods: FILE*
+ */
+
+/*--------------------------------------------------------------
+ * FILE*: Basic Methods
+ */
+void gfsmio_flush_cfile(FILE *f)
+{ if (f) fflush(f); }
+
+void gfsmio_close_cfile(FILE *f)
+{
+ if (f && f != stdin && f != stdout && f != stderr) fclose(f);
+}
+
+gboolean gfsmio_eof_cfile(FILE *f)
+{ return f ? feof(f) : FALSE; }
+
+/*--------------------------------------------------------------
+ * FILE*: Read Methods
+ */
+gboolean gfsmio_read_cfile(FILE *f, void *buf, size_t nbytes)
+{ return f ? (fread(buf,nbytes,1,f)==1) : FALSE; }
+
+ssize_t gfsmio_getdelim_cfile(FILE *f, char **lineptr, size_t *n, int delim)
+{ return f ? getdelim(lineptr, n, delim, f) : 0; }
+
+/*--------------------------------------------------------------
+ * FILE*: Write Methods
+ */
+gboolean gfsmio_write_cfile(FILE *f, const void *buf, size_t nbytes)
+{ return f ? (fwrite(buf, nbytes, 1, f)==1) : FALSE; }
+
+#ifdef HAVE_VFPRINTF
+int gfsmio_vprintf_cfile(FILE *f, const char *fmt, va_list *app)
+{ return f ? vfprintf(f, fmt, *app) : 0; }
+#endif
+
+/*======================================================================
+ * I/O: Handles: Methods: gzFile
+ */
+#ifdef GFSM_ZLIB_ENABLED
+
+/*--------------------------------------------------------------
+ * gzFile: Basic Methods
+ */
+void gfsmio_close_zfile(gzFile zf)
+{ if (zf) gzclose(zf); }
+
+void gfsmio_flush_zfile(gzFile zf)
+{ if (zf) gzflush(zf,Z_SYNC_FLUSH); }
+
+gboolean gfsmio_eof_zfile(gzFile zf)
+{ return zf ? gzeof(zf) : FALSE; }
+
+/*--------------------------------------------------------------
+ * gzFile: Read Methods
+ */
+gboolean gfsmio_read_zfile(gzFile zf, void *buf, size_t nbytes)
+{ return zf ? (gzread(zf,buf,nbytes)==nbytes) : FALSE; }
+
+/*--------------------------------------------------------------
+ * gzFile: Write Methods
+ */
+gboolean gfsmio_write_zfile(gzFile zf, const void *buf, size_t nbytes)
+{ return zf ? (gzwrite(zf, buf, nbytes)==nbytes) : FALSE; }
+
+#endif /* GFSM_ZLIB_ENABLED */
+
+
+/*======================================================================
+ * I/O: Handles: Methods: GString*
+ */
+
+/*--------------------------------------------------------------
+ * GString*: Basic Methods
+ */
+
+void gfsmio_close_gstring(gfsmPosGString *pgs)
+{ if (pgs) pgs->pos = 0; }
+
+gboolean gfsmio_eof_gstring(gfsmPosGString *pgs)
+{ return pgs && pgs->gs ? (pgs->pos >= pgs->gs->len) : TRUE; }
+
+/*--------------------------------------------------------------
+ * GString*: Read Methods
+ */
+gboolean gfsmio_read_gstring(gfsmPosGString *pgs, void *buf, size_t nbytes)
+{
+ if (!pgs || !pgs->gs || pgs->pos > pgs->gs->len) return FALSE;
+ if (pgs->pos+nbytes <= pgs->gs->len) {
+ //-- normal case: read it in
+ memcpy(buf, pgs->gs->str + pgs->pos, nbytes);
+ pgs->pos += nbytes;
+ return TRUE;
+ }
+ //-- overflow: grab what we can
+ memcpy(buf, pgs->gs->str + pgs->pos, pgs->gs->len-pgs->pos);
+ pgs->pos = pgs->gs->len;
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * GString*: Write Methods
+ */
+gboolean gfsmio_write_gstring(gfsmPosGString *pgs, const void *buf, size_t nbytes)
+{
+ if (pgs && pgs->gs) {
+ g_string_append_len(pgs->gs, buf, nbytes);
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIO.h b/gfsm/gfsm/src/libgfsm/gfsmIO.h
new file mode 100644
index 0000000..6931699
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIO.h
@@ -0,0 +1,208 @@
+/*=============================================================================*\
+ * File: gfsmIO.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: I/O
+ *
+ * Copyright (c) 2006-2008 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmIO.h
+ * \brief Abstract I/O routines
+ */
+
+#ifndef _GFSM_IO_H
+#define _GFSM_IO_H
+
+#include <gfsmConfig.h>
+#include <gfsmError.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define GFSMIO_EOF ((int)-1)
+
+/*======================================================================
+ * I/O: types
+ */
+
+/** Builtin I/O types */
+typedef enum {
+ gfsmIOTCFile, ///< I/O on a C FILE*
+ gfsmIOTZFile, ///< I/O on a zlib gzFile* (only if GFSM_ZLIB_ENABLED is defined)
+ gfsmIOTGString, ///< I/O on a GString*
+ gfsmIOTUser = 255 ///< user I/O
+} gfsmIOHandleType;
+
+/*======================================================================
+ * I/O: Handles: Function types
+ */
+
+/** Generic I/O Handle function type: fflush() and friends */
+typedef void (*gfsmIOFlushFunc) (void *handle);
+
+/** Generic I/O Handle function type: fclose() and friends */
+typedef void (*gfsmIOCloseFunc) (void *handle);
+
+/** Generic I/O Handle function type: feof() and friends */
+typedef gboolean (*gfsmIOEofFunc) (void *handle);
+
+
+/** Generic I/O Handle function type: fread() and friends */
+typedef gboolean (*gfsmIOReadFunc) (void *handle, void *buf, size_t nbytes);
+
+/** Generic I/O Handle function type: getdelim() and friends */
+typedef ssize_t (*gfsmIOGetdelimFunc) (void *handle, char **lineptr, size_t *n, int delim);
+
+
+/** Generic I/O Handle function type: fwrite() and friends */
+typedef gboolean (*gfsmIOWriteFunc) (void *handle, const void *buf, size_t nbytes);
+
+/** Generic I/O Handle function type: vprintf() and friends */
+typedef int (*gfsmIOVprintfFunc) (void *handle, const char *fmt, va_list *app);
+
+
+
+/*======================================================================
+ * I/O: Handles: structs
+ */
+
+/** \brief Generic I/O handle struct */
+typedef struct {
+ gfsmIOHandleType iotype; ///< I/O class of this handle
+ void *handle; ///< underlying handle data
+
+ gfsmIOReadFunc read_func; /** fread() and friends (either read or getc must be defined) */
+ gfsmIOGetdelimFunc getdelim_func; /** getdelim() and friends (optional) */
+
+ gfsmIOWriteFunc write_func; /** fwrite() and friends (either write or putc must be defined) */
+ gfsmIOVprintfFunc vprintf_func; /** vprintf() and friends (optional) */
+
+ gfsmIOFlushFunc flush_func; /** fflush() and friends (optional) */
+ gfsmIOCloseFunc close_func; /** fclose() and friends (optional) */
+ gfsmIOEofFunc eof_func; /** eof() and friends (optional) */
+} gfsmIOHandle;
+
+
+/** \brief GString with an associated index (read head) */
+typedef struct {
+ GString *gs; ///< associated string
+ size_t pos; ///< (read-)position
+} gfsmPosGString;
+
+/*======================================================================
+ * I/O: Handles: Constructors etc.
+ */
+
+/** create, initialize, and return a new gfsmIOHandle
+ * \param typ type of this handle
+ * \param handle_data value of the \a handle structure datum:
+ * \li for \a typ==gfsmIOTCFile , \a handle_data should be a FILE*
+ * \li for \a typ==gfsmIOTGString , \a handle_data should be a gfsmPosGString*
+ * \li for \a typ==gfsmIOTZFile , \a handle_data should be a gzFile
+ * \li for \a typ==gfsmIOTUser , \a handle_data is whatever you want
+ *
+ * \returns new gfsmIOHandle
+ */
+gfsmIOHandle *gfsmio_handle_new(gfsmIOHandleType typ, void *handle_data);
+
+/** destroy a gfsmIOHandle: does NOT implicitly call \a close or anything else */
+void gfsmio_handle_free(gfsmIOHandle *ioh);
+
+/* TODO: utilities ? file_handle_new, zfile_handle_new, gstring_handle_new, user_handle_new ? */
+
+/** Create and return a new gfsmIOHandle to an uncompressed C FILE*
+ * Caller is responsible for closing the handle.
+ */
+gfsmIOHandle *gfsmio_new_file(FILE *f);
+
+/** Create and return a new gfsmIOHandle to a C FILE* using compression (if available)
+ * Caller is responsible for closing the handle.
+ * The handle returned can always be closed without closing \a f itself.
+ */
+gfsmIOHandle *gfsmio_new_zfile(FILE *f, const char *mode, int compress_level);
+
+/** Create and return a new gfsmIOHandle to a named file.
+ * Uses gzFile if zlib support was enabled, otherwise C FILE* (uncompressed)
+ * Caller is responsible for closing the handle.
+ */
+gfsmIOHandle *gfsmio_new_filename(const char *filename, const char *mode, int compress_level, gfsmError **errp);
+
+/** Create and return a new gfsmIOHandle for a PosGString*
+ * Caller is responsible for allocation and de-allocation of the PosGString*.
+ */
+gfsmIOHandle *gfsmio_new_gstring(gfsmPosGString *pgs);
+
+/*======================================================================
+ * I/O: Handles: Methods: Basic
+ */
+
+/** close an open I/O handle (calls \a close_func) */
+void gfsmio_close(gfsmIOHandle *ioh);
+
+/** flush all data to an output handle (calls \a flush_func) */
+void gfsmio_flush(gfsmIOHandle *ioh);
+
+/** returns true if \a h is at EOF, false otherwise (or if no \a eof_func is defined) */
+gboolean gfsmio_eof(gfsmIOHandle *ioh);
+
+
+
+/*======================================================================
+ * I/O: Handles: Methods: Read
+ */
+
+/** read a single byte of data from \a h, should return GFSMIO_EOF on EOF */
+int gfsmio_getc(gfsmIOHandle *ioh);
+
+/** read \a nbytes of data from \a io into \a buf, as \a fread() */
+gboolean gfsmio_read(gfsmIOHandle *ioh, void *buf, size_t nbytes);
+
+/** wrapper for getline(), returns number of bytes read (0 on error) */
+ssize_t gfsmio_getline(gfsmIOHandle *ioh, char **lineptr, size_t *n);
+
+
+/** wrapper for getdelim(), returns number of bytes read (0 on error) */
+ssize_t gfsmio_getdelim(gfsmIOHandle *io, char **lineptr, size_t *n, int delim);
+
+
+
+/*======================================================================
+ * I/O: Handles: Methods: Write
+ */
+
+/** write a single byte to handle \a ioh, as \a fputc() */
+gboolean gfsmio_putc(gfsmIOHandle *ioh, int c);
+
+/** wrapper for puts() */
+gboolean gfsmio_puts(gfsmIOHandle *io, const char *s);
+
+/** write \a nbytes of data from \a buf into \a io, as \a fwrite() */
+gboolean gfsmio_write(gfsmIOHandle *io, const void *buf, size_t nbytes);
+
+/** wrapper for printf(): calls \a gfsmio_vprintf() */
+int gfsmio_printf(gfsmIOHandle *io, const char *fmt, ...);
+
+/** wrapper for vprintf(): calls \a vprintf_func */
+int gfsmio_vprintf(gfsmIOHandle *io, const char *fmt, va_list *app);
+
+
+#endif /* _GFSM_IO_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIndexed.c b/gfsm/gfsm/src/libgfsm/gfsmIndexed.c
new file mode 100644
index 0000000..ba36fc6
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIndexed.c
@@ -0,0 +1,157 @@
+
+/*=============================================================================*\
+ * File: gfsmIndexed.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc indices
+ *
+ * Copyright (c) 2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmIndexed.h>
+#include <gfsmArcIter.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmIndexed.hi>
+#endif
+
+/*======================================================================
+ * Constructors etc.
+ */
+
+//----------------------------------------
+gfsmIndexedAutomaton *gfsm_indexed_automaton_copy(gfsmIndexedAutomaton *dst, gfsmIndexedAutomaton *src)
+{
+ if (!dst) {
+ dst = gfsm_indexed_automaton_new_full(src->flags,
+ src->sr->type,
+ gfsm_indexed_automaton_n_states(src),
+ gfsm_indexed_automaton_n_arcs(src));
+ }
+ else {
+ gfsm_indexed_automaton_clear(dst);
+ gfsm_indexed_automaton_reserve_states(dst, gfsm_indexed_automaton_n_states(src));
+ gfsm_indexed_automaton_reserve_arcs (dst, gfsm_indexed_automaton_n_arcs(src) );
+ }
+
+ //-- copy: flags, semiring, root
+ dst->flags = src->flags;
+ gfsm_indexed_automaton_set_semiring(dst, src->sr);
+ dst->root_id = src->root_id;
+
+ //-- copy: tables
+ gfsm_weight_vector_copy (dst->state_final_weight, src->state_final_weight);
+ gfsm_arc_table_index_copy(dst->arcs, src->arcs);
+
+ return dst;
+}
+
+/*======================================================================
+ * Methods: Import & Export
+ */
+
+//----------------------------------------
+gfsmIndexedAutomaton *gfsm_automaton_to_indexed(gfsmAutomaton *fsm, gfsmIndexedAutomaton *xfsm)
+{
+ //-- maybe allocate new indexed automaton
+ if (xfsm==NULL) {
+ xfsm = gfsm_indexed_automaton_new_full(fsm->flags,
+ fsm->sr->type,
+ gfsm_automaton_n_states(fsm),
+ gfsm_automaton_n_arcs(fsm)
+ );
+ } else {
+ gfsm_indexed_automaton_clear(xfsm);
+ xfsm->flags = fsm->flags;
+ gfsm_indexed_automaton_reserve_states(xfsm,gfsm_automaton_n_states(fsm));
+ gfsm_indexed_automaton_reserve_arcs(xfsm,gfsm_automaton_n_arcs(fsm));
+ }
+ gfsm_indexed_automaton_set_semiring(xfsm,fsm->sr); //-- copy semiring
+
+ //-- set root id
+ xfsm->root_id = fsm->root_id;
+
+ //-- index final weights
+ gfsm_automaton_to_final_weight_vector(fsm, xfsm->state_final_weight);
+ gfsm_automaton_to_arc_table_index(fsm, xfsm->arcs);
+
+ //-- sort arcs (no!)
+ //gfsm_indexed_automaton_sort(xfsm, xfsm->flags.sort_mode);
+
+
+ return xfsm;
+}
+
+
+
+//----------------------------------------
+gfsmAutomaton *gfsm_indexed_to_automaton(gfsmIndexedAutomaton *xfsm, gfsmAutomaton *fsm)
+{
+ gfsmStateId qid;
+ gfsmWeight srzero;
+
+ //-- maybe allocate new automaton
+ if (fsm==NULL) {
+ fsm = gfsm_automaton_new_full(xfsm->flags, xfsm->sr->type, gfsm_indexed_automaton_n_states(xfsm));
+ } else {
+ gfsm_automaton_clear(fsm);
+ fsm->flags = xfsm->flags;
+ gfsm_automaton_set_semiring(fsm, gfsm_semiring_copy(xfsm->sr));
+ gfsm_automaton_reserve(fsm, gfsm_indexed_automaton_n_states(xfsm));
+ }
+
+ //-- set root id
+ fsm->root_id = xfsm->root_id;
+
+ //-- update state-wise
+ srzero = xfsm->sr->zero;
+ for (qid=0; qid < xfsm->state_final_weight->len; qid++) {
+ gfsmArcRange range;
+
+ //-- state_final_weight
+ gfsmWeight fw = g_array_index(xfsm->state_final_weight,gfsmWeight,qid);
+ if (fw != srzero) { gfsm_automaton_set_final_state_full(fsm,qid,TRUE,fw); }
+
+ //-- arcs
+ for (gfsm_arcrange_open_indexed(&range, xfsm, qid); gfsm_arcrange_ok(&range); gfsm_arcrange_next(&range)) {
+ gfsmArc *a = gfsm_arcrange_arc(&range);
+ gfsm_automaton_add_arc(fsm,a->source,a->target,a->lower,a->upper,a->weight);
+ }
+ gfsm_arcrange_close(&range);
+ }
+
+ return fsm;
+}
+
+/*======================================================================
+ * Methods: Accessors: gfsmIndexedAutomaton
+ */
+//-- inlined
+
+/*======================================================================
+ * Methods: Accessors: gfsmAutomaton API: Automaton
+ */
+//-- inlined
+
+/*======================================================================
+ * Methods: Accessors: gfsmAutomaton API: States
+ */
+//-- inlined
+
+/*======================================================================
+ * I/O
+ */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIndexed.h b/gfsm/gfsm/src/libgfsm/gfsmIndexed.h
new file mode 100644
index 0000000..2313c56
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIndexed.h
@@ -0,0 +1,231 @@
+
+/*=============================================================================*\
+ * File: gfsmIndexed.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: arc indices
+ *
+ * Copyright (c) 2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmIndexed.h
+ * \brief First stab at indexed automata
+ */
+
+#ifndef _GFSM_INDEXED_H
+#define _GFSM_INDEXED_H
+
+#include <gfsmArcIndex.h>
+
+/*======================================================================
+ * Types
+ */
+
+/// Type for an indexed automaton.
+typedef struct {
+ //-- gfsmAutomaton compatibility
+ gfsmAutomatonFlags flags; /**< automaton flags, for ::gfsmAutomaton compatibility */
+ gfsmSemiring *sr; /**< semiring used for arc weight computations */
+ gfsmStateId root_id; /**< id of root state, or gfsmNoState if not defined */
+ //
+ //-- Basic data
+ //gfsmBitVector *state_is_valid; /* per-state validity flags */
+ gfsmWeightVector *state_final_weight; /**< State final weight, or sr->zero */
+ gfsmArcTableIndex *arcs; /**< Arc storage (sorted primarily by source state) */
+} gfsmIndexedAutomaton;
+
+/*======================================================================
+ * Methods: gfsmIndexedAutomaton: constructors, etc.
+ */
+/// \name Constructors etc.
+//@{
+
+/** Create a new ::gfsmIndexedAutomaton, specifying some basic automaton & index structure */
+GFSM_INLINE
+gfsmIndexedAutomaton *gfsm_indexed_automaton_new_full(gfsmAutomatonFlags flags,
+ gfsmSRType srtype,
+ gfsmStateId n_states,
+ guint n_arcs);
+
+/** Create a new indexed automaton, using some default values */
+GFSM_INLINE
+gfsmIndexedAutomaton *gfsm_indexed_automaton_new(void);
+
+/** Copy a ::gfsmIndexedAutomaton \a src to \a dst. \returns \a dst */
+gfsmIndexedAutomaton *gfsm_indexed_automaton_copy(gfsmIndexedAutomaton *dst, gfsmIndexedAutomaton *src);
+
+/** Create and return an exact clone of a ::gfsmIndexedAutomaton */
+GFSM_INLINE
+gfsmIndexedAutomaton *gfsm_indexed_automaton_clone(gfsmIndexedAutomaton *xfsm);
+
+/** Clear a ::gfsmIndexedAutomaton */
+GFSM_INLINE
+void gfsm_indexed_automaton_clear(gfsmIndexedAutomaton *xfsm);
+
+/** Free a ::gfsmIndexedAutomaton */
+GFSM_INLINE
+void gfsm_indexed_automaton_free(gfsmIndexedAutomaton *xfsm);
+
+//@}
+
+/*======================================================================
+ * Methods: Import & Export
+ */
+/// \name Import & Export
+//@{
+
+/** Populate a ::gfsmIndexedAutomaton from a ::gfsmAutomaton
+ * \param fsm source automaton
+ * \param xfsm destination indexed automaton,
+ * may be passed as NULL to create a new ::gfsmIndexedAutomaton
+ * \returns (new) indexed automaton \a xfsm
+ * \note implicitly clears \a xfsm
+ */
+gfsmIndexedAutomaton *gfsm_automaton_to_indexed(gfsmAutomaton *fsm, gfsmIndexedAutomaton *xfsm);
+
+/** Export a ::gfsmIndexedAutomaton to a ::gfsmAutomaton
+ * \param xfsm source indexed automaton
+ * \param fsm destination :.gfsmAutomaton
+ * may be passed as NULL to create a new ::gfsmAutomaton
+ * \returns (new) automaton \a fsm
+ * \note implicitly clears \a fsm
+ */
+gfsmAutomaton *gfsm_indexed_to_automaton(gfsmIndexedAutomaton *xfsm, gfsmAutomaton *fsm);
+
+//@}
+
+/*======================================================================
+ * Methods: Accessors: gfsmIndexedAutomaton
+ */
+/// \name Accessors: gfsmIndexedAutomaton
+//@{
+
+/** Reserve space for at least \a n_states states */
+GFSM_INLINE
+void gfsm_indexed_automaton_reserve_states(gfsmIndexedAutomaton *xfsm, gfsmStateId n_states);
+
+/** Reserve space for at least \a n_arcs arcs */
+GFSM_INLINE
+void gfsm_indexed_automaton_reserve_arcs(gfsmIndexedAutomaton *xfsm, guint n_arcs);
+
+/** (re-)sort arcs in a ::gfsmIndexedAutomaton */
+GFSM_INLINE
+void gfsm_indexed_automaton_sort(gfsmIndexedAutomaton *xfsm, gfsmArcCompMask sort_mask);
+
+//@}
+
+/*======================================================================
+ * gfsmAutomaton API: Automaton properties
+ */
+/// \name gfsmAutomaton API: automaton properties
+//@{
+
+/** Get pointer to the semiring associated with this automaton */
+#define gfsm_indexed_automaton_get_semiring(xfsm) (xfsm->sr)
+
+/** Set the semiring associated with this automaton */
+GFSM_INLINE
+gfsmSemiring *gfsm_indexed_automaton_set_semiring(gfsmIndexedAutomaton *xfsm, gfsmSemiring *sr);
+
+/** Set the semiring associated with this automaton by semiring-type */
+GFSM_INLINE
+void gfsm_indexed_automaton_set_semiring_type(gfsmIndexedAutomaton *xfsm, gfsmSRType srtype);
+
+/** Get number of states (constant time) */
+GFSM_INLINE
+gfsmStateId gfsm_indexed_automaton_n_states(gfsmIndexedAutomaton *xfsm);
+
+/** Get total number of arcs (constant time) */
+GFSM_INLINE
+guint gfsm_indexed_automaton_n_arcs(gfsmIndexedAutomaton *xfsm);
+
+/** Get Id of root node, or gfsmNoState if undefined */
+GFSM_INLINE
+gfsmStateId gfsm_indexed_automaton_get_root(gfsmIndexedAutomaton *xfsm);
+
+/** Set Id of root node, creating state if necessary */
+GFSM_INLINE
+void gfsm_indexed_automaton_set_root(gfsmIndexedAutomaton *xfsm, gfsmStateId qid);
+
+//@}
+
+/*======================================================================
+ * Methods: Accessors: gfsmAutomaton API: States
+ */
+/// \name gfsmAutomaton API: States
+//@{
+
+/** Check whether automaton has a state with ID \a qid. */
+GFSM_INLINE
+gboolean gfsm_indexed_automaton_has_state(gfsmIndexedAutomaton *xfsm, gfsmStateId qid);
+
+/** Ensures that state \a id exists \returns \a qid */
+GFSM_INLINE
+gfsmStateId gfsm_indexed_automaton_ensure_state(gfsmIndexedAutomaton *xfsm, gfsmStateId qid);
+
+/* Remove the state with id \a qid, if any.
+ * Currently does nothing.
+ */
+GFSM_INLINE
+void gfsm_indexed_automaton_remove_state(gfsmIndexedAutomaton *fsm, gfsmStateId qid);
+
+/** Set boolean final-state flag. \returns (void) */
+#define gfsm_indexed_automaton_set_final_state(xfsm,qid,is_final) \
+ gfsm_indexed_automaton_set_final_state_full((xfsm),(qid),(is_final),(xfsm)->sr->one)
+
+/** Set final weight. \returns (void) */
+GFSM_INLINE
+void gfsm_indexed_automaton_set_final_state_full(gfsmIndexedAutomaton *fsm,
+ gfsmStateId qid,
+ gboolean is_final,
+ gfsmWeight final_weight);
+
+/** Lookup final weight. \returns TRUE iff state \a id is final, and sets \a *wp to its final weight. */
+GFSM_INLINE
+gboolean gfsm_indexed_automaton_lookup_final(gfsmIndexedAutomaton *fsm, gfsmStateId id, gfsmWeight *wp);
+
+/** Is \a qid final in \a xfsm? Really just wraps gfsm_indexed_automaton_lookup_final() */
+GFSM_INLINE
+gboolean gfsm_indexed_automaton_state_is_final(gfsmIndexedAutomaton *xfsm, gfsmStateId qid);
+
+/** Get final weight for \a qid final in \a xfsm? Really just wraps gfsm_indexed_automaton_lookup_final() */
+GFSM_INLINE
+gfsmWeight gfsm_indexed_automaton_get_final_weight(gfsmIndexedAutomaton *xfsm, gfsmStateId qid);
+
+/** Get number of outgoing arcs. \returns guint */
+GFSM_INLINE
+guint gfsm_indexed_automaton_out_degree(gfsmIndexedAutomaton *fsm, gfsmStateId qid);
+
+//@}
+
+/*======================================================================
+ * ArcRange
+ */
+///\name gfsmArcRange interface
+//@{
+
+/** Open a ::gfsmArcRange for outgoing arcs from state \a qid in \a xfsm */
+GFSM_INLINE
+void gfsm_arcrange_open_indexed(gfsmArcRange *range, gfsmIndexedAutomaton *xfsm, gfsmStateId qid);
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmIndexed.hi>
+#endif
+
+#endif /* _GFSM_INDEXED_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIndexed.hi b/gfsm/gfsm/src/libgfsm/gfsmIndexed.hi
new file mode 100644
index 0000000..670f03d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIndexed.hi
@@ -0,0 +1,294 @@
+
+/*=============================================================================*\
+ * File: gfsmIndexed.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: indexed automaton: inline definitions
+ *
+ * Copyright (c) 2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/*======================================================================
+ * Constructors etc.
+ */
+
+//----------------------------------------
+gfsmIndexedAutomaton *gfsm_indexed_automaton_new_full(gfsmAutomatonFlags flags,
+ gfsmSRType srtype,
+ gfsmStateId n_states,
+ guint n_arcs)
+
+{
+ gfsmIndexedAutomaton *xfsm = g_new0(gfsmIndexedAutomaton,1);
+#if 0
+ gfsmStateId qid;
+ gfsmWeight srzero;
+#endif
+
+ xfsm->flags = flags;
+ xfsm->sr = gfsm_semiring_new(srtype);
+ xfsm->root_id = gfsmNoState;
+
+ //xfsm->state_is_valid = gfsm_bitvector_sized_new(n_states);
+ xfsm->state_final_weight = gfsm_weight_vector_sized_new(n_states);
+ xfsm->arcs = gfsm_arc_table_index_sized_new(n_states, n_arcs);
+
+#if 0
+ //-- initialize: states
+ for (qid=0; qid < n_states; qid++) {
+ g_array_index(xfsm->state_final_weight,gfsmWeight,qid) = xfsm->sr->zero;
+ }
+#endif
+
+ return xfsm;
+}
+
+//----------------------------------------
+GFSM_INLINE
+gfsmIndexedAutomaton *gfsm_indexed_automaton_new(void)
+{
+ return gfsm_indexed_automaton_new_full(gfsmAutomatonDefaultFlags,
+ gfsmAutomatonDefaultSRType,
+ gfsmAutomatonDefaultSize,
+ gfsmAutomatonDefaultSize
+ );
+}
+
+
+//----------------------------------------
+GFSM_INLINE
+gfsmIndexedAutomaton *gfsm_indexed_automaton_clone(gfsmIndexedAutomaton *src)
+{
+ return gfsm_indexed_automaton_copy(gfsm_indexed_automaton_new_full(src->flags,
+ src->sr->type,
+ gfsm_indexed_automaton_n_states(src),
+ gfsm_indexed_automaton_n_arcs(src)),
+ src);
+}
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_clear(gfsmIndexedAutomaton *xfsm)
+{
+ //gfsm_bitvector_clear(xfsm->state_is_valid);
+ gfsm_weight_vector_resize(xfsm->state_final_weight,0);
+ gfsm_arc_table_index_resize(xfsm->arcs,0,0);
+ xfsm->root_id = gfsmNoState;
+ return;
+ }
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_free(gfsmIndexedAutomaton *xfsm)
+{
+ if (!xfsm) return;
+ if (xfsm->sr) gfsm_semiring_free(xfsm->sr);
+ //if (xfsm->state_is_valid) gfsm_bitvector_free(xfsm->state_is_valid);
+ if (xfsm->state_final_weight) gfsm_weight_vector_free(xfsm->state_final_weight);
+ if (xfsm->arcs) gfsm_arc_table_index_free(xfsm->arcs);
+ g_free(xfsm);
+}
+
+/*======================================================================
+ * Methods: Import & Export
+ */
+//-- EXTERN
+
+
+/*======================================================================
+ * Methods: Accessors: gfsmIndexedAutomaton
+ */
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_reserve_states(gfsmIndexedAutomaton *xfsm, gfsmStateId n_states)
+{
+#if 0
+ gfsmStateId n_states_old = gfsm_indexed_automaton_n_states(xfsm);
+ gfsmStateId qid;
+ gfsmWeight srzero;
+#endif
+
+ //-- resize state-indexed arrays
+ //gfsm_bitvector_resize(xfsm->state_is_valid, n_states);
+ gfsm_weight_vector_resize(xfsm->state_final_weight, n_states);
+ gfsm_arc_table_index_resize(xfsm->arcs, n_states, xfsm->arcs->tab->len);
+
+#if 0
+ //-- ... adjust final weights
+ srzero = xfsm->sr->zero;
+ for (qid=n_states_old; qid < n_states; qid++) {
+ g_array_index(xfsm->state_final_weight,gfsmWeight,qid) = srzero;
+ }
+#endif
+}
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_reserve_arcs(gfsmIndexedAutomaton *xfsm, guint n_arcs)
+{
+ gfsm_arc_table_index_resize(xfsm->arcs, xfsm->arcs->first->len-1, n_arcs);
+}
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_sort(gfsmIndexedAutomaton *xfsm, gfsmArcCompMask sort_mask)
+{
+ if (xfsm->flags.sort_mode != sort_mask && sort_mask != gfsmASMNone) {
+ gfsm_arc_table_index_sort_bymask(xfsm->arcs, sort_mask, xfsm->sr);
+ }
+ xfsm->flags.sort_mode = sort_mask;
+}
+
+
+/*======================================================================
+ * Methods: Accessors: gfsmAutomaton API: Automaton
+ */
+
+//----------------------------------------
+GFSM_INLINE
+gfsmSemiring *gfsm_indexed_automaton_set_semiring(gfsmIndexedAutomaton *xfsm, gfsmSemiring *sr)
+{
+ if (xfsm->sr) gfsm_semiring_free(xfsm->sr);
+ xfsm->sr = gfsm_semiring_copy(sr);
+ return sr;
+}
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_set_semiring_type(gfsmIndexedAutomaton *xfsm, gfsmSRType srtype)
+{
+ if (!xfsm->sr) xfsm->sr = gfsm_semiring_new(srtype);
+ else if (xfsm->sr->type != srtype) {
+ gfsm_semiring_free(xfsm->sr);
+ xfsm->sr = gfsm_semiring_new(srtype);
+ }
+}
+
+//----------------------------------------
+GFSM_INLINE
+gfsmStateId gfsm_indexed_automaton_n_states(gfsmIndexedAutomaton *xfsm)
+{ return xfsm->state_final_weight->len; }
+
+//----------------------------------------
+GFSM_INLINE
+guint gfsm_indexed_automaton_n_arcs(gfsmIndexedAutomaton *xfsm)
+{ return xfsm->arcs->tab->len; }
+
+//----------------------------------------
+GFSM_INLINE
+guint gfsm_indexed_automaton_get_root(gfsmIndexedAutomaton *xfsm)
+{ return xfsm->root_id; }
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_set_root(gfsmIndexedAutomaton *xfsm, gfsmStateId qid)
+{
+ if (qid >= gfsm_indexed_automaton_n_states(xfsm) && qid != gfsmNoState) {
+ gfsm_indexed_automaton_reserve_states(xfsm,qid+1);
+ }
+ xfsm->root_id = qid;
+}
+
+/*======================================================================
+ * Methods: Accessors: gfsmAutomaton API: States
+ */
+
+//----------------------------------------
+GFSM_INLINE
+gboolean gfsm_indexed_automaton_has_state(gfsmIndexedAutomaton *xfsm, gfsmStateId qid)
+{ return qid < gfsm_indexed_automaton_n_states(xfsm); }
+
+//----------------------------------------
+GFSM_INLINE
+gfsmStateId gfsm_indexed_automaton_ensure_state(gfsmIndexedAutomaton *xfsm, gfsmStateId qid)
+{
+ if (qid >= gfsm_indexed_automaton_n_states(xfsm) && qid != gfsmNoState) {
+ gfsm_indexed_automaton_reserve_states(xfsm,qid+1);
+ }
+ return qid;
+}
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_remove_state(gfsmIndexedAutomaton *fsm, gfsmStateId qid)
+{ return; }
+
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_indexed_automaton_set_final_state_full(gfsmIndexedAutomaton *xfsm,
+ gfsmStateId qid,
+ gboolean is_final,
+ gfsmWeight final_weight)
+{
+ gfsm_indexed_automaton_ensure_state(xfsm,qid);
+ if (!is_final) final_weight = xfsm->sr->zero;
+ g_array_index(xfsm->state_final_weight,gfsmWeight,qid) = final_weight;
+}
+
+//----------------------------------------
+GFSM_INLINE
+gboolean gfsm_indexed_automaton_lookup_final(gfsmIndexedAutomaton *xfsm, gfsmStateId qid, gfsmWeight *wp)
+{
+ if (!gfsm_indexed_automaton_has_state(xfsm,qid)) {
+ *wp = xfsm->sr->zero;
+ return FALSE;
+ }
+ *wp = g_array_index(xfsm->state_final_weight,gfsmWeight,qid);
+ return ((*wp)!=xfsm->sr->zero);
+}
+
+//----------------------------------------
+GFSM_INLINE
+gboolean gfsm_indexed_automaton_state_is_final(gfsmIndexedAutomaton *xfsm, gfsmStateId qid)
+{
+ gfsmWeight fw;
+ return gfsm_indexed_automaton_lookup_final(xfsm,qid,&fw);
+}
+
+//----------------------------------------
+GFSM_INLINE
+gfsmWeight gfsm_indexed_automaton_get_final_weight(gfsmIndexedAutomaton *xfsm, gfsmStateId qid)
+{
+ if (!gfsm_indexed_automaton_has_state(xfsm,qid)) return xfsm->sr->zero;
+ return g_array_index(xfsm->state_final_weight,gfsmWeight,qid);
+}
+
+
+//----------------------------------------
+GFSM_INLINE
+guint gfsm_indexed_automaton_out_degree(gfsmIndexedAutomaton *fsm, gfsmStateId qid)
+{
+ if (!gfsm_indexed_automaton_has_state(fsm,qid)) return 0;
+ return gfsm_arc_table_index_out_degree(fsm->arcs,qid);
+}
+
+
+/*======================================================================
+ * gfsmArcRange
+ */
+
+//----------------------------------------
+GFSM_INLINE
+void gfsm_arcrange_open_indexed(gfsmArcRange *range, gfsmIndexedAutomaton *xfsm, gfsmStateId qid)
+{
+ if (gfsm_indexed_automaton_has_state(xfsm,qid)) {
+ gfsm_arcrange_open_table_index(range,xfsm->arcs,qid);
+ } else {
+ gfsm_arcrange_close(range);
+ }
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIndexedIO.c b/gfsm/gfsm/src/libgfsm/gfsmIndexedIO.c
new file mode 100644
index 0000000..9e2f297
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIndexedIO.c
@@ -0,0 +1,464 @@
+
+/*=============================================================================*\
+ * File: gfsmIndexedIO.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: indexed automata: I/O
+ *
+ * Copyright (c) 2007 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmIndexedIO.h>
+#include <gfsmArcIter.h>
+#include <gfsmUtils.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+
+
+/*======================================================================
+ * Constants: Binary I/O
+ */
+const gfsmVersionInfo gfsm_indexed_version_bincompat_min_store =
+ {
+ 0, // major
+ 0, // minor
+ 10 // micro
+ };
+
+const gfsmVersionInfo gfsm_indexed_version_bincompat_min_check =
+ {
+ 0, // major
+ 0, // minor
+ 10 // micro
+ };
+
+const gchar gfsm_indexed_header_magic[16] = "gfsm_indexed\0";
+
+/*======================================================================
+ * Methods: Binary I/O: load()
+ */
+
+/*--------------------------------------------------------------
+ * load_bin_header()
+ */
+gboolean gfsm_indexed_automaton_load_bin_header(gfsmIndexedAutomatonHeader *hdr, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ if (!gfsmio_read(ioh, hdr, sizeof(gfsmIndexedAutomatonHeader))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("indexed_automaton_load_bin_header:size"),
+ "could not read header");
+ return FALSE;
+ }
+ else if (strcmp(hdr->magic, gfsm_indexed_header_magic) != 0) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("indexed_automaton_load_bin_header:magic"),
+ "bad magic");
+ return FALSE;
+ }
+ else if (gfsm_version_compare(hdr->version, gfsm_version_bincompat_min_check) < 0) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("indexed_automaton_load_bin_header:version"),
+ "stored format v%u.%u.%u is obsolete - need at least v%u.%u.%u",
+ hdr->version.major,
+ hdr->version.minor,
+ hdr->version.micro,
+ gfsm_indexed_version_bincompat_min_check.major,
+ gfsm_indexed_version_bincompat_min_check.minor,
+ gfsm_indexed_version_bincompat_min_check.micro);
+ return FALSE;
+ }
+ else if (gfsm_version_compare(gfsm_version, hdr->version_min) < 0) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("indexed_automaton_load_bin_header:version"),
+ "libgfsm v%u.%u.%u is obsolete - stored automaton needs at least v%u.%u.%u",
+ gfsm_version.major,
+ gfsm_version.minor,
+ gfsm_version.micro,
+ hdr->version_min.major,
+ hdr->version_min.minor,
+ hdr->version_min.micro);
+ return FALSE;
+ }
+ if (hdr->srtype == gfsmSRTUnknown || hdr->srtype >= gfsmSRTUser) {
+ //-- compatibility hack
+ hdr->srtype = gfsmAutomatonDefaultSRType;
+ }
+ return TRUE;
+}
+
+/*--------------------------------------------------------------
+ * load_bin_handle()
+ * + supports stored file versions v0.0.9 -- CURRENT
+ */
+gboolean gfsm_indexed_automaton_load_bin_handle_0_0_9(gfsmIndexedAutomatonHeader *hdr,
+ gfsmIndexedAutomaton *xfsm,
+ gfsmIOHandle *ioh,
+ gfsmError **errp)
+{
+ //-- reserve states & ars
+ gfsm_indexed_automaton_reserve_states(xfsm, hdr->n_states);
+ gfsm_indexed_automaton_reserve_arcs(xfsm, hdr->n_arcs);
+
+ //-- set automaton-global properties
+ xfsm->flags = hdr->flags;
+ gfsm_indexed_automaton_set_semiring_type(xfsm, hdr->srtype);
+ xfsm->root_id = hdr->root_id;
+
+ //------ load: state_final_weight
+ if (!gfsm_weight_vector_read_bin_handle(xfsm->state_final_weight, ioh, errp)) { return FALSE; }
+
+ //------ load: arcs
+ if (!gfsm_arc_table_index_read_bin_handle(xfsm->arcs, ioh, errp)) { return FALSE; }
+
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ * load_bin_handle()
+ * + dispatch
+ */
+gboolean gfsm_indexed_automaton_load_bin_handle(gfsmIndexedAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmIndexedAutomatonHeader hdr;
+ gfsm_indexed_automaton_clear(fsm);
+
+ //-- load header
+ if (!gfsm_indexed_automaton_load_bin_header(&hdr,ioh,errp)) return FALSE;
+
+ //-- guts
+ return gfsm_indexed_automaton_load_bin_handle_0_0_9(&hdr,fsm,ioh,errp);
+}
+
+/*--------------------------------------------------------------
+ * load_bin_file()
+ */
+gboolean gfsm_indexed_automaton_load_bin_file(gfsmIndexedAutomaton *fsm, FILE *f, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_zfile(f,"rb",-1);
+ gboolean rc = gfsm_indexed_automaton_load_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * load_bin_filename()
+ */
+gboolean gfsm_indexed_automaton_load_bin_filename(gfsmIndexedAutomaton *fsm, const gchar *filename, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename, "rb", -1, errp);
+ gboolean rc = ioh && !(*errp) && gfsm_indexed_automaton_load_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * load_bin_gstring()
+ */
+gboolean gfsm_indexed_automaton_load_bin_gstring(gfsmIndexedAutomaton *fsm, GString *gs, gfsmError **errp)
+{
+ gfsmPosGString pgs = { gs, 0 };
+ gfsmIOHandle *ioh = gfsmio_new_gstring(&pgs);
+ gboolean rc = ioh && !(*errp) && gfsm_indexed_automaton_load_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+
+/*======================================================================
+ * Methods: Binary I/O: save()
+ */
+
+/*--------------------------------------------------------------
+ * save_bin_handle()
+ */
+gboolean gfsm_indexed_automaton_save_bin_handle(gfsmIndexedAutomaton *xfsm, gfsmIOHandle *ioh, gfsmError **errp)
+{
+ gfsmIndexedAutomatonHeader hdr;
+
+ //-- create header
+ memset(&hdr, 0, sizeof(gfsmIndexedAutomatonHeader));
+ strcpy(hdr.magic, gfsm_indexed_header_magic);
+ hdr.version = gfsm_version;
+ hdr.version_min = gfsm_indexed_version_bincompat_min_store;
+ hdr.flags = xfsm->flags;
+ hdr.root_id = xfsm->root_id;
+ hdr.n_states = gfsm_indexed_automaton_n_states(xfsm);
+ hdr.n_arcs = gfsm_indexed_automaton_n_arcs(xfsm);
+ hdr.srtype = gfsm_indexed_automaton_get_semiring(xfsm)->type;
+
+ //-- write header
+ if (!gfsmio_write(ioh, &hdr, sizeof(gfsmIndexedAutomatonHeader))) {
+ g_set_error(errp, g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("indexed_automaton_save_bin:header"),
+ "could not store header");
+ return FALSE;
+ }
+
+ //------ save: state_final_weight
+ if (!gfsm_weight_vector_write_bin_handle(xfsm->state_final_weight, ioh, errp)) { return FALSE; }
+
+ //------ save: arcs
+ if (!gfsm_arc_table_index_write_bin_handle(xfsm->arcs, ioh, errp)) { return FALSE; }
+
+ return TRUE;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_file()
+ */
+gboolean gfsm_indexed_automaton_save_bin_file(gfsmIndexedAutomaton *fsm, FILE *f, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_file(f);
+ gboolean rc = ioh && !(*errp) && gfsm_indexed_automaton_save_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ //gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_filename_nc()
+ */
+gboolean gfsm_indexed_automaton_save_bin_filename_nc(gfsmIndexedAutomaton *fsm, const gchar *filename, gfsmError **errp)
+{
+ FILE *f;
+ gboolean rc;
+ if (!(f=gfsm_open_filename(filename,"wb",errp))) return FALSE;
+ rc = gfsm_indexed_automaton_save_bin_file(fsm, f, errp);
+ if (f != stdout) fclose(f);
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_filename()
+ */
+gboolean gfsm_indexed_automaton_save_bin_filename(gfsmIndexedAutomaton *fsm, const gchar *filename, int zlevel, gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename, "wb", zlevel, errp);
+ gboolean rc = ioh && !(*errp) && gfsm_indexed_automaton_save_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * save_bin_gstring()
+ */
+gboolean gfsm_indexed_automaton_save_bin_gstring(gfsmIndexedAutomaton *fsm, GString *gs, gfsmError **errp)
+{
+ gfsmPosGString pgs = { gs, gs->len };
+ gfsmIOHandle *ioh = gfsmio_new_gstring(&pgs);
+ gboolean rc = ioh && !(*errp) && gfsm_indexed_automaton_save_bin_handle(fsm, ioh, errp);
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+
+/*======================================================================
+ * Methods: Text I/O: compile() : NOT IMPLEMNENTED
+ */
+
+
+/*======================================================================
+ * Methods: Text I/O: print()
+ */
+
+/*--------------------------------------------------------------
+ * print_handle()
+ */
+gboolean gfsm_indexed_automaton_print_handle (gfsmIndexedAutomaton *xfsm,
+ gfsmIOHandle *ioh,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ gfsmStateId qid;
+ gfsmArcRange range;
+ GString *gs = g_string_new("");
+ gboolean rc = TRUE;
+ gpointer key;
+
+ if (xfsm->root_id == gfsmNoState) rc = FALSE; //-- sanity check
+
+ for (qid=0; rc && qid < gfsm_indexed_automaton_n_states(xfsm); qid++) {
+ if (!gfsm_indexed_automaton_has_state(xfsm,qid)) continue;
+
+ for (gfsm_arcrange_open_indexed(&range,xfsm,qid); gfsm_arcrange_ok(&range); gfsm_arcrange_next(&range))
+ {
+ gfsmArc *a = gfsm_arcrange_arc(&range);
+
+ //-- source state
+ if (state_alphabet && (key=gfsm_alphabet_find_key(state_alphabet,qid)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(state_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", qid);
+ gfsmio_printf(ioh, "%u", qid);
+ }
+ gfsmio_putc(ioh, '\t');
+
+ //-- sink state
+ if (state_alphabet && (key=gfsm_alphabet_find_key(state_alphabet,a->target)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(state_alphabet,key,gs);
+ gfsmio_puts(ioh,gs->str);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", a->target);
+ gfsmio_printf(ioh, "%u", a->target);
+ }
+ gfsmio_putc(ioh,'\t');
+
+ //-- lower label
+ if (lo_alphabet && (key=gfsm_alphabet_find_key(lo_alphabet,a->lower)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(lo_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ if (lo_alphabet) g_printerr("Warning: no lower label defined for Id '%u'!\n", a->lower);
+ gfsmio_printf(ioh, "%u", a->lower);
+ }
+
+ //-- upper label
+ if (xfsm->flags.is_transducer) {
+ gfsmio_putc(ioh, '\t');
+ if (hi_alphabet && (key=gfsm_alphabet_find_key(hi_alphabet,a->upper)) != gfsmNoKey) {
+ gfsm_alphabet_key2string(hi_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ if (hi_alphabet) g_printerr("Warning: no upper label defined for Id '%u'!\n", a->upper);
+ gfsmio_printf(ioh, "%u", a->upper);
+ }
+ }
+
+ //-- weight
+ if (xfsm->flags.is_weighted) { // && a->weight != fsm->sr->one
+ gfsmio_printf(ioh, "\t%g", a->weight);
+ }
+
+ gfsmio_putc(ioh, '\n');
+ }
+ gfsm_arcrange_close(&range);
+
+ //-- final?
+ if (gfsm_indexed_automaton_state_is_final(xfsm,qid)) {
+ if (state_alphabet && (key=gfsm_alphabet_find_key(state_alphabet,qid)) != NULL) {
+ gfsm_alphabet_key2string(state_alphabet,key,gs);
+ gfsmio_puts(ioh, gs->str);
+ } else {
+ gfsmio_printf(ioh, "%u", qid);
+ }
+ if (xfsm->flags.is_weighted) {
+ gfsmio_printf(ioh, "\t%g", gfsm_indexed_automaton_get_final_weight(xfsm,qid));
+ }
+ gfsmio_putc(ioh, '\n');
+ }
+ }
+
+ //-- cleanup
+ g_string_free(gs,TRUE);
+
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * print_file_full()
+ */
+gboolean gfsm_indexed_automaton_print_file_full (gfsmIndexedAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_zfile(f,"wb",zlevel);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_indexed_automaton_print_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * print_filename()
+ */
+gboolean gfsm_indexed_automaton_print_filename_full (gfsmIndexedAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp)
+{
+ gfsmIOHandle *ioh = gfsmio_new_filename(filename,"wb",zlevel,errp);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_indexed_automaton_print_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+/*--------------------------------------------------------------
+ * print_gstring_full()
+ */
+gboolean gfsm_indexed_automaton_print_gstring_full (gfsmIndexedAutomaton *fsm,
+ GString *gs,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp)
+{
+ gfsmPosGString pgs = { gs, gs->len };
+ gfsmIOHandle *ioh = gfsmio_new_gstring(&pgs);
+ gboolean rc = (ioh && !(*errp) &&
+ gfsm_indexed_automaton_print_handle(fsm,ioh,lo_alphabet,hi_alphabet,state_alphabet,errp));
+ if (ioh) {
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+ }
+ return rc;
+}
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIndexedIO.h b/gfsm/gfsm/src/libgfsm/gfsmIndexedIO.h
new file mode 100644
index 0000000..f736645
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIndexedIO.h
@@ -0,0 +1,163 @@
+
+/*=============================================================================*\
+ * File: gfsmIndexedIO.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: indexed automata: I/O
+ *
+ * Copyright (c) 2007 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmIndexedIO.h
+ * \brief Librarian routines for indexed automata.
+ */
+
+#ifndef _GFSM_INDEXED_IO_H
+#define _GFSM_INDEXED_IO_H
+
+#include <gfsmAutomatonIO.h>
+#include <gfsmIndexed.h>
+
+/*======================================================================
+ * Types
+ */
+/// Header info for binary files
+typedef struct {
+ gchar magic[16]; /**< magic header string "gfsm_indexed" */
+ gfsmVersionInfo version; /**< gfsm version which created the stored file */
+ gfsmVersionInfo version_min; /**< minimum gfsm version required to load the file */
+ gfsmAutomatonFlags flags; /**< automaton flags */
+ gfsmStateId root_id; /**< Id of root node */
+ gfsmStateId n_states; /**< number of stored states */
+ gfsmStateId n_arcs; /**< number of stored arcs */
+ guint32 srtype; /**< semiring type (cast to ::gfsmSRType) */
+ guint32 sort_mask; /**< arc-sort priorities (a ::gfsmArcCompMask) */
+ guint32 reserved2; /**< reserved */
+ guint32 reserved3; /**< reserved */
+} gfsmIndexedAutomatonHeader;
+
+/*======================================================================
+ * Constants
+ */
+
+/** Magic header string for stored ::gfsmIndexedAutomaton files */
+extern const gchar gfsm_indexed_header_magic[16];
+
+/** Minimum libgfsm version required for loading files stored by this version of libgfsm */
+extern const gfsmVersionInfo gfsm_indexed_version_bincompat_min_store;
+
+/** Minimum libgfsm version whose binary files this version of libgfsm can read */
+extern const gfsmVersionInfo gfsm_indexed_version_bincompat_min_check;
+
+/*======================================================================
+ * Methods: Binary I/O
+ */
+/// \name Indexed Automaton Methods: Binary I/O
+//@{
+
+/** Load an automaton header from a stored binary file.
+ * Returns TRUE iff the header looks valid. */
+gboolean gfsm_indexed_automaton_load_header(gfsmIndexedAutomatonHeader *hdr, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Load an automaton from a named binary file (implicitly clear()s \a fsm) */
+gboolean gfsm_indexed_automaton_load_bin_handle(gfsmIndexedAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Load an automaton from a stored binary file (implicitly clear()s \a fsm) */
+gboolean gfsm_indexed_automaton_load_bin_file(gfsmIndexedAutomaton *fsm, FILE *f, gfsmError **errp);
+
+/** Load an automaton from a named binary file (implicitly clear()s \a fsm) */
+gboolean gfsm_indexed_automaton_load_bin_filename(gfsmIndexedAutomaton *fsm, const gchar *filename, gfsmError **errp);
+
+/** Load an automaton from an in-memory buffer */
+gboolean gfsm_indexed_automaton_load_bin_gstring(gfsmIndexedAutomaton *fsm, GString *gs, gfsmError **errp);
+
+/*--------------------------------------------------------------*/
+
+/** Store an automaton in binary form to a gfsmIOHandle* */
+gboolean gfsm_indexed_automaton_save_bin_handle(gfsmIndexedAutomaton *fsm, gfsmIOHandle *ioh, gfsmError **errp);
+
+/** Store an automaton in binary form to a file */
+gboolean gfsm_indexed_automaton_save_bin_file(gfsmIndexedAutomaton *fsm, FILE *f, gfsmError **errp);
+
+/** Store an automaton to a named binary file (no compression) */
+gboolean gfsm_indexed_automaton_save_bin_filename_nc(gfsmIndexedAutomaton *fsm, const gchar *filename, gfsmError **errp);
+
+/** Store an automaton to a named binary file, possibly compressing.
+ * Set \a zlevel=-1 for default compression, and
+ * set \a zlevel=0 for no compression, otherwise should be as for zlib (1 <= zlevel <= 9)
+ */
+gboolean gfsm_indexed_automaton_save_bin_filename(gfsmIndexedAutomaton *fsm, const gchar *filename, int zlevel, gfsmError **errp);
+
+/** Append an uncompressed binary automaton to an in-memory buffer */
+gboolean gfsm_indexed_automaton_save_bin_gstring(gfsmIndexedAutomaton *fsm, GString *gs, gfsmError **errp);
+
+//@}
+
+/*======================================================================
+ * Automaton Methods: Text I/O
+ */
+/// \name Automaton Methods: Text I/O (output only)
+//@{
+
+/** Print a ::gfsmIndexedAutomaton in Ma-Bell-compatible text-format to a ::gfsmIOHandle* */
+gboolean gfsm_indexed_automaton_print_handle (gfsmIndexedAutomaton *fsm,
+ gfsmIOHandle *ioh,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+
+/** Print an automaton in Ma-Bell-compatible text-format to a FILE* */
+gboolean gfsm_indexed_automaton_print_file_full (gfsmIndexedAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp);
+
+/** Convenience macro for printing to uncompresed all-numeric-id text streams */
+#define gfsm_indexed_automaton_print_file(fsm,f,errp) \
+ gfsm_indexed_automaton_print_file_full(fsm,f,NULL,NULL,NULL,0,errp)
+
+/** Print an automaton in Ma-Bell-compatible text-format to a named file */
+gboolean gfsm_indexed_automaton_print_filename_full (gfsmIndexedAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ int zlevel,
+ gfsmError **errp);
+
+/** Convenience macro for printing to uncompressed all-numeric-id named text files */
+#define gfsm_indexed_automaton_print_filename(fsm,f,errp) \
+ gfsm_indexed_automaton_print_filename_full(fsm,f,NULL,NULL,NULL,0,errp)
+
+/** Print an automaton in Ma-Bell-compatible text-format to an in-memory buffer */
+gboolean gfsm_indexed_automaton_print_gstring_full (gfsmIndexedAutomaton *fsm,
+ GString *gs,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ gfsmError **errp);
+
+//@}
+
+#endif /* _GFSM_INDEXED_IO_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmLookup.c b/gfsm/gfsm/src/libgfsm/gfsmLookup.c
new file mode 100644
index 0000000..9b99d8f
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmLookup.c
@@ -0,0 +1,481 @@
+
+/*=============================================================================*\
+ * File: gfsmLookup.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmLookup.h>
+
+#include <gfsmAlphabet.h>
+#include <gfsmState.h>
+#include <gfsmArc.h>
+#include <gfsmArcIter.h>
+
+#include <string.h>
+
+/*======================================================================
+ * Constants
+ */
+const gfsmStateId gfsmLookupStateMapGet = 16;
+
+/*======================================================================
+ * Methods: lookup
+ */
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_automaton_lookup_full(gfsmAutomaton *fst,
+ gfsmLabelVector *input,
+ gfsmAutomaton *result,
+ gfsmStateIdVector *statemap)
+{
+ GSList *stack = NULL;
+ gfsmLookupConfig *cfg = (gfsmLookupConfig*)g_new(gfsmLookupConfig,1);
+ gfsmLookupConfig *cfg_new;
+ const gfsmState *qt;
+ gfsmState *qr;
+ gfsmLabelVal a;
+ gfsmArcIter ai;
+
+ //-- ensure result automaton exists and is clear
+ if (result==NULL) {
+ result = gfsm_automaton_shadow(fst);
+ } else {
+ gfsm_automaton_clear(result);
+ }
+ result->flags.is_transducer = TRUE;
+
+ //-- initialization
+ result->root_id = gfsm_automaton_add_state(result);
+ cfg->qt = fst->root_id;
+ cfg->qr = result->root_id;
+ cfg->i = 0;
+ stack = g_slist_prepend(stack, cfg);
+
+ //-- ye olde loope
+ while (stack != NULL) {
+ //-- pop the top element off the stack
+ cfg = (gfsmLookupConfig*)(stack->data);
+ stack = g_slist_delete_link(stack, stack);
+
+ //-- add config to the state-map, if non-NULL
+ if (statemap) {
+ if (cfg->qr >= statemap->len) {
+ g_ptr_array_set_size(statemap, cfg->qr + gfsmLookupStateMapGet);
+ }
+ g_ptr_array_index(statemap, cfg->qr) = GUINT_TO_POINTER(cfg->qt);
+ }
+
+ //-- get states
+ qt = gfsm_automaton_find_state_const(fst, cfg->qt);
+ qr = gfsm_automaton_find_state (result, cfg->qr);
+ a = (cfg->i < input->len
+ ? (gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(input, cfg->i))
+ : gfsmNoLabel);
+
+ //-- check for final states
+ if (cfg->i >= input->len && gfsm_state_is_final(qt)) {
+ gfsm_automaton_set_final_state_full(result, cfg->qr, TRUE,
+ gfsm_automaton_get_final_weight(fst, cfg->qt));
+ }
+
+ //-- handle outgoing arcs
+ for (gfsm_arciter_open_ptr(&ai, fst, (gfsmState*)qt); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai))
+ {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+
+ //-- epsilon arcs
+ if (arc->lower == gfsmEpsilon) {
+ cfg_new = (gfsmLookupConfig*)g_new(gfsmLookupConfig,1);
+ cfg_new->qt = arc->target;
+ cfg_new->qr = gfsm_automaton_add_state(result);
+ cfg_new->i = cfg->i;
+ gfsm_automaton_add_arc(result, cfg->qr, cfg_new->qr, arc->lower, arc->upper, arc->weight);
+ stack = g_slist_prepend(stack, cfg_new);
+ }
+ //-- input-matching arcs
+ else if (a != gfsmNoLabel && arc->lower == a) {
+ cfg_new = (gfsmLookupConfig*)g_new(gfsmLookupConfig,1);
+ cfg_new->qt = arc->target;
+ cfg_new->qr = gfsm_automaton_add_state(result);
+ cfg_new->i = cfg->i+1;
+ gfsm_automaton_add_arc(result, cfg->qr, cfg_new->qr, arc->lower, arc->upper, arc->weight);
+ stack = g_slist_prepend(stack, cfg_new);
+ }
+ }
+
+ //-- we're done with this config
+ g_free(cfg);
+ }
+
+ //-- set final size of the state-map
+ if (statemap) { statemap->len = result->states->len; }
+
+ return result;
+}
+
+
+/*======================================================================
+ * Methods: Viterbi
+ */
+
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_automaton_lookup_viterbi_full(gfsmAutomaton *fst,
+ gfsmLabelVector *input,
+ gfsmAutomaton *trellis,
+ gfsmStateIdVector *trellis2fst)
+{
+ //-- cols: array of (GSList <gfsmViterbiConfig*> *)
+ gfsmViterbiTable *cols = g_ptr_array_sized_new(input->len+1);
+ GSList *col, *prevcoli;
+ gfsmViterbiMap *fst2trellis = gfsm_viterbi_map_new();
+ guint i;
+ gboolean trellis2fst_is_tmp = FALSE;
+ gfsmStateId qid_trellis, qid_trellis_nxt, qid_fst;
+ gpointer ptr_qid_trellis_nxt;
+ gfsmState *q_trellis, *q_trellis_nxt, *q_fst;
+ gfsmArcIter ai;
+ gfsmWeight w_trellis;
+
+ //-- ensure trellis automaton exists and is clear
+ if (trellis==NULL) {
+ trellis = gfsm_automaton_shadow(fst);
+ } else {
+ gfsm_automaton_clear(trellis);
+ }
+ trellis->flags.is_transducer = TRUE;
+
+ //-- ensure trellis->fst stateid-map exists and is clear
+ if (!trellis2fst) {
+ trellis2fst = g_ptr_array_sized_new(input->len+1);
+ trellis2fst_is_tmp = TRUE;
+ } else if (trellis2fst->len < 2) {
+ g_ptr_array_set_size(trellis2fst, input->len+1);
+ }
+
+ //-- initial config: trellis structure
+ qid_trellis = trellis->root_id = gfsm_automaton_add_state(trellis);
+ q_trellis = gfsm_automaton_find_state(trellis, qid_trellis);
+ gfsm_automaton_set_final_state_full(trellis, qid_trellis, TRUE, fst->sr->one);
+ gfsm_automaton_add_arc(trellis, qid_trellis, qid_trellis, gfsmNoLabel, gfsmNoLabel, fst->sr->one);
+
+ //-- initial config: stateid-mappings
+ g_ptr_array_index(trellis2fst, qid_trellis) = GUINT_TO_POINTER(fst->root_id);
+ g_tree_insert(fst2trellis, GUINT_TO_POINTER(fst->root_id), GUINT_TO_POINTER(qid_trellis));
+
+ //-- initial config: epsilon-expansion on column
+ g_ptr_array_index(cols,0) = col = g_slist_prepend(NULL, GUINT_TO_POINTER(qid_trellis));
+ _gfsm_viterbi_expand_column(fst, trellis, col, trellis2fst, fst2trellis);
+
+ //-- initial config: cleanup
+ gfsm_viterbi_map_free(fst2trellis);
+
+
+ //-- ye olde loope: for each input character (i)
+ for (i=0; i < input->len; i++) {
+ gfsmLabelVal a = (gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(input, i));
+
+ fst2trellis = gfsm_viterbi_map_new();
+ col = NULL;
+
+ //-- get possible successors
+ for (prevcoli=(GSList*)g_ptr_array_index(cols,i); prevcoli != NULL; prevcoli=prevcoli->next) {
+
+ //-- get the top element of the queue
+ qid_trellis = (gfsmStateId)GPOINTER_TO_UINT(prevcoli->data);
+ qid_fst = (gfsmStateId)GPOINTER_TO_UINT(g_ptr_array_index(trellis2fst, qid_trellis));
+
+ //-- get state pointers
+ q_trellis = gfsm_automaton_find_state(trellis, qid_trellis);
+ q_fst = gfsm_automaton_find_state(fst, qid_fst);
+
+ //-- get Viterbi properties
+ w_trellis = gfsm_viterbi_node_best_weight(q_trellis);
+
+
+ //-- search for input-matching arcs & add them to the successor map for next column
+ for (gfsm_arciter_open_ptr(&ai, fst, q_fst), gfsm_arciter_seek_lower(&ai,a);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_lower(&ai,a))
+ {
+ gfsmArc *arc_fst = gfsm_arciter_arc(&ai);
+ gfsmWeight w_trellis_nxt;
+ gpointer orig_key;
+
+ //-- found a matching arc: is its target state already marked as a successor?
+ if (g_tree_lookup_extended(fst2trellis,
+ GUINT_TO_POINTER(arc_fst->target),
+ &orig_key,
+ &ptr_qid_trellis_nxt))
+ {
+ //-- yep: known successor: get old ("*_nxt") & new ("*_nxt_new") weights
+ gfsmWeight w_trellis_nxt_new = gfsm_sr_times(fst->sr, w_trellis, arc_fst->weight);
+ qid_trellis_nxt = GPOINTER_TO_UINT(ptr_qid_trellis_nxt);
+ q_trellis_nxt = gfsm_automaton_find_state(trellis, qid_trellis_nxt);
+ w_trellis_nxt = gfsm_viterbi_node_best_weight(q_trellis_nxt);
+
+ //-- is the new path better than the stored path?
+ if (gfsm_sr_less(fst->sr, w_trellis_nxt_new, w_trellis_nxt)) {
+ //-- yep: update mappings: trellis automaton
+ gfsmArc *arc_trellis_nxt = gfsm_viterbi_node_arc(q_trellis_nxt);
+ arc_trellis_nxt->target = qid_trellis;
+ arc_trellis_nxt->lower = a;
+ arc_trellis_nxt->upper = arc_fst->upper;
+ arc_trellis_nxt->weight = w_trellis_nxt_new;
+
+ //-- update mappings: trellis->fst stateid-map
+ g_ptr_array_index(trellis2fst, qid_trellis_nxt) = GUINT_TO_POINTER(arc_fst->target);
+
+ //-- update mappings: fst->trellis stateid-map
+ g_tree_insert(fst2trellis, GUINT_TO_POINTER(arc_fst->target), GUINT_TO_POINTER(qid_trellis_nxt));
+ }
+ }
+ else
+ {
+ //-- target state not already marked as a successor: mark it
+ qid_trellis_nxt = gfsm_automaton_add_state(trellis);
+ q_trellis_nxt = gfsm_automaton_find_state(trellis,qid_trellis_nxt);
+ gfsm_automaton_add_arc(trellis,
+ qid_trellis_nxt, qid_trellis,
+ a, arc_fst->upper,
+ gfsm_sr_times(fst->sr, w_trellis, arc_fst->weight));
+
+ //-- save trellis->fst stateid-map
+ if (qid_trellis_nxt >= trellis2fst->len) {
+ g_ptr_array_set_size(trellis2fst, qid_trellis_nxt + gfsmLookupStateMapGet);
+ }
+ g_ptr_array_index(trellis2fst,qid_trellis_nxt) = GUINT_TO_POINTER(arc_fst->target);
+
+ //-- save fst->trellis stateid-map
+ g_tree_insert(fst2trellis, GUINT_TO_POINTER(arc_fst->target), GUINT_TO_POINTER(qid_trellis_nxt));
+
+ //-- add new trellis state to the column
+ col = g_slist_prepend(col, GUINT_TO_POINTER(qid_trellis_nxt));
+ }
+
+ } //-- END: seek input-matching arcs
+ } //-- END: previous column iteration (prevcoli)
+
+ //-- expand epsilons in current column
+ _gfsm_viterbi_expand_column(fst, trellis, col, trellis2fst, fst2trellis);
+
+ //-- update column table
+ g_ptr_array_index(cols,i+1) = col;
+
+ //-- per-input-index cleanup
+ gfsm_viterbi_map_free(fst2trellis);
+ }
+
+ //-- final iteration (EOS): get possible "final" states
+ qid_trellis_nxt = gfsm_automaton_add_state(trellis); //-- qid_trellis_nxt: new root
+ for (prevcoli=(GSList*)g_ptr_array_index(cols,input->len); prevcoli != NULL; prevcoli=prevcoli->next) {
+
+ //-- get the top element of the queue
+ qid_trellis = (gfsmStateId)GPOINTER_TO_UINT(prevcoli->data);
+ qid_fst = (gfsmStateId)GPOINTER_TO_UINT(g_ptr_array_index(trellis2fst, qid_trellis));
+
+ //-- get state pointers
+ q_trellis = gfsm_automaton_find_state(trellis, qid_trellis);
+ q_fst = gfsm_automaton_find_state(fst, qid_fst);
+
+ //-- get Viterbi properties
+ w_trellis = gfsm_viterbi_node_best_weight(q_trellis);
+
+ //-- check for finality
+ if (q_fst->is_final) {
+ gfsm_automaton_add_arc(trellis, qid_trellis_nxt, qid_trellis,
+ gfsmEpsilon, gfsmEpsilon,
+ gfsm_sr_times(fst->sr,
+ w_trellis,
+ gfsm_automaton_get_final_weight(fst,qid_fst)));
+ }
+ }
+
+ //-- mark single best path from new root
+ qid_trellis = qid_trellis_nxt;
+ q_trellis = gfsm_automaton_find_state(trellis,qid_trellis);
+ q_trellis->arcs = gfsm_arclist_sort(q_trellis->arcs,
+ &((gfsmArcCompData){gfsmASMWeight,fst->sr,NULL,NULL}));
+
+ //-- break dummy arc on trellis final state (old root)
+ q_trellis = gfsm_automaton_find_state(trellis,trellis->root_id);
+ gfsm_arclist_free(q_trellis->arcs);
+ q_trellis->arcs = NULL;
+
+ //-- mark new root
+ trellis->root_id = qid_trellis;
+
+
+ //-- cleanup: columns
+ for (i=0; i < cols->len; i++) {
+ g_slist_free((GSList*)g_ptr_array_index(cols,i));
+ }
+
+ //-- cleanup: column array
+ g_ptr_array_free(cols,TRUE);
+ if (trellis2fst_is_tmp) g_ptr_array_free(trellis2fst,TRUE);
+ else {
+ //-- just set length
+ trellis2fst->len = trellis->states->len;
+ }
+
+ return trellis;
+}
+
+
+/*======================================================================
+ * Methods: Viterbi: expand_column
+ */
+
+//--------------------------------------------------------------
+void _gfsm_viterbi_expand_column(gfsmAutomaton *fst,
+ gfsmAutomaton *trellis,
+ gfsmViterbiColumn *col,
+ gfsmStateIdVector *trellis2fst,
+ gfsmViterbiMap *fst2trellis)
+{
+ gfsmArcIter ai;
+ gfsmViterbiColumn *coli;
+ gfsmStateId qid_trellis, qid_fst;
+ gfsmState *q_trellis;
+ gfsmArc *arc_trellis;
+ gfsmWeight w_trellis;
+
+ //-- pass-1: add everything already in the column as a literal
+ /*
+ for (coli=col; coli != NULL; coli=coli->next) {
+ node = (gfsmViterbiNode*)(coli->data);
+ if (!g_tree_lookup(fst2trellis,node->key)) {
+ g_tree_insert(cmap,node->key,node->val);
+ }
+ }
+ */
+
+ //-- pass-2: add epsilon arcs from every literal in the column
+ for (coli=col; coli != NULL; coli=coli->next) {
+ //-- get node
+ qid_trellis = (gfsmStateId)GPOINTER_TO_UINT(coli->data);
+ q_trellis = gfsm_automaton_find_state(trellis,qid_trellis);
+ arc_trellis = gfsm_viterbi_node_arc(q_trellis);
+ w_trellis = gfsm_viterbi_node_best_weight(q_trellis);
+ qid_fst = (gfsmStateId)GPOINTER_TO_UINT(g_ptr_array_index(trellis2fst,qid_trellis));
+
+ //-- search for input-epsilon arcs & add them to this column
+ for (gfsm_arciter_open(&ai,fst,qid_fst), gfsm_arciter_seek_lower(&ai,gfsmEpsilon);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_lower(&ai,gfsmEpsilon))
+ {
+ gfsmArc *arc_fst = gfsm_arciter_arc(&ai);
+ gfsmStateId qid_trellis_nxt = gfsmNoState;
+ gpointer ptr_qid_trellis_nxt;
+ gfsmState *q_trellis_nxt;
+ gfsmWeight w_trellis_nxt;
+ gpointer orig_key;
+
+ //-- found an eps-arc: is its target state already marked as a successor?
+ if (g_tree_lookup_extended(fst2trellis,
+ GUINT_TO_POINTER(arc_fst->target),
+ &orig_key,
+ &ptr_qid_trellis_nxt))
+ {
+ //-- yep: get the old ("*_eps") & new ("*_nxt") weights
+ gfsmWeight w_trellis_eps = gfsm_sr_times(fst->sr, w_trellis, arc_fst->weight);
+ qid_trellis_nxt = GPOINTER_TO_UINT(ptr_qid_trellis_nxt);
+ q_trellis_nxt = gfsm_automaton_find_state(trellis,qid_trellis_nxt);
+ w_trellis_nxt = gfsm_viterbi_node_best_weight(q_trellis_nxt);
+
+ //-- is the new eps-path better than the stored path?
+ if (gfsm_sr_less(fst->sr,w_trellis_eps,w_trellis_nxt)) {
+ //-- yep: update mappings: trellis automaton
+ gfsmArc *arc_trellis_nxt = gfsm_viterbi_node_arc(q_trellis_nxt);
+ arc_trellis_nxt->target = qid_trellis;
+ arc_trellis_nxt->lower = gfsmEpsilon;
+ arc_trellis_nxt->upper = arc_fst->upper;
+ arc_trellis_nxt->weight = w_trellis_eps;
+
+ //-- update mappings: trellis->fst stateid-map
+ g_ptr_array_index(trellis2fst, qid_trellis_nxt) = GUINT_TO_POINTER(arc_fst->target);
+
+ //-- update mappings: fst->trellis stateid-map
+ g_tree_insert(fst2trellis, GUINT_TO_POINTER(arc_fst->target), GUINT_TO_POINTER(qid_trellis_nxt));
+ }
+ else {
+ //-- eps-path is worse than the existing path: forget about it
+ ;
+ }
+ }
+ else
+ {
+ //-- eps-target state not already marked as a successor: mark it
+ qid_trellis_nxt = gfsm_automaton_add_state(trellis);
+ q_trellis_nxt = gfsm_automaton_find_state(trellis,qid_trellis_nxt);
+ gfsm_automaton_add_arc(trellis,
+ qid_trellis_nxt, qid_trellis,
+ gfsmEpsilon, arc_fst->upper,
+ gfsm_sr_times(fst->sr, w_trellis, arc_fst->weight));
+
+ //-- save trellis->fst stateid-map
+ if (qid_trellis_nxt >= trellis2fst->len) {
+ g_ptr_array_set_size(trellis2fst, qid_trellis_nxt + gfsmLookupStateMapGet);
+ }
+ g_ptr_array_index(trellis2fst,qid_trellis_nxt) = GUINT_TO_POINTER(arc_fst->target);
+
+ //-- save fst->trellis stateid-map
+ g_tree_insert(fst2trellis, GUINT_TO_POINTER(arc_fst->target), GUINT_TO_POINTER(qid_trellis_nxt));
+
+ //-- queue-up new trellis state for eps-seek
+ coli->next = g_slist_prepend(coli->next, GUINT_TO_POINTER(qid_trellis_nxt));
+ }
+
+ } //-- END: seek epsilon arcs
+
+ } //-- END column iteration
+
+}
+
+
+/*======================================================================
+ * Methods: Viterbi: Map
+ */
+
+//--------------------------------------------------------------
+#if 0
+gfsmViterbiNodeValue *gfsm_viterbi_column_map_insert_if_less(gfsmViterbiMap *vmap,
+ gfsmViterbiNodeKey key,
+ gfsmWeight w,
+ gfsmSemiring *sr)
+{
+ gpointer s_val;
+ if (s_val = gfsm_viterbi_map_lookup(vmap,key)) {
+ //-- already present
+ if (!gfsm_sr_less(sr,w,s_val->w)) return NULL; //-- (s_val->w) <= (w)
+ s_val->w = w;
+ } else {
+ //-- not already present: copy & insert
+ s_val = g_new(gfsmViterbiNodeValue,1);
+ s_val->qtrellis = gfsmNoState;
+ a_val->pqtrellis = gfsmNoState;
+ s_val->w = w;
+ g_tree_insert(col,key,s_val);
+ }
+ return s_val; //-- update occurred
+}
+#endif
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmLookup.h b/gfsm/gfsm/src/libgfsm/gfsmLookup.h
new file mode 100644
index 0000000..7157047
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmLookup.h
@@ -0,0 +1,212 @@
+
+/*=============================================================================*\
+ * File: gfsmLookup.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmLookup.h
+ * \brief Linear composition
+ */
+
+#ifndef _GFSM_LOOKUP_H
+#define _GFSM_LOOKUP_H
+
+#include <gfsmAutomaton.h>
+#include <gfsmUtils.h>
+
+/*======================================================================
+ * Types: lookup
+ */
+/** \brief Type for gfsm_automaton_lookup() computation state */
+typedef struct {
+ gfsmStateId qt; /**< current state in transducer */
+ gfsmStateId qr; /**< current state in result acceptor */
+ guint32 i; /**< current position in input vector */
+} gfsmLookupConfig;
+
+//------------------------------
+
+/** Type for gfsm_automaton_lookup_viterbi(): Trellis (1 per call) */
+typedef GPtrArray gfsmViterbiTable;
+
+/** Viterbi algorithm best-successor accumulator
+ * \arg key is a gfsmStateId (state in fst)
+ * \arg value is a gfsmStateId (state in trellis)
+ */
+typedef GTree gfsmViterbiMap;
+
+/** Key type for gfsmViterbiMap (state-id in fst) */
+typedef gfsmStateId gfsmViterbiMapKey;
+
+/** Value type for gfsmViterbiMap (state-id in trellis) */
+typedef gfsmStateId gfsmViterbiMapValue;
+
+/** Type for Viterbi trellis column (1 per input index)
+ * \arg data is a gfsmStateId in trellis automaton
+ */
+typedef GSList gfsmViterbiColumn;
+
+/** Type for Viterbi trellis nodes: state in trellis automaton
+ * \arg state \a q has exactly one outgoing arc \a arc=((gfsmArc*)a->ars->data)
+ * \arg best preceeding state in trellis is \a arc->target
+ * \arg label of best arc from best preceeding state in trellis is \a arc->lower
+ * \arg total weight of best path to this state is \a arc->weight
+ */
+typedef gfsmState gfsmViterbiNode;
+
+
+/*======================================================================
+ * Constants
+ */
+
+/** Number of states to pre-allocate when extending state-map vector on lookup_full() (>= 1) */
+extern const gfsmStateId gfsmLookupStateMapGet;
+
+
+/*======================================================================
+ * Methods: lookup
+ */
+///\name Lookup
+//@{
+
+//------------------------------
+/** Compose linear automaton specified by \a input with the transducer
+ * \a fst , storing result in \a result.
+ * \param fst transducer (lower-upper)
+ * \param input input labels (lower)
+ * \param result output transducer or NULL
+ * \returns \a result if non-NULL, otherwise a new automaton.
+ */
+#define gfsm_automaton_lookup(fst,input,result) \
+ gfsm_automaton_lookup_full((fst),(input),(result),NULL)
+
+//------------------------------
+/** Compose linear automaton specified by \a input with the transducer
+ * \a fst , storing result in \a result , and storing state-translation map \a statemap.
+ * \param fst transducer (lower-upper)
+ * \param input input labels (lower)
+ * \param result output transducer or NULL
+ * \param statemap if non-NULL, maps \a result StateIds (indices) to \a fst StateIds (values) on return.
+ * Not implicitly created or cleared.
+ * \returns \a result if non-NULL, otherwise a new automaton.
+ */
+gfsmAutomaton *gfsm_automaton_lookup_full(gfsmAutomaton *fst,
+ gfsmLabelVector *input,
+ gfsmAutomaton *result,
+ gfsmStateIdVector *statemap);
+
+//@}
+
+
+/*======================================================================
+ * Methods: Viterbi
+ */
+///\name Viterbi Lookup
+//@{
+
+//------------------------------
+/** Get the best path for input \a input in the transducer \a fst using the Viterbi algorithm.
+ * \param fst transducer (lower-upper)
+ * \param input input labels (lower)
+ * \param trellis output fsm or NULL
+ * \returns \a trellis if non-NULL, otherwise a new automaton representing the (reversed) Viterbi trellis.
+ * \arg labels (lower & upper) in \a trellis represent upper labels of \a fst
+ * \arg arc-weights in \a trellis represent Viterbi algorithm weights (gamma)
+ * \arg arc-targets in \a trellis represent the best preceeding state (psi)
+ */
+#define gfsm_automaton_lookup_viterbi(fst,input,trellis) \
+ gfsm_automaton_lookup_viterbi_full((fst),(input),(trellis),NULL)
+
+//------------------------------
+/** Get the best path for input \a input in the transducer \a fst using the Viterbi algorithm.
+ * \param fst transducer (lower-upper)
+ * \param input input labels (lower)
+ * \param trellis output fsm or NULL
+ * \param trellis2fst if non-NULL, maps \a trellis StateIds (indices) to \a fst StateIds (values) on return.
+ * If NULL, a temporary vector will be created & freed.
+ * \returns \a trellis if non-NULL, otherwise a new automaton representing the (reversed) Viterbi trellis.
+ * \arg lower-labels in \a trellis represent \a input labels
+ * \arg upper-labels of \a trellis represent upper labels of \a fst
+ * \arg arc-weights in \a trellis represent Viterbi algorithm weights (gamma)
+ * \arg arc-targets in \a trellis represent the best preceeding state (psi)
+ * \arg root state of \a trellis has arcs sorted by total path weight (best-first)
+ */
+gfsmAutomaton *gfsm_automaton_lookup_viterbi_full(gfsmAutomaton *fst,
+ gfsmLabelVector *input,
+ gfsmAutomaton *trellis,
+ gfsmStateIdVector *trellis2fst);
+
+//@}
+
+/*======================================================================
+ * Viterbi: Utilities
+ */
+///\name Viterbi Low-level Utilities
+//@{
+
+
+//------------------------------
+// expand_column()
+
+/** Expand lower-epsilon arcs from \a fst into \a col. */
+void _gfsm_viterbi_expand_column(gfsmAutomaton *fst,
+ gfsmAutomaton *trellis,
+ gfsmViterbiColumn *col,
+ gfsmStateIdVector *trellis2fst,
+ gfsmViterbiMap *fst2trellis);
+
+
+//------------------------------
+// gfsmViterbiMap
+
+/** Create a new gfsmViterbiMap */
+#define gfsm_viterbi_map_new() \
+ g_tree_new_full((GCompareDataFunc)gfsm_uint_compare, NULL, NULL, NULL)
+
+
+/** Free a gfsmViterbiMap */
+#define gfsm_viterbi_map_free(vmap) g_tree_destroy(vmap)
+
+
+/** Lookup stored value in a gfsmViterbiColumnMap
+ * \returns gpointer to the stored value for \a key in \a vmap
+ */
+#define gfsm_viterbi_map_lookup(vmap,key) g_tree_lookup((vmap),(key))
+
+/** Insert a literal value into a gfsmViterbiColumnMap */
+#define gfsm_viterbi_map_insert(vmap,key,val) g_tree_insert((vmap),(gpointer)(key),(gpointer)(val))
+
+
+//------------------------------
+// gfsmViterbiNode
+
+/** gfsmViterbiNode: Accessor: unique outgoing arc for \a nod */
+//#define gfsm_viterbi_node_arc(nod) ((gfsmArc*)((nod)->arcs->data))
+#define gfsm_viterbi_node_arc(nod) gfsm_arclist_arc((nod)->arcs)
+
+/** gfsmViterbiNode: Accessor: Best preceeding state accessor for \a nod */
+#define gfsm_viterbi_node_best_prevstate(nod) gfsm_viterbi_node_arc(nod)->target
+
+/** gfsmViterbiNode: Accessor: Total weight of best path to \a nod */
+#define gfsm_viterbi_node_best_weight(nod) gfsm_viterbi_node_arc(nod)->weight
+
+//@}
+
+#endif /* _GFSM_LOOKUP_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmMem.c b/gfsm/gfsm/src/libgfsm/gfsmMem.c
new file mode 100644
index 0000000..57198d7
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmMem.c
@@ -0,0 +1,36 @@
+
+/*=============================================================================*\
+ * File: gfsmMem.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: memory utilities
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmMem.h>
+
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmMem.hi>
+#endif
+
+/*----------------------------------------------------------------------
+ * Allocators
+ */
+GAllocator *gfsm_node_allocator = NULL;
+GAllocator *gfsm_slist_allocator = NULL;
+GAllocator *gfsm_list_allocator = NULL;
+gboolean gfsm_allocators_enabled = FALSE;
diff --git a/gfsm/gfsm/src/libgfsm/gfsmMem.h b/gfsm/gfsm/src/libgfsm/gfsmMem.h
new file mode 100644
index 0000000..4791d26
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmMem.h
@@ -0,0 +1,110 @@
+
+/*=============================================================================*\
+ * File: gfsmMem.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: memory utilities (currently unused)
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmMem.h
+ * \brief Memory utilities
+ */
+
+#ifndef _GFSM_MEM_H
+#define _GFSM_MEM_H
+
+#include <glib.h>
+#include <gfsmConfig.h>
+
+/*----------------------------------------------------------------------
+ * Allocators: variables
+ */
+
+/** Default GNode allocator */
+extern GAllocator *gfsm_node_allocator;
+
+/** Default GSList allocator */
+extern GAllocator *gfsm_slist_allocator;
+
+/** Default GList allocator */
+extern GAllocator *gfsm_list_allocator;
+
+/** Whether gfsm allocators are currently enabled */
+extern gboolean gfsm_allocators_enabled;
+
+
+/*----------------------------------------------------------------------
+ * Allocators
+ * - these aren't used by default!
+ */
+
+/** Ensure that gfsm allocators are defined and non-NULL */
+GFSM_INLINE
+void gfsm_allocators_init(void);
+
+/** Push gfsm allocators to the stack */
+GFSM_INLINE
+void gfsm_allocators_enable(void);
+
+/** Pop gfsm allocators from the stack */
+GFSM_INLINE
+void gfsm_allocators_disable(void);
+
+/** Free all memory allocated by the gfsm allocators */
+GFSM_INLINE
+void gfsm_allocators_free(void);
+
+
+/*----------------------------------------------------------------------
+ * Copying
+ */
+/** Abstract copy function */
+typedef gpointer (*gfsmDupNFunc) (gconstpointer src, gsize size);
+
+/** Abstract duplication function */
+typedef gpointer (*gfsmDupFunc) (gconstpointer src);
+
+/** String copy function for NUL-terminated strings */
+GFSM_INLINE
+gpointer gfsm_string_dup_n (gconstpointer src, gsize size);
+
+/** size-based copy function */
+GFSM_INLINE
+gpointer gfsm_mem_dup_n (gconstpointer src, gsize size);
+
+/** String duplication function for NUL-terminated strings */
+#define gfsm_string_dup g_strdup
+
+/** String duplication function for GString*s */
+GFSM_INLINE
+GString *gfsm_gstring_dup (GString *gstr);
+
+/** Byte-assignment for GString*s */
+GFSM_INLINE
+void gfsm_gstring_assign_bytes (GString *gstr, const gchar *src, gsize len);
+
+/** Byte-vector creation for GString*s */
+GFSM_INLINE
+GString *gfsm_gstring_new_bytes (const gchar *src, gsize len);
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmMem.hi>
+#endif
+
+#endif /* _GFSM_MEM_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmMem.hi b/gfsm/gfsm/src/libgfsm/gfsmMem.hi
new file mode 100644
index 0000000..4b9819d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmMem.hi
@@ -0,0 +1,135 @@
+
+/*=============================================================================*\
+ * File: gfsmMem.def
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: memory utilities: inline definitions
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <string.h>
+
+/*----------------------------------------------------------------------
+ * init_allocators()
+ */
+GFSM_INLINE
+void gfsm_allocators_init(void)
+{
+ if (!gfsm_node_allocator) gfsm_node_allocator = g_allocator_new("gfsm_node_allocator",128);
+ if (!gfsm_slist_allocator) gfsm_slist_allocator = g_allocator_new("gfsm_slist_allocator",128);
+ if (!gfsm_list_allocator) gfsm_list_allocator = g_allocator_new("gfsm_list_allocator",128);
+}
+
+/*----------------------------------------------------------------------
+ * allocators_enable()
+ */
+GFSM_INLINE
+void gfsm_allocators_enable(void)
+{
+ if (!gfsm_allocators_enabled) {
+ gfsm_allocators_init();
+ g_node_push_allocator(gfsm_node_allocator);
+ g_slist_push_allocator(gfsm_slist_allocator);
+ g_list_push_allocator(gfsm_list_allocator);
+ gfsm_allocators_enabled = TRUE;
+ }
+}
+
+/*----------------------------------------------------------------------
+ * allocators_disable()
+ */
+GFSM_INLINE
+void gfsm_allocators_disable(void)
+{
+ if (gfsm_allocators_enabled) {
+ g_node_pop_allocator();
+ g_slist_pop_allocator();
+ g_list_pop_allocator();
+ gfsm_allocators_enabled = FALSE;
+ }
+}
+
+
+/*----------------------------------------------------------------------
+ * allocators_free()
+ */
+GFSM_INLINE
+void gfsm_allocators_free(void)
+{
+ gfsm_allocators_disable();
+
+ if (gfsm_node_allocator) g_allocator_free(gfsm_node_allocator);
+ if (gfsm_slist_allocator) g_allocator_free(gfsm_slist_allocator);
+ if (gfsm_list_allocator) g_allocator_free(gfsm_list_allocator);
+
+ gfsm_node_allocator=NULL;
+ gfsm_slist_allocator=NULL;
+ gfsm_list_allocator=NULL;
+}
+
+
+/*----------------------------------------------------------------------
+ * string_dup_n()
+ */
+GFSM_INLINE
+gpointer gfsm_string_dup_n(gconstpointer src, gsize size)
+{
+#ifndef __cplusplus
+ return g_strndup(src,size);
+#else
+ return g_strndup(static_cast<const gchar *>(src), size);
+#endif
+}
+
+/*----------------------------------------------------------------------
+ * mem_dup_n()
+ */
+GFSM_INLINE
+gpointer gfsm_mem_dup_n(gconstpointer src, gsize size)
+{ return g_memdup(src,size); };
+
+/*----------------------------------------------------------------------
+ * gstring_dup()
+ */
+GFSM_INLINE
+GString *gfsm_gstring_dup (GString *gstr)
+{
+ GString *dst = g_string_sized_new(gstr->len);
+ g_string_append_len(dst, gstr->str, gstr->len);
+ return dst;
+}
+
+/*----------------------------------------------------------------------
+ * gstring_asign_bytes()
+ */
+GFSM_INLINE
+void gfsm_gstring_assign_bytes (GString *gstr, const gchar *src, gsize len)
+{
+ g_string_truncate(gstr, 0);
+ g_string_append_len(gstr, src, gstr->len);
+}
+
+/*----------------------------------------------------------------------
+ * gstring_new_bytes()
+ */
+GFSM_INLINE
+GString *gfsm_gstring_new_bytes (const gchar *src, gsize len)
+{
+ GString *dst = g_string_sized_new(src[len]=='\0' ? len : (len+1));
+ g_string_append_len(dst,src,len);
+ return dst;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmPaths.c b/gfsm/gfsm/src/libgfsm/gfsmPaths.c
new file mode 100644
index 0000000..7b5faa5
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmPaths.c
@@ -0,0 +1,431 @@
+
+/*=============================================================================*\
+ * File: gfsmPaths.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmPaths.h>
+#include <gfsmArc.h>
+#include <gfsmArcIter.h>
+
+
+/*======================================================================
+ * Methods: Path Utilities: gfsmLabelVector
+ */
+
+//--------------------------------------------------------------
+gfsmLabelVector *gfsm_label_vector_copy(gfsmLabelVector *dst, gfsmLabelVector *src)
+{
+ int i;
+ g_ptr_array_set_size(dst, src->len);
+ for (i=0; i < src->len; i++) {
+ g_ptr_array_index(dst,i) = g_ptr_array_index(src,i);
+ }
+ return dst;
+}
+
+//--------------------------------------------------------------
+gfsmLabelVector *gfsm_label_vector_reverse(gfsmLabelVector *v)
+{
+ guint i, mid;
+ gpointer tmp;
+ mid = v->len/2;
+ for (i=0; i < mid; i++) {
+ tmp = g_ptr_array_index(v,i);
+ g_ptr_array_index(v,i) = g_ptr_array_index(v,v->len-i-1);
+ g_ptr_array_index(v,v->len-i-1) = tmp;
+ }
+ return v;
+}
+
+/*======================================================================
+ * Methods: Path Utilities: gfsmPath
+ */
+
+//--------------------------------------------------------------
+gfsmPath *gfsm_path_new_full(gfsmLabelVector *lo, gfsmLabelVector *hi, gfsmWeight w)
+{
+ gfsmPath *p = g_new(gfsmPath,1);
+ p->lo = lo ? lo : g_ptr_array_new();
+ p->hi = hi ? hi : g_ptr_array_new();
+ p->w = w;
+ return p;
+}
+
+//--------------------------------------------------------------
+gfsmPath *gfsm_path_new_copy(gfsmPath *p1)
+{
+ gfsmPath *p = g_new(gfsmPath,1);
+
+ p->lo = g_ptr_array_sized_new(p1->lo->len);
+ p->hi = g_ptr_array_sized_new(p1->hi->len);
+
+ gfsm_label_vector_copy(p->lo, p1->lo);
+ gfsm_label_vector_copy(p->hi, p1->hi);
+
+ p->w = p1->w;
+
+ return p;
+}
+
+//--------------------------------------------------------------
+gfsmPath *gfsm_path_new_append(gfsmPath *p1, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight w, gfsmSemiring *sr)
+{
+ gfsmPath *p = g_new(gfsmPath,1);
+
+ if (lo != gfsmEpsilon) {
+ p->lo = g_ptr_array_sized_new(p1->lo->len+1);
+ gfsm_label_vector_copy(p->lo, p1->lo);
+ g_ptr_array_add(p->lo, GUINT_TO_POINTER(lo));
+ } else {
+ p->lo = g_ptr_array_sized_new(p1->lo->len);
+ gfsm_label_vector_copy(p->lo, p1->lo);
+ }
+
+ if (hi != gfsmEpsilon) {
+ p->hi = g_ptr_array_sized_new(p1->hi->len+1);
+ gfsm_label_vector_copy(p->hi, p1->hi);
+ g_ptr_array_add(p->hi, GUINT_TO_POINTER(hi));
+ } else {
+ p->hi = g_ptr_array_sized_new(p1->hi->len);
+ gfsm_label_vector_copy(p->hi, p1->hi);
+ }
+
+ p->w = gfsm_sr_times(sr, p1->w, w);
+
+ return p;
+}
+
+//--------------------------------------------------------------
+gfsmPath *gfsm_path_new_times_w(gfsmPath *p1, gfsmWeight w, gfsmSemiring *sr)
+{
+ gfsmPath *p = g_new(gfsmPath,1);
+
+ p->lo = g_ptr_array_sized_new(p1->lo->len);
+ gfsm_label_vector_copy(p->lo, p1->lo);
+
+ p->hi = g_ptr_array_sized_new(p1->hi->len);
+ gfsm_label_vector_copy(p->hi, p1->hi);
+
+ p->w = gfsm_sr_times(sr, p1->w, w);
+
+ return p;
+}
+
+//--------------------------------------------------------------
+void gfsm_path_push(gfsmPath *p, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight w, gfsmSemiring *sr)
+{
+ if (lo != gfsmEpsilon) g_ptr_array_add(p->lo, GUINT_TO_POINTER(lo));
+ if (hi != gfsmEpsilon) g_ptr_array_add(p->hi, GUINT_TO_POINTER(hi));
+ p->w = gfsm_sr_times(sr, p->w, w);
+}
+
+
+//--------------------------------------------------------------
+void gfsm_path_pop(gfsmPath *p, gfsmLabelVal lo, gfsmLabelVal hi)
+{
+ if (lo != gfsmEpsilon) g_ptr_array_remove_index_fast(p->lo, p->lo->len-1);
+ if (hi != gfsmEpsilon) g_ptr_array_remove_index_fast(p->hi, p->hi->len-1);
+}
+
+//--------------------------------------------------------------
+int gfsm_label_vector_compare(const gfsmLabelVector *v1, const gfsmLabelVector *v2)
+{
+ int i;
+ gfsmLabelVal lab1, lab2;
+ if (v1==v2) return 0;
+
+ for (i=0; i < v1->len && i < v2->len; i++) {
+ lab1 = (gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(v1,i));
+ lab2 = (gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(v2,i));
+ if (lab1 < lab2) return -1;
+ if (lab1 > lab2) return 1;
+ }
+ if (v1->len < v2->len) return -1;
+ if (v1->len > v2->len) return 1;
+ return 0;
+}
+
+//--------------------------------------------------------------
+int gfsm_path_compare_data(const gfsmPath *p1, const gfsmPath *p2, gfsmSemiring *sr)
+{
+ int cmp;
+ if (p1==p2) return 0;
+ if ((cmp=gfsm_sr_compare(sr, p1->w, p2->w))!=0) return cmp;
+ if ((cmp=gfsm_label_vector_compare(p1->lo,p2->lo))!=0) return cmp;
+ if ((cmp=gfsm_label_vector_compare(p1->hi,p2->hi))!=0) return cmp;
+ return 0;
+}
+
+//--------------------------------------------------------------
+gfsmPath *gfsm_path_reverse(gfsmPath *p)
+{
+ if (p->lo) gfsm_label_vector_reverse(p->lo);
+ if (p->hi) gfsm_label_vector_reverse(p->hi);
+ return p;
+}
+
+//--------------------------------------------------------------
+void gfsm_path_free(gfsmPath *p)
+{
+ if (!p) return;
+ if (p->lo) g_ptr_array_free(p->lo,TRUE);
+ if (p->hi) g_ptr_array_free(p->hi,TRUE);
+ g_free(p);
+}
+
+/*======================================================================
+ * Methods: Automaton Serialization: paths()
+ */
+
+//--------------------------------------------------------------
+gfsmSet *gfsm_automaton_paths(gfsmAutomaton *fsm, gfsmSet *paths)
+{
+ return gfsm_automaton_paths_full(fsm, paths, (fsm->flags.is_transducer ? gfsmLSBoth : gfsmLSLower));
+}
+
+//--------------------------------------------------------------
+gfsmSet *gfsm_automaton_paths_full(gfsmAutomaton *fsm, gfsmSet *paths, gfsmLabelSide which)
+{
+ gfsmPath *tmp = gfsm_path_new(fsm->sr);
+ if (paths==NULL) {
+ paths = gfsm_set_new_full((GCompareDataFunc)gfsm_path_compare_data,
+ (gpointer)fsm->sr,
+ (GDestroyNotify)gfsm_path_free);
+ }
+ _gfsm_automaton_paths_r(fsm, paths, which, fsm->root_id, tmp);
+ gfsm_path_free(tmp);
+ return paths;
+}
+
+//--------------------------------------------------------------
+gfsmSet *_gfsm_automaton_paths_r(gfsmAutomaton *fsm,
+ gfsmSet *paths,
+ gfsmLabelSide which,
+ gfsmStateId q,
+ gfsmPath *path)
+{
+ gfsmArcIter ai;
+ gfsmWeight fw;
+
+ //-- if final state, add to set of full paths
+ if (gfsm_automaton_lookup_final(fsm,q,&fw)) {
+ gfsmWeight path_w = path->w;
+ path->w = gfsm_sr_times(fsm->sr, fw, path_w);
+
+ if (!gfsm_set_contains(paths,path)) {
+ gfsm_set_insert(paths, gfsm_path_new_copy(path));
+ }
+ path->w = path_w;
+ }
+
+ //-- investigate all outgoing arcs
+ for (gfsm_arciter_open(&ai, fsm, q); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+ gfsmWeight w = path->w;
+ gfsmLabelVal lo,hi;
+
+ if (which==gfsmLSLower) {
+ lo = arc->lower;
+ hi = gfsmEpsilon;
+ } else if (which==gfsmLSUpper) {
+ lo = gfsmEpsilon;
+ hi = arc->upper;
+ } else {
+ lo = arc->lower;
+ hi = arc->upper;
+ }
+
+ gfsm_path_push(path, lo, hi, arc->weight, fsm->sr);
+ _gfsm_automaton_paths_r(fsm, paths, which, arc->target, path);
+
+ gfsm_path_pop(path, lo, hi);
+ path->w = w;
+ }
+ gfsm_arciter_close(&ai);
+
+ return paths;
+}
+
+/*======================================================================
+ * Methods: Automaton Serialization: paths_to_strings()
+ */
+
+//--------------------------------------------------------------
+GSList *gfsm_paths_to_strings(gfsmSet *paths,
+ gfsmAlphabet *abet_lo,
+ gfsmAlphabet *abet_hi,
+ gfsmSemiring *sr,
+ gboolean warn_on_undefined,
+ gboolean att_style,
+ GSList *strings)
+{
+ gfsmPathsToStringsOptions opts =
+ {
+ abet_lo,
+ abet_hi,
+ sr,
+ warn_on_undefined,
+ att_style,
+ NULL
+ };
+
+ gfsm_set_foreach(paths, (GTraverseFunc)_gfsm_paths_to_strings_foreach_func, &opts);
+
+ return g_slist_reverse(opts.strings);
+}
+
+//--------------------------------------------------------------
+gboolean _gfsm_paths_to_strings_foreach_func(gfsmPath *path,
+ gpointer value_dummy,
+ gfsmPathsToStringsOptions *opts)
+{
+ GString *gs = gfsm_path_to_gstring(path, NULL,
+ opts->abet_lo, opts->abet_hi, opts->sr,
+ opts->warn_on_undefined, opts->att_style);
+ opts->strings = g_slist_prepend(opts->strings, gs->str);
+ g_string_free(gs,FALSE);
+
+ return FALSE;
+}
+
+//--------------------------------------------------------------
+GString *gfsm_path_to_gstring(gfsmPath *path,
+ GString *gs,
+ gfsmAlphabet *abet_lo,
+ gfsmAlphabet *abet_hi,
+ gfsmSemiring *sr,
+ gboolean warn_on_undefined,
+ gboolean att_style)
+{
+ if (!gs) gs = g_string_new("");
+ if (abet_lo && path->lo->len > 0) {
+ gfsm_alphabet_labels_to_gstring(abet_lo, path->lo, gs, warn_on_undefined, att_style);
+ }
+ if (abet_hi && path->hi->len > 0) {
+ g_string_append(gs," : ");
+ gfsm_alphabet_labels_to_gstring(abet_hi, path->hi, gs, warn_on_undefined, att_style);
+ }
+ if (gfsm_sr_compare(sr, path->w, sr->one) != 0) {
+ g_string_append_printf(gs," <%g>",path->w);
+ }
+ return gs;
+}
+
+//--------------------------------------------------------------
+char *gfsm_path_to_string(gfsmPath *path,
+ gfsmAlphabet *abet_lo,
+ gfsmAlphabet *abet_hi,
+ gfsmSemiring *sr,
+ gboolean warn_on_undefined,
+ gboolean att_style)
+{
+ GString *gs = gfsm_path_to_gstring(path,NULL,abet_lo,abet_hi,sr,warn_on_undefined,att_style);
+ char *s = gs->str;
+ g_string_free(gs,FALSE);
+ return s;
+}
+
+
+/*======================================================================
+ * Methods: Viterbi trellis: paths
+ */
+
+//--------------------------------------------------------------
+gfsmSet *gfsm_viterbi_trellis_paths_full(gfsmAutomaton *trellis, gfsmSet *paths, gfsmLabelSide which)
+{
+ gfsmArcIter ai;
+
+ //-- sanity check: create path-set if given as NULL
+ if (!paths) {
+ paths = gfsm_set_new_full((GCompareDataFunc)gfsm_path_compare_data,
+ (gpointer)trellis->sr,
+ (GDestroyNotify)gfsm_path_free);
+ }
+
+ //-- get & follow pseudo-root of all paths
+ for (gfsm_arciter_open(&ai, trellis, trellis->root_id); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+ gfsmPath *path = gfsm_path_new(trellis->sr);
+
+ _gfsm_viterbi_trellis_bestpath_r(trellis, path, which, arc->target);
+ path->w = arc->weight;
+
+ //-- reverse the path we've created
+ gfsm_path_reverse(path);
+
+ //-- ... and maybe insert it
+ if (gfsm_set_contains(paths,path)) {
+ //-- oops: we've already got this one: free it
+ gfsm_path_free(path);
+ } else {
+ //-- it's a bona-fide new path: insert it
+ gfsm_set_insert(paths,path);
+ }
+ }
+
+ return paths;
+}
+
+//--------------------------------------------------------------
+gfsmPath *gfsm_viterbi_trellis_bestpath_full(gfsmAutomaton *trellis, gfsmPath *path, gfsmLabelSide which)
+{
+ gfsmArcIter ai;
+
+ //-- sanity check: create path if NULL
+ if (!path) { path = gfsm_path_new(trellis->sr); }
+
+ //-- get & follow pseudo-root of best path
+ gfsm_arciter_open(&ai, trellis, trellis->root_id);
+ if (gfsm_arciter_ok(&ai)) {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+ _gfsm_viterbi_trellis_bestpath_r(trellis, path, which, arc->target);
+ path->w = arc->weight;
+ } else {
+ path->w = trellis->sr->zero;
+ }
+
+ //-- reverse the path we've created
+ gfsm_path_reverse(path);
+
+ return path;
+}
+
+//--------------------------------------------------------------
+void _gfsm_viterbi_trellis_bestpath_r(gfsmAutomaton *trellis,
+ gfsmPath *path,
+ gfsmLabelSide which,
+ gfsmStateId qid)
+{
+ while (TRUE) {
+ gfsmArcIter ai;
+ gfsm_arciter_open(&ai, trellis, qid);
+
+ if (gfsm_arciter_ok(&ai)) {
+ gfsmArc *arc = gfsm_arciter_arc(&ai);
+ gfsm_path_push(path,
+ (which!=gfsmLSUpper ? arc->lower : gfsmEpsilon),
+ (which!=gfsmLSLower ? arc->upper : gfsmEpsilon),
+ trellis->sr->one, trellis->sr);
+ qid = arc->target;
+ }
+ else break;
+ }
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmPaths.h b/gfsm/gfsm/src/libgfsm/gfsmPaths.h
new file mode 100644
index 0000000..27d83cf
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmPaths.h
@@ -0,0 +1,240 @@
+/*=============================================================================*\
+ * File: gfsmPaths.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmPaths.h
+ * \brief Path discovery & enumeration
+ */
+
+#ifndef _GFSM_PATHS_H
+#define _GFSM_PATHS_H
+
+#include <gfsmAutomaton.h>
+
+/*======================================================================
+ * Types: paths
+ */
+
+/// Type for an automaton path
+typedef struct {
+ gfsmLabelVector *lo; /**< lower label sequence */
+ gfsmLabelVector *hi; /**< upper label sequence */
+ gfsmWeight w; /**< weight attached to this path */
+} gfsmPath;
+
+
+
+/*======================================================================
+ * Methods: Path Utilities
+ */
+
+///\name Path Utilities
+//@{
+
+//------------------------------
+/** Copy gfsmLabelVector. \returns \a dst */
+gfsmLabelVector *gfsm_label_vector_copy(gfsmLabelVector *dst, gfsmLabelVector *src);
+
+/** Duplicate a gfsmLabelVector. \returns \a dst */
+#define gfsm_label_vector_dup(src) \
+ gfsm_label_vector_copy(g_ptr_array_sized_new(src->len), src)
+
+/** Reverse a gfsmLabelVector. \returns \a v */
+gfsmLabelVector *gfsm_label_vector_reverse(gfsmLabelVector *v);
+
+//------------------------------
+/** Create and return a new gfsmPath, specifying components
+ * If either of \a lo or \a hi are NULL, a new vector will be created.
+ */
+gfsmPath *gfsm_path_new_full(gfsmLabelVector *lo, gfsmLabelVector *hi, gfsmWeight w);
+
+/** Create and return a new empty gfsmPath, specifying semiring. */
+#define gfsm_path_new(sr) \
+ gfsm_path_new_full(NULL,NULL,gfsm_sr_one(sr))
+
+/** Create and return a new gfsmPath as a copy of an existing gfsmPath */
+gfsmPath *gfsm_path_new_copy(gfsmPath *p1);
+
+/** Create and return a new gfsmPath, appending to an existing path */
+gfsmPath *gfsm_path_new_append(gfsmPath *p1, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight w, gfsmSemiring *sr);
+
+/** Create and return a new gfsmPath as a copy of an existing gfsmPath with weight multiplied by \a w */
+gfsmPath *gfsm_path_new_times_w(gfsmPath *p1, gfsmWeight w, gfsmSemiring *sr);
+
+/** Append an arc to a gfsmPath */
+void gfsm_path_push(gfsmPath *p, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight w, gfsmSemiring *sr);
+
+/** Pop an arc from a gfsmPath */
+void gfsm_path_pop(gfsmPath *p, gfsmLabelVal lo, gfsmLabelVal hi);
+
+/** 3-way path comparison function. */
+gint gfsm_path_compare_data(const gfsmPath *p1, const gfsmPath *p2, gfsmSemiring *sr);
+
+/** Reverse a gfsmPath */
+gfsmPath *gfsm_path_reverse(gfsmPath *p);
+
+/** Destroy a gfsmPath */
+void gfsm_path_free(gfsmPath *p);
+//@}
+
+/*======================================================================
+ * Methods: Automaton Serialization
+ */
+
+///\name Automaton Serialization
+//@{
+
+//------------------------------
+/** Serialize a gfsmAutomaton to a set of (gfsmPath*)s.
+ * Really just a wrapper for gfsm_automaton_paths_full()
+ *
+ * \param fsm Acyclic automaton to be serializd
+ * \param paths output set or NULL
+ *
+ * \returns \a paths if non-NULL, otherwise a new gfsmSet*.
+ */
+gfsmSet *gfsm_automaton_paths(gfsmAutomaton *fsm, gfsmSet *paths);
+
+/** Serialize a gfsmAutomaton to a set of (gfsmPath*)s.
+ *
+ * Causes deep recursion for cyclic automata.
+ * Returns a gfsmSet whose elements are (gfsmPath*)s.
+ * allocated with g_new(). It is the caller's responsibility to free the
+ * returned objects.
+ *
+ * \param fsm Acyclic automaton to be serializd
+ * \param which Which side of arc-labels to serialize
+ * \param paths output set or NULL
+ *
+ * \returns \a paths if non-NULL, otherwise a new gfsmSet*.
+ */
+gfsmSet *gfsm_automaton_paths_full(gfsmAutomaton *fsm, gfsmSet *paths, gfsmLabelSide which);
+
+
+/** Recursive guts for gfsm_automaton_paths() */
+gfsmSet *_gfsm_automaton_paths_r(gfsmAutomaton *fsm,
+ gfsmSet *paths,
+ gfsmLabelSide which,
+ gfsmStateId q,
+ gfsmPath *path);
+
+
+//------------------------------
+/** Convert a gfsmPathSet to a list of (char*)s.
+ * \a abet_lo and \a abet_hi should be (gfsmStringAlphabet*)s.
+ */
+GSList *gfsm_paths_to_strings(gfsmSet *paths,
+ gfsmAlphabet *abet_lo,
+ gfsmAlphabet *abet_hi,
+ gfsmSemiring *sr,
+ gboolean warn_on_undefined,
+ gboolean att_style,
+ GSList *strings);
+
+/** \brief Utility struct for gfsm_paths_to_strings() */
+typedef struct gfsmPathsToStringsOptions_ {
+ gfsmAlphabet *abet_lo; ///< should be a gfsmStringAlphabet*
+ gfsmAlphabet *abet_hi; ///< should be a gfsmStringAlphabet*
+ gfsmSemiring *sr; ///< semiring for weight-based set sorting
+ gboolean warn_on_undefined; ///< warn on undefined symbols?
+ gboolean att_style; ///< use ATT-style output?
+ GSList *strings; ///< output list
+} gfsmPathsToStringsOptions;
+
+/** backwards compatible type alias */
+#define _gfsm_paths_to_strings_options gfsmPathsToStringsOptions_
+
+/** Utility for gfsm_paths_to_strings() */
+gboolean _gfsm_paths_to_strings_foreach_func(gfsmPath *path,
+ gpointer value_dummy,
+ gfsmPathsToStringsOptions *opts);
+
+/** Append string for a single gfsmPath* to a GString,
+ * which may be NULL to allocate a new string.
+ * \returns \a gs if non-NULL, otherwise a new GString*.
+ * \warning it is the caller's responsibility to free the returned GString*.
+ */
+GString *gfsm_path_to_gstring(gfsmPath *path,
+ GString *gs,
+ gfsmAlphabet *abet_lo,
+ gfsmAlphabet *abet_hi,
+ gfsmSemiring *sr,
+ gboolean warn_on_undefined,
+ gboolean att_style);
+
+/** Allocate and return a new string (char*) for a single gfsmPath*.
+ * \returns new (char*) representing \a path.
+ * \warning it is the callers responsibility to free the returned \a char*.
+ */
+char *gfsm_path_to_string(gfsmPath *path,
+ gfsmAlphabet *abet_lo,
+ gfsmAlphabet *abet_hi,
+ gfsmSemiring *sr,
+ gboolean warn_on_undefined,
+ gboolean att_style);
+
+
+//------------------------------
+
+/** Extract upper side of all paths from a Viterbi trellis.
+ *
+ * Returns a gfsmSet whose elements are (gfsmPath*)s.
+ * allocated with g_new(). It is the caller's responsibility to free the
+ * returned objects.
+ *
+ * \returns \a paths if non-NULL, otherwise a new gfsmSet*.
+ */
+#define gfsm_viterbi_trellis_paths(trellis,paths) \
+ gfsm_viterbi_trellis_paths_full((trellis),(paths),gfsmLSUpper)
+
+
+/** Extract all paths from a Viterbi trellis.
+ *
+ * Returns a gfsmSet whose elements are (gfsmPath*)s.
+ * allocated with g_new(). It is the caller's responsibility to free the
+ * returned objects.
+ *
+ * \returns \a paths if non-NULL, otherwise a new gfsmSet*.
+ */
+gfsmSet *gfsm_viterbi_trellis_paths_full(gfsmAutomaton *trellis, gfsmSet *paths, gfsmLabelSide which);
+
+
+/** Extract the upper-side of the best path from a Viterbi trellis.
+ * \returns \a path if non-NULL, otherwise a new gfsmPath*.
+ */
+#define gfsm_viterbi_trellis_bestpath(trellis,path) \
+ gfsm_viterbi_trellis_bestpath_full((trellis),(path),gfsmLSUpper)
+
+/** Extract the best path from a Viterbi trellis.
+ * \returns \a path if non-NULL, otherwise a new gfsmPath*.
+ */
+gfsmPath *gfsm_viterbi_trellis_bestpath_full(gfsmAutomaton *trellis, gfsmPath *path, gfsmLabelSide which);
+
+/** Guts for gfsm_viterbi_trellis_*path*() */
+void _gfsm_viterbi_trellis_bestpath_r(gfsmAutomaton *trellis,
+ gfsmPath *path,
+ gfsmLabelSide which,
+ gfsmStateId qid);
+
+//@}
+
+
+#endif /* _GFSM_PATHS_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmRegex.lex.h b/gfsm/gfsm/src/libgfsm/gfsmRegex.lex.h
new file mode 100644
index 0000000..209d7de
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmRegex.lex.h
@@ -0,0 +1,342 @@
+#ifndef gfsmRegex_yyHEADER_H
+#define gfsmRegex_yyHEADER_H 1
+#define gfsmRegex_yyIN_HEADER 1
+
+#line 6 "gfsmRegex.lex.h"
+
+#line 8 "gfsmRegex.lex.h"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+int gfsmRegex_yylex_init (yyscan_t* scanner);
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void gfsmRegex_yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void gfsmRegex_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE gfsmRegex_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void gfsmRegex_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void gfsmRegex_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void gfsmRegex_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void gfsmRegex_yypop_buffer_state (yyscan_t yyscanner );
+
+YY_BUFFER_STATE gfsmRegex_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE gfsmRegex_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE gfsmRegex_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *gfsmRegex_yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *gfsmRegex_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void gfsmRegex_yyfree (void * ,yyscan_t yyscanner );
+
+/* Begin user sect3 */
+
+#define yytext_ptr yytext_r
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+#define STATE_ESCAPE 1
+#define STATE_BRACKETED 2
+#define STATE_BRACKETED_SEP 3
+#define STATE_BRACKETED_ESCAPE 4
+#define STATE_COMMENT 5
+#define STATE_WEIGHT 6
+#define STATE_UINT 7
+
+#endif
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int gfsmRegex_yylex_destroy (yyscan_t yyscanner );
+
+int gfsmRegex_yyget_debug (yyscan_t yyscanner );
+
+void gfsmRegex_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE gfsmRegex_yyget_extra (yyscan_t yyscanner );
+
+void gfsmRegex_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *gfsmRegex_yyget_in (yyscan_t yyscanner );
+
+void gfsmRegex_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *gfsmRegex_yyget_out (yyscan_t yyscanner );
+
+void gfsmRegex_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+
+int gfsmRegex_yyget_leng (yyscan_t yyscanner );
+
+char *gfsmRegex_yyget_text (yyscan_t yyscanner );
+
+int gfsmRegex_yyget_lineno (yyscan_t yyscanner );
+
+void gfsmRegex_yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * gfsmRegex_yyget_lval (yyscan_t yyscanner );
+
+void gfsmRegex_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int gfsmRegex_yywrap (yyscan_t yyscanner );
+#else
+extern int gfsmRegex_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int gfsmRegex_yylex \
+ (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int gfsmRegex_yylex \
+ (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 195 "gfsmRegex.lex.l"
+
+
+#line 341 "gfsmRegex.lex.h"
+#undef gfsmRegex_yyIN_HEADER
+#endif /* gfsmRegex_yyHEADER_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmRegex.lex.l b/gfsm/gfsm/src/libgfsm/gfsmRegex.lex.l
new file mode 100644
index 0000000..d8b3e95
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmRegex.lex.l
@@ -0,0 +1,201 @@
+/*======================================================================
+ * Flex Options
+ */
+/*%option outfile="gfsmRegex.lex.c"*/
+%option header-file="gfsmRegex.lex.h"
+%option outfile="lex.yy.c"
+%option prefix="gfsmRegex_yy"
+%option reentrant
+%option 8bit
+%option yylineno
+
+%option bison-bridge
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+#include <gfsmMem.h>
+#include <gfsmRegexCompiler.h>
+
+#include "gfsmRegex.tab.h"
+
+#define my_compiler ((gfsmRegexCompiler*)yyextra)
+#define my_gstr (my_compiler->gstr)
+#define my_abet (my_compiler->abet)
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+DIGIT [0-9]
+SPACE [[:space:]]
+WCHAR [^\<\[\\ \t\n\r\#]
+BCHAR [^\\\]\ \t\n\r\=]
+UTF8PREFIX "Ã"
+
+%x STATE_ESCAPE
+%x STATE_BRACKETED
+%x STATE_BRACKETED_SEP
+%x STATE_BRACKETED_ESCAPE
+%x STATE_COMMENT
+%x STATE_WEIGHT
+%x STATE_UINT
+
+/*======================================================================
+ * Rules
+ */
+%%
+
+{UTF8PREFIX}+. {
+ yylval->gs = gfsm_gstring_new_bytes(yytext,yyleng);
+ return TOK_STRING;
+}
+
+"\\" { BEGIN(STATE_ESCAPE); }
+
+"#" { BEGIN(STATE_COMMENT); }
+
+"[" {
+ BEGIN(STATE_BRACKETED);
+ return '[';
+}
+
+"<" { BEGIN(STATE_WEIGHT); return '<'; }
+
+"(" { return '('; }
+")" { return ')'; }
+
+"*" { return '*'; }
+"+" { return '+'; }
+"^" { BEGIN(STATE_UINT); return '|'; }
+"?" { return '?'; }
+"!" { return '!'; }
+"|" { return '|'; }
+"&" { return '&'; }
+":" { return ':'; }
+"@" { return '@'; }
+"-" { return '-'; /*"/1"{return PROJ1;}*/ /*"/2"{return PROJ2;}*/ }
+
+"$" { return '$'; /* non-AT&T: determinize */ }
+"%" { return '%'; /* non-AT&T: rmepsilon */ }
+"~" { return '~'; /* non-AT&T: connect */ }
+
+{SPACE} { /* ignore */ }
+
+{WCHAR} {
+ yylval->c = yytext[0];
+ return TOK_CHAR;
+}
+
+
+
+<STATE_WEIGHT>([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? {
+ yylval->w = strtod(yytext,NULL);
+ return TOK_WEIGHT;
+}
+
+<STATE_WEIGHT>\> {
+ BEGIN(INITIAL);
+ return '>';
+}
+
+
+
+<STATE_UINT>{DIGIT}+ {
+ BEGIN(INITIAL);
+ yylval->u = strtol(yytext,NULL,0);
+ return TOK_UINT;
+}
+
+
+<STATE_COMMENT>[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ }
+
+
+
+
+<STATE_ESCAPE>. {
+ BEGIN(INITIAL);
+ yylval->c = yytext[0];
+ return TOK_CHAR;
+}
+
+
+<STATE_BRACKETED>{UTF8PREFIX}+. {
+ g_string_append_len(my_gstr,yytext,yyleng);
+}
+<STATE_BRACKETED>{SPACE}*"]" {
+ unput(']');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) {
+ yylval->gs = gfsm_gstring_dup(my_gstr);
+ return TOK_STRING;
+ }
+}
+<STATE_BRACKETED>{BCHAR}+ {
+ g_string_append(my_gstr, yytext);
+}
+<STATE_BRACKETED>({SPACE}*)"="({SPACE}*) {
+ unput('=');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) {
+ yylval->gs = gfsm_gstring_dup(my_gstr);
+ return TOK_STRING;
+ }
+}
+<STATE_BRACKETED>{SPACE}+ {
+ unput(' ');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) {
+ yylval->gs = gfsm_gstring_dup(my_gstr);
+ return TOK_STRING;
+ }
+}
+<STATE_BRACKETED>\\ {
+ BEGIN(STATE_BRACKETED_ESCAPE);
+}
+
+
+<STATE_BRACKETED_SEP>"]" {
+ BEGIN(INITIAL);
+ if (my_gstr->len) {
+ g_string_truncate(my_gstr,0);
+ return ']';
+ }
+}
+<STATE_BRACKETED_SEP>"=" {
+ BEGIN(STATE_BRACKETED);
+ g_string_truncate(my_gstr,0);
+ return '=';
+}
+<STATE_BRACKETED_SEP>" " {
+ BEGIN(STATE_BRACKETED);
+ if (my_gstr->len) {
+ g_string_truncate(my_gstr,0);
+ return ' ';
+ }
+}
+
+
+<STATE_BRACKETED_ESCAPE>. {
+ BEGIN(STATE_BRACKETED);
+ g_string_append_c(my_gstr, yytext[0]);
+}
+
+
+
+<*>. {
+ gfsm_scanner_carp(yyextra, "bad character '%s'", yytext);
+ return TOK_UNKNOWN;
+}
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+GFSM_SCANNER_YYWRAP(gfsmRegex_yy)
diff --git a/gfsm/gfsm/src/libgfsm/gfsmRegex.tab.h b/gfsm/gfsm/src/libgfsm/gfsmRegex.tab.h
new file mode 100644
index 0000000..deebb3e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmRegex.tab.h
@@ -0,0 +1,84 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ TOK_UNKNOWN = 258,
+ TOK_CHAR = 259,
+ TOK_UINT = 260,
+ TOK_STRING = 261,
+ TOK_WEIGHT = 262,
+ CONCAT = 263,
+ LABCONCAT = 264,
+ WEIGHT = 265
+ };
+#endif
+/* Tokens. */
+#define TOK_UNKNOWN 258
+#define TOK_CHAR 259
+#define TOK_UINT 260
+#define TOK_STRING 261
+#define TOK_WEIGHT 262
+#define CONCAT 263
+#define LABCONCAT 264
+#define WEIGHT 265
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 31 "gfsmRegex.tab.y"
+{
+ gfsmAutomaton *fsm; //-- automaton
+ GString *gs; //-- needs to be freed by hand
+ gchar c;
+ guint32 u;
+ gfsmWeight w;
+}
+/* Line 1489 of yacc.c. */
+#line 77 "gfsmRegex.tab.h"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmRegex.tab.y b/gfsm/gfsm/src/libgfsm/gfsmRegex.tab.y
new file mode 100644
index 0000000..5bbb4aa
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmRegex.tab.y
@@ -0,0 +1,149 @@
+/*======================================================================
+ * Bison Options
+ */
+%pure_parser
+
+%{
+/*======================================================================
+ * Bison C Header
+ */
+#include <gfsmRegexCompiler.h>
+#include <gfsmAutomatonIO.h>
+#include <string.h>
+
+#include "gfsmRegex.tab.h"
+#include "gfsmRegex.lex.h"
+
+#define my_compiler ((gfsmRegexCompiler*)reparser)
+
+#define YYLEX_PARAM ((gfsmRegexCompiler*)reparser)->scanner.yyscanner
+#define YYPARSE_PARAM reparser
+
+#define YYERROR_VERBOSE 1
+#define gfsmRegex_yyerror(msg) \
+ gfsm_scanner_carp((gfsmScanner*)reparser, (msg));
+
+%}
+
+/*======================================================================
+ * Bison Definitions
+ */
+%union {
+ gfsmAutomaton *fsm; //-- automaton
+ GString *gs; //-- needs to be freed by hand
+ gchar c;
+ guint32 u;
+ gfsmWeight w;
+}
+
+%token <c> TOK_UNKNOWN TOK_CHAR
+%token <u> TOK_UINT
+%token <gs> TOK_STRING
+%token <w> TOK_WEIGHT
+
+%type <u> label
+%type <w> weight
+%type <fsm> regex
+
+/*
+empty { $$=gfsm_regex_automaton_epsilon(my_compiler); }
+*/
+
+/*
+ | gfsmRETChar %prec LAB
+ { $$=gfsm_regex_automaton_lab(my_compiler, $1); }
+*/
+
+// -- Operator precedence and associativity
+%left CONCAT
+%left LABCONCAT
+%left WEIGHT
+%right '%' //-- non-AT&T: rmepsilon: % REGEX
+%right '$' //-- non-AT&T: determinize: $ REGEX
+%right '~' //-- non-AT&T: connect: ~ REGEX
+%left '*' '+' '?' '^'
+%right '!'
+%left '@'
+%left ':'
+%left '-'
+%left '&'
+%left '|'
+
+/*======================================================================
+ * Bison Rules
+ */
+%%
+
+regex: '('regex ')'
+ { $$=$2; }
+
+ | label
+ { $$=gfsm_regex_compiler_label_fsm(my_compiler, $1); }
+
+ | label regex %prec LABCONCAT
+ { $$=gfsm_regex_compiler_prepend_lab(my_compiler, $1, $2); }
+
+ | regex regex %prec CONCAT
+ { $$=gfsm_regex_compiler_concat(my_compiler, $1, $2); }
+
+ | '%' regex
+ { $$=gfsm_regex_compiler_rmepsilon(my_compiler, $2); /* non-ATT */ }
+
+ | '$' regex
+ { $$=gfsm_regex_compiler_determinize(my_compiler, $2); /* non-ATT */ }
+
+ | '~' regex
+ { $$=gfsm_regex_compiler_connect(my_compiler, $2); /* non-ATT */ }
+
+ | regex '*'
+ { $$=gfsm_regex_compiler_closure(my_compiler,$1,FALSE); }
+
+ | regex '+'
+ { $$=gfsm_regex_compiler_closure(my_compiler,$1,TRUE); }
+
+ | regex '^' TOK_UINT
+ { $$=gfsm_regex_compiler_power(my_compiler,$1,$3); }
+
+ | regex '?'
+ { $$=gfsm_regex_compiler_optional(my_compiler,$1); }
+
+ | '!' regex
+ { $$=gfsm_regex_compiler_complement(my_compiler,$2); }
+
+ | regex '|' regex
+ { $$=gfsm_regex_compiler_union(my_compiler,$1,$3); }
+
+ | regex '&' regex
+ { $$=gfsm_regex_compiler_intersect(my_compiler,$1,$3); }
+
+ | regex ':' regex
+ { $$=gfsm_regex_compiler_product(my_compiler,$1,$3); }
+
+ | regex '@' regex
+ { $$=gfsm_regex_compiler_compose(my_compiler,$1,$3); }
+
+ | regex '-' regex
+ { $$=gfsm_regex_compiler_difference(my_compiler,$1,$3); }
+
+ | regex weight %prec WEIGHT
+ { $$=gfsm_regex_compiler_weight(my_compiler,$1,$2); }
+ ;
+
+label: TOK_CHAR
+ { $$=gfsm_regex_compiler_char2label(my_compiler, $1); }
+
+ | TOK_STRING
+ { $$=gfsm_regex_compiler_gstring2label(my_compiler, $1); }
+
+ | '[' TOK_STRING ']'
+ { $$=gfsm_regex_compiler_gstring2label(my_compiler, $2); }
+ ;
+
+weight: '<' TOK_WEIGHT '>' { $$=$2; }
+ ;
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.c b/gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.c
new file mode 100644
index 0000000..c25ba2d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.c
@@ -0,0 +1,315 @@
+
+/*=============================================================================*\
+ * File: gfsmRegexCompiler.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmRegexCompiler.h>
+#include <gfsmArith.h>
+#include <gfsmUtils.h>
+
+#include "gfsmRegex.tab.h"
+#include "gfsmRegex.lex.h"
+
+extern int gfsmRegex_yyparse(gfsmRegexCompiler *rec);
+
+/*======================================================================
+ * Regex Compiler: Constructors etc.
+ */
+
+//--------------------------------------------------------------
+gfsmRegexCompiler *gfsm_regex_compiler_new_full(const gchar *name,
+ gfsmAlphabet *abet,
+ gfsmSRType srtype,
+ gboolean emit_warnings)
+{
+ gfsmRegexCompiler *rec = g_new0(gfsmRegexCompiler,1);
+ char *myname = (name ? ((char*)name) : "gfsmRegexCompiler");
+ gfsm_scanner_init(&(rec->scanner), myname, gfsmRegex_yy);
+ rec->fsm = NULL;
+ rec->abet = abet;
+ rec->srtype = srtype;
+ rec->scanner.emit_warnings = emit_warnings;
+ rec->gstr = g_string_new("");
+ return rec;
+}
+
+//--------------------------------------------------------------
+void gfsm_regex_compiler_free(gfsmRegexCompiler *rec, gboolean free_alphabet, gboolean free_automaton)
+{
+ if (free_alphabet && rec->abet) gfsm_alphabet_free(rec->abet);
+ if (free_automaton && rec->fsm) gfsm_automaton_free(rec->fsm);
+ g_string_free(rec->gstr,TRUE);
+ gfsm_scanner_free(&(rec->scanner)); //-- ought to free the rest
+}
+
+//--------------------------------------------------------------
+void gfsm_regex_compiler_reset(gfsmRegexCompiler *rec, gboolean free_automaton)
+{
+ if (free_automaton && rec->fsm) gfsm_automaton_free(rec->fsm);
+ g_string_truncate(rec->gstr,0);
+ rec->fsm = NULL;
+ g_clear_error(&(rec->scanner.err));
+}
+
+/*======================================================================
+ * Regex Compiler: Methods
+ */
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_parse(gfsmRegexCompiler *rec)
+{
+ gfsmRegex_yyparse(rec);
+ if (rec->scanner.err) {
+ if (rec->fsm) gfsm_automaton_free(rec->fsm);
+ rec->fsm = NULL;
+ }
+ return rec->fsm;
+}
+
+
+
+/*======================================================================
+ * Regex Compiler: Alphabet Utilities
+ */
+
+//--------------------------------------------------------------
+gfsmLabelVal gfsm_regex_compiler_char2label(gfsmRegexCompiler *rec, gchar c)
+{
+ gchar cs[2] = {c,'\0'};
+ gfsmLabelVal lab = gfsm_alphabet_find_label(rec->abet, cs);
+ if (lab==gfsmNoLabel) {
+ gfsm_scanner_carp(&(rec->scanner),
+ "Warning: no label for character '%c' in alphabet: using gfsmNoLabel", c);
+ g_clear_error(&(rec->scanner.err));
+ }
+ return lab;
+}
+
+//--------------------------------------------------------------
+gfsmLabelVal gfsm_regex_compiler_gstring2label(gfsmRegexCompiler *rec, GString *gs)
+{
+ gfsmLabelVal lab = gfsm_alphabet_find_label(rec->abet, gs->str);
+ if (lab==gfsmNoLabel) {
+ gfsm_scanner_carp(&(rec->scanner),
+ "Warning: no label for string '%s' in alphabet: using gfsmNoLabel", gs->str);
+ g_clear_error(&(rec->scanner.err));
+ }
+ g_string_free(gs,TRUE);
+ return lab;
+}
+
+
+/*======================================================================
+ * Regex Compiler: Automaton Utilities
+ */
+#define RETURN(rec,_fsm) (rec)->fsm=(_fsm); return (_fsm);
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_new_fsm(gfsmRegexCompiler *rec)
+{
+ gfsmAutomaton *fsm = gfsm_automaton_new_full(gfsmAutomatonDefaultFlags,
+ rec->srtype,
+ gfsmAutomatonDefaultSize);
+ fsm->flags.is_transducer = FALSE;
+ return fsm;
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_epsilon_fsm(gfsmRegexCompiler *rec)
+{
+ gfsmAutomaton *fsm = gfsm_regex_compiler_new_fsm(rec);
+ fsm->root_id = gfsm_automaton_add_state(fsm);
+ gfsm_automaton_set_final_state(fsm,fsm->root_id,TRUE);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_label_fsm(gfsmRegexCompiler *rec, gfsmLabelVal lab)
+{
+ gfsmAutomaton *fsm = gfsm_regex_compiler_new_fsm(rec);
+ gfsmStateId labid;
+ fsm->root_id = gfsm_automaton_add_state(fsm);
+ labid = gfsm_automaton_add_state(fsm);
+ gfsm_automaton_add_arc(fsm, fsm->root_id, labid, lab, lab, fsm->sr->one);
+ gfsm_automaton_set_final_state(fsm,labid,TRUE);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_concat(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2)
+{
+ gfsm_automaton_concat(fsm1, fsm2);
+ gfsm_automaton_free(fsm2);
+ RETURN(rec,fsm1);
+}
+
+
+//--------------------------------------------------------------
+struct gfsm_regex_append_lab_data_ {
+ gfsmAutomaton *fsm;
+ gfsmLabelVal lab;
+ gfsmStateId newid;
+};
+
+gboolean _gfsm_regex_append_lab_foreach_func(gfsmStateId qid, gpointer pw,
+ struct gfsm_regex_append_lab_data_ *data)
+{
+ gfsm_automaton_get_state(data->fsm,qid)->is_final = FALSE;
+ gfsm_automaton_add_arc(data->fsm, qid, data->newid, data->lab, data->lab, gfsm_ptr2weight(pw));
+ return FALSE;
+}
+
+gfsmAutomaton *gfsm_regex_compiler_append_lab(gfsmRegexCompiler *rec, gfsmAutomaton *fsm, gfsmLabelVal lab)
+{
+ struct gfsm_regex_append_lab_data_ data = { fsm, lab, gfsm_automaton_add_state(fsm) };
+ gfsm_weightmap_foreach(fsm->finals,
+ (GTraverseFunc)_gfsm_regex_append_lab_foreach_func,
+ &data);
+ gfsm_weightmap_clear(fsm->finals);
+ gfsm_automaton_set_final_state(fsm, data.newid, TRUE);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_prepend_lab(gfsmRegexCompiler *rec, gfsmLabelVal lab, gfsmAutomaton *fsm)
+{
+ gfsmStateId qid = gfsm_automaton_add_state(fsm);
+ gfsm_automaton_add_arc(fsm, qid, fsm->root_id, lab, lab, fsm->sr->one);
+ fsm->root_id = qid;
+ RETURN(rec,fsm);
+}
+
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_closure(gfsmRegexCompiler *rec, gfsmAutomaton *fsm, gboolean is_plus)
+{
+ gfsm_automaton_closure(fsm,is_plus);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_power(gfsmRegexCompiler *rec, gfsmAutomaton *fsm, guint32 n)
+{
+ gfsm_automaton_n_closure(fsm,n);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_project(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm,
+ gfsmLabelSide which)
+{
+ gfsm_automaton_project(fsm,which);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_optional(gfsmRegexCompiler *rec, gfsmAutomaton *fsm)
+{
+ gfsm_automaton_optional(fsm);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_complement(gfsmRegexCompiler *rec, gfsmAutomaton *fsm)
+{
+ gfsm_automaton_complement_full(fsm,rec->abet);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_union(gfsmRegexCompiler *rec, gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsm_automaton_union(fsm1,fsm2);
+ gfsm_automaton_free(fsm2);
+ RETURN(rec,fsm1);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_intersect(gfsmRegexCompiler *rec, gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsm_automaton_intersect(fsm1,fsm2);
+ gfsm_automaton_free(fsm2);
+ RETURN(rec,fsm1);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_product(gfsmRegexCompiler *rec, gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsm_automaton_product2(fsm1,fsm2);
+ gfsm_automaton_free(fsm2);
+ RETURN(rec,fsm1);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_compose(gfsmRegexCompiler *rec, gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsm_automaton_compose(fsm1,fsm2);
+ gfsm_automaton_free(fsm2);
+ RETURN(rec,fsm1);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_difference(gfsmRegexCompiler *rec, gfsmAutomaton *fsm1, gfsmAutomaton *fsm2)
+{
+ gfsm_automaton_difference(fsm1,fsm2);
+ gfsm_automaton_free(fsm2);
+ RETURN(rec,fsm1);
+}
+
+//--------------------------------------------------------------
+/** Weight */
+gfsmAutomaton *gfsm_regex_compiler_weight(gfsmRegexCompiler *rec, gfsmAutomaton *fsm, gfsmWeight w)
+{
+ gfsm_automaton_arith_final(fsm, gfsmAOSRTimes, w, FALSE);
+ RETURN(rec,fsm);
+}
+
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_rmepsilon(gfsmRegexCompiler *rec, gfsmAutomaton *fsm)
+{
+ gfsm_automaton_rmepsilon(fsm);
+ //gfsm_automaton_connect(fsm);
+ //gfsm_automaton_renumber_states(fsm);
+ RETURN(rec,fsm);
+}
+
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_determinize(gfsmRegexCompiler *rec, gfsmAutomaton *fsm)
+{
+ gfsm_automaton_determinize(fsm);
+ RETURN(rec,fsm);
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_compiler_connect(gfsmRegexCompiler *rec, gfsmAutomaton *fsm)
+{
+ gfsm_automaton_connect(fsm);
+ gfsm_automaton_renumber_states(fsm);
+ RETURN(rec,fsm);
+}
+
+#undef RETURN
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.h b/gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.h
new file mode 100644
index 0000000..f88c6fc
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.h
@@ -0,0 +1,223 @@
+
+/*=============================================================================*\
+ * File: gfsmRegexCompiler.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmRegexCompiler.h
+ * \brief Regular expression compiler
+ *
+ * \file gfsmRegex.lex.h
+ * \brief flex-generated lexer headers for gfsmRegexCompiler
+ *
+ * \file gfsmRegex.tab.h
+ * \brief bison-generated parser headers for gfsmRegexCompiler
+ *
+ * \union YYSTYPE
+ * \brief bison-generated parser rule-value union
+ *
+ * \struct yy_buffer_state
+ * \brief flex-generated lexer input buffer state struct
+ */
+
+#ifndef _GFSM_REGEX_COMPILER_H
+#define _GFSM_REGEX_COMPILER_H
+
+#include <gfsmScanner.h>
+#include <gfsmAlgebra.h>
+
+/*======================================================================
+ * Types
+ */
+
+/** \brief Type for a regular expression compiler */
+typedef struct {
+ gfsmScanner scanner; ///< underlying scanner
+ gfsmSRType srtype; ///< semiring type
+ gfsmAutomaton *fsm; ///< regex automaton under construction
+ gfsmAlphabet *abet; ///< alphabet
+ GString *gstr; ///< string buffer
+} gfsmRegexCompiler;
+
+/*======================================================================
+ * Regex Compiler: Constructors etc.
+ */
+///\name Regex Compiler: Constructors etc.
+//@{
+
+/** Create and return a new gfsmRegexCompiler */
+gfsmRegexCompiler *gfsm_regex_compiler_new_full(const gchar *name,
+ gfsmAlphabet *abet,
+ gfsmSRType srtype,
+ gboolean emit_warnings);
+
+/** Create and return a new gfsmRegexCompiler, no alphabet */
+#define gfsm_regex_compiler_new() \
+ gfsm_regex_compiler_new_full("gfsmRegexCompiler", NULL, gfsmAutomatonDefaultSRType, TRUE);
+
+/** Destroy a gfsmRegexCompiler.
+ * \param free_automaton whether to free the stored alphabet, if present
+ * \param free_automaton whether to free the parsed automaton, if present
+ */
+void gfsm_regex_compiler_free(gfsmRegexCompiler *rec, gboolean free_alphabet, gboolean free_automaton);
+
+/** Reset regex compiler; possibly freeing associated automaton */
+void gfsm_regex_compiler_reset(gfsmRegexCompiler *rec, gboolean free_automaton);
+
+//@}
+
+/*======================================================================
+ * Regex Compiler: Methods
+ */
+//@{
+
+/**
+ * Parse an automaton from the currently selected input source.
+ * \returns parsed automaton, or \a NULL on error
+ */
+gfsmAutomaton *gfsm_regex_compiler_parse(gfsmRegexCompiler *rec);
+
+//@}
+
+/*======================================================================
+ * Regex Compiler: Alphabet Utilities
+ */
+///\name Regex Compiler: Alphabet Utilities
+//@{
+
+/** Get a label value for a single character */
+gfsmLabelVal gfsm_regex_compiler_char2label(gfsmRegexCompiler *rec, gchar c);
+
+/** Get a label value for a GString* (implicitly frees \a gs) */
+gfsmLabelVal gfsm_regex_compiler_gstring2label(gfsmRegexCompiler *rec, GString *gs);
+
+//@}
+
+/*======================================================================
+ * Regex Compiler: Automaton Utilities
+ */
+///\name Regex Compiler: Automaton Utilities
+//@{
+
+//--------------------------------------------------------------
+/** New full-fleded automaton */
+gfsmAutomaton *gfsm_regex_compiler_new_fsm(gfsmRegexCompiler *rec);
+
+/** New Epsilon recognizer */
+gfsmAutomaton *gfsm_regex_compiler_epsilon_fsm(gfsmRegexCompiler *rec);
+
+/** New single-character recognizer */
+gfsmAutomaton *gfsm_regex_compiler_label_fsm(gfsmRegexCompiler *rec, gfsmLabelVal lab);
+
+
+//--------------------------------------------------------------
+/** Single-label concatenation: (low-level): append */
+gfsmAutomaton *gfsm_regex_compiler_append_lab(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm,
+ gfsmLabelVal lab);
+
+/** Single-label concatenation (low-level): prepend */
+gfsmAutomaton *gfsm_regex_compiler_prepend_lab(gfsmRegexCompiler *rec,
+ gfsmLabelVal lab,
+ gfsmAutomaton *fsm);
+
+/** General concatenation */
+gfsmAutomaton *gfsm_regex_compiler_concat(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2);
+
+//--------------------------------------------------------------
+/** Closure */
+gfsmAutomaton *gfsm_regex_compiler_closure(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm,
+ gboolean is_plus);
+
+/** Power (n-ary closure) */
+gfsmAutomaton *gfsm_regex_compiler_power(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm,
+ guint32 n);
+
+/** Optionality */
+gfsmAutomaton *gfsm_regex_compiler_optional(gfsmRegexCompiler *rec, gfsmAutomaton *fsm);
+
+//--------------------------------------------------------------
+/** Projection */
+gfsmAutomaton *gfsm_regex_compiler_project(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm,
+ gfsmLabelSide which);
+
+//--------------------------------------------------------------
+/** Complement */
+gfsmAutomaton *gfsm_regex_compiler_complement(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm);
+
+//--------------------------------------------------------------
+/** Union */
+gfsmAutomaton *gfsm_regex_compiler_union(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2);
+
+//--------------------------------------------------------------
+/** Intersection */
+gfsmAutomaton *gfsm_regex_compiler_intersect(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2);
+
+//--------------------------------------------------------------
+/** Product */
+gfsmAutomaton *gfsm_regex_compiler_product(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2);
+
+//--------------------------------------------------------------
+/** Composition */
+gfsmAutomaton *gfsm_regex_compiler_compose(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2);
+
+//--------------------------------------------------------------
+/** Difference */
+gfsmAutomaton *gfsm_regex_compiler_difference(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmAutomaton *fsm2);
+
+//--------------------------------------------------------------
+/** Weight (final) */
+gfsmAutomaton *gfsm_regex_compiler_weight(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm1,
+ gfsmWeight w);
+
+//--------------------------------------------------------------
+/** Remove epsilons */
+gfsmAutomaton *gfsm_regex_compiler_rmepsilon(gfsmRegexCompiler *rec, gfsmAutomaton *fsm);
+
+
+//--------------------------------------------------------------
+/** Determinize */
+gfsmAutomaton *gfsm_regex_compiler_determinize(gfsmRegexCompiler *rec, gfsmAutomaton *fsm);
+
+//--------------------------------------------------------------
+/** Connect */
+gfsmAutomaton *gfsm_regex_compiler_connect(gfsmRegexCompiler *rec, gfsmAutomaton *fsm);
+
+//@}
+
+
+#endif /* _GFSM_REGEX_COMPILER_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmScanner.c b/gfsm/gfsm/src/libgfsm/gfsmScanner.c
new file mode 100644
index 0000000..afa2632
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmScanner.c
@@ -0,0 +1,246 @@
+
+/*=============================================================================*\
+ * File: gfsmScanner.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmScanner.h>
+#include <gfsmUtils.h>
+#include <string.h>
+
+/*======================================================================
+ * Constants
+ */
+const char *gfsmScannerDefaultName = "gfsmScanner";
+
+const char *gfsmScannerDefaultFilename = "input";
+
+/*======================================================================
+ * gfsmScanner: Constructors etc.
+ */
+
+//--------------------------------------------------------------
+gfsmScanner *gfsm_scanner_new_full(const char *name,
+ gfsmFlexScannerInitFunc yyinit_func,
+ gfsmFlexScannerFreeFunc yyfree_func,
+ gfsmFlexScannerScanFileFunc yyscan_file_func,
+ gfsmFlexScannerScanBytesFunc yyscan_bytes_func,
+ gfsmFlexScannerScanPopFunc yyscan_pop_func,
+ gfsmFlexScannerGetTextFunc yyget_text_func,
+ gfsmFlexScannerGetPosFunc yyget_lineno_func,
+ gfsmFlexScannerSetPosFunc yyset_lineno_func,
+ gfsmFlexScannerSetExtraFunc yyset_extra_func)
+{
+ return gfsm_scanner_init_full(g_new0(gfsmScanner,1),
+ name,
+ yyinit_func,
+ yyfree_func,
+ yyscan_file_func,
+ yyscan_bytes_func,
+ yyscan_pop_func,
+ yyget_text_func,
+ yyget_lineno_func,
+ yyset_lineno_func,
+ yyset_extra_func);
+}
+
+//--------------------------------------------------------------
+gfsmScanner *gfsm_scanner_init_full(gfsmScanner *scanner,
+ const char *name,
+ gfsmFlexScannerInitFunc yyinit_func,
+ gfsmFlexScannerFreeFunc yyfree_func,
+ gfsmFlexScannerScanFileFunc yyscan_file_func,
+ gfsmFlexScannerScanBytesFunc yyscan_bytes_func,
+ gfsmFlexScannerScanPopFunc yyscan_pop_func,
+ gfsmFlexScannerGetTextFunc yyget_text_func,
+ gfsmFlexScannerGetPosFunc yyget_lineno_func,
+ gfsmFlexScannerSetPosFunc yyset_lineno_func,
+ gfsmFlexScannerSetExtraFunc yyset_extra_func)
+{
+ scanner->data = NULL;
+ scanner->name = (char *)name;
+ scanner->filename = NULL;
+ scanner->err = NULL;
+
+ //-- funcs: init, free
+ scanner->yyfree_func = yyfree_func;
+
+ //-- data & funcs: buffer switching
+ scanner->infile = NULL;
+ scanner->yyscan_file_func = yyscan_file_func;
+ scanner->yyscan_bytes_func = yyscan_bytes_func;
+ scanner->yyscan_pop_func = yyscan_pop_func;
+
+ //-- funcs: text
+ scanner->yyget_text_func = yyget_text_func;
+
+ //-- funcs: position
+ scanner->yyget_lineno_func = yyget_lineno_func;
+ scanner->yyset_lineno_func = yyset_lineno_func;
+
+ //-- initialize underlying scanner
+ if (yyinit_func) (*yyinit_func)(&(scanner->yyscanner));
+
+ //-- set extra data
+ if (yyset_extra_func) (*yyset_extra_func)(scanner, scanner->yyscanner);
+
+ return scanner;
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_free(gfsmScanner *scanner)
+{
+ gfsm_scanner_close(scanner);
+ if (scanner->yyfree_func) (*(scanner->yyfree_func))(scanner->yyscanner);
+ g_clear_error(&(scanner->err));
+ g_free(scanner);
+}
+
+
+/*======================================================================
+ * gfsmScanner: I/O Selection
+ */
+
+//--------------------------------------------------------------
+void gfsm_scanner_close(gfsmScanner *scanner)
+{
+ (*(scanner->yyscan_pop_func))(scanner->yyscanner);
+ if (scanner->infile) {
+ fclose(scanner->infile);
+ scanner->infile = NULL;
+ }
+ if (scanner->filename) {
+ g_free(scanner->filename);
+ scanner->filename = NULL;
+ }
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_scan_file(gfsmScanner *scanner, FILE *f)
+{
+ gfsm_scanner_close(scanner);
+ (*(scanner->yyscan_file_func))(f, scanner->yyscanner);
+ (*(scanner->yyset_lineno_func))(1, scanner->yyscanner);
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_scan_filename(gfsmScanner *scanner, const char *filename)
+{
+ g_clear_error(&(scanner->err));
+ FILE *f = gfsm_open_filename(filename, "r", &(scanner->err));
+ gfsm_scanner_scan_file(scanner,f);
+ scanner->filename = g_strdup(filename);
+ scanner->infile = f;
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_scan_bytes(gfsmScanner *scanner, const char *bytes, int len)
+{
+ gfsm_scanner_close(scanner);
+ (*(scanner->yyscan_bytes_func))(bytes, len, scanner->yyscanner);
+ (*(scanner->yyset_lineno_func))(1, scanner->yyscanner);
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_scan_gstring(gfsmScanner *scanner, GString *gstr)
+{
+ gfsm_scanner_scan_bytes(scanner, gstr->str, gstr->len);
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_scan_string(gfsmScanner *scanner, const char *str)
+{
+ gfsm_scanner_scan_bytes(scanner, str, strlen(str));
+}
+
+
+
+/*======================================================================
+ * gfsmScanner: Flex utilities
+ */
+
+//--------------------------------------------------------------
+int gfsm_scanner_yywrap(gfsmScanner *scanner)
+{ return 1; }
+
+
+/*======================================================================
+ * gfsmScanner: error reporting
+ */
+
+//--------------------------------------------------------------
+void gfsm_scanner_carp(gfsmScanner *scanner, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap,fmt);
+ gfsm_scanner_carp_full_v(scanner,
+ g_quark_from_static_string("gfsm"),
+ g_quark_from_static_string("scanner_error"),
+ fmt, ap);
+ va_end(ap);
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_carp_full(gfsmScanner *scanner,
+ GQuark domain,
+ gint code,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start(ap,fmt);
+ gfsm_scanner_carp_full_v(scanner,domain,code,fmt,ap);
+ va_end(ap);
+}
+
+//--------------------------------------------------------------
+void gfsm_scanner_carp_full_v(gfsmScanner *scanner,
+ GQuark domain,
+ gint code,
+ const char *fmt,
+ va_list ap)
+{
+ char *msg = g_strdup_vprintf(fmt, ap);
+
+ if (scanner->err) {
+ g_error_free(scanner->err);
+ scanner->err = NULL;
+ }
+
+ g_set_error(&(scanner->err), domain, code,
+ "%s: %s in %s%s%s at line %u%s%s%s",
+ (scanner->name ? scanner->name : gfsmScannerDefaultName),
+ msg,
+ (scanner->filename ? "file \"" : ""),
+ (scanner->filename ? scanner->filename : gfsmScannerDefaultFilename),
+ (scanner->filename ? "\"" : ""),
+ (scanner->yyget_lineno_func ? (*(scanner->yyget_lineno_func))(scanner->yyscanner) : 0),
+ //--
+ (scanner->yyget_text_func ? ", near \"" : ""),
+ (scanner->yyget_text_func ? (*(scanner->yyget_text_func))(scanner->yyscanner) : ""),
+ (scanner->yyget_text_func ? "\"" : "")
+ );
+
+ if (scanner->emit_warnings) {
+ fprintf(stderr, "%s\n", scanner->err->message);
+ }
+
+ g_free(msg);
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmScanner.h b/gfsm/gfsm/src/libgfsm/gfsmScanner.h
new file mode 100644
index 0000000..d587486
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmScanner.h
@@ -0,0 +1,262 @@
+/*=============================================================================*\
+ * File: gfsmScanner.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmScanner.h
+ * \brief flex scanner utilities
+ */
+
+#ifndef _GFSM_SCANNER_H
+#define _GFSM_SCANNER_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <gfsmError.h>
+
+/*======================================================================
+ * Types
+ */
+
+//------------------------------------------------------
+/// Opaque type for generic flex lexers
+typedef void* gfsmFlexScanner;
+
+//------------------------------------------------------
+/// Opaque type for generic flex lexer buffers
+typedef void* gfsmFlexBufferState;
+
+//------------------------------------------------------
+/// typedef for flex scanner init() functions
+typedef int (*gfsmFlexScannerInitFunc) (gfsmFlexScanner yyscanner);
+
+/// typedef for flex scanner destroy() functions
+typedef int (*gfsmFlexScannerFreeFunc) (gfsmFlexScanner yyscanner);
+
+//------------------------------------------------------
+/// typedef for flex scanner lineno() and column() accessors
+typedef int (*gfsmFlexScannerGetPosFunc) (gfsmFlexScanner yyscanner);
+
+/// typedef for flex scanner lineno() and column() manipulators
+typedef void (*gfsmFlexScannerSetPosFunc) (int pos, gfsmFlexScanner yyscanner);
+
+//------------------------------------------------------
+/// typedef for flex scanner set_extra() function
+typedef void (*gfsmFlexScannerSetExtraFunc) (void *extra, gfsmFlexScanner yyscanner);
+
+/// typedef for flex scanner get_extra() function
+typedef void* (*gfsmFlexScannerGetExtraFunc) (gfsmFlexScanner yyscanner);
+
+//------------------------------------------------------
+/// typedef for flex scanner get_text() function
+typedef char* (*gfsmFlexScannerGetTextFunc) (gfsmFlexScanner yyscanner);
+
+//------------------------------------------------------
+/// typedef for flex scanner restart() function
+typedef void (*gfsmFlexScannerScanFileFunc) (FILE *in, gfsmFlexScanner yyscanner);
+
+/// typedef for flex scanner scan_bytes() function
+typedef void (*gfsmFlexScannerScanBytesFunc) (const char *str, int len, gfsmFlexScanner yyscanner);
+
+/// typedef for flex scanner pop_buffer_state() function
+typedef void (*gfsmFlexScannerScanPopFunc) (gfsmFlexScanner yyscanner);
+
+
+//------------------------------------------------------
+
+/** \brief Extra data struct for generic flex scanners.
+ * \detail To use, add the line
+ * \code #define YY_EXTRA_TYPE gfsmScannerExtra*
+ * to scanner.l
+ */
+typedef struct {
+ gfsmFlexScanner yyscanner; ///< underlying flex scanner
+ void *data; ///< user data
+ char *name; ///< name of this scanner, for errors & warnings; may be NULL
+ FILE *infile; ///< current input file if we opened it ourselves, else NULL
+ char *filename; ///< name of input file or NULL
+ gfsmError *err; ///< Holds scanner error if something goes wrong
+ gboolean emit_warnings; ///< write warnings to stderr
+
+ //-- funcs: init, free
+ gfsmFlexScannerFreeFunc yyfree_func; ///< ${PREFIX}lex_destroy(yyscanner)
+
+ //-- funcs & data: buffer switching
+ gfsmFlexScannerScanFileFunc yyscan_file_func; ///< ${PREFIX}restart(FILE*,yyscanner)
+ gfsmFlexScannerScanBytesFunc yyscan_bytes_func; ///< ${PREFIX}_scan_bytes(bytes,len,yyscanner)
+ gfsmFlexScannerScanPopFunc yyscan_pop_func; ///< ${PREFIX}pop_buffer_state(yyscanner)
+
+ //-- funcs: text
+ gfsmFlexScannerGetTextFunc yyget_text_func; ///< ${PREFIX}get_text(yyscanner)
+
+ //-- funcs: position
+ gfsmFlexScannerGetPosFunc yyget_lineno_func; ///< ${PREFIX}get_lineno(yyscanner)
+ gfsmFlexScannerSetPosFunc yyset_lineno_func; ///< ${PREFIX}set_lineno(yyscanner)
+
+ //-- funcs: extra data
+ gfsmFlexScannerSetExtraFunc yyset_extra_func; ///< ${PREFIX}get_extra(yyscanner)
+
+} gfsmScanner;
+
+
+/*======================================================================
+ * Constants
+ */
+/** Default scanner name */
+extern const char *gfsmScannerDefaultName;
+
+/** Default scanner filename */
+extern const char *gfsmScannerDefaultFilename;
+
+/*======================================================================
+ * gfsmScanner: Constructors etc.
+ */
+
+/// \name gfsmScanner: Constructors etc.
+//@{
+
+
+/** Initialize and return a gfsmScanner given the flex prefix.
+ * Scanner is initialized for a reentrant flex scanner with prefix PREFIX.
+ */
+#define gfsm_scanner_init(scanner,name,PREFIX) \
+ gfsm_scanner_init_full((scanner), \
+ (name), \
+ (gfsmFlexScannerInitFunc) ( PREFIX ## lex_init ), \
+ (gfsmFlexScannerFreeFunc) ( PREFIX ## lex_destroy ), \
+ (gfsmFlexScannerScanFileFunc) ( PREFIX ## restart ), \
+ (gfsmFlexScannerScanBytesFunc) ( PREFIX ## _scan_bytes ), \
+ (gfsmFlexScannerScanPopFunc) ( PREFIX ## pop_buffer_state ), \
+ (gfsmFlexScannerGetTextFunc) ( PREFIX ## get_text ), \
+ (gfsmFlexScannerGetPosFunc) ( PREFIX ## get_lineno ), \
+ (gfsmFlexScannerSetPosFunc) ( PREFIX ## set_lineno ), \
+ (gfsmFlexScannerSetExtraFunc) ( PREFIX ## set_extra ) )
+
+/** Create, initialize, and return a new gfsmScanner given the a flex prefix.
+ * Scanner is initialized for a reentrant flex scanner with prefix PREFIX.
+ */
+#define gfsm_scanner_new(name,PREFIX) \
+ gfsm_scanner_init( g_new0(gfsmScanner,1), (name), PREFIX )
+
+
+/** Create, initialize, and return a new gfsmFlexScanner \a scanner.
+ * Underlying flex scanner will be available as \a scanner->yyscanner.
+ */
+gfsmScanner *gfsm_scanner_new_full(const char *name,
+ gfsmFlexScannerInitFunc yyinit_func,
+ gfsmFlexScannerFreeFunc yyfree_func,
+ gfsmFlexScannerScanFileFunc yyscan_file_func,
+ gfsmFlexScannerScanBytesFunc yyscan_bytes_func,
+ gfsmFlexScannerScanPopFunc yyscan_pop_func,
+ gfsmFlexScannerGetTextFunc yyget_text_func,
+ gfsmFlexScannerGetPosFunc yyget_lineno_func,
+ gfsmFlexScannerSetPosFunc yyset_lineno_func,
+ gfsmFlexScannerSetExtraFunc yyset_extra_func);
+
+
+
+/** Initialize a gfsmScanner. */
+gfsmScanner *gfsm_scanner_init_full(gfsmScanner *scanner,
+ const char *name,
+ gfsmFlexScannerInitFunc yyinit_func,
+ gfsmFlexScannerFreeFunc yyfree_func,
+ gfsmFlexScannerScanFileFunc yyscan_file_func,
+ gfsmFlexScannerScanBytesFunc yyscan_bytes_func,
+ gfsmFlexScannerScanPopFunc yyscan_pop_func,
+ gfsmFlexScannerGetTextFunc yyget_text_func,
+ gfsmFlexScannerGetPosFunc yyget_lineno_func,
+ gfsmFlexScannerSetPosFunc yyset_lineno_func,
+ gfsmFlexScannerSetExtraFunc yyset_extra_func);
+
+/** Frees memory associated with a gfsmScanner.
+ * Calls \a scanner->yyfree_func() to destroy the underlying flex scanner.
+ */
+void gfsm_scanner_free(gfsmScanner *scanner);
+
+
+/*======================================================================
+ * gfsmScanner: I/O Selection
+ */
+
+/// \name gfsmScanner: I/O Selection
+//@{
+
+/** Close any file associated with a scanner */
+void gfsm_scanner_close(gfsmScanner *scanner);
+
+/** Scan from an open FILE* */
+void gfsm_scanner_scan_file(gfsmScanner *scanner, FILE *f);
+
+/** Scan from a named file */
+void gfsm_scanner_scan_filename(gfsmScanner *scanner, const char *filename);
+
+/** Scan an in-memory buffer */
+void gfsm_scanner_scan_bytes(gfsmScanner *scanner, const char *bytes, int len);
+
+/** Scan from a GString* */
+void gfsm_scanner_scan_gstring(gfsmScanner *scanner, GString *gstr);
+
+/** Scan a NUL-terminated string */
+void gfsm_scanner_scan_string(gfsmScanner *scanner, const char *str);
+
+//@}
+
+/*======================================================================
+ * Scanner Methods: Flex scanner utilities
+ */
+/// \name gfsmScanner: Flex Scanner Utilities
+//@{
+
+/** Can be used as an input wrapper; doesn't wrap input at all */
+int gfsm_scanner_yywrap(gfsmScanner *scanner);
+
+/** Use default yywrap */
+#define GFSM_SCANNER_YYWRAP(PREFIX) \
+ int PREFIX ## wrap(gfsmFlexScanner yyscanner) \
+ { return gfsm_scanner_yywrap( yyscanner ); }
+
+//@}
+
+/*======================================================================
+ * Scanner Methods: Errors
+ */
+/// \name gfsmScanner: Error Reporting
+//@{
+
+/** Wrapper for gfsm_scanner_carp_full_v(); sets \a scanner->err */
+void gfsm_scanner_carp(gfsmScanner *scanner, const char *fmt, ...);
+
+/** Wrapper for gfsm_scanner_carp_full_v(); sets \a scanner->err */
+void gfsm_scanner_carp_full(gfsmScanner *scanner,
+ GQuark domain,
+ gint code,
+ const char *fmt,
+ ...);
+
+/** Warning function - sets \a scanner->err */
+void gfsm_scanner_carp_full_v(gfsmScanner *scanner,
+ GQuark domain,
+ gint code,
+ const char *fmt,
+ va_list ap);
+//@}
+
+#endif /* _GFSM_SCANNER_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmSemiring.c b/gfsm/gfsm/src/libgfsm/gfsmSemiring.c
new file mode 100644
index 0000000..a1620dc
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmSemiring.c
@@ -0,0 +1,104 @@
+/*=============================================================================*\
+ * File: gfsmSemiring.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmSemiring.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmSemiring.hi>
+#endif
+
+/*======================================================================
+ * Semiring: methods: constructors etc.
+ */
+
+
+
+/*======================================================================
+ * Semiring: methods: general accessors
+ */
+
+/*--------------------------------------------------------------
+ * compare()
+ */
+gint gfsm_sr_compare(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y)
+{
+ switch (sr->type) {
+ case gfsmSRTLog:
+ case gfsmSRTTropical: return (x < y ? -1 : (x > y ? 1 : 0));
+ case gfsmSRTTrivial: return 0;
+
+ case gfsmSRTPLog: return (x < y ? 1 : (x > y ? -1 : 0));
+
+ case gfsmSRTUser:
+ return (gfsm_sr_compare(sr,x,y) ? -1 : (gfsm_sr_compare(sr,y,x) ? 1 : 0));
+ if (((gfsmUserSemiring*)sr)->less_func) {
+ if ((*((gfsmUserSemiring*)sr)->less_func)(sr,x,y)) return -1;
+ if ((*((gfsmUserSemiring*)sr)->less_func)(sr,y,x)) return 1;
+ return 0;
+ }
+
+ case gfsmSRTBoolean:
+ case gfsmSRTReal:
+ default: return (x > y ? -1 : (x < y ? 1 : 0));
+ }
+ return 0; //-- should never happen
+}
+
+/*======================================================================
+ * Semiring: string utilities
+ */
+
+/*--------------------------------------------------------------
+ * name_to_type()
+ */
+gfsmSRType gfsm_sr_name_to_type(const char *name)
+{
+ if (strcmp(name,"boolean") ==0) return gfsmSRTBoolean;
+ else if (strcmp(name,"log") ==0) return gfsmSRTLog;
+ else if (strcmp(name,"plog") ==0) return gfsmSRTPLog;
+ else if (strcmp(name,"real") ==0) return gfsmSRTReal;
+ else if (strcmp(name,"trivial") ==0) return gfsmSRTTrivial;
+ else if (strcmp(name,"tropical") ==0) return gfsmSRTTropical;
+ else if (strcmp(name,"user") ==0) return gfsmSRTUser;
+ return gfsmSRTUnknown;
+}
+
+/*--------------------------------------------------------------
+ * type_to_name()
+ */
+gchar *gfsm_sr_type_to_name(gfsmSRType type)
+{
+ switch (type) {
+ case gfsmSRTBoolean: return "boolean";
+ case gfsmSRTLog: return "log";
+ case gfsmSRTPLog: return "plog";
+ case gfsmSRTTrivial: return "trivial";
+ case gfsmSRTTropical: return "tropical";
+ case gfsmSRTReal: return "real";
+ default: return "unknown";
+ }
+}
+
+/*======================================================================
+ * Semiring: general utilities
+ */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmSemiring.h b/gfsm/gfsm/src/libgfsm/gfsmSemiring.h
new file mode 100644
index 0000000..e03b5ce
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmSemiring.h
@@ -0,0 +1,183 @@
+/*=============================================================================*\
+ * File: gfsmSemiring.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmSemiring.h
+ * \brief semiring types & operations
+ */
+
+#ifndef _GFSM_SEMIRING_H
+#define _GFSM_SEMIRING_H
+
+#include <gfsmCommon.h>
+#include <float.h>
+
+/*======================================================================
+ * Semiring: types
+ */
+/** Builtin semiring types
+ * \see fsmcost(3)
+ */
+typedef enum {
+ gfsmSRTUnknown = 0, ///< unknown semiring (should never happen)
+ gfsmSRTBoolean = 1, ///< boolean semiring <set:{0,1}, plus:||, times:&&, less:>, zero:0, one:1>
+ gfsmSRTLog = 2, ///< negative log semiring <set:[-inf,inf], plus:-log(e^-x+e^-y), times:+, less:<, zero:inf, one:0>
+ gfsmSRTReal = 3, ///< real semiring: <set:[0,inf], plus:+, times:*, less:<, zero:0, one:1>
+ gfsmSRTTrivial = 4, ///< trivial semiring <set:{0}, plus:+, times:+, less:!=, zero:0, one:0>
+ gfsmSRTTropical = 5, ///< tropical semiring: <set:[-inf,inf], plus:min, times:+, less:<, zero:inf, one:0>
+ gfsmSRTPLog = 6, ///< positive log semiring <set:[-inf,inf], plus:log(e^x+e^y), times:+, less:>, zero:-inf, one:0>
+ gfsmSRTUser = 256 ///< user-defined semiring
+} gfsmSRType;
+
+/*======================================================================
+ * Semiring: types: structs
+ */
+/// struct to represent a builtin semi-ring for gfsm arc weights
+typedef struct {
+ gfsmSRType type; /**< type of this semiring */
+ gfsmWeight zero; /**< nil element of this semiring (identity for '+') */
+ gfsmWeight one; /**< unity element of this semiring (idendity for '*') */
+} gfsmSemiring;
+
+/*======================================================================
+ * Semiring: types: functions
+ */
+/** Type for user-defined semiring unary predicates (i.e. member) */
+typedef gboolean (*gfsmSRUnaryPredicate) (gfsmSemiring *sr, gfsmWeight x);
+
+/// Type for user-defined semiring binary predicates (i.e. equal) */
+typedef gboolean (*gfsmSRBinaryPredicate) (gfsmSemiring *sr, gfsmWeight x, gfsmWeight y);
+
+/// Type for user-defined semiring unary operations */
+typedef gfsmWeight (*gfsmSRUnaryOp) (gfsmSemiring *sr, gfsmWeight x);
+
+/// Type for user-defined semiring binary operations */
+typedef gfsmWeight (*gfsmSRBinaryOp) (gfsmSemiring *sr, gfsmWeight x, gfsmWeight y);
+
+
+/*======================================================================
+ * Semiring: types: user structs
+ */
+/// User-defined semirings for gfsm operations
+typedef struct {
+ gfsmSemiring sr; /**< inheritance magic */
+
+ //-- user-defined semirings *must* set these functions
+ gfsmSRBinaryPredicate equal_func; /**< equality predicate */
+ gfsmSRBinaryPredicate less_func; /**< order predicate */
+ gfsmSRBinaryOp plus_func; /**< addition operation */
+ gfsmSRBinaryOp times_func; /**< multiplication operation */
+} gfsmUserSemiring;
+
+/*======================================================================
+ * Semiring: methods: constructors etc.
+ */
+///\name Constructors etc.
+//@{
+
+/** Create, initialize (for builtin types), and return new semiring of type \a type */
+GFSM_INLINE
+gfsmSemiring *gfsm_semiring_new(gfsmSRType type);
+
+/** Initialize and return a builtin semiring */
+GFSM_INLINE
+void gfsm_semiring_init(gfsmSemiring *sr, gfsmSRType type);
+
+/** Initialize and return a semiring */
+GFSM_INLINE
+gfsmUserSemiring *gfsm_user_semiring_new(gfsmSRBinaryPredicate equal_func,
+ gfsmSRBinaryPredicate less_func,
+ gfsmSRBinaryOp plus_func,
+ gfsmSRBinaryOp times_func);
+
+/** Copy a semiring */
+GFSM_INLINE
+gfsmSemiring *gfsm_semiring_copy(gfsmSemiring *sr);
+
+/** Destroy a gfsmSemiring */
+GFSM_INLINE
+void gfsm_semiring_free(gfsmSemiring *sr);
+//@}
+
+/*======================================================================
+ * Semiring: general accessors
+ */
+///\name General Accessors
+//@{
+
+/** Get 'zero' element of the ::gfsmSemiring* \a sr */
+GFSM_INLINE
+gfsmWeight gfsm_sr_zero(gfsmSemiring *sr);
+
+/** Get 'one' element of the ::gfsmSemiring* \a sr */
+GFSM_INLINE
+gfsmWeight gfsm_sr_one(gfsmSemiring *sr);
+
+/** Check equality of elements \a x and \a y with respect to ::gfsmSemiring* \a sr */
+GFSM_INLINE
+gboolean gfsm_sr_equal(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y);
+
+/** Check semiring element order */
+GFSM_INLINE
+gboolean gfsm_sr_less(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y);
+
+/** 3-way comparison for semiring values */
+gint gfsm_sr_compare(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y);
+
+/** Semiring addition */
+GFSM_INLINE
+gfsmWeight gfsm_sr_plus(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y);
+
+/** Semiring multiplication */
+GFSM_INLINE
+gfsmWeight gfsm_sr_times(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y);
+//@}
+
+/*======================================================================
+ * Semiring: methods: string utilities
+ */
+///\name String utilities
+//@{
+/** Convert symbolic name of a semiring to a gfsmSRType */
+gfsmSRType gfsm_sr_name_to_type(const char *name);
+
+/** Convert a gfsmSRType to a (constant) symbolic name */
+gchar *gfsm_sr_type_to_name(gfsmSRType type);
+//@}
+
+/*======================================================================
+ * Semiring: methods: general utilities
+ */
+///\name General utilities
+//@{
+/** stable log addition.
+ * \returns log(exp(x)+exp(y))
+ */
+GFSM_INLINE
+gfsmWeight gfsm_log_add(gfsmWeight x, gfsmWeight y);
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmSemiring.hi>
+#endif
+
+#endif /* _GFSM_SEMIRING_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmSemiring.hi b/gfsm/gfsm/src/libgfsm/gfsmSemiring.hi
new file mode 100644
index 0000000..cff434b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmSemiring.hi
@@ -0,0 +1,257 @@
+
+/*=============================================================================*\
+ * File: gfsmSemiring.def
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: semirings: inline definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <float.h>
+#include <math.h>
+#include <string.h>
+
+/*======================================================================
+ * Semiring: general utilities
+ */
+
+// LOG_BIG = log(1E31)
+#define LOG_BIG 71.3801378828154
+/*
+//#define LOG_ZERO -FLT_MAX
+#define LOG_ZERO -1E+38F
+#define LOG_ONE 0
+#define LOG_NONE 1
+*/
+GFSM_INLINE
+gfsmWeight gfsm_log_add(gfsmWeight x, gfsmWeight y)
+{
+ if (y-x > LOG_BIG) return y;
+ else if (x-y > LOG_BIG) return x;
+ /*else return min(x,y) + log(exp(x-min(x,y)) + exp(y-min(x,y))); */
+ else if (x<y) return x + log( 1 + exp(y-x));
+ else return y + log(exp(x-y) + 1);
+}
+#undef LOG_BIG
+
+
+/*======================================================================
+ * Semiring: methods: constructors etc.
+ */
+
+/*--------------------------------------------------------------
+ * init()
+ */
+GFSM_INLINE
+void gfsm_semiring_init(gfsmSemiring *sr, gfsmSRType type)
+{
+ memset(sr, 0, type==gfsmSRTUser ? sizeof(gfsmUserSemiring) : sizeof(gfsmSemiring));
+ sr->type = type;
+ switch (type) {
+ case gfsmSRTBoolean:
+ sr->zero = 0;
+ sr->one = 1;
+ break;
+ case gfsmSRTLog:
+ sr->zero = FLT_MAX;
+ sr->one = 0;
+ break;
+ case gfsmSRTPLog:
+ sr->zero = -FLT_MAX;
+ sr->one = 0;
+ break;
+ case gfsmSRTTrivial:
+ sr->zero = 0;
+ sr->one = 0;
+ break;
+ case gfsmSRTTropical:
+ sr->zero = FLT_MAX;
+ sr->one = 0;
+ break;
+ case gfsmSRTReal:
+ default:
+ sr->zero = 0;
+ sr->one = 1;
+ break;
+ }
+}
+
+/*--------------------------------------------------------------
+ * new()
+ */
+GFSM_INLINE
+gfsmSemiring *gfsm_semiring_new(gfsmSRType type)
+{
+ gfsmSemiring *sr = (gfsmSemiring*)g_new(gfsmSemiring,1);
+ gfsm_semiring_init(sr,type);
+ return sr;
+}
+
+/*--------------------------------------------------------------
+ * user_new()
+ */
+GFSM_INLINE
+gfsmUserSemiring *gfsm_user_semiring_new(gfsmSRBinaryPredicate equal_func,
+ gfsmSRBinaryPredicate less_func,
+ gfsmSRBinaryOp plus_func,
+ gfsmSRBinaryOp times_func)
+{
+ gfsmUserSemiring *sr = g_new(gfsmUserSemiring, 1);
+ gfsm_semiring_init((gfsmSemiring*)sr,gfsmSRTUser);
+ sr->equal_func = equal_func;
+ sr->less_func = less_func;
+ sr->plus_func = plus_func;
+ sr->times_func = times_func;
+ return sr;
+}
+
+/*--------------------------------------------------------------
+ * copy()
+ */
+GFSM_INLINE
+gfsmSemiring *gfsm_semiring_copy(gfsmSemiring *sr)
+{
+ if (sr->type==gfsmSRTUser)
+ return (gfsmSemiring*)gfsm_user_semiring_new(((gfsmUserSemiring*)sr)->equal_func,
+ ((gfsmUserSemiring*)sr)->less_func,
+ ((gfsmUserSemiring*)sr)->plus_func,
+ ((gfsmUserSemiring*)sr)->times_func);
+ return gfsm_semiring_new(sr->type);
+}
+
+/*--------------------------------------------------------------
+ * free()
+ */
+GFSM_INLINE
+void gfsm_semiring_free(gfsmSemiring *sr)
+{
+ if (sr->type==gfsmSRTUser) g_free((gfsmUserSemiring*)sr);
+ else g_free(sr);
+}
+
+
+/*======================================================================
+ * Semiring: methods: general accessors
+ */
+
+/*--------------------------------------------------------------
+ * zero()
+ */
+GFSM_INLINE
+gfsmWeight gfsm_sr_zero(gfsmSemiring *sr) { return sr ? sr->zero : 0; }
+
+/*--------------------------------------------------------------
+ * one()
+ */
+GFSM_INLINE
+gfsmWeight gfsm_sr_one(gfsmSemiring *sr) { return sr ? sr->one : 1; }
+
+/*--------------------------------------------------------------
+ * equal()
+ */
+GFSM_INLINE
+gboolean gfsm_sr_equal(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y)
+{
+ return (sr->type == gfsmSRTUser && ((gfsmUserSemiring*)sr)->equal_func
+ ? ((*((gfsmUserSemiring*)sr)->equal_func)(sr,x,y)) \
+ : (x==y));
+}
+
+/*--------------------------------------------------------------
+ * less()
+ */
+GFSM_INLINE
+gboolean gfsm_sr_less(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y)
+{
+ switch (sr->type) {
+ case gfsmSRTLog:
+ case gfsmSRTTropical: return (x < y);
+
+ case gfsmSRTPLog: return (x > y);
+
+ case gfsmSRTTrivial: return 0;
+
+ case gfsmSRTUser:
+ if (((gfsmUserSemiring*)sr)->less_func)
+ return (*((gfsmUserSemiring*)sr)->less_func)(sr,x,y);
+
+ case gfsmSRTBoolean:
+ case gfsmSRTReal:
+ default: return (x > y);
+ }
+ return FALSE; //-- should never happen
+}
+
+/*--------------------------------------------------------------
+ * plus()
+ */
+GFSM_INLINE
+gfsmWeight gfsm_sr_plus(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y)
+{
+ switch (sr->type) {
+ case gfsmSRTBoolean: return x || y;
+ //case gfsmSRTLog: return -log(exp(-x) + exp(-y));
+ case gfsmSRTLog: return -gfsm_log_add(-x,-y);
+ case gfsmSRTPLog: return gfsm_log_add( x, y);
+ case gfsmSRTTropical: return (x < y ? x : y);
+ case gfsmSRTTrivial: return 0;
+
+ case gfsmSRTUser:
+ if (((gfsmUserSemiring*)sr)->plus_func)
+ return (*((gfsmUserSemiring*)sr)->plus_func)(sr,x,y);
+
+ case gfsmSRTReal:
+ default: return x + y;
+ }
+ return sr->zero; //-- should never happen
+}
+
+/*--------------------------------------------------------------
+ * times()
+ */
+GFSM_INLINE
+gfsmWeight gfsm_sr_times(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y)
+{
+ switch (sr->type) {
+ case gfsmSRTBoolean: return x && y;
+ case gfsmSRTLog:
+ case gfsmSRTPLog:
+ case gfsmSRTTropical: return x + y;
+ case gfsmSRTTrivial: return 0;
+
+ case gfsmSRTUser:
+ if (((gfsmUserSemiring*)sr)->times_func)
+ return (*((gfsmUserSemiring*)sr)->times_func)(sr,x,y);
+
+ case gfsmSRTReal:
+ default: return x * y;
+ }
+ return sr->zero; //-- should never happen
+}
+
+/*--------------------------------------------------------------
+ * div()
+ */
+/*gboolean gfsm_sr_div(gfsmSemiring *sr, gfsmWeight x, gfsmWeight y)
+ { return (sr->div_func ? ((*sr->div_func)(sr,x,y)) : (x/y)); }
+*/
+//@}
+
+
+/*======================================================================
+ * Semiring: string utilities
+ */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmSet.c b/gfsm/gfsm/src/libgfsm/gfsmSet.c
new file mode 100644
index 0000000..1083caa
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmSet.c
@@ -0,0 +1,143 @@
+/*=============================================================================*\
+ * File: gfsmSet.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmSet.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmSet.hi>
+#endif
+
+/*======================================================================
+ * Constructors etc.
+ */
+
+/*--------------------------------------------------------------
+ * copy_foreach_func()
+ */
+gboolean gfsm_set_copy_foreach_func(gpointer key, gpointer value, gfsmSet *data)
+{
+ if (data) g_tree_insert(data,key,value);
+ return FALSE; // don't stop iterating
+}
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+void gfsm_set_clear(gfsmSet *set)
+{
+ guint i;
+ GPtrArray *keys = g_ptr_array_sized_new(gfsm_set_size(set));
+ gfsm_set_to_ptr_array(set,keys);
+ for (i=0; i < keys->len; i++) {
+ g_tree_remove(set, g_ptr_array_index(keys,i));
+ }
+ g_ptr_array_free(keys,TRUE);
+}
+
+
+/*======================================================================
+ * Algebra
+ */
+
+/*--------------------------------------------------------------
+ * union_func()
+ */
+gboolean gfsm_set_union_func(gpointer key, gpointer value, gfsmSetUnionData *data)
+{
+ if (!data->dupfunc) {
+ //-- no memory hairiness: just insert
+ gfsm_set_insert(data->dst, key);
+ } else {
+ if (!gfsm_set_contains(data->dst, key))
+ gfsm_set_insert(data->dst, (*data->dupfunc)(key));
+ }
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * difference_func()
+ */
+gboolean gfsm_set_difference_func(gpointer key, gpointer value, gfsmSet *set1)
+{
+ gfsm_set_remove(set1,key);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * intersection()
+ */
+gfsmSet *gfsm_set_intersection(gfsmSet *set1, gfsmSet *set2)
+{
+ guint i;
+ GPtrArray *elts1 = g_ptr_array_sized_new(gfsm_set_size(set1));
+ gfsm_set_to_ptr_array(set1,elts1);
+ for (i=0; i < elts1->len; i++) {
+ gpointer elt = g_ptr_array_index(elts1,i);
+ if (!gfsm_set_contains(set2,elt)) gfsm_set_remove(set1,elt);
+ }
+ g_ptr_array_free(elts1,TRUE);
+ return set1;
+}
+
+
+/*======================================================================
+ * Converters
+ */
+
+/*--------------------------------------------------------------
+ * to_slist_foreach_func()
+ */
+gboolean gfsm_set_to_slist_foreach_func(gpointer key, gpointer value, GSList **dst)
+{
+ *dst = g_slist_prepend(*dst, key);
+ return FALSE; //-- don't stop iterating
+}
+
+/*--------------------------------------------------------------
+ * to_ptr_array_foreach_func()
+ */
+gboolean gfsm_set_to_ptr_array_foreach_func(gpointer key, gpointer value, GPtrArray *dst)
+{
+ g_ptr_array_add(dst,key);
+ return FALSE;
+}
+
+/*======================================================================
+ * Debugging
+ */
+#ifdef GFSM_DEBUG_ENABLED
+
+gboolean gfsm_set_print_foreach_func(gpointer key, gpointer data, FILE *f)
+{
+ fprintf(f, " %u", GPOINTER_TO_UINT(key));
+ return FALSE;
+}
+
+void gfsm_set_print_uint(gfsmSet *set, FILE *f)
+{
+ fputc('{',f);
+ g_tree_foreach(set, (GTraverseFunc)gfsm_set_print_foreach_func, f);
+ fputs(" }", f);
+}
+
+#endif /*GFSM_DEBUG_ENABLED*/
diff --git a/gfsm/gfsm/src/libgfsm/gfsmSet.h b/gfsm/gfsm/src/libgfsm/gfsmSet.h
new file mode 100644
index 0000000..c95c26e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmSet.h
@@ -0,0 +1,163 @@
+
+/*=============================================================================*\
+ * File: gfsmSet.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmSet.h
+ * \brief Abstract set type using GTree
+ */
+
+#ifndef _GFSM_SET_H
+#define _GFSM_SET_H
+
+#include <gfsmMem.h>
+
+/*======================================================================
+ * Types
+ */
+/** \brief Type for sets of pointers
+ * \detail really just an ugly wrapper for GTree
+ */
+typedef GTree gfsmSet;
+
+
+/*======================================================================
+ * Constructors etc.
+ */
+///\name gfsmSet: Constructors etc.
+//@{
+/** Create and return a new set */
+GFSM_INLINE
+gfsmSet *gfsm_set_new_full(GCompareDataFunc key_cmp_func, gpointer key_cmp_data, GDestroyNotify key_free_func);
+
+/** gfsm_set_new(key_compare_func): create and return a new set
+ * (returned set will not free elements)
+ */
+GFSM_INLINE
+gfsmSet *gfsm_set_new(GCompareFunc key_cmp_func);
+
+/** Copy set \a src to \a dst. \returns \a dst */
+GFSM_INLINE
+gfsmSet *gfsm_set_copy(gfsmSet *dst, gfsmSet *src);
+
+/** Utilitiy for gfsm_set_copy() */
+gboolean gfsm_set_copy_foreach_func(gpointer key, gpointer value, gfsmSet *dst);
+
+/** clear a set */
+void gfsm_set_clear(gfsmSet *set);
+
+/** Destroy a set
+ * \code void gfsm_set_free(gfsmSet *set); \endcode
+ */
+#define gfsm_set_free g_tree_destroy
+
+//@}
+
+
+/*======================================================================
+ * Accessors
+ */
+///\name gfsmSet: Accessors
+//@{
+/** check set membership */
+#define gfsm_set_contains(set,key) g_tree_lookup(set,key)
+
+/** insert a new key into the set */
+#define gfsm_set_insert(set,key) g_tree_insert(set,key,(gpointer)1)
+
+/** get size of set */
+#define gfsm_set_size(set) g_tree_nnodes(set)
+
+/** Remove an element from a set */
+#define gfsm_set_remove(set,key) g_tree_remove(set,key)
+
+/** Traversal (see g_tree_foreach) */
+#define gfsm_set_foreach(set,func,data) g_tree_foreach(set,func,data)
+//@}
+
+/*======================================================================
+ * set: Algebra
+ */
+///\name gfsmSet: Algebra
+//@{
+
+/** Add all elements of set \a set2 to \a set1.
+ * If \a dupfunc is non-NULL, it will be used to copy elements from \a set2,
+ * otherwise elements will be copied as literal gpointer values.
+ * \returns altered \a set1
+ */
+GFSM_INLINE
+gfsmSet *gfsm_set_union(gfsmSet *set1, gfsmSet *set2, gfsmDupFunc dupfunc);
+
+/** Remove all elements in \a set2 from \a set1.
+ * \returns altered \a set1 */
+GFSM_INLINE
+gfsmSet *gfsm_set_difference(gfsmSet *set1, gfsmSet *set2);
+
+/** Remove all elements from \a set1 which are not also in \a set2.
+ * \returns altered \a set1 */
+gfsmSet *gfsm_set_intersection(gfsmSet *set1, gfsmSet *set2);
+
+//@}
+
+
+/*======================================================================
+ * Converters
+ */
+///\name gfsmSet: converters
+//@{
+
+/** Get a GSList of a set's elements */
+GFSM_INLINE
+GSList *gfsm_set_to_slist(gfsmSet *set);
+
+/** Low-level utilitity for gfsm_set_to_slist() */
+gboolean gfsm_set_to_slist_foreach_func(gpointer key, gpointer value, GSList **dst);
+
+/** Append a set's elements to a GPtrArray */
+GFSM_INLINE
+void gfsm_set_to_ptr_array(gfsmSet *set, GPtrArray *array);
+
+/** Low-level foreach utilitity for gfsm_set_to_array() */
+gboolean gfsm_set_to_ptr_array_foreach_func(gpointer key, gpointer value, GPtrArray *dst);
+//@}
+
+/*======================================================================
+ * Debugging
+ */
+#ifdef GFSM_DEBUG_ENABLED
+#include <stdio.h>
+
+///\name gfsmSet: debugging
+//@{
+
+/** Dump contents of a gfsmSet using '%u' to a FILE* */
+void gfsm_set_print_uint(gfsmSet *set, FILE *f);
+
+//@}
+#endif /* GFSM_DEBUG_ENABLED */
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmSet.hi>
+#endif
+
+#endif /* _GFSM_SET_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmSet.hi b/gfsm/gfsm/src/libgfsm/gfsmSet.hi
new file mode 100644
index 0000000..6ff98af
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmSet.hi
@@ -0,0 +1,136 @@
+/*=============================================================================*\
+ * File: gfsmSet.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/*======================================================================
+ * Converters
+ */
+
+/*--------------------------------------------------------------
+ * to_slist()
+ */
+GFSM_INLINE
+GSList *gfsm_set_to_slist(gfsmSet *set)
+{
+ GSList *l = NULL;
+ gfsm_set_foreach(set,(GTraverseFunc)gfsm_set_to_slist_foreach_func, &l);
+ return l;
+}
+
+/*--------------------------------------------------------------
+ * to_ptr_array()
+ */
+GFSM_INLINE
+void gfsm_set_to_ptr_array(gfsmSet *set, GPtrArray *array)
+{
+ gfsm_set_foreach(set,(GTraverseFunc)gfsm_set_to_ptr_array_foreach_func, array);
+}
+
+
+/*======================================================================
+ * Constructors etc.
+ */
+
+/*--------------------------------------------------------------
+ * new_full()
+ */
+GFSM_INLINE
+gfsmSet *gfsm_set_new_full(GCompareDataFunc key_cmp_func, gpointer key_cmp_data, GDestroyNotify key_free_func)
+{
+ return g_tree_new_full(key_cmp_func, key_cmp_data, key_free_func, NULL);
+}
+
+/*--------------------------------------------------------------
+ * new()
+ */
+GFSM_INLINE
+gfsmSet *gfsm_set_new(GCompareFunc key_cmp_func)
+{
+ return g_tree_new(key_cmp_func);
+}
+
+/*--------------------------------------------------------------
+ * copy()
+ */
+GFSM_INLINE
+gfsmSet *gfsm_set_copy(gfsmSet *dst, gfsmSet *src)
+{
+ gfsm_set_clear(dst);
+ g_tree_foreach(src, (GTraverseFunc)gfsm_set_copy_foreach_func, dst);
+ return dst;
+}
+
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+//-- extern
+
+/*--------------------------------------------------------------
+ * free()
+ */
+#if 0
+GFSM_INLINE
+void gfsm_set_free(gfsmSet *set)
+{
+ g_tree_destroy(set);
+}
+#endif
+
+
+/*======================================================================
+ * Set Algebra
+ */
+
+/*--------------------------------------------------------------
+ * union(): data
+ */
+typedef struct {
+ gfsmSet *dst;
+ gfsmDupFunc dupfunc;
+} gfsmSetUnionData;
+
+
+/*--------------------------------------------------------------
+ * union()
+ */
+gboolean gfsm_set_union_func(gpointer key, gpointer value, gfsmSetUnionData *data);
+
+GFSM_INLINE
+gfsmSet *gfsm_set_union(gfsmSet *set1, gfsmSet *set2, gfsmDupFunc dupfunc)
+{
+ gfsmSetUnionData data = { set1, dupfunc };
+ g_tree_foreach(set2, (GTraverseFunc)gfsm_set_union_func, &data);
+ return set1;
+}
+
+/*--------------------------------------------------------------
+ * difference()
+ */
+gboolean gfsm_set_difference_func(gpointer key, gpointer value, gfsmSet *set1);
+
+GFSM_INLINE
+gfsmSet *gfsm_set_difference(gfsmSet *set1, gfsmSet *set2)
+{
+ g_tree_foreach(set2, (GTraverseFunc)gfsm_set_difference_func, set1);
+ return set1;
+}
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmState.c b/gfsm/gfsm/src/libgfsm/gfsmState.c
new file mode 100644
index 0000000..c7bb5f6
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmState.c
@@ -0,0 +1,30 @@
+
+/*=============================================================================*\
+ * File: gfsmState.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: states: extern
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmConfig.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmState.h>
+# include <gfsmState.hi>
+#endif
diff --git a/gfsm/gfsm/src/libgfsm/gfsmState.h b/gfsm/gfsm/src/libgfsm/gfsmState.h
new file mode 100644
index 0000000..a3fd363
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmState.h
@@ -0,0 +1,109 @@
+
+/*=============================================================================*\
+ * File: gfsmState.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: states
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmState.h
+ * \brief Automaton state definitions & utilities
+ */
+
+#ifndef _GFSM_STATE_H
+#define _GFSM_STATE_H
+
+#include <gfsmArcList.h>
+
+/*======================================================================
+ * Types
+ */
+
+/// Automaton state structure
+typedef struct {
+ guint32 is_valid : 1; /**< whether this is a valid state */
+ guint32 is_final : 1; /**< whether this is a final state */
+ guint32 is_temp : 1; /**< whether this state should be freed on gfsm_state_close() */
+ guint32 arc_list_temp : 1; /**< whether arc list should be freed on gfsm_state_close() */
+ guint32 arc_data_temp : 1; /**< whether arc data should be freed on gfsm_state_close(): implies arc_list_temp=1 */
+ guint32 unused : 27; /**< reserved */
+ gfsmArcList *arcs; /**< list of outgoing arcs */
+} gfsmState;
+
+
+/*======================================================================
+ * Methods: gfsmState: Constructors etc.
+ */
+/// \name gfsmState: Constructors etc.
+//@{
+/** Create a new state (generic) */
+GFSM_INLINE
+gfsmState *gfsm_state_new_full(gboolean is_final, gfsmArcList *arcs);
+
+/** Create a new state (empty) */
+GFSM_INLINE
+gfsmState *gfsm_state_new(void);
+
+/** Copy an existing state */
+GFSM_INLINE
+gfsmState *gfsm_state_copy(gfsmState *dst, const gfsmState *src);
+
+/** Clear an existing state */
+GFSM_INLINE
+void gfsm_state_clear(gfsmState *s);
+
+/** Destroy a state */
+GFSM_INLINE
+void gfsm_state_free(gfsmState *s, gboolean free_arcs);
+
+/** Close a state (generic) */
+GFSM_INLINE
+void gfsm_state_close(gfsmState *s);
+
+//@}
+
+/*======================================================================
+ * Methods: gfsmState: Accessors
+ */
+///\name gfsmState: Accessors
+//@{
+
+/** Check if state is valid */
+GFSM_INLINE
+gboolean gfsm_state_is_ok(const gfsmState *s);
+
+/** Check for final state */
+GFSM_INLINE
+gboolean gfsm_state_is_final(const gfsmState *s);
+
+/** Set final state flag */
+GFSM_INLINE
+void gfsm_state_set_final(gfsmState *s, gboolean is_final);
+
+/** Get number of outgoing arcs */
+GFSM_INLINE
+guint gfsm_state_out_degree(const gfsmState *s);
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmState.hi>
+#endif
+
+#endif /* _GFSM_STATE_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmState.hi b/gfsm/gfsm/src/libgfsm/gfsmState.hi
new file mode 100644
index 0000000..15b2669
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmState.hi
@@ -0,0 +1,144 @@
+
+/*=============================================================================*\
+ * File: gfsmState.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: states: inline definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmMem.h>
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+
+/*--------------------------------------------------------------
+ * new_full()
+ */
+GFSM_INLINE
+gfsmState *gfsm_state_new_full(gboolean is_final, gfsmArcList *arcs)
+{
+ gfsmState *s = g_new(gfsmState,1);
+ s->is_valid = TRUE;
+ s->is_final = is_final;
+ s->arcs = arcs;
+ return s;
+}
+
+/*--------------------------------------------------------------
+ * new()
+ */
+GFSM_INLINE
+gfsmState *gfsm_state_new(void)
+{
+ return gfsm_state_new_full(FALSE, NULL);
+}
+
+/*--------------------------------------------------------------
+ * clear()
+ */
+GFSM_INLINE
+void gfsm_state_clear(gfsmState *s)
+{
+ gfsm_arclist_free(s->arcs);
+ s->is_valid = FALSE;
+ s->is_final = FALSE;
+ s->arcs = NULL;
+}
+
+/*--------------------------------------------------------------
+ * clone()
+ */
+GFSM_INLINE
+gfsmState *gfsm_state_copy(gfsmState *dst, const gfsmState *src)
+{
+ gfsm_state_clear(dst);
+ if (!src->is_valid) return dst;
+ dst->is_valid = src->is_valid;
+ dst->is_final = src->is_final;
+ //dst->arcs = g_slist_concat(gfsm_arclist_clone(src->arcs), dst->arcs);
+ dst->arcs = gfsm_arclist_clone(src->arcs);
+ return dst;
+}
+
+
+/*--------------------------------------------------------------
+ * free()
+ */
+GFSM_INLINE
+void gfsm_state_free(gfsmState *s, gboolean free_arcs)
+{
+ if (free_arcs && s->arcs) gfsm_arclist_free(s->arcs);
+ g_free(s);
+}
+
+/*--------------------------------------------------------------
+ * close()
+ */
+GFSM_INLINE
+void gfsm_state_close(gfsmState *s)
+{
+ if (s->arc_data_temp) {
+ //-- data=temp, list=temp
+ gfsm_arclist_free(s->arcs);
+ s->arcs = NULL;
+ }
+#if 0 //-- only sensible for GSList arclists
+ else if (s->arc_list_temp) {
+ //-- data=shared, list=temp
+ g_slist_free(s->arcs);
+ s->arcs = NULL;
+ }
+#endif
+ if (s->is_temp) { g_free(s); }
+}
+
+/*======================================================================
+ * Methods: Accessors
+ */
+
+/*--------------------------------------------------------------
+ * is_ok()
+ */
+GFSM_INLINE
+gboolean gfsm_state_is_ok(const gfsmState *s)
+{ return s && s->is_valid; }
+
+
+/*--------------------------------------------------------------
+ * is_final()
+ */
+GFSM_INLINE
+gboolean gfsm_state_is_final(const gfsmState *s)
+{ return s && s->is_final; }
+
+/*--------------------------------------------------------------
+ * set_final()
+ */
+GFSM_INLINE
+void gfsm_state_set_final(gfsmState *s, gboolean is_final)
+{ s->is_final=is_final; }
+
+/*--------------------------------------------------------------
+ * out_degree()
+ */
+GFSM_INLINE
+guint gfsm_state_out_degree(const gfsmState *s)
+{
+ return gfsm_arclist_length(s->arcs);
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmStateSet.c b/gfsm/gfsm/src/libgfsm/gfsmStateSet.c
new file mode 100644
index 0000000..0afc852
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmStateSet.c
@@ -0,0 +1,222 @@
+
+/*=============================================================================*\
+ * File: gfsmStateSet.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmStateSet.h>
+#include <gfsmArcIter.h>
+
+//-- no-inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmStateSet.hi>
+#endif
+
+/*======================================================================
+ * Constants
+ */
+const guint gfsmStateSetDefaultSize = 2;
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+//-- inlined
+
+/*======================================================================
+ * Methods: Accessors
+ */
+
+//--------------------------------------------------------------
+// find()
+gfsmStateSetIter gfsm_stateset_find(gfsmStateSet *sset, gfsmStateId id)
+{
+ gfsmStateSetIter sseti;
+ gfsmStateId iid;
+ for (sseti = gfsm_stateset_iter_begin(sset);
+ (iid=gfsm_stateset_iter_id(sseti)) != gfsmNoState;
+ sseti = gfsm_stateset_iter_next(sset,sseti))
+ {
+ if (id == iid) return sseti;
+ else if (id < iid) return NULL;
+ }
+ return NULL;
+}
+
+//--------------------------------------------------------------
+// insert()
+gboolean gfsm_stateset_insert(gfsmStateSet *sset, gfsmStateId id)
+{
+ guint i;
+ for (i = 0; i < sset->len && id > g_array_index(sset,gfsmStateId,i); i++) ;
+
+ if (i == sset->len) {
+ g_array_append_val(sset,id);
+ }
+ else if (id == g_array_index(sset,gfsmStateId,i)) {
+ return TRUE;
+ }
+ else {
+ g_array_insert_val(sset,i,id);
+ }
+ return FALSE;
+}
+
+//--------------------------------------------------------------
+// union()
+gfsmStateSet *gfsm_stateset_union(gfsmStateSet *sset1, gfsmStateSet *sset2)
+{
+ guint i1=0, i2;
+ for (i2=0; i2 < sset2->len; i2++) {
+ gfsmStateId id = g_array_index(sset2,gfsmStateId,i2);
+ for (; i1 < sset1->len && id > g_array_index(sset1,gfsmStateId,i1); i1++) ;
+
+ if (i1 == sset1->len) g_array_append_val(sset1,id);
+ else if (id == g_array_index(sset1,gfsmStateId,i1)) continue;
+ else g_array_insert_val(sset1,i1,id);
+ }
+ return sset1;
+}
+
+//--------------------------------------------------------------
+// remove()
+gboolean gfsm_stateset_remove(gfsmStateSet *sset, gfsmStateId id) {
+ guint i;
+ for (i = 0; i < sset->len && id > g_array_index(sset,gfsmStateId,i); i++) ;
+ if (i != sset->len && id == g_array_index(sset,gfsmStateId,i)) {
+ g_array_remove_index(sset,i);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------
+// equal()
+gboolean gfsm_stateset_equal(gfsmStateSet *sset1, gfsmStateSet *sset2)
+{
+ guint i;
+ if (sset1->len != sset2->len) return FALSE;
+ for (i=0; i < sset1->len; i++) {
+ if (g_array_index(sset1,gfsmStateId,i) != g_array_index(sset2,gfsmStateId,i)) return FALSE;
+ }
+ return TRUE;
+}
+
+//--------------------------------------------------------------
+// foreach()
+void gfsm_stateset_foreach(gfsmStateSet *sset, gfsmStateSetForeachFunc func, gpointer data)
+{
+ guint i;
+ for (i = 0; i < sset->len; i++) {
+ if ((*func)(g_array_index(sset,gfsmStateId,i), data)) break;
+ }
+}
+
+
+/*======================================================================
+ * Methods: iterators
+ */
+//-- inlined
+
+/*======================================================================
+ * Methods: Utilities
+ */
+
+/*--------------------------------------------------------------
+ * hash()
+ */
+guint gfsm_stateset_hash(gfsmStateSet *sset)
+{
+ guint hv = 0;
+ gfsmStateSetIter sseti;
+ gfsmStateId iid;
+ for (sseti = gfsm_stateset_iter_begin(sset);
+ (iid=gfsm_stateset_iter_id(sseti)) != gfsmNoState;
+ sseti = gfsm_stateset_iter_next(sset,sseti))
+ {
+ hv += 5*iid;
+ }
+ return hv;
+}
+
+
+/*======================================================================
+ * Methods: Automaton access
+ */
+
+//--------------------------------------------------------------
+// has_final_state()
+gboolean gfsm_stateset_has_final_state(gfsmStateSet *sset, gfsmAutomaton *fsm)
+{
+ guint i;
+ for (i = 0; i < sset->len; i++) {
+ if (gfsm_automaton_is_final_state(fsm, g_array_index(sset,gfsmStateId,i))) return TRUE;
+ }
+ return FALSE;
+}
+
+//--------------------------------------------------------------
+// lookup_final_weight()
+gboolean gfsm_stateset_lookup_final_weight(gfsmStateSet *sset, gfsmAutomaton *fsm, gfsmWeight *wp)
+{
+ guint i;
+ gboolean rc=FALSE;
+ *wp = fsm->sr->one;
+ gfsmWeight w;
+ for (i = 0; i < sset->len; i++) {
+ gfsmStateId id = g_array_index(sset,gfsmStateId,i);
+ if (gfsm_automaton_lookup_final(fsm,id,&w)) {
+ *wp = gfsm_sr_plus(fsm->sr, *wp, w);
+ rc = TRUE;
+ }
+ }
+ return rc;
+}
+
+/*--------------------------------------------------------------
+ * populate()
+ */
+void gfsm_stateset_populate(gfsmStateSet *sset,
+ gfsmAutomaton *fsm,
+ gfsmStateId id,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi)
+{
+ gfsmArcIter ai;
+ if (gfsm_stateset_insert(sset,id)) return;
+
+ for (gfsm_arciter_open(&ai,fsm,id), gfsm_arciter_seek_both(&ai,lo,hi);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_both(&ai,lo,hi))
+ {
+ gfsm_stateset_populate(sset,fsm,gfsm_arciter_arc(&ai)->target,lo,hi);
+ }
+ gfsm_arciter_close(&ai);
+}
+
+/*--------------------------------------------------------------
+ * has_final_state()
+ */
+//--inlined
+
+/*--------------------------------------------------------------
+ * lookup_final_weight()
+ */
+//--inlined
diff --git a/gfsm/gfsm/src/libgfsm/gfsmStateSet.h b/gfsm/gfsm/src/libgfsm/gfsmStateSet.h
new file mode 100644
index 0000000..e520df2
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmStateSet.h
@@ -0,0 +1,219 @@
+
+/*=============================================================================*\
+ * File: gfsmStateSet.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmStateSet.h
+ * \brief Sets of (gfsmStateId)s
+ */
+
+#ifndef _GFSM_STATESET_H
+#define _GFSM_STATESET_H
+
+#include <gfsmAutomaton.h>
+
+/*======================================================================
+ * Types
+ */
+
+/** \brief typedef for sets of automaton state-Ids
+ * \detail current implementation uses a sorted array
+*/
+typedef GArray gfsmStateSet;
+
+/** \brief typedef for weighted sets of automaton state-Ids */
+typedef struct {
+ gfsmStateSet *set; /**< Set of gfsmStateIds */
+ gfsmWeight weight; /**< Weight of this set */
+} gfsmWeightedStateSet;
+
+
+/*======================================================================
+ * Constants
+ */
+///\name Constants
+//@{
+/** Default initial size of state-sets */
+extern const guint gfsmStateSetDefaultSize;
+//@}
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+/// \name Constructors etc.
+//@{
+
+/** Create and return a new state-set, giving initial reserved size */
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_sized_new(guint isize);
+
+/** Create and return a new state-set */
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_new(void);
+
+/** Create and return a new singleton state-set */
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_new_singleton(gfsmStateId id);
+
+/** clear a state-set */
+GFSM_INLINE
+void gfsm_stateset_clear(gfsmStateSet *sset);
+
+/** Create and return an exact copy of a state-set */
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_clone(gfsmStateSet *src);
+
+/** destroy a state-set */
+GFSM_INLINE
+void gfsm_stateset_free(gfsmStateSet *sset);
+
+//@}
+
+/*======================================================================
+ * Methods: Accessors
+ */
+///\name Accessors
+//@{
+
+/** Get minimum element of a state-set */
+GFSM_INLINE
+gfsmStateId gfsm_stateset_min(gfsmStateSet *sset);
+
+/** Get number of elements in a state-set */
+GFSM_INLINE
+guint gfsm_stateset_size(gfsmStateSet *sset);
+
+/** Check whether a state-id is contained in a state-set */
+GFSM_INLINE
+gboolean gfsm_stateset_contains(gfsmStateSet *sset, gfsmStateId id);
+
+/** Insert a single state-id into a state-set.
+ * \returns true iff \a sset already contained \a id
+ */
+gboolean gfsm_stateset_insert(gfsmStateSet *sset, gfsmStateId id);
+
+/** Assign \a sset1 to be the union of itself with \a sset2 */
+gfsmStateSet *gfsm_stateset_union(gfsmStateSet *sset1, gfsmStateSet *sset2);
+
+/** Remove a state-id from a state-set
+ * \returns true iff \a sset contained \a id
+ */
+gboolean gfsm_stateset_remove(gfsmStateSet *sset, gfsmStateId id);
+
+/** Equality test */
+gboolean gfsm_stateset_equal(gfsmStateSet *sset1, gfsmStateSet *sset2);
+//@}
+
+/*======================================================================
+ * Methods: Iteration
+ */
+///\name Iteration
+//@{
+
+/// state-set iterator type
+typedef gfsmStateId* gfsmStateSetIter;
+
+/** Iterator access: get current state-id, or gfsmNoState if none defined */
+#define gfsm_stateset_iter_id(sseti) \
+ ((sseti) ? *(sseti) : gfsmNoState)
+
+/** Check validity of a state-set iterator */
+#define gfsm_stateset_iter_ok(sseti) \
+ ((sseti)!=NULL)
+
+/** Get first state in the state-set.
+ * \returns iterator (value) pointing to the first state in the
+ * state-set.
+ */
+#define gfsm_stateset_iter_begin(sset) \
+ ((gfsmStateId*)((sset)->data))
+
+/** Increment a state-set iterator one position. */
+#define gfsm_stateset_iter_next(sset,sseti) \
+ ((++(sseti)) < (((gfsmStateId*)((sset)->data))+((sset)->len)) \
+ ? (sseti) \
+ : NULL)
+
+/** Find an iterator pointing to the element for \a id in \a sset,
+ * or a bad iterator if no such element exists */
+gfsmStateSetIter gfsm_stateset_find(gfsmStateSet *sset, gfsmStateId id);
+
+//@}
+
+/*======================================================================
+ * Methods: Utiltiies
+ */
+///\name Utilities
+//@{
+
+/// typedef for iteration functions: return TRUE to stop iteration
+typedef gboolean (*gfsmStateSetForeachFunc) (gfsmStateId id, gpointer data);
+
+/** General iteration utilitiy for state-sets */
+void gfsm_stateset_foreach(gfsmStateSet *sset, gfsmStateSetForeachFunc func, gpointer data);
+
+/** Hashing function for state-sets */
+guint gfsm_stateset_hash(gfsmStateSet *sset);
+
+//@}
+
+/*======================================================================
+ * Methods: Automaton
+ */
+///\name Methods: Automaton access
+//@{
+
+/** Populate a state-set representing targets of arcs with
+ * lower label \a lo and upper label \a hi leaving state with id \a id
+ * in automaton \a fsm.
+ *
+ * If either \a lo or \a hi is gfsmNoLabel, the corresponding labels
+ * will be ignored.
+ *
+ * Note that this method does not clear \a sset.
+ */
+void gfsm_stateset_populate(gfsmStateSet *sset,
+ gfsmAutomaton *fsm,
+ gfsmStateId id,
+ gfsmLabelVal lo,
+ gfsmLabelVal hi);
+
+/** Convenience macro to populate a state-set from I/O-epsilon arcs */
+#define gfsm_stateset_populate_eps(sset,fsm,id) \
+ gfsm_stateset_populate((sset),(fsm),(id),gfsmEpsilon,gfsmEpsilon)
+
+/** Returns true iff some \a id in \a sset is a final state in \a fsm */
+gboolean gfsm_stateset_has_final_state(gfsmStateSet *sset, gfsmAutomaton *fsm);
+
+/** Lookup sum of final weights in \a fsm of states \a id in \a sset
+ * Returns TRUE iff at least one state in \a sset is final, and
+ * sets \a *wp to the sum of final weights.
+ */
+gboolean gfsm_stateset_lookup_final_weight(gfsmStateSet *sset, gfsmAutomaton *fsm, gfsmWeight *wp);
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmStateSet.hi>
+#endif
+
+#endif /* _GFSM_STATESET_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmStateSet.hi b/gfsm/gfsm/src/libgfsm/gfsmStateSet.hi
new file mode 100644
index 0000000..c2d1248
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmStateSet.hi
@@ -0,0 +1,154 @@
+
+/*=============================================================================*\
+ * File: gfsmStateSet.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: state sets: inlined definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+
+//--------------------------------------------------------------
+// sized_new()
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_sized_new(guint isize)
+{
+ return g_array_sized_new(FALSE,TRUE,sizeof(gfsmStateId),isize);
+}
+
+//--------------------------------------------------------------
+// new()
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_new(void)
+{
+ return gfsm_stateset_sized_new(gfsmStateSetDefaultSize);
+}
+
+//--------------------------------------------------------------
+// new_singleton()
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_new_singleton(gfsmStateId id)
+{
+ gfsmStateSet *sset = gfsm_stateset_new();
+ g_array_insert_val(sset,0,id);
+ return sset;
+}
+
+//--------------------------------------------------------------
+// clear()
+GFSM_INLINE
+void gfsm_stateset_clear(gfsmStateSet *sset)
+{
+ g_array_set_size(sset,0);
+}
+
+//--------------------------------------------------------------
+// clone()
+GFSM_INLINE
+gfsmStateSet *gfsm_stateset_clone(gfsmStateSet *src)
+{
+ return g_array_append_vals(gfsm_stateset_sized_new(src->len), src->data, src->len);
+}
+
+//--------------------------------------------------------------
+// free()
+GFSM_INLINE
+void gfsm_stateset_free(gfsmStateSet *sset)
+{
+ g_array_free(sset,TRUE);
+}
+
+/*======================================================================
+ * Methods: Accessors
+ */
+
+//--------------------------------------------------------------
+// min()
+GFSM_INLINE
+gfsmStateId gfsm_stateset_min(gfsmStateSet *sset)
+{
+ return sset->len > 0 ? (*((gfsmStateId*)sset->data)) : gfsmNoState;
+}
+
+//--------------------------------------------------------------
+// size()
+GFSM_INLINE
+guint gfsm_stateset_size(gfsmStateSet *sset)
+{
+ return sset->len;
+}
+
+//--------------------------------------------------------------
+// find()
+//--EXTERN
+
+//--------------------------------------------------------------
+// contains()
+GFSM_INLINE
+gboolean gfsm_stateset_contains(gfsmStateSet *sset, gfsmStateId id)
+{
+ gfsmStateSetIter sseti = gfsm_stateset_find(sset,id);
+ return sseti != NULL && *sseti != gfsmNoState;
+}
+
+//--------------------------------------------------------------
+// insert()
+//--EXTERN
+
+//--------------------------------------------------------------
+// union()
+//--EXTERN
+
+//--------------------------------------------------------------
+// remove()
+//--EXTERN
+
+//--------------------------------------------------------------
+// equal()
+//--EXTERN
+
+/*======================================================================
+ * Methods: Utilities
+ */
+
+//--------------------------------------------------------------
+// hash()
+//--EXTERN
+
+
+//--------------------------------------------------------------
+// foreach()
+//--EXTERN
+
+/*======================================================================
+ * Methods: Automaton access
+ */
+
+//--------------------------------------------------------------
+// populate()
+//--EXTERN
+
+//--------------------------------------------------------------
+// has_final_state()
+//--EXTERN
+
+//--------------------------------------------------------------
+// lookup_final_weight()
+//--EXTERN
diff --git a/gfsm/gfsm/src/libgfsm/gfsmTrie.c b/gfsm/gfsm/src/libgfsm/gfsmTrie.c
new file mode 100644
index 0000000..952e55d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmTrie.c
@@ -0,0 +1,282 @@
+
+/*=============================================================================*\
+ * File: gfsmTrie.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2006 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmTrie.h>
+#include <gfsmArcIter.h>
+
+/*======================================================================
+ * Constants
+ */
+
+const gfsmAutomatonFlags gfsmTrieDefaultFlags =
+ {
+ TRUE, //-- is_transducer:1
+ TRUE, //-- is_weighted:1
+ TRUE, //-- is_deterministic:1
+ gfsmASMLower, //-- sort_mode:24
+ 0 //-- unused:5
+ };
+
+const gfsmSRType gfsmTrieDefaultSRType = gfsmSRTReal;
+
+
+/*======================================================================
+ * Methods: ensure path (adding weight)
+ */
+
+//--------------------------------------------------------------
+gfsmStateId gfsm_trie_add_path(gfsmTrie *trie,
+ gfsmLabelVector *lo,
+ gfsmLabelVector *hi,
+ gfsmWeight w)
+{
+ return gfsm_trie_add_path_full(trie,lo,hi,w,TRUE,TRUE,TRUE,NULL);
+}
+
+
+//--------------------------------------------------------------
+gfsmStateId gfsm_trie_add_path_full(gfsmTrie *trie,
+ gfsmLabelVector *lo,
+ gfsmLabelVector *hi,
+ gfsmWeight w,
+ gboolean add_to_arcs,
+ gboolean add_to_state_final,
+ gboolean add_to_path_final,
+ gfsmStateIdVector *path_states
+ )
+{
+ gfsmStateId qid;
+ guint i;
+
+ //-- ensure trie has a root state
+ if (!gfsm_automaton_has_state(trie,trie->root_id)) {
+ trie->root_id = gfsm_automaton_add_state(trie);
+ }
+ qid = trie->root_id;
+
+ //-- initialize state-path, if specified
+ if (path_states) {
+ g_ptr_array_set_size(path_states, (lo ? lo->len : 0) + (hi ? hi->len : 0));
+ path_states->len = 0;
+ g_ptr_array_add(path_states, GUINT_TO_POINTER(qid));
+ }
+
+ //-- add lower path
+ for (i=0; lo && i < lo->len; i++) {
+ if (add_to_state_final) {
+ gfsm_automaton_set_final_state_full(trie, qid, TRUE,
+ gfsm_sr_plus(trie->sr, w, gfsm_automaton_get_final_weight(trie, qid)));
+ }
+ qid = gfsm_trie_get_arc_lower(trie, qid, ((gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(lo,i))), w, add_to_arcs);
+ if (path_states) g_ptr_array_add(path_states, GUINT_TO_POINTER(qid));
+ }
+
+ //-- add upper path
+ for (i=0; hi && i < hi->len; i++) {
+ if (add_to_state_final) {
+ gfsm_automaton_set_final_state_full(trie, qid, TRUE,
+ gfsm_sr_plus(trie->sr, w, gfsm_automaton_get_final_weight(trie, qid)));
+ }
+ qid = gfsm_trie_get_arc_upper(trie, qid, ((gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(hi,i))), w, add_to_arcs);
+ if (path_states) g_ptr_array_add(path_states, GUINT_TO_POINTER(qid));
+ }
+
+ //-- add final epsilon-arc
+ //qid = gfsm_trie_get_arc_both(trie, qid, gfsmEpsilon, gfsmEpsilon, w, add_to_arcs);
+ //if (path_states) g_ptr_array_add(path_states,qid);
+
+ if (add_to_state_final || add_to_path_final) {
+ gfsm_automaton_set_final_state_full(trie, qid, TRUE,
+ gfsm_sr_plus(trie->sr, w, gfsm_automaton_get_final_weight(trie, qid)));
+ } else {
+ gfsm_automaton_set_final_state(trie,qid,TRUE);
+ }
+
+ return qid;
+}
+
+/*======================================================================
+ * Methods: find prefix
+ */
+gfsmStateId gfsm_trie_find_prefix(gfsmTrie *trie,
+ gfsmLabelVector *lo,
+ gfsmLabelVector *hi,
+ guint *lo_i,
+ guint *hi_i,
+ gfsmWeight *w_last,
+ gfsmStateIdVector *path_states
+ )
+{
+ gfsmStateId qid = trie->root_id;
+ gfsmWeight fw, w = gfsm_sr_zero(trie->sr);
+ guint i, j=0;
+ gfsmArc *a;
+
+ //-- initialize state-path, if specified
+ if (path_states) {
+ g_ptr_array_set_size(path_states, (lo ? lo->len : 0) + (hi ? hi->len : 0));
+ path_states->len = 0;
+ g_ptr_array_add(path_states, GUINT_TO_POINTER(qid));
+ }
+
+ //-- find lower path
+ for (i=0; lo && i < lo->len; i++) {
+ if ( !(a=gfsm_trie_find_arc_lower(trie, qid, ((gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(lo,i))))) )
+ break;
+
+ qid = a->target;
+ w = a->weight;
+ if (path_states) g_ptr_array_add(path_states, GUINT_TO_POINTER(qid));
+ }
+
+ //-- find upper path
+ if (i==lo->len) {
+ for (j=0; hi && j < hi->len; j++) {
+ if ( !(a = gfsm_trie_find_arc_upper(trie, qid, ((gfsmLabelVal)GPOINTER_TO_UINT(g_ptr_array_index(hi,j))))) )
+ break;
+
+ qid = a->target;
+ w = a->weight;
+ if (path_states) g_ptr_array_add(path_states, GUINT_TO_POINTER(qid));
+ }
+
+ //-- final state?
+ if (j==hi->len && gfsm_automaton_lookup_final(trie, qid, &fw))
+ w = fw;
+ }
+
+ //-- output variables
+ if (lo_i) *lo_i = i;
+ if (hi_i) *hi_i = j;
+ if (w_last) *w_last = w;
+
+ return qid;
+}
+
+/*======================================================================
+ * Methods: find arcs
+ */
+
+//--------------------------------------------------------------
+gfsmArc* gfsm_trie_find_arc_lower(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab)
+{
+ gfsmArcIter ai;
+ gfsmArc *a=NULL;
+ for (gfsm_arciter_open(&ai, trie, qid), gfsm_arciter_seek_lower(&ai, lab);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_lower(&ai,lab))
+ {
+ a = gfsm_arciter_arc(&ai);
+ break;
+ }
+ gfsm_arciter_close(&ai);
+ return a;
+}
+
+//--------------------------------------------------------------
+gfsmArc* gfsm_trie_find_arc_upper(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab)
+{
+ gfsmArcIter ai;
+ gfsmArc *a=NULL;
+ for (gfsm_arciter_open(&ai, trie, qid), gfsm_arciter_seek_upper(&ai, lab);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_upper(&ai,lab))
+ {
+ a = gfsm_arciter_arc(&ai);
+ break;
+ }
+ gfsm_arciter_close(&ai);
+ return a;
+}
+
+//--------------------------------------------------------------
+gfsmArc* gfsm_trie_find_arc_both(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lo, gfsmLabelVal hi)
+{
+ gfsmArcIter ai;
+ gfsmArc *a=NULL;
+ for (gfsm_arciter_open(&ai,trie,qid), gfsm_arciter_seek_both(&ai,lo,hi);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_both(&ai,lo,hi))
+ {
+ a = gfsm_arciter_arc(&ai);
+ break;
+ }
+ gfsm_arciter_close(&ai);
+ return a;
+}
+
+
+/*======================================================================
+ * Methods: find or insert arcs
+ */
+
+//--------------------------------------------------------------
+gfsmStateId gfsm_trie_get_arc_lower(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab, gfsmWeight w, gboolean add_weight)
+{
+ gfsmArc *a=gfsm_trie_find_arc_lower(trie,qid,lab);
+
+ if (a==NULL) {
+ gfsmStateId qid2 = gfsm_automaton_add_state(trie);
+ gfsm_automaton_add_arc(trie,qid,qid2,lab,gfsmEpsilon, add_weight ? w : trie->sr->zero);
+ return qid2;
+ }
+
+ //-- found an existing arc
+ if (add_weight) a->weight = gfsm_sr_plus(trie->sr, a->weight, w);
+ return a->target;
+}
+
+//--------------------------------------------------------------
+gfsmStateId gfsm_trie_get_arc_upper(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab, gfsmWeight w, gboolean add_weight)
+{
+ gfsmArc *a=gfsm_trie_find_arc_upper(trie,qid,lab);
+
+ if (a==NULL) {
+ gfsmStateId qid2 = gfsm_automaton_add_state(trie);
+ gfsm_automaton_add_arc(trie,qid,qid2,gfsmEpsilon,lab, add_weight ? w : trie->sr->zero);
+ //trie->flags.is_deterministic = TRUE; //-- HACK
+ return qid2;
+ }
+
+ //-- found an existing arc
+ if (add_weight) a->weight = gfsm_sr_plus(trie->sr, a->weight, w);
+ return a->target;
+}
+
+//--------------------------------------------------------------
+gfsmStateId gfsm_trie_get_arc_both(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight w, gboolean add_weight)
+{
+ gfsmArc *a=gfsm_trie_find_arc_both(trie,qid,lo,hi);
+
+ if (a==NULL) {
+ gfsmStateId qid2 = gfsm_automaton_add_state(trie);
+ gfsm_automaton_add_arc(trie,qid,qid2,lo,hi, add_weight ? w : trie->sr->zero);
+ //trie->flags.is_deterministic = TRUE; //-- HACK
+ return qid2;
+ }
+
+ //-- found an existing arc
+ if (add_weight) a->weight = gfsm_sr_plus(trie->sr, a->weight, w);
+ return a->target;
+}
+
diff --git a/gfsm/gfsm/src/libgfsm/gfsmTrie.h b/gfsm/gfsm/src/libgfsm/gfsmTrie.h
new file mode 100644
index 0000000..430e1c1
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmTrie.h
@@ -0,0 +1,201 @@
+
+/*=============================================================================*\
+ * File: gfsmTrie.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmTrie.h
+ * \brief Deterministic prefix tree automata
+ */
+
+#ifndef _GFSM_TRIE_H
+#define _GFSM_TRIE_H
+
+#include <gfsmAutomaton.h>
+
+/*======================================================================
+ * Types: Trie
+ */
+/** Alias for gfsmAutomaton */
+typedef gfsmAutomaton gfsmTrie;
+
+/*======================================================================
+ * Constants
+ */
+/** Default initial Trie flags */
+extern const gfsmAutomatonFlags gfsmTrieDefaultFlags;
+
+/** Default initial Trie semiring */
+extern const gfsmSRType gfsmTrieDefaultSRType;
+
+
+/*======================================================================
+ * Methods: Constructors etc.
+ */
+///\name Constructors etc.
+//@{
+
+//------------------------------
+/** Create a new ::gfsmTrie automaton */
+#define gfsm_trie_new() \
+ gfsm_automaton_new_full(gfsmTrieDefaultFlags, gfsmTrieDefaultSRType, gfsmAutomatonDefaultSize)
+
+//@}
+
+
+/*======================================================================
+ * Methods: Manipulation
+ */
+///\name Manipulation
+//@{
+
+//------------------------------
+/** Add a string-pair \a (lo,hi) to the trie with weight \a w
+ * \param trie Trie
+ * \param lo lower string (NULL for epsilon)
+ * \param trie upper string (NULL for epsilon)
+ * \param w weight which is added (gfsm_sr_plus) to all arcs for this pair
+ * \returns Id of the final state of the added path
+ *
+ * \note really just a wrapper for \a gfsm_trie_add_path_full() with
+ * \a add_to_arcs=true , \a add_to_state_final=true, \a add_to_path_final=true.
+ */
+gfsmStateId gfsm_trie_add_path(gfsmTrie *trie,
+ gfsmLabelVector *lo,
+ gfsmLabelVector *hi,
+ gfsmWeight w);
+
+//------------------------------
+/** Add a string-pair \a (lo,hi) to the trie with weight \a w
+ * \param trie Trie
+ * \param lo lower string (NULL for epsilon)
+ * \param hi upper string (NULL for epsilon)
+ * \param w weight associated with this pair
+ * \param add_to_arcs whether to add (gfsm_sr_plus) \a w to all arc-weights
+ * \param add_to_state_final whether to add (gfsm_sr_plus) \a w to all intermediate state final-weights;
+ * implies that all states will be marked as final in the resulting automaton
+ * \param add_to_path_final whether to add (gfsm_sr_plus) \a w to the final weight for the last node
+ * in the path
+ * \param path_states If non-NULL, contains the state-path corresponding to \a (lo,hi) on return
+ * \returns Id of the final state of the added path
+ */
+gfsmStateId gfsm_trie_add_path_full(gfsmTrie *trie,
+ gfsmLabelVector *lo,
+ gfsmLabelVector *hi,
+ gfsmWeight w,
+ gboolean add_to_arcs,
+ gboolean add_to_state_final,
+ gboolean add_to_path_final,
+ gfsmStateIdVector *path_states
+ );
+
+/*======================================================================
+ * Methods: find path
+ */
+/** Find state of longest prefix for a string-pair \a (lo,hi) in the trie.
+ * \param trie Trie
+ * \param lo lower string (NULL for epsilon)
+ * \param hi upper string (NULL for epsilon)
+ * \param lo_i on return holds number of labels in \a lo which were matched
+ * \param hi_i on return holds number of labels in \a hi which were matched
+ * \param w_last pointer to weight of last arc followed or final weight
+ * \param path_states if non-NULL, contains the state-path corresponding to the prefix on return
+ * \returns Id of the state matching the longest prefix of \a (lo,hi)
+ */
+gfsmStateId gfsm_trie_find_prefix(gfsmTrie *trie,
+ gfsmLabelVector *lo,
+ gfsmLabelVector *hi,
+ guint *lo_i,
+ guint *hi_i,
+ gfsmWeight *w_last,
+ gfsmStateIdVector *path_states
+ );
+
+
+/*======================================================================
+ * Methods: find arcs
+ */
+/** Find an arc from state \a qid with lower label \a lab in trie \a trie.
+ * \param trie Trie
+ * \param qid outgoing state qid
+ * \param lab lower label
+ * \returns gfsmArc* or NULL on failure
+ */
+gfsmArc* gfsm_trie_find_arc_lower(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab);
+
+/** Find an arc from state \a qid with upper label \a lab in trie \a trie.
+ * \param trie Trie
+ * \param qid outgoing state qid
+ * \param lab upper label id
+ * \returns gfsmArc* or NULL on failure
+ */
+gfsmArc* gfsm_trie_find_arc_upper(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab);
+
+/** Find an arc from state \a qid with lower label \a lo and upper label \a hi in trie \a trie.
+ * \param trie Trie
+ * \param qid outgoing state qid
+ * \param lo lower label id
+ * \param hi upper label id
+ * \returns gfsmArc* or NULL on failure
+ */
+gfsmArc* gfsm_trie_find_arc_both(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lo, gfsmLabelVal hi);
+
+
+/*======================================================================
+ * Methods: find or insert arcs
+ */
+/** Find or insert an arc from state \a qid with lower label \a lab in trie \a trie;
+ * adding weight \a w.
+ * \param trie Trie
+ * \param qid outgoing state qid
+ * \param lab lower label
+ * \param w arc weight
+ * \param add_weight whether to add weight to the arc
+ * \returns gfsmStateId of the (unique) destination state
+ */
+gfsmStateId gfsm_trie_get_arc_lower(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab, gfsmWeight w, gboolean add_weight);
+
+/** Find or insert an arc from state \a qid with upper label \a lab in trie \a trie;
+ * adding weight \a w.
+ * \param trie Trie
+ * \param qid outgoing state qid
+ * \param lab upper label
+ * \param w arc weight
+ * \param add_weight whether to add weight to the arc
+ * \returns gfsmStateId of the (unique) destination state
+ */
+gfsmStateId gfsm_trie_get_arc_upper(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lab, gfsmWeight w, gboolean add_weight);
+
+/** Find or insert an arc from state \a qid with lower label \a lo and upper label \a hi
+ * with weight \a w in trie \a trie.
+ * \param trie Trie
+ * \param qid outgoing state qid
+ * \param lo lower label id
+ * \param hi upper label id
+ * \param w arc weight
+ * \param add_weight whether to add weight to the arc
+ * \returns gfsmStateId of the (unique) destination state
+ */
+gfsmStateId gfsm_trie_get_arc_both(gfsmTrie *trie, gfsmStateId qid, gfsmLabelVal lo, gfsmLabelVal hi, gfsmWeight w, gboolean add_weight);
+
+//@}
+
+
+#endif /* _GFSM_LOOKUP_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmUtils.c b/gfsm/gfsm/src/libgfsm/gfsmUtils.c
new file mode 100644
index 0000000..2fe8e1e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmUtils.c
@@ -0,0 +1,101 @@
+/*=============================================================================*\
+ * File: gfsmUtils.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <glib.h>
+#include <gfsmUtils.h>
+#include <gfsmError.h>
+#include <string.h>
+#include <errno.h>
+
+/*======================================================================
+ * glib utility functions
+ */
+
+/*--------------------------------------------------------------
+ * int_compare()
+ */
+gint gfsm_int_compare(gconstpointer a, gconstpointer b)
+{
+ return (GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a));
+}
+
+/*--------------------------------------------------------------
+ * int_compare_data()
+ */
+gint gfsm_int_compare_data(gconstpointer a, gconstpointer b, gpointer data)
+{
+ return (GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a));
+}
+
+/*--------------------------------------------------------------
+ * uint_compare()
+ */
+#define gfsm_uint_compare_code(a,b) \
+ ( GPOINTER_TO_UINT(a) < GPOINTER_TO_UINT(b) ? (-1) : (GPOINTER_TO_UINT(a) == GPOINTER_TO_UINT(b) ? 0 : 1) )
+ //( (gint) ((glong((guint)b)) - (glong((guint)a))) );
+
+gint gfsm_uint_compare(gconstpointer a, gconstpointer b)
+{
+ return gfsm_uint_compare_code(GPOINTER_TO_UINT(a),GPOINTER_TO_UINT(b));
+}
+
+/*--------------------------------------------------------------
+ * uint_compare_data()
+ */
+gint gfsm_uint_compare_data(gconstpointer a, gconstpointer b, gpointer data)
+{
+ return gfsm_uint_compare_code(a,b);
+}
+
+/*======================================================================
+ * Hash Utilties
+ */
+/*--------------------------------------------------------------
+ * gfsm_hash_clear_func()
+ */
+gboolean gfsm_hash_clear_func (gpointer key, gpointer value, gpointer user_data)
+{ return TRUE; };
+
+
+/*======================================================================
+ * File Utilties
+ */
+
+/*--------------------------------------------------------------
+ * open_filename()
+ */
+FILE *gfsm_open_filename(const char *filename, const char *mode, gfsmError **errp)
+{
+ FILE *f;
+ if (strcmp(filename,"-")==0) {
+ if (strchr(mode,'w')) f = stdout;
+ else f = stdin;
+ }
+ else if (!(f = fopen(filename,mode))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("fopen"), //-- code
+ "open failed for file '%s': %s",
+ filename, strerror(errno));
+ }
+ return f;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmUtils.h b/gfsm/gfsm/src/libgfsm/gfsmUtils.h
new file mode 100644
index 0000000..3734197
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmUtils.h
@@ -0,0 +1,72 @@
+
+/*=============================================================================*\
+ * File: gfsmUtils.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmUtils.h
+ * \brief Miscellaneous utilities
+ */
+
+#ifndef _GFSM_UTILS_H
+#define _GFSM_UTILS_H
+
+#include <stdio.h>
+#include <gfsmError.h>
+
+/*======================================================================
+ * Constants
+ */
+/*(none)*/
+
+/*======================================================================
+ * glib utility functions
+ */
+/** 3-way comparison predicate for integers */
+gint gfsm_int_compare(gconstpointer a, gconstpointer b);
+
+/** 3-way comparison predicate for integers, with user-data slot */
+gint gfsm_int_compare_data(gconstpointer a, gconstpointer b, gpointer data);
+
+/** 3-way comparison predicate for unsigned integers */
+gint gfsm_uint_compare(gconstpointer a, gconstpointer b);
+
+/** 3-way comparison predicate for unsigned integers, with user-data slot */
+gint gfsm_uint_compare_data(gconstpointer a, gconstpointer b, gpointer data);
+
+/*======================================================================
+ * Hash Utilties
+ */
+/** Utility function to clear hash tables */
+gboolean gfsm_hash_clear_func (gpointer key, gpointer value, gpointer user_data);
+
+/*======================================================================
+ * File Utilties
+ */
+/* Open a named file.
+ * The filename \a "-" may be used to indicate stdin or stdout,
+ * depending on \a mode.
+ *
+ * If the file cannot be opened, **errp is set (if non-NULL) and NULL is returned.
+ */
+FILE *gfsm_open_filename(const char *filename, const char *mode, gfsmError **errp);
+
+
+#endif /* _GFSM_UTILS_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmVersion.c b/gfsm/gfsm/src/libgfsm/gfsmVersion.c
new file mode 100644
index 0000000..86f55b3
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmVersion.c
@@ -0,0 +1,52 @@
+
+/*=============================================================================*\
+ * File: gfsmVersion.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmVersion.h>
+#include <gfsmUtils.h>
+
+#ifdef HAVE_CONFIG_H
+#include <gfsmConfig.h>
+#endif
+
+/*======================================================================
+ * Constants
+ */
+const gfsmVersionInfo gfsm_version =
+ {
+ GFSM_VERSION_MAJOR,
+ GFSM_VERSION_MINOR,
+ GFSM_VERSION_MICRO
+ };
+
+const char *gfsm_version_string = PACKAGE_VERSION;
+
+/*======================================================================
+ * Comparison
+ */
+int gfsm_version_compare(gfsmVersionInfo v1, gfsmVersionInfo v2)
+{
+ int rc;
+ if ((rc=gfsm_uint_compare(GUINT_TO_POINTER(v1.major),GUINT_TO_POINTER(v2.major)))) return rc;
+ else if ((rc=gfsm_uint_compare(GUINT_TO_POINTER(v1.minor),GUINT_TO_POINTER(v2.minor)))) return rc;
+ return gfsm_uint_compare(GUINT_TO_POINTER(v1.micro),GUINT_TO_POINTER(v2.micro));
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmVersion.h b/gfsm/gfsm/src/libgfsm/gfsmVersion.h
new file mode 100644
index 0000000..7e0a530
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmVersion.h
@@ -0,0 +1,73 @@
+
+/*=============================================================================*\
+ * File: gfsmVersion.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmVersion.h
+ * \brief Library version information
+ */
+
+#ifndef _GFSM_VERSION_H
+#define _GFSM_VERSION_H
+
+#include <glib.h>
+
+/*======================================================================
+ * Types
+ */
+/// Library Version information
+typedef struct {
+ guint32 major; /**< major version */
+ guint32 minor; /**< minor version */
+ guint32 micro; /**< micro version */
+} gfsmVersionInfo;
+
+/*======================================================================
+ * Constants
+ */
+/** Current version information */
+extern const gfsmVersionInfo gfsm_version;
+
+/** Current version string */
+extern const char *gfsm_version_string;
+
+/*======================================================================
+ * Comparison
+ */
+/** 3-way comparison two gfsmVersionInfo structures */
+int gfsm_version_compare(gfsmVersionInfo v1, gfsmVersionInfo v2);
+
+/** Equality check for gfsmVersionInfo structures */
+#define gfsm_version_eq(v1,v2) (gfsm_version_compare((gfsmVersionInfo)(v1),(gfsmVersionInfo)(v2))==0)
+
+/** Less-than comparison for gfsmVersionInfo structures: v1 < v2 */
+#define gfsm_version_less(v1,v2) (gfsm_version_compare((gfsmVersionInfo)(v1),(gfsmVersionInfo)(v2))<0)
+
+/** Less-than-or-equal comparison for gfsmVersionInfo structures: v1 <= v2 */
+#define gfsm_version_le(v1,v2) (gfsm_version_compare((gfsmVersionInfo)(v1),(gfsmVersionInfo)(v2))<=0)
+
+/** Greater-than comparison for gfsmVersionInfo structures: v1 > v2 */
+#define gfsm_version_greater(v1,v2) (gfsm_version_compare((gfsmVersionInfo)(v1),(gfsmVersionInfo)(v2))>0)
+
+/** Greater-than-or-equal comparison for gfsmVersionInfo structures: v1 >= v2 */
+#define gfsm_version_ge(v1,v2) (gfsm_version_compare((gfsmVersionInfo)(v1),(gfsmVersionInfo)(v2))>=0)
+
+#endif /* _GFSM_VERSION_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmWeightMap.c b/gfsm/gfsm/src/libgfsm/gfsmWeightMap.c
new file mode 100644
index 0000000..090b0d3
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmWeightMap.c
@@ -0,0 +1,54 @@
+/*=============================================================================*\
+ * File: gfsmWeightmap.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: weight maps: extern definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmWeightMap.h>
+#include <gfsmCompound.h>
+
+//-- (no-)inline definitions
+#ifndef GFSM_INLINE_ENABLED
+# include <gfsmWeightMap.hi>
+#endif
+
+//--------------------------------------------------------------
+// weightmap_to_array_foreach_func_()
+static
+gboolean gfsm_weightmap_to_array_foreach_func_(gpointer stateid_p, gpointer weight_p, gfsmStateWeightPairArray *array)
+{
+ gfsmStateWeightPair wp;
+ wp.id = GPOINTER_TO_UINT(stateid_p);
+ wp.w = gfsm_ptr2weight(weight_p);
+ g_array_append_val(array,wp);
+ return FALSE; //-- continue traversal
+}
+
+//--------------------------------------------------------------
+gfsmStateWeightPairArray *gfsm_weightmap_to_array(gfsmWeightMap *weightmap, gfsmStateWeightPairArray *array)
+{
+ if (!array) {
+ array = g_array_sized_new(FALSE,FALSE,sizeof(gfsmStateWeightPair),gfsm_weightmap_size(weightmap));
+ } else {
+ g_array_set_size(array,gfsm_weightmap_size(weightmap));
+ array->len = 0;
+ }
+ gfsm_weightmap_foreach(weightmap, (GTraverseFunc)gfsm_weightmap_to_array_foreach_func_, array);
+ return array;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gfsmWeightMap.h b/gfsm/gfsm/src/libgfsm/gfsmWeightMap.h
new file mode 100644
index 0000000..ef7a5d7
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmWeightMap.h
@@ -0,0 +1,222 @@
+
+/*=============================================================================*\
+ * File: gfsmWeightMap.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library
+ *
+ * Copyright (c) 2005-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+/** \file gfsmWeightMap.h
+ * \brief Abstract map from gpointers to gfsmWeights using GTree
+ */
+
+#ifndef _GFSM_WEIGHTMAP_H
+#define _GFSM_WEIGHTMAP_H
+
+#include <gfsmSet.h>
+#include <gfsmSemiring.h>
+
+/*======================================================================
+ * Types
+ */
+/** \brief Type for maps from arbitrary data to gfsmWeights with a balanced binary tree.
+ * \detail really just an ugly wrapper for GTree
+ */
+typedef GTree gfsmWeightMap;
+
+/** \brief Structure for mapping arbitrary data to gfsmWeights with a hash.
+ * \detail really just an ugly wrapper for GHashTable
+ */
+typedef struct {
+ GHashTable *table; ///< hash table which does the dirty work
+ gfsmDupFunc key_dup; ///< key copying function
+} gfsmWeightHash;
+
+/** \brief Union type for converting between gfsmWeight and gpointer.
+ * \detail Requires that sizeof(gpointer)>=sizeof(gfsmWeight) in order to work properly.
+ */
+typedef union {
+ gfsmWeight w; /**< Interpret underlying binary data as a gfsmWeight */
+ gpointer p; /**< Interpret underlying binary data as a gpointer */
+} gfsmWeightOrPointer;
+
+/** \brief Type for a GArray of ::gfsmStateWeightPair */
+typedef GArray gfsmStateWeightPairArray;
+
+/*======================================================================
+ * gfsmWeight <-> gpointer conversions
+ */
+
+///\name gfsmWeight <-> gpointer Conversions
+//@{
+
+/** Convert a gpointer to a gfsmWeight */
+GFSM_INLINE
+gfsmWeight gfsm_ptr2weight(const gpointer p);
+
+/** Macro to convert gfsmWeight->gpointer */
+GFSM_INLINE
+gpointer gfsm_weight2ptr(const gfsmWeight w);
+
+//@}
+
+/*======================================================================
+ * gfsmWeightMap: Constructors etc.
+ */
+
+///\name gfsmWeightMap: Constructors etc.
+//@{
+
+/** Create and return a new ::gfsmWeightMap
+ */
+GFSM_INLINE
+gfsmWeightMap *gfsm_weightmap_new_full(GCompareDataFunc key_cmp_func,
+ gpointer key_cmp_data,
+ GDestroyNotify key_free_func);
+
+/** Create and return a new weightmap which does not stored keys. */
+GFSM_INLINE
+gfsmWeightMap *gfsm_weightmap_new(GCompareFunc key_cmp_func);
+
+/** Copy weightmap \a src to \a dst. \returns \a dst */
+GFSM_INLINE
+gfsmWeightMap *gfsm_weightmap_copy(gfsmWeightMap *dst, gfsmWeightMap *src);
+
+/** Clear a ::gfsmWeightMap */
+GFSM_INLINE
+void gfsm_weightmap_clear(gfsmWeightMap *wm);
+
+/** Destroy a weightmap */
+GFSM_INLINE
+void gfsm_weightmap_free(gfsmWeightMap *wm);
+//@}
+
+
+/*======================================================================
+ * Accessors
+ */
+///\name gfsmWeightmap: Accessors
+//@{
+
+/** lookup: check weightmap membership */
+GFSM_INLINE
+gboolean gfsm_weightmap_contains(gfsmWeightMap *weightmap, gconstpointer key);
+
+/** extended lookup: get weight associated with key */
+GFSM_INLINE
+gboolean gfsm_weightmap_lookup(gfsmWeightMap *weightmap, gconstpointer key, gfsmWeight *wp);
+
+/** insert a new key->weight mapping into the weightmap */
+//#define _gfsm_weightmap_insert(weightmap,key,w) g_tree_insert((weightmap),((gpointer)(key)),gfsm_weight2ptr(w))
+
+/** insert a new key->weight mapping into the weightmap */
+GFSM_INLINE
+void gfsm_weightmap_insert(gfsmWeightMap *weightmap, gconstpointer key, gfsmWeight w);
+
+/** Get size of weightmap */
+#define gfsm_weightmap_size(weightmap) g_tree_nnodes(weightmap)
+
+/** Remove an element from a weightmap */
+#define gfsm_weightmap_remove(weightmap,key) g_tree_remove((weightmap),((gpointer)(key)))
+
+/** Traversal (see g_tree_foreach) */
+#define gfsm_weightmap_foreach(weightmap,func,data) g_tree_foreach((weightmap),(func),(data))
+
+/** Copy contents of a ::gfsmWeightMap into a ::gfsmStateWeightPairArray
+ * \param weightmap weightmap to examine
+ * \param array array to be populated, or NULL to allocate a new array
+ * \returns \a array, or a newly allocated ::gfsmStateWeightPairArray
+ * \note Caller is responsible for freeing \a array when it is no longer needed.
+ */
+gfsmStateWeightPairArray *gfsm_weightmap_to_array(gfsmWeightMap *weightmap, gfsmStateWeightPairArray *array);
+
+//@}
+
+
+
+/*======================================================================
+ * gfsmWeightHash: Constructors etc.
+ */
+///\name gfsmWeightHash: Constructors etc.
+//@{
+/** Create and return a new hashing weight-map */
+GFSM_INLINE
+gfsmWeightHash *gfsm_weighthash_new_full(gfsmDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func);
+
+/** create & return a new hashing weightmap (returned map will not copy or free keys */
+#define gfsm_weighthash_new(key_hash_f,key_equal_f) \
+ gfsm_weighthash_new_full(NULL,(key_hash_f),(key_equal_f),NULL)
+
+/** clear a weight-hash */
+GFSM_INLINE
+void gfsm_weighthash_clear(gfsmWeightHash *wh);
+
+/** destroy a weight-hash */
+GFSM_INLINE
+void gfsm_weighthash_free(gfsmWeightHash *wh);
+//@}
+
+
+/*======================================================================
+ * gfsmWeightHash: Accessors
+ */
+///\name gfsmWeightHash: Accessors
+//@{
+
+/** extended lookup: get weight associated with key */
+GFSM_INLINE
+gboolean gfsm_weighthash_lookup(gfsmWeightHash *wh, gconstpointer key, gfsmWeight *wp);
+
+/** insert a key->weight mapping into the weighthash */
+GFSM_INLINE
+void gfsm_weighthash_insert(gfsmWeightHash *wh, gconstpointer key, gfsmWeight w);
+
+/** Possibly insert a key->weight mapping into the weighthash
+ * The mapping \a (key=>w) is inserted if either no mapping for \a key exists in \a wh,
+ * or if \a w is strictly less-than the stored weight for \a key according to \a sr.
+ *
+ * \returns TRUE if the mapping was updated, otherwise FALSE.
+ */
+GFSM_INLINE
+gboolean gfsm_weighthash_insert_if_less(gfsmWeightHash *wh, gconstpointer key, gfsmWeight w, gfsmSemiring *sr);
+
+/** Possibly insert a key->weight mapping into the weighthash
+ * The mapping \a (key=>w) is inserted if no mapping for \a key exists in \a wh.
+ * Otherwise, the stored weight \a (stored_w) for \a key is set to \a (w+stored_w)
+ * just in case \a (w+stored_w) is strictly less than \a stored_w for \a key according to \a sr.
+ *
+ * \returns TRUE if the mapping was updated, otherwise FALSE.
+ */
+GFSM_INLINE
+gboolean gfsm_weighthash_insert_sum_if_less(gfsmWeightHash *wh, gconstpointer key, gfsmWeight w, gfsmSemiring *sr);
+
+/** Traversal (see g_hash_table_foreach) */
+#define gfsm_weighthash_foreach(wh,func,data) \
+ g_hash_table_foreach((wh)->table,(func),(data))
+
+//@}
+
+//-- inline definitions
+#ifdef GFSM_INLINE_ENABLED
+# include <gfsmWeightMap.hi>
+#endif
+
+#endif /* _GFSM_WEIGHTMAP_H */
diff --git a/gfsm/gfsm/src/libgfsm/gfsmWeightMap.hi b/gfsm/gfsm/src/libgfsm/gfsmWeightMap.hi
new file mode 100644
index 0000000..1361bb8
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmWeightMap.hi
@@ -0,0 +1,232 @@
+/*=============================================================================*\
+ * File: gfsmWeightmap.hi
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: weight maps: inlined definitions
+ *
+ * Copyright (c) 2004-2007 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmUtils.h>
+
+/*======================================================================
+ * gfsmWeight <-> gpointer conversions
+ */
+GFSM_INLINE
+gfsmWeight gfsm_ptr2weight(const gpointer p)
+{
+ gfsmWeightOrPointer wp;
+ wp.p=p;
+ return wp.w;
+}
+
+GFSM_INLINE
+gpointer gfsm_weight2ptr(const gfsmWeight w)
+{
+ gfsmWeightOrPointer wp;
+ wp.p=0;
+ wp.w=w;
+ return wp.p;
+}
+
+
+/*======================================================================
+ * gfsmWeightMap: Constructors etc.
+ */
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmWeightMap *gfsm_weightmap_new_full(GCompareDataFunc key_cmp_func,
+ gpointer key_cmp_data,
+ GDestroyNotify key_free_func)
+{
+ return g_tree_new_full(key_cmp_func,key_cmp_data,key_free_func,NULL);
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmWeightMap *gfsm_weightmap_new(GCompareFunc key_cmp_func)
+{
+ return g_tree_new(key_cmp_func);
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmWeightMap *gfsm_weightmap_copy(gfsmWeightMap *dst, gfsmWeightMap *src)
+{
+ return gfsm_set_copy(dst,src);
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+void gfsm_weightmap_clear(gfsmWeightMap *wm)
+{ gfsm_set_clear(wm); }
+
+//--------------------------------------------------------------
+GFSM_INLINE
+void gfsm_weightmap_free(gfsmWeightMap *wm)
+{
+ gfsm_set_free(wm);
+}
+
+/*======================================================================
+ * gfsmWeightMap: Accessors
+ */
+
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gboolean gfsm_weightmap_contains(gfsmWeightMap *weightmap, gconstpointer key)
+{
+ gfsmWeight w;
+ return gfsm_weightmap_lookup(weightmap, key, &w);
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gboolean gfsm_weightmap_lookup(gfsmWeightMap *weightmap, gconstpointer key, gfsmWeight *wp)
+{
+ gpointer orig_key, orig_value;
+ if (g_tree_lookup_extended(weightmap, key, &orig_key, &orig_value)) {
+ *wp = gfsm_ptr2weight(orig_value);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+void gfsm_weightmap_insert(gfsmWeightMap *weightmap, gconstpointer key, gfsmWeight w)
+{
+ g_tree_insert(weightmap, (gpointer)key, gfsm_weight2ptr(w));
+}
+
+/*======================================================================
+ * gfsmWeighHash: Constructors etc.
+ */
+//--------------------------------------------------------------
+GFSM_INLINE
+gfsmWeightHash *gfsm_weighthash_new_full(gfsmDupFunc key_dup_func,
+ GHashFunc key_hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func)
+{
+ gfsmWeightHash *wh = g_new(gfsmWeightHash,1);
+ wh->table = g_hash_table_new_full(key_hash_func, key_equal_func, key_destroy_func, NULL);
+ wh->key_dup = key_dup_func;
+ return wh;
+}
+
+
+//--------------------------------------------------------------
+GFSM_INLINE
+void gfsm_weighthash_clear(gfsmWeightHash *wh)
+{
+ g_hash_table_foreach_remove(wh->table, gfsm_hash_clear_func,NULL);
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+void gfsm_weighthash_free(gfsmWeightHash *wh)
+{
+ g_hash_table_destroy(wh->table);
+ g_free(wh);
+}
+
+
+/*======================================================================
+ * gfsmWeightHash: Accessors
+ */
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gboolean gfsm_weighthash_lookup(gfsmWeightHash *wh, gconstpointer key, gfsmWeight *wp)
+{
+ gpointer s_key, s_val;
+ if (g_hash_table_lookup_extended(wh->table, key, &s_key, &s_val)) {
+ *wp = gfsm_ptr2weight(s_val);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+void gfsm_weighthash_insert(gfsmWeightHash *wh, gconstpointer key, gfsmWeight w)
+{
+ gpointer s_key, s_val;
+ if (wh->key_dup && g_hash_table_lookup_extended(wh->table, key, &s_key, &s_val)) {
+ //-- already present: steal & replace
+ g_hash_table_steal(wh->table, s_key);
+ g_hash_table_insert(wh->table, s_key, gfsm_weight2ptr(w));
+ }
+ else {
+ //-- not yet present: insert new mapping
+ if (wh->key_dup) s_key = (*(wh->key_dup))(key);
+ else s_key = (gpointer)key;
+ g_hash_table_insert(wh->table, s_key, gfsm_weight2ptr(w));
+ }
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gboolean gfsm_weighthash_insert_if_less(gfsmWeightHash *wh, gconstpointer key, gfsmWeight w, gfsmSemiring *sr)
+{
+ gpointer s_key, s_val;
+ if (wh->key_dup && g_hash_table_lookup_extended(wh->table, key, &s_key, &s_val)) {
+ //-- already present
+ gfsmWeight s_w = gfsm_ptr2weight(s_val);
+ if (!gfsm_sr_less(sr, w, s_w)) return FALSE; //-- (s_w) <= (w) : no update required
+
+ //-- steal & update
+ g_hash_table_steal(wh->table, s_key);
+ g_hash_table_insert(wh->table, s_key, gfsm_weight2ptr(w));
+ }
+ else {
+ //-- not yet present: insert new mapping
+ if (wh->key_dup) s_key = (*(wh->key_dup))(key);
+ else s_key = (gpointer)key;
+ g_hash_table_insert(wh->table, s_key, gfsm_weight2ptr(w));
+ }
+
+ return TRUE; //-- update performed
+}
+
+//--------------------------------------------------------------
+GFSM_INLINE
+gboolean gfsm_weighthash_insert_sum_if_less(gfsmWeightHash *wh, gconstpointer key, gfsmWeight w, gfsmSemiring *sr)
+{
+ gpointer s_key, s_val;
+ if (wh->key_dup && g_hash_table_lookup_extended(wh->table, key, &s_key, &s_val)) {
+ //-- already present
+ gfsmWeight s_w = gfsm_ptr2weight(s_val);
+ w = gfsm_sr_plus(sr,w,s_w);
+ if (!gfsm_sr_less(sr,w,s_w)) return FALSE; //-- (s_w) <= (w+s_w) : no update required
+
+ //-- steal & update
+ g_hash_table_steal(wh->table, s_key);
+ g_hash_table_insert(wh->table, s_key, gfsm_weight2ptr(w));
+ }
+ else {
+ //-- not yet present: insert new mapping
+ if (wh->key_dup) s_key = (*(wh->key_dup))(key);
+ else s_key = (gpointer)key;
+ g_hash_table_insert(wh->table, s_key, gfsm_weight2ptr(w));
+ }
+
+ return TRUE; //-- update performed
+}
+
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/.cvsignore b/gfsm/gfsm/src/libgfsm/gnulib/.cvsignore
new file mode 100644
index 0000000..8ef01bb
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/.cvsignore
@@ -0,0 +1,13 @@
+.*~
+*~
+*.o
+*.lo
+*.a
+*.la
+*.so
+
+Makefile
+Makefile.in
+
+orig
+.libs
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/Makefile.am b/gfsm/gfsm/src/libgfsm/gnulib/Makefile.am
new file mode 100644
index 0000000..e879251
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/Makefile.am
@@ -0,0 +1,70 @@
+## Process this file with automake to produce Makefile.in.
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is free software, distributed under the terms of the GNU
+# General Public License. As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Automake, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=src/libgfsm/gnulib --m4-base=m4 --aux-dir=config --lgpl --libtool --macro-prefix=gl getdelim vasprintf
+
+##-- moo: cpp flags
+AM_CPPFLAGS = -I. -I.. -I@srcdir@ -I@srcdir@/..
+AM_CFLAGS = @gfsm_OFLAGS@ @gfsm_WFLAGS@
+
+AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies
+
+noinst_LTLIBRARIES = libgnu.la
+
+libgnu_la_SOURCES =
+libgnu_la_LIBADD = @LTLIBOBJS@
+EXTRA_DIST =
+BUILT_SOURCES =
+SUFFIXES =
+MOSTLYCLEANFILES =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+
+## begin gnulib module alloca-opt
+
+BUILT_SOURCES += $(ALLOCA_H)
+EXTRA_DIST += alloca_.h
+
+# We need the following in order to create <alloca.h> when the system
+# doesn't have one that works with the given compiler.
+alloca.h: alloca_.h
+ cp $(srcdir)/alloca_.h $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += alloca.h alloca.h-t
+
+## end gnulib module alloca-opt
+
+## begin gnulib module size_max
+
+libgnu_la_SOURCES += size_max.h
+
+## end gnulib module size_max
+
+## begin gnulib module vasnprintf
+
+libgnu_la_SOURCES += printf-args.h printf-parse.h vasnprintf.h
+
+## end gnulib module vasnprintf
+
+## begin gnulib module vasprintf
+
+libgnu_la_SOURCES += vasprintf.h
+
+## end gnulib module vasprintf
+
+## begin gnulib module xsize
+
+libgnu_la_SOURCES += xsize.h
+
+## end gnulib module xsize
+
+
+# Makefile.am ends here
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/Makefile.in b/gfsm/gfsm/src/libgfsm/gnulib/Makefile.in
new file mode 100644
index 0000000..9b296a8
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/Makefile.in
@@ -0,0 +1,555 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is free software, distributed under the terms of the GNU
+# General Public License. As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Automake, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=src/libgfsm/gnulib --m4-base=m4 --aux-dir=config --lgpl --libtool --macro-prefix=gl getdelim vasprintf
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/libgfsm/gnulib
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in asnprintf.c \
+ asprintf.c getdelim.c getdelim.h printf-args.c printf-parse.c \
+ vasnprintf.c vasprintf.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/alloca.m4 \
+ $(top_srcdir)/m4/eoverflow.m4 $(top_srcdir)/m4/getdelim.m4 \
+ $(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/intmax_t.m4 \
+ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/longdouble.m4 \
+ $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/onceonly_2_57.m4 \
+ $(top_srcdir)/m4/signed.m4 $(top_srcdir)/m4/size_max.m4 \
+ $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/vasnprintf.m4 \
+ $(top_srcdir)/m4/vasprintf.m4 $(top_srcdir)/m4/wchar_t.m4 \
+ $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/libgfsm/gfsmConfigAuto.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libgnu_la_DEPENDENCIES = @LTLIBOBJS@
+am_libgnu_la_OBJECTS =
+libgnu_la_OBJECTS = $(am_libgnu_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src/libgfsm
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libgnu_la_SOURCES)
+DIST_SOURCES = $(libgnu_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+ALLOCA_H = @ALLOCA_H@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BINDIST_CPU = @BINDIST_CPU@
+BINDIST_OS = @BINDIST_OS@
+BINDIST_PKGNAME = @BINDIST_PKGNAME@
+BINDIST_RELEASE = @BINDIST_RELEASE@
+BISON = @BISON@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIG_DOC_WANT_DVI = @CONFIG_DOC_WANT_DVI@
+CONFIG_DOC_WANT_HTML = @CONFIG_DOC_WANT_HTML@
+CONFIG_DOC_WANT_LATEX = @CONFIG_DOC_WANT_LATEX@
+CONFIG_DOC_WANT_MAN = @CONFIG_DOC_WANT_MAN@
+CONFIG_DOC_WANT_PDF = @CONFIG_DOC_WANT_PDF@
+CONFIG_DOC_WANT_PS = @CONFIG_DOC_WANT_PS@
+CONFIG_DOC_WANT_TXT = @CONFIG_DOC_WANT_TXT@
+CONFIG_OPTIONS = @CONFIG_OPTIONS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK = @DISTCHECK@
+DOC_GOGS = @DOC_GOGS@
+DOC_MAN1_GOGS = @DOC_MAN1_GOGS@
+DOC_MAN5_PODS = @DOC_MAN5_PODS@
+DOC_PODS = @DOC_PODS@
+DOC_PROG_INDEX_SKEL = @DOC_PROG_INDEX_SKEL@
+DOC_WANT_DVI_FALSE = @DOC_WANT_DVI_FALSE@
+DOC_WANT_DVI_TRUE = @DOC_WANT_DVI_TRUE@
+DOC_WANT_HTML_FALSE = @DOC_WANT_HTML_FALSE@
+DOC_WANT_HTML_TRUE = @DOC_WANT_HTML_TRUE@
+DOC_WANT_LATEX_FALSE = @DOC_WANT_LATEX_FALSE@
+DOC_WANT_LATEX_TRUE = @DOC_WANT_LATEX_TRUE@
+DOC_WANT_MAN_FALSE = @DOC_WANT_MAN_FALSE@
+DOC_WANT_MAN_TRUE = @DOC_WANT_MAN_TRUE@
+DOC_WANT_PDF_FALSE = @DOC_WANT_PDF_FALSE@
+DOC_WANT_PDF_TRUE = @DOC_WANT_PDF_TRUE@
+DOC_WANT_PS_FALSE = @DOC_WANT_PS_FALSE@
+DOC_WANT_PS_TRUE = @DOC_WANT_PS_TRUE@
+DOC_WANT_TXT_FALSE = @DOC_WANT_TXT_FALSE@
+DOC_WANT_TXT_TRUE = @DOC_WANT_TXT_TRUE@
+DOXYGEN = @DOXYGEN@
+DOXYGEN_SOURCES = @DOXYGEN_SOURCES@
+DOXY_DEFINES = @DOXY_DEFINES@
+DOXY_FILTER = @DOXY_FILTER@
+DOXY_INPUT_FILTER = @DOXY_INPUT_FILTER@
+DOXY_TAGFILES = @DOXY_TAGFILES@
+DOXY_WANT_HTML = @DOXY_WANT_HTML@
+DOXY_WANT_LATEX = @DOXY_WANT_LATEX@
+DOXY_WANT_MAN = @DOXY_WANT_MAN@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EOVERFLOW = @EOVERFLOW@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FLEX = @FLEX@
+GFSM_SRC_SUBDIRS = @GFSM_SRC_SUBDIRS@
+GFSM_SUBDIRS = @GFSM_SUBDIRS@
+GFSM_VERSION_MAJOR = @GFSM_VERSION_MAJOR@
+GFSM_VERSION_MICRO = @GFSM_VERSION_MICRO@
+GFSM_VERSION_MINOR = @GFSM_VERSION_MINOR@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GREP = @GREP@
+HAVE_BISON_FALSE = @HAVE_BISON_FALSE@
+HAVE_BISON_TRUE = @HAVE_BISON_TRUE@
+HAVE_DOXYGEN_FALSE = @HAVE_DOXYGEN_FALSE@
+HAVE_DOXYGEN_TRUE = @HAVE_DOXYGEN_TRUE@
+HAVE_DOXY_FILTER_FALSE = @HAVE_DOXY_FILTER_FALSE@
+HAVE_DOXY_FILTER_TRUE = @HAVE_DOXY_FILTER_TRUE@
+HAVE_FLEX_FALSE = @HAVE_FLEX_FALSE@
+HAVE_FLEX_TRUE = @HAVE_FLEX_TRUE@
+HAVE_OPTGEN_FALSE = @HAVE_OPTGEN_FALSE@
+HAVE_OPTGEN_TRUE = @HAVE_OPTGEN_TRUE@
+HAVE_POD2HTML_FALSE = @HAVE_POD2HTML_FALSE@
+HAVE_POD2HTML_TRUE = @HAVE_POD2HTML_TRUE@
+HAVE_POD2LATEX_FALSE = @HAVE_POD2LATEX_FALSE@
+HAVE_POD2LATEX_TRUE = @HAVE_POD2LATEX_TRUE@
+HAVE_POD2MAN_FALSE = @HAVE_POD2MAN_FALSE@
+HAVE_POD2MAN_TRUE = @HAVE_POD2MAN_TRUE@
+HAVE_POD2TEXT_FALSE = @HAVE_POD2TEXT_FALSE@
+HAVE_POD2TEXT_TRUE = @HAVE_POD2TEXT_TRUE@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+OPTGEN_PERL = @OPTGEN_PERL@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POD2HTML = @POD2HTML@
+POD2LATEX = @POD2LATEX@
+POD2MAN = @POD2MAN@
+POD2TEXT = @POD2TEXT@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gfsm_LIBS = @gfsm_LIBS@
+gfsm_OFLAGS = @gfsm_OFLAGS@
+gfsm_WFLAGS = @gfsm_WFLAGS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+pkgdocdir = @pkgdocdir@
+pkgdoclibdir = @pkgdoclibdir@
+pkgdocprogdir = @pkgdocprogdir@
+pkgdoctutdir = @pkgdoctutdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+spkgincludedir = @spkgincludedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AM_CPPFLAGS = -I. -I.. -I@srcdir@ -I@srcdir@/..
+AM_CFLAGS = @gfsm_OFLAGS@ @gfsm_WFLAGS@
+AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies
+noinst_LTLIBRARIES = libgnu.la
+libgnu_la_SOURCES = size_max.h printf-args.h printf-parse.h \
+ vasnprintf.h vasprintf.h xsize.h
+libgnu_la_LIBADD = @LTLIBOBJS@
+EXTRA_DIST = alloca_.h
+BUILT_SOURCES = $(ALLOCA_H)
+SUFFIXES =
+MOSTLYCLEANFILES = alloca.h alloca.h-t
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/libgfsm/gnulib/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnits src/libgfsm/gnulib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgnu.la: $(libgnu_la_OBJECTS) $(libgnu_la_DEPENDENCIES)
+ $(LINK) $(libgnu_la_LDFLAGS) $(libgnu_la_OBJECTS) $(libgnu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-info-am
+
+
+# We need the following in order to create <alloca.h> when the system
+# doesn't have one that works with the given compiler.
+alloca.h: alloca_.h
+ cp $(srcdir)/alloca_.h $@-t
+ mv $@-t $@
+
+# Makefile.am ends here
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/alloca_.h b/gfsm/gfsm/src/libgfsm/gnulib/alloca_.h
new file mode 100644
index 0000000..65a40ff
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/alloca_.h
@@ -0,0 +1,52 @@
+/* Memory allocation on the stack.
+
+ Copyright (C) 1995, 1999, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
+ means there is a real alloca function. */
+#ifndef _GNULIB_ALLOCA_H
+# define _GNULIB_ALLOCA_H
+
+/* alloca (N) returns a pointer to N bytes of memory
+ allocated on the stack, which will last until the function returns.
+ Use of alloca should be avoided:
+ - inside arguments of function calls - undefined behaviour,
+ - in inline functions - the allocation may actually last until the
+ calling function returns,
+ - for huge N (say, N >= 65536) - you never know how large (or small)
+ the stack is, and when the stack cannot fulfill the memory allocation
+ request, the program just crashes.
+ */
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#else
+# include <stddef.h>
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+#endif /* _GNULIB_ALLOCA_H */
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/asnprintf.c b/gfsm/gfsm/src/libgfsm/gnulib/asnprintf.c
new file mode 100644
index 0000000..ddc2cd3
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/asnprintf.c
@@ -0,0 +1,37 @@
+/* Formatted output to strings.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "vasnprintf.h"
+
+#include <stdarg.h>
+
+char *
+asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+{
+ va_list args;
+ char *result;
+
+ va_start (args, format);
+ result = vasnprintf (resultbuf, lengthp, format, args);
+ va_end (args);
+ return result;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/asprintf.c b/gfsm/gfsm/src/libgfsm/gnulib/asprintf.c
new file mode 100644
index 0000000..71466b3
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/asprintf.c
@@ -0,0 +1,37 @@
+/* Formatted output to strings.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "vasprintf.h"
+
+#include <stdarg.h>
+
+int
+asprintf (char **resultp, const char *format, ...)
+{
+ va_list args;
+ int result;
+
+ va_start (args, format);
+ result = vasprintf (resultp, format, args);
+ va_end (args);
+ return result;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/getdelim.c b/gfsm/gfsm/src/libgfsm/gnulib/getdelim.c
new file mode 100644
index 0000000..ab9a4eb
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/getdelim.c
@@ -0,0 +1,128 @@
+/* getdelim.c --- Implementation of replacement getdelim function.
+ Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+/* Ported from glibc by Simon Josefsson. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "getdelim.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+#ifndef SSIZE_MAX
+# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+#endif
+#if !HAVE_FLOCKFILE
+# undef flockfile
+# define flockfile(x) ((void) 0)
+#endif
+#if !HAVE_FUNLOCKFILE
+# undef funlockfile
+# define funlockfile(x) ((void) 0)
+#endif
+
+/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
+ NUL-terminate it). *LINEPTR is a pointer returned from malloc (or
+ NULL), pointing to *N characters of space. It is realloc'ed as
+ necessary. Returns the number of characters read (not including
+ the null terminator), or -1 on error or EOF. */
+
+ssize_t
+getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
+{
+ ssize_t result;
+ size_t cur_len = 0;
+
+ if (lineptr == NULL || n == NULL || fp == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ flockfile (fp);
+
+ if (*lineptr == NULL || *n == 0)
+ {
+ *n = 120;
+ *lineptr = (char *) malloc (*n);
+ if (*lineptr == NULL)
+ {
+ result = -1;
+ goto unlock_return;
+ }
+ }
+
+ for (;;)
+ {
+ int i;
+
+ i = getc (fp);
+ if (i == EOF)
+ {
+ result = -1;
+ break;
+ }
+
+ /* Make enough space for len+1 (for final NUL) bytes. */
+ if (cur_len + 1 >= *n)
+ {
+ size_t needed_max =
+ SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
+ size_t needed = 2 * *n + 1; /* Be generous. */
+ char *new_lineptr;
+
+ if (needed_max < needed)
+ needed = needed_max;
+ if (cur_len + 1 >= needed)
+ {
+ result = -1;
+ goto unlock_return;
+ }
+
+ new_lineptr = (char *) realloc (*lineptr, needed);
+ if (new_lineptr == NULL)
+ {
+ result = -1;
+ goto unlock_return;
+ }
+
+ *lineptr = new_lineptr;
+ *n = needed;
+ }
+
+ (*lineptr)[cur_len] = i;
+ cur_len++;
+
+ if (i == delimiter)
+ break;
+ }
+ (*lineptr)[cur_len] = '\0';
+ result = cur_len ? cur_len : result;
+
+ unlock_return:
+ funlockfile (fp);
+ return result;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/getdelim.h b/gfsm/gfsm/src/libgfsm/gnulib/getdelim.h
new file mode 100644
index 0000000..9e6c931
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/getdelim.h
@@ -0,0 +1,28 @@
+/* getdelim.h --- Prototype for replacement getdelim function.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+/* Written by Simon Josefsson. */
+
+/* Get size_t, FILE, ssize_t. And getdelim, if available. */
+# include <stddef.h>
+# include <stdio.h>
+# include <sys/types.h>
+
+#if !HAVE_DECL_GETDELIM
+ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *stream);
+#endif /* !HAVE_GETDELIM */
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/printf-args.c b/gfsm/gfsm/src/libgfsm/gnulib/printf-args.c
new file mode 100644
index 0000000..ba4b8b3
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/printf-args.c
@@ -0,0 +1,118 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "printf-args.h"
+
+#ifdef STATIC
+STATIC
+#endif
+int
+printf_fetchargs (va_list args, arguments *a)
+{
+ size_t i;
+ argument *ap;
+
+ for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
+ switch (ap->type)
+ {
+ case TYPE_SCHAR:
+ ap->a.a_schar = va_arg (args, /*signed char*/ int);
+ break;
+ case TYPE_UCHAR:
+ ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
+ break;
+ case TYPE_SHORT:
+ ap->a.a_short = va_arg (args, /*short*/ int);
+ break;
+ case TYPE_USHORT:
+ ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
+ break;
+ case TYPE_INT:
+ ap->a.a_int = va_arg (args, int);
+ break;
+ case TYPE_UINT:
+ ap->a.a_uint = va_arg (args, unsigned int);
+ break;
+ case TYPE_LONGINT:
+ ap->a.a_longint = va_arg (args, long int);
+ break;
+ case TYPE_ULONGINT:
+ ap->a.a_ulongint = va_arg (args, unsigned long int);
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ ap->a.a_longlongint = va_arg (args, long long int);
+ break;
+ case TYPE_ULONGLONGINT:
+ ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
+ break;
+#endif
+ case TYPE_DOUBLE:
+ ap->a.a_double = va_arg (args, double);
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ ap->a.a_longdouble = va_arg (args, long double);
+ break;
+#endif
+ case TYPE_CHAR:
+ ap->a.a_char = va_arg (args, int);
+ break;
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ ap->a.a_wide_char = va_arg (args, wint_t);
+ break;
+#endif
+ case TYPE_STRING:
+ ap->a.a_string = va_arg (args, const char *);
+ break;
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ ap->a.a_wide_string = va_arg (args, const wchar_t *);
+ break;
+#endif
+ case TYPE_POINTER:
+ ap->a.a_pointer = va_arg (args, void *);
+ break;
+ case TYPE_COUNT_SCHAR_POINTER:
+ ap->a.a_count_schar_pointer = va_arg (args, signed char *);
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ ap->a.a_count_short_pointer = va_arg (args, short *);
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ ap->a.a_count_int_pointer = va_arg (args, int *);
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ ap->a.a_count_longint_pointer = va_arg (args, long int *);
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
+ break;
+#endif
+ default:
+ /* Unknown type. */
+ return -1;
+ }
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/printf-args.h b/gfsm/gfsm/src/libgfsm/gnulib/printf-args.h
new file mode 100644
index 0000000..3806246
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/printf-args.h
@@ -0,0 +1,136 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _PRINTF_ARGS_H
+#define _PRINTF_ARGS_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* Get wchar_t. */
+#ifdef HAVE_WCHAR_T
+# include <stddef.h>
+#endif
+
+/* Get wint_t. */
+#ifdef HAVE_WINT_T
+# include <wchar.h>
+#endif
+
+/* Get va_list. */
+#include <stdarg.h>
+
+
+/* Argument types */
+typedef enum
+{
+ TYPE_NONE,
+ TYPE_SCHAR,
+ TYPE_UCHAR,
+ TYPE_SHORT,
+ TYPE_USHORT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_LONGINT,
+ TYPE_ULONGINT,
+#ifdef HAVE_LONG_LONG
+ TYPE_LONGLONGINT,
+ TYPE_ULONGLONGINT,
+#endif
+ TYPE_DOUBLE,
+#ifdef HAVE_LONG_DOUBLE
+ TYPE_LONGDOUBLE,
+#endif
+ TYPE_CHAR,
+#ifdef HAVE_WINT_T
+ TYPE_WIDE_CHAR,
+#endif
+ TYPE_STRING,
+#ifdef HAVE_WCHAR_T
+ TYPE_WIDE_STRING,
+#endif
+ TYPE_POINTER,
+ TYPE_COUNT_SCHAR_POINTER,
+ TYPE_COUNT_SHORT_POINTER,
+ TYPE_COUNT_INT_POINTER,
+ TYPE_COUNT_LONGINT_POINTER
+#ifdef HAVE_LONG_LONG
+, TYPE_COUNT_LONGLONGINT_POINTER
+#endif
+} arg_type;
+
+/* Polymorphic argument */
+typedef struct
+{
+ arg_type type;
+ union
+ {
+ signed char a_schar;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long int a_longint;
+ unsigned long int a_ulongint;
+#ifdef HAVE_LONG_LONG
+ long long int a_longlongint;
+ unsigned long long int a_ulonglongint;
+#endif
+ float a_float;
+ double a_double;
+#ifdef HAVE_LONG_DOUBLE
+ long double a_longdouble;
+#endif
+ int a_char;
+#ifdef HAVE_WINT_T
+ wint_t a_wide_char;
+#endif
+ const char* a_string;
+#ifdef HAVE_WCHAR_T
+ const wchar_t* a_wide_string;
+#endif
+ void* a_pointer;
+ signed char * a_count_schar_pointer;
+ short * a_count_short_pointer;
+ int * a_count_int_pointer;
+ long int * a_count_longint_pointer;
+#ifdef HAVE_LONG_LONG
+ long long int * a_count_longlongint_pointer;
+#endif
+ }
+ a;
+}
+argument;
+
+typedef struct
+{
+ size_t count;
+ argument *arg;
+}
+arguments;
+
+
+/* Fetch the arguments, putting them into a. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_fetchargs (va_list args, arguments *a);
+
+#endif /* _PRINTF_ARGS_H */
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/printf-parse.c b/gfsm/gfsm/src/libgfsm/gnulib/printf-parse.c
new file mode 100644
index 0000000..afd6247
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/printf-parse.c
@@ -0,0 +1,536 @@
+/* Formatted output to strings.
+ Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+/* Get size_t, NULL. */
+#include <stddef.h>
+
+/* Get intmax_t. */
+#if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+#endif
+
+/* malloc(), realloc(), free(). */
+#include <stdlib.h>
+
+/* Checked size_t computations. */
+#include "xsize.h"
+
+#if WIDE_CHAR_VERSION
+# define PRINTF_PARSE wprintf_parse
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+#else
+# define PRINTF_PARSE printf_parse
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
+{
+ const CHAR_T *cp = format; /* pointer into format */
+ size_t arg_posn = 0; /* number of regular arguments consumed */
+ size_t d_allocated; /* allocated elements of d->dir */
+ size_t a_allocated; /* allocated elements of a->arg */
+ size_t max_width_length = 0;
+ size_t max_precision_length = 0;
+
+ d->count = 0;
+ d_allocated = 1;
+ d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
+ if (d->dir == NULL)
+ /* Out of memory. */
+ return -1;
+
+ a->count = 0;
+ a_allocated = 0;
+ a->arg = NULL;
+
+#define REGISTER_ARG(_index_,_type_) \
+ { \
+ size_t n = (_index_); \
+ if (n >= a_allocated) \
+ { \
+ size_t memory_size; \
+ argument *memory; \
+ \
+ a_allocated = xtimes (a_allocated, 2); \
+ if (a_allocated <= n) \
+ a_allocated = xsum (n, 1); \
+ memory_size = xtimes (a_allocated, sizeof (argument)); \
+ if (size_overflow_p (memory_size)) \
+ /* Overflow, would lead to out of memory. */ \
+ goto error; \
+ memory = (a->arg \
+ ? realloc (a->arg, memory_size) \
+ : malloc (memory_size)); \
+ if (memory == NULL) \
+ /* Out of memory. */ \
+ goto error; \
+ a->arg = memory; \
+ } \
+ while (a->count <= n) \
+ a->arg[a->count++].type = TYPE_NONE; \
+ if (a->arg[n].type == TYPE_NONE) \
+ a->arg[n].type = (_type_); \
+ else if (a->arg[n].type != (_type_)) \
+ /* Ambiguous type for positional argument. */ \
+ goto error; \
+ }
+
+ while (*cp != '\0')
+ {
+ CHAR_T c = *cp++;
+ if (c == '%')
+ {
+ size_t arg_index = ARG_NONE;
+ DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
+
+ /* Initialize the next directive. */
+ dp->dir_start = cp - 1;
+ dp->flags = 0;
+ dp->width_start = NULL;
+ dp->width_end = NULL;
+ dp->width_arg_index = ARG_NONE;
+ dp->precision_start = NULL;
+ dp->precision_end = NULL;
+ dp->precision_arg_index = ARG_NONE;
+ dp->arg_index = ARG_NONE;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory later. */
+ goto error;
+ arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+
+ /* Read the flags. */
+ for (;;)
+ {
+ if (*cp == '\'')
+ {
+ dp->flags |= FLAG_GROUP;
+ cp++;
+ }
+ else if (*cp == '-')
+ {
+ dp->flags |= FLAG_LEFT;
+ cp++;
+ }
+ else if (*cp == '+')
+ {
+ dp->flags |= FLAG_SHOWSIGN;
+ cp++;
+ }
+ else if (*cp == ' ')
+ {
+ dp->flags |= FLAG_SPACE;
+ cp++;
+ }
+ else if (*cp == '#')
+ {
+ dp->flags |= FLAG_ALT;
+ cp++;
+ }
+ else if (*cp == '0')
+ {
+ dp->flags |= FLAG_ZERO;
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Parse the field width. */
+ if (*cp == '*')
+ {
+ dp->width_start = cp;
+ cp++;
+ dp->width_end = cp;
+ if (max_width_length < 1)
+ max_width_length = 1;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory later. */
+ goto error;
+ dp->width_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->width_arg_index == ARG_NONE)
+ {
+ dp->width_arg_index = arg_posn++;
+ if (dp->width_arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->width_arg_index, TYPE_INT);
+ }
+ else if (*cp >= '0' && *cp <= '9')
+ {
+ size_t width_length;
+
+ dp->width_start = cp;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->width_end = cp;
+ width_length = dp->width_end - dp->width_start;
+ if (max_width_length < width_length)
+ max_width_length = width_length;
+ }
+
+ /* Parse the precision. */
+ if (*cp == '.')
+ {
+ cp++;
+ if (*cp == '*')
+ {
+ dp->precision_start = cp - 1;
+ cp++;
+ dp->precision_end = cp;
+ if (max_precision_length < 2)
+ max_precision_length = 2;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory
+ later. */
+ goto error;
+ dp->precision_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->precision_arg_index == ARG_NONE)
+ {
+ dp->precision_arg_index = arg_posn++;
+ if (dp->precision_arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
+ }
+ else
+ {
+ size_t precision_length;
+
+ dp->precision_start = cp - 1;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->precision_end = cp;
+ precision_length = dp->precision_end - dp->precision_start;
+ if (max_precision_length < precision_length)
+ max_precision_length = precision_length;
+ }
+ }
+
+ {
+ arg_type type;
+
+ /* Parse argument type/size specifiers. */
+ {
+ int flags = 0;
+
+ for (;;)
+ {
+ if (*cp == 'h')
+ {
+ flags |= (1 << (flags & 1));
+ cp++;
+ }
+ else if (*cp == 'L')
+ {
+ flags |= 4;
+ cp++;
+ }
+ else if (*cp == 'l')
+ {
+ flags += 8;
+ cp++;
+ }
+#ifdef HAVE_INTMAX_T
+ else if (*cp == 'j')
+ {
+ if (sizeof (intmax_t) > sizeof (long))
+ {
+ /* intmax_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (intmax_t) > sizeof (int))
+ {
+ /* intmax_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+#endif
+ else if (*cp == 'z' || *cp == 'Z')
+ {
+ /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+ because the warning facility in gcc-2.95.2 understands
+ only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
+ if (sizeof (size_t) > sizeof (long))
+ {
+ /* size_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (size_t) > sizeof (int))
+ {
+ /* size_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else if (*cp == 't')
+ {
+ if (sizeof (ptrdiff_t) > sizeof (long))
+ {
+ /* ptrdiff_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (ptrdiff_t) > sizeof (int))
+ {
+ /* ptrdiff_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Read the conversion character. */
+ c = *cp++;
+ switch (c)
+ {
+ case 'd': case 'i':
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGLONGINT;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_LONGINT;
+ else if (flags & 2)
+ type = TYPE_SCHAR;
+ else if (flags & 1)
+ type = TYPE_SHORT;
+ else
+ type = TYPE_INT;
+ break;
+ case 'o': case 'u': case 'x': case 'X':
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_ULONGLONGINT;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_ULONGINT;
+ else if (flags & 2)
+ type = TYPE_UCHAR;
+ else if (flags & 1)
+ type = TYPE_USHORT;
+ else
+ type = TYPE_UINT;
+ break;
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+#ifdef HAVE_LONG_DOUBLE
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGDOUBLE;
+ else
+#endif
+ type = TYPE_DOUBLE;
+ break;
+ case 'c':
+ if (flags >= 8)
+#ifdef HAVE_WINT_T
+ type = TYPE_WIDE_CHAR;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_CHAR;
+ break;
+#ifdef HAVE_WINT_T
+ case 'C':
+ type = TYPE_WIDE_CHAR;
+ c = 'c';
+ break;
+#endif
+ case 's':
+ if (flags >= 8)
+#ifdef HAVE_WCHAR_T
+ type = TYPE_WIDE_STRING;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_STRING;
+ break;
+#ifdef HAVE_WCHAR_T
+ case 'S':
+ type = TYPE_WIDE_STRING;
+ c = 's';
+ break;
+#endif
+ case 'p':
+ type = TYPE_POINTER;
+ break;
+ case 'n':
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_COUNT_LONGLONGINT_POINTER;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_COUNT_LONGINT_POINTER;
+ else if (flags & 2)
+ type = TYPE_COUNT_SCHAR_POINTER;
+ else if (flags & 1)
+ type = TYPE_COUNT_SHORT_POINTER;
+ else
+ type = TYPE_COUNT_INT_POINTER;
+ break;
+ case '%':
+ type = TYPE_NONE;
+ break;
+ default:
+ /* Unknown conversion character. */
+ goto error;
+ }
+ }
+
+ if (type != TYPE_NONE)
+ {
+ dp->arg_index = arg_index;
+ if (dp->arg_index == ARG_NONE)
+ {
+ dp->arg_index = arg_posn++;
+ if (dp->arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->arg_index, type);
+ }
+ dp->conversion = c;
+ dp->dir_end = cp;
+ }
+
+ d->count++;
+ if (d->count >= d_allocated)
+ {
+ size_t memory_size;
+ DIRECTIVE *memory;
+
+ d_allocated = xtimes (d_allocated, 2);
+ memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
+ if (size_overflow_p (memory_size))
+ /* Overflow, would lead to out of memory. */
+ goto error;
+ memory = realloc (d->dir, memory_size);
+ if (memory == NULL)
+ /* Out of memory. */
+ goto error;
+ d->dir = memory;
+ }
+ }
+ }
+ d->dir[d->count].dir_start = cp;
+
+ d->max_width_length = max_width_length;
+ d->max_precision_length = max_precision_length;
+ return 0;
+
+error:
+ if (a->arg)
+ free (a->arg);
+ if (d->dir)
+ free (d->dir);
+ return -1;
+}
+
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef PRINTF_PARSE
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/printf-parse.h b/gfsm/gfsm/src/libgfsm/gnulib/printf-parse.h
new file mode 100644
index 0000000..6d254e4
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/printf-parse.h
@@ -0,0 +1,74 @@
+/* Parse printf format string.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _PRINTF_PARSE_H
+#define _PRINTF_PARSE_H
+
+#include "printf-args.h"
+
+
+/* Flags */
+#define FLAG_GROUP 1 /* ' flag */
+#define FLAG_LEFT 2 /* - flag */
+#define FLAG_SHOWSIGN 4 /* + flag */
+#define FLAG_SPACE 8 /* space flag */
+#define FLAG_ALT 16 /* # flag */
+#define FLAG_ZERO 32
+
+/* arg_index value indicating that no argument is consumed. */
+#define ARG_NONE (~(size_t)0)
+
+/* A parsed directive. */
+typedef struct
+{
+ const char* dir_start;
+ const char* dir_end;
+ int flags;
+ const char* width_start;
+ const char* width_end;
+ size_t width_arg_index;
+ const char* precision_start;
+ const char* precision_end;
+ size_t precision_arg_index;
+ char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
+ size_t arg_index;
+}
+char_directive;
+
+/* A parsed format string. */
+typedef struct
+{
+ size_t count;
+ char_directive *dir;
+ size_t max_width_length;
+ size_t max_precision_length;
+}
+char_directives;
+
+
+/* Parses the format string. Fills in the number N of directives, and fills
+ in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+ to the end of the format string. Also fills in the arg_type fields of the
+ arguments and the needed count of arguments. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_parse (const char *format, char_directives *d, arguments *a);
+
+#endif /* _PRINTF_PARSE_H */
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/size_max.h b/gfsm/gfsm/src/libgfsm/gnulib/size_max.h
new file mode 100644
index 0000000..3bb87ae
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/size_max.h
@@ -0,0 +1,27 @@
+/* size_max.h -- declare SIZE_MAX through system headers
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Written by Simon Josefsson.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef GNULIB_SIZE_MAX_H
+#define GNULIB_SIZE_MAX_H
+
+# include <limits.h>
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+
+#endif /* GNULIB_SIZE_MAX_H */
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.c b/gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.c
new file mode 100644
index 0000000..1e5ecd5
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.c
@@ -0,0 +1,901 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 1999, 2002-2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#ifndef IN_LIBINTL
+# include <alloca.h>
+#endif
+
+/* Specification. */
+#if WIDE_CHAR_VERSION
+# include "vasnwprintf.h"
+#else
+# include "vasnprintf.h"
+#endif
+
+#include <stdio.h> /* snprintf(), sprintf() */
+#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
+#include <string.h> /* memcpy(), strlen() */
+#include <errno.h> /* errno */
+#include <limits.h> /* CHAR_BIT, INT_MAX */
+#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+/* Checked size_t computations. */
+#include "xsize.h"
+
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
+#ifdef HAVE_WCHAR_T
+# ifdef HAVE_WCSLEN
+# define local_wcslen wcslen
+# else
+ /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+ a dependency towards this library, here is a local substitute.
+ Define this substitute only once, even if this file is included
+ twice in the same compilation unit. */
+# ifndef local_wcslen_defined
+# define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+ const wchar_t *ptr;
+
+ for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+ ;
+ return ptr - s;
+}
+# endif
+# endif
+#endif
+
+#if WIDE_CHAR_VERSION
+# define VASNPRINTF vasnwprintf
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+# define PRINTF_PARSE wprintf_parse
+# define USE_SNPRINTF 1
+# if HAVE_DECL__SNWPRINTF
+ /* On Windows, the function swprintf() has a different signature than
+ on Unix; we use the _snwprintf() function instead. */
+# define SNPRINTF _snwprintf
+# else
+ /* Unix. */
+# define SNPRINTF swprintf
+# endif
+#else
+# define VASNPRINTF vasnprintf
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+# define PRINTF_PARSE printf_parse
+# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
+# if HAVE_DECL__SNPRINTF
+ /* Windows. */
+# define SNPRINTF _snprintf
+# else
+ /* Unix. */
+# define SNPRINTF snprintf
+# endif
+#endif
+
+CHAR_T *
+VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
+{
+ DIRECTIVES d;
+ arguments a;
+
+ if (PRINTF_PARSE (format, &d, &a) < 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+#define CLEANUP() \
+ free (d.dir); \
+ if (a.arg) \
+ free (a.arg);
+
+ if (printf_fetchargs (args, &a) < 0)
+ {
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+ {
+ size_t buf_neededlength;
+ CHAR_T *buf;
+ CHAR_T *buf_malloced;
+ const CHAR_T *cp;
+ size_t i;
+ DIRECTIVE *dp;
+ /* Output string accumulator. */
+ CHAR_T *result;
+ size_t allocated;
+ size_t length;
+
+ /* Allocate a small buffer that will hold a directive passed to
+ sprintf or snprintf. */
+ buf_neededlength =
+ xsum4 (7, d.max_width_length, d.max_precision_length, 6);
+#if HAVE_ALLOCA
+ if (buf_neededlength < 4000 / sizeof (CHAR_T))
+ {
+ buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
+ buf_malloced = NULL;
+ }
+ else
+#endif
+ {
+ size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
+ if (size_overflow_p (buf_memsize))
+ goto out_of_memory_1;
+ buf = (CHAR_T *) malloc (buf_memsize);
+ if (buf == NULL)
+ goto out_of_memory_1;
+ buf_malloced = buf;
+ }
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+ /* Ensures that allocated >= needed. Aborts through a jump to
+ out_of_memory if needed is SIZE_MAX or otherwise too big. */
+#define ENSURE_ALLOCATION(needed) \
+ if ((needed) > allocated) \
+ { \
+ size_t memory_size; \
+ CHAR_T *memory; \
+ \
+ allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
+ if ((needed) > allocated) \
+ allocated = (needed); \
+ memory_size = xtimes (allocated, sizeof (CHAR_T)); \
+ if (size_overflow_p (memory_size)) \
+ goto out_of_memory; \
+ if (result == resultbuf || result == NULL) \
+ memory = (CHAR_T *) malloc (memory_size); \
+ else \
+ memory = (CHAR_T *) realloc (result, memory_size); \
+ if (memory == NULL) \
+ goto out_of_memory; \
+ if (result == resultbuf && length > 0) \
+ memcpy (memory, result, length * sizeof (CHAR_T)); \
+ result = memory; \
+ }
+
+ for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
+ {
+ if (cp != dp->dir_start)
+ {
+ size_t n = dp->dir_start - cp;
+ size_t augmented_length = xsum (length, n);
+
+ ENSURE_ALLOCATION (augmented_length);
+ memcpy (result + length, cp, n * sizeof (CHAR_T));
+ length = augmented_length;
+ }
+ if (i == d.count)
+ break;
+
+ /* Execute a single directive. */
+ if (dp->conversion == '%')
+ {
+ size_t augmented_length;
+
+ if (!(dp->arg_index == ARG_NONE))
+ abort ();
+ augmented_length = xsum (length, 1);
+ ENSURE_ALLOCATION (augmented_length);
+ result[length] = '%';
+ length = augmented_length;
+ }
+ else
+ {
+ if (!(dp->arg_index != ARG_NONE))
+ abort ();
+
+ if (dp->conversion == 'n')
+ {
+ switch (a.arg[dp->arg_index].type)
+ {
+ case TYPE_COUNT_SCHAR_POINTER:
+ *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_short_pointer = length;
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_int_pointer = length;
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
+ break;
+#endif
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ CHAR_T *p;
+ unsigned int prefix_count;
+ int prefixes[2];
+#if !USE_SNPRINTF
+ size_t tmp_length;
+ CHAR_T tmpbuf[700];
+ CHAR_T *tmp;
+
+ /* Allocate a temporary buffer of sufficient size for calling
+ sprintf. */
+ {
+ size_t width;
+ size_t precision;
+
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ width = (arg < 0 ? (unsigned int) (-arg) : arg);
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ }
+
+ precision = 6;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ precision = (arg < 0 ? 0 : arg);
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ }
+ }
+
+ switch (dp->conversion)
+ {
+
+ case 'd': case 'i': case 'u':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ break;
+
+ case 'o':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ break;
+
+ case 'x': case 'X':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ break;
+
+ case 'f': case 'F':
+# ifdef HAVE_LONG_DOUBLE
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) (LDBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 10; /* sign, decimal point etc. */
+ else
+# endif
+ tmp_length =
+ (unsigned int) (DBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 10; /* sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, precision);
+ break;
+
+ case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+ tmp_length =
+ 12; /* sign, decimal point, exponent etc. */
+ tmp_length = xsum (tmp_length, precision);
+ break;
+
+ case 'c':
+# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
+ if (type == TYPE_WIDE_CHAR)
+ tmp_length = MB_CUR_MAX;
+ else
+# endif
+ tmp_length = 1;
+ break;
+
+ case 's':
+# ifdef HAVE_WCHAR_T
+ if (type == TYPE_WIDE_STRING)
+ {
+ tmp_length =
+ local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
+
+# if !WIDE_CHAR_VERSION
+ tmp_length = xtimes (tmp_length, MB_CUR_MAX);
+# endif
+ }
+ else
+# endif
+ tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
+ break;
+
+ case 'p':
+ tmp_length =
+ (unsigned int) (sizeof (void *) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading 0x */
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
+ }
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
+
+ if (size_overflow_p (tmp_memsize))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ tmp = (CHAR_T *) malloc (tmp_memsize);
+ if (tmp == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ }
+#endif
+
+ /* Construct the format string for calling snprintf or
+ sprintf. */
+ p = buf;
+ *p++ = '%';
+ if (dp->flags & FLAG_GROUP)
+ *p++ = '\'';
+ if (dp->flags & FLAG_LEFT)
+ *p++ = '-';
+ if (dp->flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ if (dp->flags & FLAG_SPACE)
+ *p++ = ' ';
+ if (dp->flags & FLAG_ALT)
+ *p++ = '#';
+ if (dp->flags & FLAG_ZERO)
+ *p++ = '0';
+ if (dp->width_start != dp->width_end)
+ {
+ size_t n = dp->width_end - dp->width_start;
+ memcpy (p, dp->width_start, n * sizeof (CHAR_T));
+ p += n;
+ }
+ if (dp->precision_start != dp->precision_end)
+ {
+ size_t n = dp->precision_end - dp->precision_start;
+ memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
+ p += n;
+ }
+
+ switch (type)
+ {
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ case TYPE_ULONGLONGINT:
+ *p++ = 'l';
+ /*FALLTHROUGH*/
+#endif
+ case TYPE_LONGINT:
+ case TYPE_ULONGINT:
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+#endif
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+#endif
+ *p++ = 'l';
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ *p++ = 'L';
+ break;
+#endif
+ default:
+ break;
+ }
+ *p = dp->conversion;
+#if USE_SNPRINTF
+ p[1] = '%';
+ p[2] = 'n';
+ p[3] = '\0';
+#else
+ p[1] = '\0';
+#endif
+
+ /* Construct the arguments for calling snprintf or sprintf. */
+ prefix_count = 0;
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
+ }
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
+ }
+
+#if USE_SNPRINTF
+ /* Prepare checking whether snprintf returns the count
+ via %n. */
+ ENSURE_ALLOCATION (xsum (length, 1));
+ result[length] = '\0';
+#endif
+
+ for (;;)
+ {
+ size_t maxlen;
+ int count;
+ int retcount;
+
+ maxlen = allocated - length;
+ count = -1;
+ retcount = 0;
+
+#if USE_SNPRINTF
+# define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ arg, &count); \
+ break; \
+ case 1: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ prefixes[0], arg, &count); \
+ break; \
+ case 2: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ prefixes[0], prefixes[1], arg, \
+ &count); \
+ break; \
+ default: \
+ abort (); \
+ }
+#else
+# define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ count = sprintf (tmp, buf, arg); \
+ break; \
+ case 1: \
+ count = sprintf (tmp, buf, prefixes[0], arg); \
+ break; \
+ case 2: \
+ count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
+ arg); \
+ break; \
+ default: \
+ abort (); \
+ }
+#endif
+
+ switch (type)
+ {
+ case TYPE_SCHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_schar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UCHAR:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_SHORT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_short;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_USHORT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_INT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_int;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UINT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_LONGINT:
+ {
+ long int arg = a.arg[dp->arg_index].a.a_longint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGINT:
+ {
+ unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ {
+ long long int arg = a.arg[dp->arg_index].a.a_longlongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGLONGINT:
+ {
+ unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_DOUBLE:
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_CHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ {
+ wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_STRING:
+ {
+ const char *arg = a.arg[dp->arg_index].a.a_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ {
+ const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_POINTER:
+ {
+ void *arg = a.arg[dp->arg_index].a.a_pointer;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ default:
+ abort ();
+ }
+
+#if USE_SNPRINTF
+ /* Portability: Not all implementations of snprintf()
+ are ISO C 99 compliant. Determine the number of
+ bytes that snprintf() has produced or would have
+ produced. */
+ if (count >= 0)
+ {
+ /* Verify that snprintf() has NUL-terminated its
+ result. */
+ if (count < maxlen && result[length + count] != '\0')
+ abort ();
+ /* Portability hack. */
+ if (retcount > count)
+ count = retcount;
+ }
+ else
+ {
+ /* snprintf() doesn't understand the '%n'
+ directive. */
+ if (p[1] != '\0')
+ {
+ /* Don't use the '%n' directive; instead, look
+ at the snprintf() return value. */
+ p[1] = '\0';
+ continue;
+ }
+ else
+ {
+ /* Look at the snprintf() return value. */
+ if (retcount < 0)
+ {
+ /* HP-UX 10.20 snprintf() is doubly deficient:
+ It doesn't understand the '%n' directive,
+ *and* it returns -1 (rather than the length
+ that would have been required) when the
+ buffer is too small. */
+ size_t bigger_need =
+ xsum (xtimes (allocated, 2), 12);
+ ENSURE_ALLOCATION (bigger_need);
+ continue;
+ }
+ else
+ count = retcount;
+ }
+ }
+#endif
+
+ /* Attempt to handle failure. */
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+#if !USE_SNPRINTF
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+#endif
+
+ /* Make room for the result. */
+ if (count >= maxlen)
+ {
+ /* Need at least count bytes. But allocate
+ proportionally, to avoid looping eternally if
+ snprintf() reports a too small count. */
+ size_t n =
+ xmax (xsum (length, count), xtimes (allocated, 2));
+
+ ENSURE_ALLOCATION (n);
+#if USE_SNPRINTF
+ continue;
+#endif
+ }
+
+#if USE_SNPRINTF
+ /* The snprintf() result did fit. */
+#else
+ /* Append the sprintf() result. */
+ memcpy (result + length, tmp, count * sizeof (CHAR_T));
+ if (tmp != tmpbuf)
+ free (tmp);
+#endif
+
+ length += count;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Add the final NUL. */
+ ENSURE_ALLOCATION (xsum (length, 1));
+ result[length] = '\0';
+
+ if (result != resultbuf && length + 1 < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ CHAR_T *memory;
+
+ memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ *lengthp = length;
+ if (length > INT_MAX)
+ goto length_overflow;
+ return result;
+
+ length_overflow:
+ /* We could produce such a big string, but its length doesn't fit into
+ an 'int'. POSIX says that snprintf() fails with errno = EOVERFLOW in
+ this case. */
+ if (result != resultbuf)
+ free (result);
+ errno = EOVERFLOW;
+ return NULL;
+
+ out_of_memory:
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ out_of_memory_1:
+ CLEANUP ();
+ errno = ENOMEM;
+ return NULL;
+ }
+}
+
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef VASNPRINTF
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.h b/gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.h
new file mode 100644
index 0000000..3ed5714
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.h
@@ -0,0 +1,77 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 2002-2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _VASNPRINTF_H
+#define _VASNPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get size_t. */
+#include <stddef.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ You can pass a preallocated buffer for the result in RESULTBUF and its
+ size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+ If successful, return the address of the string (this may be = RESULTBUF
+ if no dynamic memory allocation was necessary) and set *LENGTHP to the
+ number of resulting bytes, excluding the trailing NUL. Upon error, set
+ errno and return NULL.
+
+ When dynamic memory allocation occurs, the preallocated buffer is left
+ alone (with possibly modified contents). This makes it possible to use
+ a statically allocated or stack-allocated buffer, like this:
+
+ char buf[100];
+ size_t len = sizeof (buf);
+ char *output = vasnprintf (buf, &len, format, args);
+ if (output == NULL)
+ ... error handling ...;
+ else
+ {
+ ... use the output string ...;
+ if (output != buf)
+ free (output);
+ }
+ */
+extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNPRINTF_H */
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/vasprintf.c b/gfsm/gfsm/src/libgfsm/gnulib/vasprintf.c
new file mode 100644
index 0000000..3ee1721
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/vasprintf.c
@@ -0,0 +1,42 @@
+/* Formatted output to strings.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "vasprintf.h"
+
+#include <stdlib.h>
+
+#include "vasnprintf.h"
+
+int
+vasprintf (char **resultp, const char *format, va_list args)
+{
+ size_t length;
+ char *result = vasnprintf (NULL, &length, format, args);
+ if (result == NULL)
+ return -1;
+
+ *resultp = result;
+ /* Return the number of resulting bytes, excluding the trailing NUL.
+ If it wouldn't fit in an 'int', vasnprintf() would have returned NULL
+ and set errno to EOVERFLOW. */
+ return length;
+}
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/vasprintf.h b/gfsm/gfsm/src/libgfsm/gnulib/vasprintf.h
new file mode 100644
index 0000000..d12514b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/vasprintf.h
@@ -0,0 +1,63 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _VASPRINTF_H
+#define _VASPRINTF_H
+
+#if HAVE_VASPRINTF
+
+/* Get asprintf(), vasprintf() declarations. */
+#include <stdio.h>
+
+#else
+
+/* Get va_list. */
+#include <stdarg.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ If the memory allocation succeeds, store the address of the string in
+ *RESULT and return the number of resulting bytes, excluding the trailing
+ NUL. Upon memory allocation error, or some other error, return -1. */
+extern int asprintf (char **result, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+extern int vasprintf (char **result, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif /* _VASPRINTF_H */
diff --git a/gfsm/gfsm/src/libgfsm/gnulib/xsize.h b/gfsm/gfsm/src/libgfsm/gnulib/xsize.h
new file mode 100644
index 0000000..65356bb
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gnulib/xsize.h
@@ -0,0 +1,108 @@
+/* xsize.h -- Checked size_t computations.
+
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _XSIZE_H
+#define _XSIZE_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* Get SIZE_MAX. */
+#include <limits.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+/* The size of memory objects is often computed through expressions of
+ type size_t. Example:
+ void* p = malloc (header_size + n * element_size).
+ These computations can lead to overflow. When this happens, malloc()
+ returns a piece of memory that is way too small, and the program then
+ crashes while attempting to fill the memory.
+ To avoid this, the functions and macros in this file check for overflow.
+ The convention is that SIZE_MAX represents overflow.
+ malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
+ implementation that uses mmap --, it's recommended to use size_overflow_p()
+ or size_in_bounds_p() before invoking malloc().
+ The example thus becomes:
+ size_t size = xsum (header_size, xtimes (n, element_size));
+ void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
+*/
+
+/* Convert an arbitrary value >= 0 to type size_t. */
+#define xcast_size_t(N) \
+ ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
+
+/* Sum of two sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum (size_t size1, size_t size2)
+{
+ size_t sum = size1 + size2;
+ return (sum >= size1 ? sum : SIZE_MAX);
+}
+
+/* Sum of three sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum3 (size_t size1, size_t size2, size_t size3)
+{
+ return xsum (xsum (size1, size2), size3);
+}
+
+/* Sum of four sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
+{
+ return xsum (xsum (xsum (size1, size2), size3), size4);
+}
+
+/* Maximum of two sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xmax (size_t size1, size_t size2)
+{
+ /* No explicit check is needed here, because for any n:
+ max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */
+ return (size1 >= size2 ? size1 : size2);
+}
+
+/* Multiplication of a count with an element size, with overflow check.
+ The count must be >= 0 and the element size must be > 0.
+ This is a macro, not an inline function, so that it works correctly even
+ when N is of a wider tupe and N > SIZE_MAX. */
+#define xtimes(N, ELSIZE) \
+ ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
+
+/* Check for overflow. */
+#define size_overflow_p(SIZE) \
+ ((SIZE) == SIZE_MAX)
+/* Check against overflow. */
+#define size_in_bounds_p(SIZE) \
+ ((SIZE) != SIZE_MAX)
+
+#endif /* _XSIZE_H */
diff --git a/gfsm/gfsm/src/libgfsm/graveyard.c b/gfsm/gfsm/src/libgfsm/graveyard.c
new file mode 100644
index 0000000..8df1638
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/graveyard.c
@@ -0,0 +1,631 @@
+//=================================================================================
+// arc sorting (old)
+//=================================================================================
+
+/// Typedef for mode-dependent arc-sorting parameters
+/** \see gfsm_arc_compare(), gfsm_arclist_sort(), gfsm_automaton_arcsort() */
+typedef struct {
+ gfsmArcSortMode mode; /**< sort mode */
+ gfsmSemiring *sr; /**< semiring for weight-mode, otherwise ignored */
+} gfsmArcSortDataOLD;
+
+/** Old-style default 3-way comparison on arcs (inline version)
+ * \param a1 first arc to compare
+ * \param a2 second arc to compare
+ * \param sdata specifies comparison mode
+ * \returns
+ * negative, zero, or positive integer depending on whether
+ * \a a1 is less-than, equal-to, or greater-than \a a2 according to \a sdata.
+ * \note
+ * \li Prefer gfsm_arc_compare_inline() for literal direct arc comparisons in new code
+ * \li Prefer gfsm_arc_compare() if you're passing function pointers around, since
+ * its address is guaranteed not to change between compilation units.
+ */
+GFSM_INLINE
+gint gfsm_arc_compare_inline(gfsmArc *a1, gfsmArc *a2, gfsmArcSortDataOLD *sdata);
+
+/** Old-style default 3-way comparison on arcs (extern version)
+ * Really just a wrapper for gfsm_arc_compare_inline()
+ */
+gint gfsm_arc_compare(gfsmArc *a1, gfsmArc *a2, gfsmArcSortDataOLD *sdata);
+
+GFSM_INLINE
+gint gfsm_arc_compare_inline(gfsmArc *a1, gfsmArc *a2, gfsmArcSortData *sdata)
+{
+ if (!a1) {
+ if (!a2) return 0;
+ return 1;
+ }
+ if (!a2) return -1;
+ switch (sdata->mode) {
+ case gfsmASMLower:
+ if (a1->lower < a2->lower) return -1;
+ if (a1->lower > a2->lower) return 1;
+ if (a1->upper < a2->upper) return -1;
+ if (a1->upper > a2->upper) return 1;
+ //if (a1->source < a2->source) return -1;
+ //if (a1->source > a2->source) return 1;
+ if (a1->target < a2->target) return -1;
+ if (a1->target > a2->target) return 1;
+ return 0;
+ case gfsmASMUpper:
+ if (a1->upper < a2->upper) return -1;
+ if (a1->upper > a2->upper) return 1;
+ if (a1->lower < a2->lower) return -1;
+ if (a1->lower > a2->lower) return 1;
+ //if (a1->source < a2->source) return -1;
+ //if (a1->source > a2->source) return 1;
+ if (a1->target < a2->target) return -1;
+ if (a1->target > a2->target) return 1;
+ return 0;
+ case gfsmASMWeight:
+ return gfsm_sr_compare(sdata->sr, a1->weight, a2->weight);
+ case gfsmASMNone:
+ default:
+ return (GPOINTER_TO_INT(a2)-GPOINTER_TO_INT(a1));
+ }
+ return 0;
+}
+
+/** Backwards-compatible wrapper for gfsm_arc_compare_bymask() */
+gint gfsm_arc_compare(gfsmArc *a1, gfsmArc *a2, gfsmArcSortDataOLD *sdata);
+
+/** Return symbolic name of an (old-style) arc-sort mode */
+const gchar *gfsm_arc_sortmode_to_name(gfsmArcSortModeOLD mode);
+
+/*--------------------------------------------------------------
+ * compare()
+ */
+gint gfsm_arc_compare(gfsmArc *a1, gfsmArc *a2, gfsmArcSortDataOLD *sdata)
+{
+ gfsmArcCompData acdata = { 0, sdata->sr, NULL,NULL };
+ switch (sdata->mode) {
+ case gfsmASMLowerOLD: acdata.mask = gfsmASMLower; break;
+ case gfsmASMUpperOLD: acdata.mask = gfsmASMUpper; break;
+ case gfsmASMWeightOLD: acdata.mask = gfsmASMWeight; break;
+ default:
+ break;
+ }
+ return gfsm_arc_compare_bymask_inline(a1,a2,&acdata);
+}
+
+//=================================================================================
+// statepair2weightXXX
+//=================================================================================
+
+/// Typedef for mapping (gfsmStatePair)s to (gfsmWeight)s
+/// used by gfsm_automaton_rmepsilon()
+typedef struct {
+ gfsmWeightMap *wm; /**< underlying weight-map */
+ gfsmSemiring *sr; /**< semiring used for comparison */
+} gfsmStatePair2WeightMap;
+
+/// Typedef for mapping (gfsmStatePair)s to (gfsmWeight)s
+/// used by gfsm_automaton_rmepsilon()
+typedef struct {
+ GHashTable *h; /**< underlying hash */
+ gfsmSemiring *sr; /**< semiring used for comparison */
+} gfsmStatePair2WeightHash;
+
+/*======================================================================
+ * Methods: gfsmStatePair2WeightHash
+ */
+///\name gfsmStatePair2WeightHash Methods
+//@{
+
+
+/** create a new gfsmStatePair2WeightHash (copies & frees keys)
+ * \see gfsmWeightHash
+ */
+gfsmStatePair2WeightHash *gfsm_statepair2weighthash_new(gfsmSemiring *sr);
+
+/** Hash \a sp to \a w in \a spw.
+ * \returns TRUE if \a sp was already present in \a spw with a less-than-or-equal weight */
+gboolean gfsm_statepair2weighthash_insert(gfsmStatePair2WeightHash *sp2wh, gfsmStatePair *sp, gfsmWeight w);
+
+/** Lookup weight for \a sp in \a sp2wh .
+ * \returns TRUE if \a sp was already present in \a sp2wh and sets \a *wp to its stored weight */
+gboolean gfsm_statepair2weighthash_lookup(gfsmStatePair2WeightHash *sp2wh, gfsmStatePair *sp, gfsmWeight *wp);
+
+/** Clear a gfsmStatePair2WeightHash */
+#define gfsm_statepair2weighthash_clear(sp2wh) \
+ g_hash_free((sp2wh)->h)
+
+/** Free all memory allocated by a gfsmStatePair2WeightHash */
+void gfsm_statepair2weighthash_free(gfsmStatePair2WeightHash *sp2wh);
+
+/** Alias; \sa gfsm_weighthash_foreach() */
+#define gfsm_statepair2weighthash_foreach(sp2wh,func,data) \
+ gfsm_weighthash_foreach((sp2wh)->h,(func),(data))
+
+//@}
+
+
+/*======================================================================
+ * Methods: gfsmStatePair2WeightMap
+ */
+
+/*--------------------------------------------------------------
+ * statepair2weightmap_new()
+ */
+gfsmStatePair2WeightMap *gfsm_statepair2weightmap_new(gfsmSemiring *sr)
+{
+ gfsmStatePair2WeightMap *sp2wm = g_new(gfsmStatePair2WeightMap,1);
+ sp2wm->wm = gfsm_weightmap_new_full((GCompareDataFunc)gfsm_statepair_compare,
+ sr,
+ (GDestroyNotify)g_free);
+ sp2wm->sr = sr;
+ return sp2wm;
+}
+
+/*--------------------------------------------------------------
+ * statepair2weightmap_insert()
+ */
+gboolean gfsm_statepair2weightmap_insert(gfsmStatePair2WeightMap *spw, gfsmStatePair *sp, gfsmWeight w)
+{
+ gpointer orig_key;
+ gpointer orig_val;
+ if (g_tree_lookup_extended(spw->wm, sp, &orig_key, &orig_val)) {
+ //-- already present: is the stored weight better?
+ if (gfsm_sr_less(spw->sr, gfsm_ptr2weight(orig_val), w)) {
+ return TRUE;
+ }
+ }
+ //-- either not present or we need to update the stored weight because (w) is better
+ gfsm_weightmap_insert(spw->wm, gfsm_statepair_clone(sp), w);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * statepair2weightmap_lookup()
+ */
+gboolean gfsm_statepair2weightmap_lookup(gfsmStatePair2WeightMap *spw, gfsmStatePair *sp, gfsmWeight *wp)
+{
+ gpointer orig_key;
+ return g_tree_lookup_extended(spw->wm, sp, &orig_key, &((gpointer*)wp));
+}
+
+/*--------------------------------------------------------------
+ * statepair2weightmap_free()
+ */
+void gfsm_statepair2weightmap_free(gfsmStatePair2WeightMap *sp2wm)
+{
+ gfsm_weightmap_free(sp2wm->wm);
+ g_free(sp2wm);
+}
+
+/*======================================================================
+ * Methods: gfsmStatePair2WeightHash
+ */
+
+/*--------------------------------------------------------------
+ * statepair2weighthash_new()
+ */
+gfsmStatePair2WeightHash *gfsm_statepair2weighthash_new(gfsmSemiring *sr)
+{
+ gfsmStatePair2WeightHash *sp2wh = g_new(gfsmStatePair2WeightHash,1);
+ sp2wh->h = g_hash_table_new_full((GHashFunc)gfsm_statepair_hash,
+ (GEqualFunc)gfsm_statepair_equal,
+ (GDestroyNotify)gfsm_statepair_free,
+ NULL);
+ sp2wh->sr = sr;
+ return sp2wh;
+}
+
+/*--------------------------------------------------------------
+ * statepair2weighthash_insert()
+ */
+gboolean gfsm_statepair2weighthash_insert(gfsmStatePair2WeightHash *sp2wh, gfsmStatePair *sp, gfsmWeight w)
+{
+ gpointer orig_key;
+ gpointer orig_val;
+ if (g_tree_lookup_extended(spw->h, sp, &orig_key, &orig_val)) {
+ //-- already present: is (stored_weight+w) better than (stored_weight)?
+ gfsmWeight ow = gfsm_ptr2weight(orig_val);
+ w = gfsm_sr_plus(sp2wh->sr, ow, w);
+ if (gfsm_sr_less(sp2wh->sr, ow, w)) {
+ return TRUE;
+ }
+ //-- adding new weight is better
+ g_hash_table_steal(sp2wh->h, orig_key);
+ g_hash_table_insert(sp2wh->h, orig_key, gfsm_weight2ptr(w));
+ }
+ else {
+ //-- pair (sp) was not present: copy & insert
+ g_hash_table_insert(sp2wh->h, gfsm_statepair_clone(sp), gfsm_weight2ptr(w));
+ }
+ return FALSE; //-- either not present or updated
+}
+
+/*--------------------------------------------------------------
+ * statepair2weighthash_lookup()
+ */
+gboolean gfsm_statepair2weighthash_lookup(gfsmStatePair2WeightHash *sp2wh, gfsmStatePair *sp, gfsmWeight *wp)
+{
+ gpointer orig_key;
+ return g_hash_table_lookup_extended(spw->wm, sp, &orig_key, &((gpointer*)wp));
+}
+
+/*--------------------------------------------------------------
+ * statepair2weighthash_free()
+ */
+void gfsm_statepair2weighthash_free(gfsmStatePair2WeightHash *sp2wh)
+{
+ gfsm_weighthash_free(sp2wh->wm);
+ g_free(sp2wh);
+}
+
+
+//=================================================================================
+// DETERMINIZE (v1)
+//=================================================================================
+
+/*--------------------------------------------------------------
+ * _determinize_lp2ec_foreach_func()
+ */
+typedef struct {
+ gfsmAutomaton *nfa;
+ gfsmAutomaton *dfa;
+ gfsmStateId dfa_src_id;
+ gfsmEnum *ec2id;
+ gfsmStateSet *ec_tmp;
+} gfsmLp2EcForeachData;
+
+gboolean _gfsm_determinize_lp2ec_foreach_func(gfsmLabelPair lp,
+ gfsmWeightedStateSet *wss,
+ gfsmLp2EcForeachData *data)
+{
+ gfsmStateId ec2id_val;
+ gfsmStateSet *ec2id_key;
+
+ if ( gfsm_enum_lookup_extended(data->ec2id,
+ wss->set,
+ (gpointer)(&ec2id_key),
+ (gpointer)(&ec2id_val)) )
+ {
+ //-- target node-set is already present: just add an arc in @dfa
+ gfsm_automaton_add_arc(data->dfa,
+ data->dfa_src_id,
+ ec2id_val,
+ gfsm_labelpair_lower(lp),
+ gfsm_labelpair_upper(lp),
+ wss->weight);
+
+ //-- ... and maybe free the embedded state set
+ if (wss->set != ec2id_key) gfsm_stateset_free(wss->set);
+ wss->set = NULL;
+ }
+ else
+ {
+ //-- image of equiv-class (wss->set) was not yet present: make a new one
+ ec2id_val = gfsm_automaton_ensure_state(data->dfa,
+ gfsm_enum_insert(data->ec2id, wss->set));
+
+ //-- ... add @dfa arc
+ gfsm_automaton_add_arc(data->dfa,
+ data->dfa_src_id,
+ ec2id_val,
+ gfsm_labelpair_lower(lp),
+ gfsm_labelpair_upper(lp),
+ wss->weight);
+
+ //-- ... and recurse
+ _gfsm_determinize_visit_state(data->nfa, data->dfa,
+ wss->set, ec2id_val,
+ data->ec2id, data->ec_tmp);
+ }
+ return FALSE;
+}
+
+
+/*--------------------------------------------------------------
+ * _determinize_visit_state()
+ */
+void _gfsm_determinize_visit_state(gfsmAutomaton *nfa, gfsmAutomaton *dfa,
+ gfsmStateSet *nfa_ec, gfsmStateId dfa_id,
+ gfsmEnum *ec2id, gfsmStateSet *ec_tmp)
+{
+ GTree *lp2ecw; //-- maps label-pairs@nfa.src.ec => (eq-class@nfa.sink, sum(weight))
+ gfsmStateSetIter eci;
+ gfsmStateId ecid;
+ gfsmLp2EcForeachData lp2ec_foreach_data;
+ gfsmWeight fw;
+
+ //-- check for final state
+ if (gfsm_stateset_lookup_final_weight(nfa_ec,nfa,&fw)) {
+ gfsm_automaton_set_final_state_full(dfa, dfa_id, TRUE, fw);
+ }
+
+ //-- build label-pair => (sink-eqc, sum(weight)) mapping 'lp2ecw' for node-set nfa_ec
+ lp2ecw = g_tree_new_full(((GCompareDataFunc)
+ gfsm_labelpair_compare_with_data), //-- key_comp_func
+ NULL, //-- key_comp_data
+ NULL, //-- key_free_func
+ (GDestroyNotify)g_free); //-- val_free_func
+
+ for (eci=gfsm_stateset_iter_begin(nfa_ec);
+ (ecid=gfsm_stateset_iter_id(eci)) != gfsmNoState;
+ eci=gfsm_stateset_iter_next(nfa_ec,eci))
+ {
+ gfsmArcIter ai;
+ for (gfsm_arciter_open(&ai, nfa, ecid); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ gfsmLabelPair lp;
+ gfsmLabelPair *lp2ec_key;
+ gfsmWeightedStateSet *lp2ec_val;
+
+ if (a->lower==gfsmEpsilon && a->upper==gfsmEpsilon) continue; //-- ignore eps arcs
+ lp = gfsm_labelpair_new(a->lower, a->upper);
+
+ //-- populate state-set with all nodes eps-reachable from this arc's target
+ gfsm_stateset_clear(ec_tmp);
+ gfsm_stateset_populate_eps(ec_tmp, nfa, a->target);
+
+ //-- add equivalence class to local mapping
+ if ( g_tree_lookup_extended(lp2ecw,
+ (gpointer)lp,
+ (gpointer)(&lp2ec_key),
+ (gpointer)(&lp2ec_val)) )
+ {
+ //-- already present: compute union and add new arc's weight
+ gfsm_stateset_union(lp2ec_val->set, ec_tmp);
+ lp2ec_val->weight = gfsm_sr_plus(nfa->sr, lp2ec_val->weight, a->weight);
+ }
+ else
+ {
+ //-- not yet present: insert new value
+ lp2ec_val = g_new(gfsmWeightedStateSet,1);
+ lp2ec_val->set = gfsm_stateset_clone(ec_tmp);
+ lp2ec_val->weight = a->weight;
+ g_tree_insert(lp2ecw, (gpointer)lp, lp2ec_val);
+ }
+ }
+
+ //-- tmp-cleanup
+ gfsm_arciter_close(&ai);
+ }
+
+ //-- stateset-iter (eci) cleanup
+ //(none)
+
+ //-- insert computed arcs into @dfa
+ lp2ec_foreach_data.nfa = nfa;
+ lp2ec_foreach_data.dfa = dfa;
+ lp2ec_foreach_data.dfa_src_id = dfa_id;
+ lp2ec_foreach_data.ec2id = ec2id;
+ lp2ec_foreach_data.ec_tmp = ec_tmp;
+ g_tree_foreach(lp2ecw,
+ (GTraverseFunc)_gfsm_determinize_lp2ec_foreach_func,
+ (gpointer)(&lp2ec_foreach_data));
+
+ //-- cleanup
+ g_tree_destroy(lp2ecw);
+
+ /*
+ g_printerr("_gfsm_automaton_determinize_visit_state(): not yet implemented!");
+ g_assert_not_reached();
+ */
+}
+
+/*--------------------------------------------------------------
+ * determinize()
+ */
+gfsmAutomaton *gfsm_automaton_determinize(gfsmAutomaton *nfa)
+{
+ if (!nfa->flags.is_deterministic) {
+ gfsmAutomaton *dfa = gfsm_automaton_determinize_full(nfa,NULL);
+ gfsm_automaton_swap(nfa,dfa);
+ gfsm_automaton_free(dfa);
+ }
+ return nfa;
+}
+
+/*--------------------------------------------------------------
+ * determinize_full()
+ */
+gfsmAutomaton *gfsm_automaton_determinize_full(gfsmAutomaton *nfa, gfsmAutomaton *dfa)
+{
+ gfsmEnum *ec2id; //-- (global) maps literal(equiv-class@nfa) => node-id@dfa
+ gfsmStateSet *nfa_ec; //-- (temp) equiv-class@nfa
+ gfsmStateId dfa_id; //-- (temp) id @ dfa
+ gfsmStateSet *ec_tmp; //-- (temp) equiv-class@nfa
+
+ //-- sanity check(s)
+ if (!nfa) return NULL;
+ else if (nfa->flags.is_deterministic) {
+ if (dfa) gfsm_automaton_copy(dfa,nfa);
+ else dfa = gfsm_automaton_clone(nfa);
+ return dfa;
+ }
+
+ //-- initialization: nfa
+ //gfsm_automaton_arcsort(nfa,gfsmASMLower);
+
+ //-- initialization: dfa
+ if (!dfa) {
+ dfa = gfsm_automaton_shadow(nfa);
+ } else {
+ gfsm_automaton_clear(dfa);
+ gfsm_automaton_copy_shallow(dfa,nfa);
+ }
+ dfa->flags.sort_mode = gfsmASMNone; //-- avoid "smart" arc-insertion
+
+ //-- initialization: ec2id
+ ec2id = gfsm_enum_new_full(NULL /*(gfsmDupFunc)gfsm_stateset_clone*/ ,
+ (GHashFunc)gfsm_stateset_hash,
+ (GEqualFunc)gfsm_stateset_equal,
+ (GDestroyNotify)gfsm_stateset_free);
+
+ //-- initialization: nfa_ec
+ nfa_ec = gfsm_stateset_sized_new(32);
+ ec_tmp = gfsm_stateset_sized_new(32);
+ gfsm_stateset_populate_eps(nfa_ec, nfa, nfa->root_id);
+
+ //-- set root in dfa
+ dfa_id = gfsm_automaton_ensure_state(dfa, gfsm_enum_insert(ec2id, nfa_ec));
+ gfsm_automaton_set_root(dfa, dfa_id);
+
+ //-- guts: determinize recursively outwards from root node
+ _gfsm_determinize_visit_state(nfa, dfa, nfa_ec, dfa_id, ec2id, ec_tmp);
+
+ //-- set flag in dfa
+ dfa->flags.is_deterministic = TRUE;
+
+ //-- cleanup
+ //gfsm_stateset_free(nfa_ec); //-- this ought to be freed by gfsm_enum_free(ec2id)
+ gfsm_stateset_free(ec_tmp); //-- ... but not this
+ gfsm_enum_free(ec2id);
+
+ return dfa;
+}
+
+//=================================================================================
+// END DETERMINIZE (v1)
+//=================================================================================
+
+
+
+//-------------------------------------------------------------------------------
+#define GFSM_ALPHABET_CSET \
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!\"#$%&'()*+,-./0123456789:;<=>?" \
+ "\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264" \
+ "\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310" \
+ "\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334" \
+ "\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360"
+
+const GScannerConfig gfsm_alphabet_scanner_config = {
+ /* Character sets */
+ ( " \t\r\n" ) /* skip chars */,
+ ( GFSM_ALPHABET_CSET ) /* identifier_first */,
+ ( GFSM_ALPHABET_CSET ) /* identifier_nth */,
+ "" /* comment_single */,
+
+ FALSE /* case_sensitive */,
+ FALSE /* skip_comment_multi */,
+ FALSE /* skip_comment_single */,
+ FALSE /* scan_comment_multi */,
+ FALSE /* scan_comment_single */,
+ TRUE /* scan_identifier */,
+ TRUE /* scan_identifier_1char */,
+ FALSE /* scan_identifier_NULL */,
+ FALSE /* scan_symbols */,
+
+ FALSE /* scan_binary */,
+ TRUE /* scan_octal */,
+ FALSE /* scan_float */,
+ TRUE /* scan_hex */,
+ FALSE /* scan_hex_dollar */,
+
+ FALSE /* scan_string_sq : string: 'anything' */,
+ FALSE /* scan_string_dq : string: "\\-escapes!\n" */,
+ TRUE /* numbers_2_int : bin, octal, hex => int */,
+ FALSE /* int_2_float : int => G_TOKEN_FLOAT? */,
+ FALSE /* identifier_2_string : 1 */,
+ FALSE /* 2_token : 1 : return G_TOKEN_CHAR? */,
+ FALSE /* symbol_2_token : 1 */,
+ FALSE /* scope_0_fallback : try scope 0 on lookups? */,
+ //FALSE /* store_int64 : use value.v_int64 rather than v_int */,
+ //0 /* padding_dummy; */
+};
+
+gboolean gfsm_automaton_compile_file (gfsmAutomaton *fsm, FILE *f, const gchar *filename)
+{
+ GScanner *scanner = g_scanner_new(&gfsm_automaton_scanner_config);
+ GTokenType typ;
+
+ g_scanner_input_file(scanner, fileno(f));
+ while ((typ = g_scanner_get_next_token(scanner)) != G_TOKEN_EOF) {
+ g_printerr("<DEBUG:SCANNER:%u.%u> typ=%d : ",
+ g_scanner_cur_line(scanner), g_scanner_cur_position(scanner), typ);
+
+ switch (typ) {
+ case G_TOKEN_INT:
+ g_printerr("(INT) value=%ld\n", g_scanner_cur_value(scanner).v_int);
+ break;
+
+ case G_TOKEN_FLOAT:
+ g_printerr("(FLOAT) value=%g\n", g_scanner_cur_value(scanner).v_float);
+ break;
+
+ case G_TOKEN_CHAR:
+ g_printerr("(CHAR) value=%d\n", g_scanner_cur_value(scanner).v_char);
+ break;
+
+ default:
+ g_printerr("(?) text='%s'\n", scanner->text); //'text' is private: debugging use only!
+ break;
+ }
+ }
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ * scanner template for compile_file()
+ */
+const GScannerConfig gfsm_automaton_scanner_config = {
+ /* Character sets */
+ ( " \t\r" ) /* skip chars */,
+ ( "" ) /* identifier_first */,
+ ( "" ) /* identifier_nth */,
+ "#\n" /* comment_single */,
+
+ FALSE /* case_sensitive */,
+
+ FALSE /* skip_comment_multi */,
+ FALSE /* skip_comment_single */,
+ FALSE /* scan_comment_multi */,
+
+ FALSE /* scan_identifier */,
+ FALSE /* scan_identifier_1char */,
+ FALSE /* scan_identifier_NULL */,
+ FALSE /* scan_symbols */,
+
+ FALSE /* scan_binary */,
+ TRUE /* scan_octal */,
+ TRUE /* scan_float */,
+ TRUE /* scan_hex */,
+ FALSE /* scan_hex_dollar */,
+
+ FALSE /* scan_string_sq : string: 'anything' */,
+ FALSE /* scan_string_dq : string: "\\-escapes!\n" */,
+ TRUE /* numbers_2_int : bin, octal, hex => int */,
+ FALSE /* int_2_float : int => G_TOKEN_FLOAT? */,
+ FALSE /* identifier_2_string : 1 */,
+ FALSE /* 2_token : 1 : return G_TOKEN_CHAR? */,
+ FALSE /* symbol_2_token : 1 */,
+ FALSE /* scope_0_fallback : try scope 0 on lookups? */,
+ FALSE /* store_int64 : use value.v_int64 rather than v_int */,
+ //0 /* padding_dummy; */
+};
+
+/*--------------------------------------------------------------
+ * gfsm_automaton_scan_field()
+ */
+gboolean gfsm_automaton_scan_field(GScanner *scanner,
+ GTokenType expect1,
+ GTokenType expect2,
+ gboolean complain_on_newline)
+{
+ GTokenType typ;
+ while (1) {
+ typ = g_scanner_get_next_token(scanner);
+ if (expect1 != typ
+ && expect2 != typ
+ && (typ == G_TOKEN_CHAR || typ == G_TOKEN_EOF)
+ && g_scanner_cur_value(scanner).v_char == '\n')
+ {
+ //-- return but don't complain on unexpected newlines
+ if (complain_on_newline)
+ g_scanner_unexp_token(scanner, expect1, NULL, NULL, NULL, NULL, TRUE);
+ return FALSE;
+ }
+
+ if (expect1 != typ && expect2 != typ) {
+ g_scanner_unexp_token(scanner, expect1, NULL, NULL, NULL, NULL, TRUE);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/gfsm/gfsm/src/libgfsm/inc2dot.perl b/gfsm/gfsm/src/libgfsm/inc2dot.perl
new file mode 100755
index 0000000..f406262
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/inc2dot.perl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w
+
+%inc = qw();
+%nod = qw();
+foreach $file (@ARGV) {
+ open(F,"<$file") or die("$0: open failed for '$file': $!");
+ @incs = qw();
+ while (<F>) {
+ chomp;
+ if ($_ =~ m/^\s*\#\s*include\s*[\<\"\']\s*(\S+)[\>\"\']/) { push(@incs,$1); }
+ }
+ close(F);
+ $inc{$file} = [@incs];
+ @nod{$file,@incs} = undef;
+}
+
+##-- subs
+sub safestr {
+ my $str = shift;
+ $str =~ s/[\.\,\+\-\=]/_/g;
+ return $str;
+}
+
+##-- write dot file
+print
+ ("digraph include {\n",
+ " rankdir = LR;\n",
+ " rotate = 90;\n",
+ );
+
+##-- all nodes
+foreach $f (sort keys(%nod)) {
+ $f_str = safestr($f);
+ if (exists($inc{$f})) { $attrs = "[ label=\"$f\", shape=box ]"; }
+ else { $attrs = "[ label=\"$f\", shape=box, style=filled, fill=gray ]"; }
+ print " $f_str $attrs;\n";
+
+ ##-- arcs
+ if (defined($incs=$inc{$f})) {
+ foreach $i (@$incs) {
+ $i_str = safestr($i);
+ if (exists($inc{$i})) { $e_attrs = "[ color=black ]"; }
+ else { $e_attrs = "[ color=red, style=dashed ]" }
+ print "\t$f_str -> $i_str $e_attrs;\n"
+ }
+ }
+}
+print "}\n";
diff --git a/gfsm/gfsm/src/libgfsm/tests/.cvsignore b/gfsm/gfsm/src/libgfsm/tests/.cvsignore
new file mode 100644
index 0000000..ef3800b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/.cvsignore
@@ -0,0 +1,38 @@
+*~
+.*~
+
+*.gfst
+*.output
+*.lex.c
+*.lex.h
+*.tab.c
+*.tab.h
+*.gz
+
+tagh*
+*.dat
+negra*
+lts-grimm.*
+
+offsettest
+priotest
+seek2test
+seek3test
+seektest
+gfsmlabdump
+iotest
+pathtest
+ftest
+memtest-general
+calctest
+calc2test
+flextest
+flex2test
+flex3test
+compretest
+comprelex
+compre2test
+structtest
+
+flextest.c
+flextest.h
diff --git a/gfsm/gfsm/src/libgfsm/tests/Makefile b/gfsm/gfsm/src/libgfsm/tests/Makefile
new file mode 100644
index 0000000..f4ec863
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/Makefile
@@ -0,0 +1,116 @@
+TARGETS = priotest
+
+KNOWN_TARGETS = \
+ priotest \
+ seek3test \
+ seek2test \
+ offsettest \
+ arctab-1test \
+ seektest \
+ gfsmlabdump \
+ iotest \
+ structtest \
+ pathtest \
+ memtest \
+ memtest-general \
+ ftest \
+ flextest \
+ calctest \
+ flex2test \
+ calc2test \
+ flex3test \
+ compretest \
+ comprelex \
+ compre2test
+
+
+CC = gcc
+#CC = ccmalloc --no-wrapper gcc
+LD = $(CC)
+
+CPPFLAGS = -I. -I.. -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
+CFLAGS ?= -O2 -pipe
+#CFLAGS ?= -Wall -g
+#CFLAGS += -Wall -g
+#CFLAGS = -Wall -g
+CFLAGS += -Wall -Winline
+
+LDFLAGS = -L../libgfsm/.libs -L/usr/local/lib -L/usr/lib
+LIBS = -lz -lglib-2.0 -lm
+GFSMLIBS = ../.libs/libgfsm.a
+
+LEX ?= flex
+FLEX ?= flex
+FLEXFLAGS ?=
+BISON ?= bison
+BISONFLAGS ?= --verbose
+
+all: $(TARGETS)
+
+##-- keep intermediate files
+.SECONDARY:
+
+seektest.o: seektest.c labprobs.h
+seektest: seektest.o
+
+##-- flex
+%.lex.c %.lex.h: %.l
+ $(FLEX) $(FLEXFLAGS) --outfile="$*.lex.c" --header-file="$*.lex.h" $^
+
+calctest.lex.o: calctest.tab.h
+
+calc2test.lex.o: calc2test.tab.h ../gfsmRegexCompiler.h
+
+compretest.lex.o: compretest.tab.h ../gfsmRegexCompiler.h
+
+comprelex.lex.o: compretest.lex.c compretest.lex.h ../gfsmRegexCompiler.h
+
+##-- gfsmlabdump
+gfsmlabdump: gfsmlabdump.o ../.libs/libgfsm.a
+ $(LD) $(LDFLAGS) -o $@ $< $(GFSMLIBS) $(LIBS)
+
+##-- bison
+%.tab.c %.tab.h: %.y
+ $(BISON) $(BISONFLAGS) --defines --file-prefix="$*" --name-prefix="$*_yy" $^
+
+##-- flex+bison
+calctest: calctest.lex.o calctest.tab.o $(GFSMLIBS)
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+calc2test: calc2test.lex.o calc2test.tab.o $(GFSMLIBS)
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+flex2test: flex2test.lex.o $(GFSMLIBS)
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+flex3test: flex3test.lex.o $(GFSMLIBS)
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+compretest: compretest.lex.o compretest.tab.o $(GFSMLIBS)
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+comprelex: comprelex.lex.o $(GFSMLIBS)
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+compre2test: compre2test.o $(GFSMLIBS)
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+##-- io
+iotest: iotest.o
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+##-- .c -> .o
+%.o: %.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
+
+##-- clean
+clean:
+ rm -f *.o *.lo *.tab.[ch] *.lex.[ch] $(KNOWN_TARGETS)
+
+
+##-- executables
+%test: %test.o
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
+
+%-general: %-general.o
+ $(LD) $(LDFLAGS) -o $@ $^ $(GFSMLIBS) $(LIBS)
diff --git a/gfsm/gfsm/src/libgfsm/tests/NOTES.lookup b/gfsm/gfsm/src/libgfsm/tests/NOTES.lookup
new file mode 100644
index 0000000..538feaf
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/NOTES.lookup
@@ -0,0 +1,26 @@
+lookup (NITERS=524288)
+ real 0m3.410s
+ user 0m3.403s
+ sys 0m0.002s
+
+ -> iters/s = 153750.147 = 153.75 K
+
+ : lookup @ 153.75 K iters/s
+
+lookup + paths (NITERS=524288)
+ real 0m5.880s
+ user 0m5.873s
+ sys 0m0.002s
+
+ -> iters/s = 89164.626 = 89.16 K
+
+ : paths @ (52488/(5.88-3.41)) = 21250.2 = 21.25 K iters/s
+
+lookup + paths + strings (NITERS=524288)
+ real 0m9.013s
+ user 0m9.005s
+ sys 0m0.002s
+
+ -> iters/s = 58170.199 = 58.17 K
+
+ : strings @ (52488/(9.013-5.88)) = 16753.27 = 16.75 K iters/s
diff --git a/gfsm/gfsm/src/libgfsm/tests/alphachurn.c b/gfsm/gfsm/src/libgfsm/tests/alphachurn.c
new file mode 100644
index 0000000..8ea47a8
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/alphachurn.c
@@ -0,0 +1,11 @@
+#include <gfsmAlphabet.h>
+#include <stdlib.h>
+
+int main (void) {
+ gfsmStringAlphabet *a = gfsm_string_alphabet_new();
+
+ gfsm_string_alphabet_load_filename(a,"test.lab");
+ gfsm_string_alphabet_save_filename(a,"-");
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/arctab-1test.c b/gfsm/gfsm/src/libgfsm/tests/arctab-1test.c
new file mode 100644
index 0000000..d4cdb4b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/arctab-1test.c
@@ -0,0 +1,54 @@
+#include <gfsm.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (int argc, char **argv)
+{
+ const char *infilename = "-";
+ const char *prog = argv[0];
+ gfsmAutomaton *fsm=NULL;
+ gfsmError *err=NULL;
+ gfsmArcTableIndex *ix=NULL;
+ gfsmArcLabelIndex *lx=NULL;
+
+ if (argc > 1) { infilename = argv[1]; }
+
+ //-- load automaton
+ fprintf(stderr, "%s: loading file: '%s'... ", prog,infilename); fflush(stderr);
+ fsm = gfsm_automaton_new();
+ if ( !(gfsm_automaton_load_bin_filename(fsm,infilename,&err)) ) {
+ fprintf(stderr, "FAILED: %s\n", (err ? err->message : "?"));
+ exit(1);
+ }
+ fprintf(stderr, "loaded.\n"); fflush(stderr);
+
+ //-- ArcTableIndex
+ fprintf(stderr, "%s: creating ArcTableIndex... ", prog); fflush(stderr);
+ if ( !(ix = gfsm_automaton_to_arc_table_index(fsm,ix)) ) {
+ fprintf(stderr, "FAILED\n");
+ exit(2);
+ }
+ fprintf(stderr, "created.\n"); fflush(stderr);
+ //
+ //-- sort table (todo: check for existing sort mode?!)
+ fprintf(stderr, "%s: sorting ArcTableIndex (priority sort)... ", prog); fflush(stderr);
+ gfsm_arc_table_index_priority_sort(ix,gfsmASP_LW,fsm->sr);
+ fprintf(stderr, "sorted.\n"); fflush(stderr);
+
+ //-- ArcLabelIndex
+ fprintf(stderr, "%s: creating ArcLabelIndex... ", prog); fflush(stderr);
+ if ( !(lx = gfsm_automaton_to_arc_label_index_lower(fsm,lx)) ) {
+ fprintf(stderr, "FAILED\n");
+ exit(3);
+ }
+ fprintf(stderr, "created.\n"); fflush(stderr);
+
+ //-- cleanup
+ fprintf(stderr, "%s: cleanup... ", prog); fflush(stderr);
+ gfsm_automaton_free(fsm);
+ gfsm_arc_table_index_free(ix);
+ gfsm_arc_label_index_free(lx);
+ fprintf(stderr, "done.\n"); fflush(stderr);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/arytest.c b/gfsm/gfsm/src/libgfsm/tests/arytest.c
new file mode 100644
index 0000000..d766b89
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/arytest.c
@@ -0,0 +1,27 @@
+#include <glib.h>
+#include <stdio.h>
+
+int main (void) {
+ GPtrArray *a;
+ gpointer p;
+ g_mem_set_vtable(glib_mem_profiler_table);
+
+ printf("<PROF:1>--------\n");
+
+
+ a = g_ptr_array_sized_new(128);
+ g_ptr_array_set_size(a,1024);
+ p = g_ptr_array_free(a,TRUE);
+ printf("p=ptr_array_free()=%p\n", p);
+
+ printf("<CHUNKS:1>--------\n");
+ //g_mem_chunk_info();
+
+ //printf("<CHUNKS:2>--------\n");
+ g_blow_chunks();
+ //g_mem_chunk_info();
+
+ printf("<PROF:2>--------\n");
+ g_mem_profile();
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/arytest2.c b/gfsm/gfsm/src/libgfsm/tests/arytest2.c
new file mode 100644
index 0000000..ebef7f5
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/arytest2.c
@@ -0,0 +1,63 @@
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void print_array(const char *label, GArray *a) {
+ int i;
+ printf("Array %s: {", label);
+ for (i=0; i < a->len; i++) {
+ printf(" %d", g_array_index(a,int,i));
+ }
+ printf(" }\n");
+}
+
+gint compare_int(int *x, int *y) {
+ return (*x)-(*y);
+ //return (*x < *y ? -1 : (*x > *y ? 1 : 0));
+}
+
+int main (int argc, char **argv) {
+ GArray *a1, *a2;
+ int i, val;
+
+ a1 = g_array_new(FALSE, TRUE, sizeof(int));
+ a2 = g_array_new(FALSE, TRUE, sizeof(int));
+ for (i=1; i < argc; i++) {
+ val = strtol(argv[i],NULL,10);
+ g_array_append_val(a1,val);
+ }
+ print_array("a1", a1);
+
+ //-- insert(0,0)
+ val = 0;
+ g_array_insert_val(a1,0,val);
+ printf("--\n");
+ print_array("a1/insert(0,0)",a1);
+
+ //-- copy a1 into a2
+ g_array_append_vals(a2,a1->data,a1->len);
+ print_array("a2", a2);
+ printf("--\n");
+
+ //-- move elements of a1 up one notch
+ /*-- NOT ok
+ g_array_insert_vals(a1, 1, a1->data, a1->len-1);
+ g_array_index(a1,int,0) = 0;
+ */
+
+ /*-- ok */
+ i = 0;
+ g_array_insert_val(a1,0,i);
+ print_array("a1/moved", a1);
+ printf("--\n");
+
+ //-- sort
+ //g_array_sort(a1,NULL); //-- NOT ok
+ g_array_sort(a1,(GCompareFunc)compare_int); //-- ok
+ print_array("a1/sorted", a1);
+
+ g_array_free(a1,TRUE);
+ g_array_free(a2,TRUE);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/asciigen.perl b/gfsm/gfsm/src/libgfsm/tests/asciigen.perl
new file mode 100755
index 0000000..1cabeb9
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/asciigen.perl
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+
+@ascii = (ord('A')..ord('Z'),
+ ord('a')..ord('z'),
+ ord('!')..ord('/'),
+ ord('0')..ord('9'),
+ ord(':')..ord('?'));
+
+foreach $c (@ascii) {
+ print chr($c);
+}
+print "\n";
+
+foreach $c (161..255) {
+ printf("\\%o", $c);
+}
+print "\n";
diff --git a/gfsm/gfsm/src/libgfsm/tests/bvtest.c b/gfsm/gfsm/src/libgfsm/tests/bvtest.c
new file mode 100644
index 0000000..3cf190a
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/bvtest.c
@@ -0,0 +1,30 @@
+#include <gfsm.h>
+
+int main (int argc, char **argv) {
+ int i;
+ guint bit;
+ gfsmBitVector *bv = gfsm_bitvector_new();
+
+ for (i = 0; i <= 16 ; i++) {
+ printf("\t%d bits ~= %d bytes @ %d\n",
+ i, _gfsm_bitvector_bits2bytes(i), i%8);
+ }
+
+ for (i = 1; i < argc; i++) {
+ sscanf(argv[i], "%u", &bit);
+ printf("%s: setting bit=%u : bit2byte=%u\n", *argv, bit, _gfsm_bitvector_bits2bytes(bit));
+ gfsm_bitvector_set(bv,bit,1);
+ }
+
+ printf("%s: vector [bytes=%u ; bits=%u] =\n",
+ *argv, bv->len, gfsm_bitvector_size(bv));
+ for (bit = 0; bit < gfsm_bitvector_size(bv); bit++) {
+ if ((bit%8)==0) fputc(' ', stdout);
+ fputc((gfsm_bitvector_get(bv,bit) ? '1' : '0'), stdout);
+ }
+ printf("\n");
+
+ gfsm_bitvector_free(bv);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/calc2test.l b/gfsm/gfsm/src/libgfsm/tests/calc2test.l
new file mode 100644
index 0000000..7072a4c
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/calc2test.l
@@ -0,0 +1,56 @@
+/*======================================================================
+ * Flex Options
+ */
+%option outfile="calc2test.lex.c"
+%option header-file="calc2test.lex.h"
+%option prefix="calc2test_yy"
+%option reentrant
+%option 8bit
+%option yylineno
+
+%option bison-bridge
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+/* bison stuff */
+#include <gfsmScanner.h>
+#include "calc2test.tab.h"
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+
+/*======================================================================
+ * Flex Rules
+ */
+%%
+
+([[:digit:]]*\.?)[[:digit:]]+ { yylval->dbl = strtod(yytext,NULL); return NUMBER;}
+
+\( { return LPAREN; }
+\) { return RPAREN; }
+\+ { return PLUS; }
+\- { return MINUS; }
+\* { return TIMES; }
+\/ { return DIV; }
+
+\n { return NEWLINE; }
+
+[[:space:]] { /* ignore */ }
+
+. { return OTHER; /* ignore */ }
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+//-- wrapper: use default
+GFSM_SCANNER_YYWRAP(calc2test_yy)
diff --git a/gfsm/gfsm/src/libgfsm/tests/calc2test.y b/gfsm/gfsm/src/libgfsm/tests/calc2test.y
new file mode 100644
index 0000000..4754613
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/calc2test.y
@@ -0,0 +1,89 @@
+/*======================================================================
+ * Bison Options
+ */
+%pure_parser
+
+%{
+/*======================================================================
+ * Bison C Header
+ */
+#include <stdio.h>
+#include <gfsmScanner.h>
+#include "calc2test.tab.h"
+#include "calc2test.lex.h"
+
+typedef struct calc2testDataS {
+ gfsmScanner scanner;
+ double val;
+} calc2testData;
+
+#define YYLEX_PARAM ((calc2testData*)pparam)->scanner.yyscanner
+#define YYPARSE_PARAM pparam
+
+#define YYERROR_VERBOSE 1
+#define calc2test_yyerror(msg) \
+ gfsm_scanner_carp((gfsmScanner*)pparam, (msg));
+
+%}
+
+/*======================================================================
+ * Bison Definitions
+ */
+%union {
+ double dbl;
+}
+
+%token <dbl> NUMBER PLUS MINUS TIMES DIV LPAREN RPAREN NEWLINE OTHER
+%type <dbl> expr exprs
+
+%left PLUS MINUS
+%left TIMES DIV
+%nonassoc UMINUS
+
+/*======================================================================
+ * Bison Rules
+ */
+%%
+
+exprs: /* empty */
+ { $$=0; }
+ | exprs expr NEWLINE
+ { printf("%g\n", $2); ((calc2testData*)pparam)->val=$$=$2; }
+ ;
+
+expr: LPAREN expr RPAREN { $$=$2; }
+ | MINUS expr { $$=-$2; }
+ | expr TIMES expr { $$=$1*$3; }
+ | expr DIV expr { $$=$1/$3; }
+ | expr PLUS expr { $$=$1+$3; }
+ | expr MINUS expr %prec UMINUS { $$=$1-$3; }
+ | NUMBER { $$=$1; }
+ ;
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+void calc2test_yyerror_func(const char *msg)
+{
+ fprintf(stderr, "yyerror: %s\n", msg);
+}
+
+
+int main (void) {
+ calc2testData *pparams = g_new0(calc2testData,1);
+ gfsm_scanner_init((gfsmScanner*)pparams, "calctest2Scanner", calc2test_yy);
+
+ calc2test_yyparse(pparams);
+ if (pparams->scanner.err) {
+ fprintf(stderr, "Error: %s\n", pparams->scanner.err->message);
+ }
+
+ printf("Final calctest value=%g\n", pparams->val);
+
+ gfsm_scanner_free((gfsmScanner*)pparams);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/calctest.l b/gfsm/gfsm/src/libgfsm/tests/calctest.l
new file mode 100644
index 0000000..1a03bc1
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/calctest.l
@@ -0,0 +1,52 @@
+/*======================================================================
+ * Flex Options
+ */
+%option outfile="calctest.lex.c"
+%option header-file="calctest.lex.h"
+%option prefix="calctest_yy"
+%option reentrant
+%option 8bit
+
+%option bison-bridge
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+/* bison stuff */
+#include "calctest.tab.h"
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+
+/*======================================================================
+ * Flex Rules
+ */
+%%
+
+([[:digit:]]*\.?)[[:digit:]]+ { yylval->dbl = strtod(yytext,NULL); return NUMBER;}
+
+\( { return LPAREN; }
+\) { return RPAREN; }
+\+ { return PLUS; }
+\- { return MINUS; }
+\* { return TIMES; }
+\/ { return DIV; }
+
+\n { return NEWLINE; }
+
+. { return OTHER; /* ignore */ }
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+//-- wrapper: don't
+int calctest_yywrap(yyscan_t yyscanner) { return 1; }
diff --git a/gfsm/gfsm/src/libgfsm/tests/calctest.y b/gfsm/gfsm/src/libgfsm/tests/calctest.y
new file mode 100644
index 0000000..befec0e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/calctest.y
@@ -0,0 +1,118 @@
+/*======================================================================
+ * Bison Options
+ */
+%pure_parser
+
+%{
+/*======================================================================
+ * Bison C Header
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include "calctest.tab.h"
+#include "calctest.lex.h"
+
+typedef struct _yyparse_param {
+ char *name;
+ char *filename;
+ yyscan_t scanner;
+ float val;
+} yyparseParam;
+
+#define YYLEX_PARAM ((yyparseParam*)pparam)->scanner
+#define YYPARSE_PARAM pparam
+
+extern void calctest_yyerror(const char *msg);
+extern void calctest_yycarp(yyparseParam *pparams, const char *fmt, ...);
+
+%}
+
+/*======================================================================
+ * Bison Definitions
+ */
+%union {
+ double dbl;
+}
+
+%token <dbl> NUMBER PLUS MINUS TIMES DIV LPAREN RPAREN NEWLINE OTHER
+%type <dbl> expr exprs
+
+%left PLUS MINUS
+%left TIMES DIV
+%nonassoc UMINUS
+
+/*======================================================================
+ * Bison Rules
+ */
+%%
+
+exprs: /* empty */
+ { $$=0; }
+ | exprs expr NEWLINE
+ { printf("%g\n", $2); ((yyparseParam*)pparam)->val=$$=$2; }
+ ;
+
+expr: LPAREN expr RPAREN { $$=$2; }
+ | MINUS expr { $$=-$2; }
+ | expr TIMES expr { $$=$1*$3; }
+ | expr DIV expr { $$=$1/$3; }
+ | expr PLUS expr { $$=$1+$3; }
+ | expr MINUS expr %prec UMINUS { $$=$1-$3; }
+ | NUMBER { $$=$1; }
+ | OTHER
+ {
+ calctest_yycarp((yyparseParam*)pparam, "Failed to parse expression");
+ YYABORT;
+ }
+ ;
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+void calctest_yyerror(const char *msg)
+{
+ fprintf(stderr, "yyerror: %s\n", msg);
+}
+
+void calctest_yycarp(yyparseParam *pparams, const char *fmt, ...)
+{
+ va_list ap;
+ fprintf(stderr, "%s: ", (pparams->name ? pparams->name : "calctest_parser"));
+
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fprintf(stderr, " in %s%s%s at line %u, column %u.\n",
+ (pparams->filename ? "file \"" : ""),
+ (pparams->filename ? pparams->filename : "input"),
+ (pparams->filename ? "\"" : ""),
+ calctest_yyget_lineno(pparams->scanner),
+ calctest_yyget_column(pparams->scanner));
+}
+
+int main (void) {
+ yyscan_t scanner;
+ yyparseParam pparams;
+
+ calctest_yylex_init(&scanner); //-- initialize reentrant flex scanner
+
+ pparams.name = NULL;
+ pparams.filename = NULL;
+ //--
+ //pparams.name = "myParser";
+ //pparams.filename = "(stdin)";
+
+ pparams.scanner = scanner;
+
+ calctest_yyparse(&pparams);
+
+ calctest_yylex_destroy(pparams.scanner); //-- cleanup reentrant flex scanner
+
+ printf("Final calctest value=%g\n", pparams.val);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/commatest.c b/gfsm/gfsm/src/libgfsm/tests/commatest.c
new file mode 100644
index 0000000..b704970
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/commatest.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main (void) {
+ int x = 0;
+
+ x = 1, printf("foo\n"), printf("bar\n"), x=2, printf("%d\n", x);
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/compre2test.c b/gfsm/gfsm/src/libgfsm/tests/compre2test.c
new file mode 100644
index 0000000..07d2b07
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/compre2test.c
@@ -0,0 +1,41 @@
+#include <gfsmRegexCompiler.h>
+#include <gfsmAutomatonIO.h>
+
+
+/*======================================================================
+ * User C Code
+ */
+
+int main (int argc, char **argv) {
+ gfsmRegexCompiler *rec = gfsm_regex_compiler_new();
+ gfsmAutomaton *fsm = NULL;
+
+ //-- initialization
+ rec->abet = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(rec->abet, "test.lab", &(rec->scanner.err))) {
+ g_printerr("%s: load failed for labels file '%s': %s\n",
+ *argv, "test.lab", (rec->scanner.err ? rec->scanner.err->message : "?"));
+ exit(2);
+ }
+
+ //-- debug: lexer
+ rec->scanner.emit_warnings = TRUE;
+
+ //-- parse
+ fsm = gfsm_regex_compiler_parse(rec);
+
+ //-- sanity check
+ if (rec->scanner.err) {
+ fprintf(stderr, "%s: %s\n", *argv, rec->scanner.err->message);
+ }
+
+ if (fsm) {
+ gfsm_automaton_save_bin_file(fsm, stdout, NULL);
+ } else {
+ fprintf(stderr, "%s: Error: no fsm!\n", *argv);
+ }
+
+ gfsm_regex_compiler_free(rec,TRUE,TRUE);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/comprelex.l b/gfsm/gfsm/src/libgfsm/tests/comprelex.l
new file mode 100644
index 0000000..b82178d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/comprelex.l
@@ -0,0 +1,297 @@
+/*======================================================================
+ * Flex Options
+ */
+%option outfile="comprelex.lex.c"
+%option header-file="comprelex.lex.h"
+%option prefix="compretest_yy"
+%option reentrant
+%option 8bit
+%option yylineno
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+#include <gfsmRegexCompiler.h>
+//#include "compretest.tab.h"
+
+#define my_compiler ((gfsmRegexCompiler*)yyextra)
+#define my_gstr (my_compiler->gstr)
+#define my_abet (my_compiler->abet)
+
+typedef enum {
+ TOK_UNKNOWN =256,
+ TOK_CHAR =257,
+ TOK_STRING =258,
+ TOK_WEIGHT =259,
+ TOK_UINT =260,
+ TOK_BRACKETED =261,
+ TOK_EOF =262
+} TokenType;
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+DIGIT [0-9]
+SPACE [[:space:]]
+WCHAR [^\<\[\\ \t\n\r\#]
+BCHAR [^\\\]\ \t\n\r\=]
+UTF8PREFIX "Ã"
+
+%x STATE_ESCAPE
+%x STATE_BRACKETED
+%x STATE_BRACKETED_SEP
+%x STATE_BRACKETED_ESCAPE
+%x STATE_COMMENT
+%x STATE_WEIGHT
+%x STATE_UINT
+
+/*======================================================================
+ * Rules
+ */
+%%
+
+{UTF8PREFIX}+. {
+ g_string_truncate(my_gstr,0);
+ g_string_append_len(my_gstr,yytext,yyleng);
+ return TOK_STRING;
+}
+
+"\\" { BEGIN(STATE_ESCAPE); }
+
+"#" { BEGIN(STATE_COMMENT); }
+
+"[" {
+ BEGIN(STATE_BRACKETED);
+ return '[';
+}
+
+"<" { BEGIN(STATE_WEIGHT); return '<'; }
+
+"(" { return '('; }
+")" { return ')'; }
+
+"*" { return '*'; }
+"+" { return '+'; }
+"^" { BEGIN(STATE_UINT); return '|'; }
+"?" { return '?'; }
+"!" { return '!'; }
+"|" { return '|'; }
+"&" { return '&'; }
+":" { return ':'; }
+"@" { return '@'; }
+"-" { return '-'; /*"/1"{return PROJ1;}*/ /*"/2"{return PROJ2;}*/ }
+
+"$" { return '$'; /* non-AT&T: determinize */ }
+"%" { return '%'; /* non-AT&T: rmepsilon */ }
+"~" { return '~'; /* non-AT&T: connect */ }
+
+{SPACE} { /* ignore */ }
+
+{WCHAR} {
+ //yylval->u = gfsm_alphabet_find_label(my_abet, yytext);
+ return TOK_CHAR;
+}
+
+
+
+<STATE_WEIGHT>([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? {
+ //yylval->w = strtod(yytext,NULL);
+ return TOK_WEIGHT;
+}
+
+<STATE_WEIGHT>\> {
+ BEGIN(INITIAL);
+ return '>';
+}
+
+
+
+<STATE_UINT>{DIGIT}+ {
+ BEGIN(INITIAL);
+ //yylval->u = strtol(yytext,NULL,0);
+ return TOK_UINT;
+}
+
+
+<STATE_COMMENT>[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ }
+
+
+
+
+<STATE_ESCAPE>. {
+ BEGIN(INITIAL);
+ return TOK_CHAR;
+}
+
+
+
+<STATE_BRACKETED>{UTF8PREFIX}+. {
+ g_string_append_len(my_gstr,yytext,yyleng);
+}
+<STATE_BRACKETED>{SPACE}*"]" {
+ unput(']');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) return TOK_STRING;
+}
+<STATE_BRACKETED>{BCHAR}+ {
+ g_string_append(my_gstr, yytext);
+ //return TOK_STRING;
+}
+<STATE_BRACKETED>({SPACE}*)"="({SPACE}*) {
+ unput('=');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) return TOK_STRING;
+}
+<STATE_BRACKETED>{SPACE}+ {
+ unput(' ');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) return TOK_STRING;
+}
+<STATE_BRACKETED>\\ {
+ BEGIN(STATE_BRACKETED_ESCAPE);
+}
+
+
+<STATE_BRACKETED_SEP>"]" {
+ BEGIN(INITIAL);
+ if (my_gstr->len) {
+ g_string_truncate(my_gstr,0);
+ return ']';
+ }
+}
+<STATE_BRACKETED_SEP>"=" {
+ BEGIN(STATE_BRACKETED);
+ g_string_truncate(my_gstr,0);
+ return '=';
+}
+<STATE_BRACKETED_SEP>" " {
+ BEGIN(STATE_BRACKETED);
+ if (my_gstr->len) {
+ g_string_truncate(my_gstr,0);
+ return ' ';
+ }
+}
+
+
+
+<STATE_BRACKETED_ESCAPE>. {
+ BEGIN(STATE_BRACKETED);
+ g_string_append_c(my_gstr, yytext[0]);
+ //return TOK_STRING;
+}
+
+
+
+<*>. {
+ gfsm_scanner_carp(yyextra, "bad character '%s'", yytext);
+ return TOK_UNKNOWN;
+}
+
+<<EOF>> { return TOK_EOF; }
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+void testme(gfsmScanner *scanner) {
+ TokenType tok;
+ double weight;
+ unsigned int uint;
+
+ while ((tok=compretest_yylex(scanner->yyscanner)) != TOK_EOF) {
+ switch (tok) {
+ case TOK_CHAR:
+ printf("(char) '%s'\n", compretest_yyget_text(scanner->yyscanner));
+ break;
+
+ case TOK_BRACKETED:
+ printf("(bracketed) text=\"%s\" gstr=\"%s\"\n",
+ compretest_yyget_text(scanner->yyscanner),
+ ((gfsmRegexCompiler*)scanner)->gstr->str);
+ break;
+
+ case TOK_STRING:
+ printf("(string) gstr=\"%s\"\n",
+ //compretest_yyget_text(scanner->yyscanner),
+ ((gfsmRegexCompiler*)scanner)->gstr->str
+ );
+ break;
+
+ case '[':
+ printf("(left-bracket) text=\"%s\"\n", compretest_yyget_text(scanner->yyscanner));
+ break;
+
+ case ']':
+ printf("(right-bracket) text=\"%s\"\n", compretest_yyget_text(scanner->yyscanner));
+ break;
+
+ case ' ':
+ printf("(space) text=\"%s\"\n", compretest_yyget_text(scanner->yyscanner));
+ break;
+
+ case '=':
+ printf("(equal) text=\"%s\"\n", compretest_yyget_text(scanner->yyscanner));
+ break;
+
+ case TOK_WEIGHT:
+ weight = strtod(compretest_yyget_text(scanner->yyscanner),NULL);
+ printf("(weight) =%g\n", weight);
+ break;
+
+ case TOK_UINT:
+ uint = strtol(compretest_yyget_text(scanner->yyscanner),NULL,0);
+ printf("(uint) =%d\n", uint);
+ break;
+
+ default:
+ printf("(other=%d~'%c'): (%s)\n", tok, tok, compretest_yyget_text(scanner->yyscanner));
+ break;
+ }
+
+ if (scanner->err) {
+ fprintf(stderr, "Error: %s\n", scanner->err->message);
+ g_clear_error(&(scanner->err));
+ break;
+ }
+ }
+}
+
+int main(int argc,char **argv) {
+ gfsmRegexCompiler *reparser = g_new0(gfsmRegexCompiler,1);
+ gfsm_scanner_init((gfsmScanner*)reparser, "gfsmRegexCompiler", compretest_yy);
+
+ //-- initialization
+ reparser->srtype = gfsmSRTTropical;
+ reparser->gstr = g_string_new("");
+ reparser->abet = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(reparser->abet, "test.lab", &(reparser->scanner.err))) {
+ g_printerr("%s: load failed for labels file '%s': %s\n",
+ *argv, "test.lab", (reparser->scanner.err ? reparser->scanner.err->message : "?"));
+ exit(2);
+ }
+
+ //-- debug: lexer
+ reparser->scanner.emit_warnings = TRUE;
+
+ //-- lex
+ testme((gfsmScanner*)reparser);
+
+ //-- sanity check
+ if (reparser->scanner.err) {
+ fprintf(stderr, "Error: %s\n", reparser->scanner.err->message);
+ }
+
+ gfsm_scanner_free((gfsmScanner*)reparser);
+
+ return 0;
+}
+
+
+GFSM_SCANNER_YYWRAP(compretest_yy)
diff --git a/gfsm/gfsm/src/libgfsm/tests/compretest.l b/gfsm/gfsm/src/libgfsm/tests/compretest.l
new file mode 100644
index 0000000..731655c
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/compretest.l
@@ -0,0 +1,199 @@
+/*======================================================================
+ * Flex Options
+ */
+%option outfile="compretest.lex.c"
+%option header-file="compretest.lex.h"
+%option prefix="compretest_yy"
+%option reentrant
+%option 8bit
+%option yylineno
+
+%option bison-bridge
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+#include <gfsmMem.h>
+#include <gfsmRegexCompiler.h>
+#include "compretest.tab.h"
+
+#define my_compiler ((gfsmRegexCompiler*)yyextra)
+#define my_gstr (my_compiler->gstr)
+#define my_abet (my_compiler->abet)
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+DIGIT [0-9]
+SPACE [[:space:]]
+WCHAR [^\<\[\\ \t\n\r\#]
+BCHAR [^\\\]\ \t\n\r\=]
+UTF8PREFIX "Ã"
+
+%x STATE_ESCAPE
+%x STATE_BRACKETED
+%x STATE_BRACKETED_SEP
+%x STATE_BRACKETED_ESCAPE
+%x STATE_COMMENT
+%x STATE_WEIGHT
+%x STATE_UINT
+
+/*======================================================================
+ * Rules
+ */
+%%
+
+{UTF8PREFIX}+. {
+ yylval->gs = gfsm_gstring_new_bytes(yytext,yyleng);
+ return TOK_STRING;
+}
+
+"\\" { BEGIN(STATE_ESCAPE); }
+
+"#" { BEGIN(STATE_COMMENT); }
+
+"[" {
+ BEGIN(STATE_BRACKETED);
+ return '[';
+}
+
+"<" { BEGIN(STATE_WEIGHT); return '<'; }
+
+"(" { return '('; }
+")" { return ')'; }
+
+"*" { return '*'; }
+"+" { return '+'; }
+"^" { BEGIN(STATE_UINT); return '|'; }
+"?" { return '?'; }
+"!" { return '!'; }
+"|" { return '|'; }
+"&" { return '&'; }
+":" { return ':'; }
+"@" { return '@'; }
+"-" { return '-'; /*"/1"{return PROJ1;}*/ /*"/2"{return PROJ2;}*/ }
+
+"$" { return '$'; /* non-AT&T: determinize */ }
+"%" { return '%'; /* non-AT&T: rmepsilon */ }
+"~" { return '~'; /* non-AT&T: connect */ }
+
+{SPACE} { /* ignore */ }
+
+{WCHAR} {
+ yylval->c = yytext[0];
+ return TOK_CHAR;
+}
+
+
+
+<STATE_WEIGHT>([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? {
+ yylval->w = strtod(yytext,NULL);
+ return TOK_WEIGHT;
+}
+
+<STATE_WEIGHT>\> {
+ BEGIN(INITIAL);
+ return '>';
+}
+
+
+
+<STATE_UINT>{DIGIT}+ {
+ BEGIN(INITIAL);
+ yylval->u = strtol(yytext,NULL,0);
+ return TOK_UINT;
+}
+
+
+<STATE_COMMENT>[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ }
+
+
+
+
+<STATE_ESCAPE>. {
+ BEGIN(INITIAL);
+ yylval->c = yytext[0];
+ return TOK_CHAR;
+}
+
+
+<STATE_BRACKETED>{UTF8PREFIX}+. {
+ g_string_append_len(my_gstr,yytext,yyleng);
+}
+<STATE_BRACKETED>{SPACE}*"]" {
+ unput(']');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) {
+ yylval->gs = gfsm_gstring_dup(my_gstr);
+ return TOK_STRING;
+ }
+}
+<STATE_BRACKETED>{BCHAR}+ {
+ g_string_append(my_gstr, yytext);
+}
+<STATE_BRACKETED>({SPACE}*)"="({SPACE}*) {
+ unput('=');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) {
+ yylval->gs = gfsm_gstring_dup(my_gstr);
+ return TOK_STRING;
+ }
+}
+<STATE_BRACKETED>{SPACE}+ {
+ unput(' ');
+ BEGIN(STATE_BRACKETED_SEP);
+ if (my_gstr->len) {
+ yylval->gs = gfsm_gstring_dup(my_gstr);
+ return TOK_STRING;
+ }
+}
+<STATE_BRACKETED>\\ {
+ BEGIN(STATE_BRACKETED_ESCAPE);
+}
+
+
+<STATE_BRACKETED_SEP>"]" {
+ BEGIN(INITIAL);
+ if (my_gstr->len) {
+ g_string_truncate(my_gstr,0);
+ return ']';
+ }
+}
+<STATE_BRACKETED_SEP>"=" {
+ BEGIN(STATE_BRACKETED);
+ g_string_truncate(my_gstr,0);
+ return '=';
+}
+<STATE_BRACKETED_SEP>" " {
+ BEGIN(STATE_BRACKETED);
+ if (my_gstr->len) {
+ g_string_truncate(my_gstr,0);
+ return ' ';
+ }
+}
+
+
+<STATE_BRACKETED_ESCAPE>. {
+ BEGIN(STATE_BRACKETED);
+ g_string_append_c(my_gstr, yytext[0]);
+}
+
+
+
+<*>. {
+ gfsm_scanner_carp(yyextra, "bad character '%s'", yytext);
+ return TOK_UNKNOWN;
+}
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+GFSM_SCANNER_YYWRAP(compretest_yy)
diff --git a/gfsm/gfsm/src/libgfsm/tests/compretest.y b/gfsm/gfsm/src/libgfsm/tests/compretest.y
new file mode 100644
index 0000000..d55f488
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/compretest.y
@@ -0,0 +1,185 @@
+/*======================================================================
+ * Bison Options
+ */
+%pure_parser
+
+%{
+/*======================================================================
+ * Bison C Header
+ */
+#include <gfsmRegexCompiler.h>
+#include <gfsmAutomatonIO.h>
+
+#include "compretest.tab.h"
+#include "compretest.lex.h"
+
+#define my_compiler ((gfsmRegexCompiler*)reparser)
+
+#define YYLEX_PARAM ((gfsmRegexCompiler*)reparser)->scanner.yyscanner
+#define YYPARSE_PARAM reparser
+
+#define YYERROR_VERBOSE 1
+#define compretest_yyerror(msg) \
+ gfsm_scanner_carp((gfsmScanner*)reparser, (msg));
+
+%}
+
+/*======================================================================
+ * Bison Definitions
+ */
+%union {
+ gfsmAutomaton *fsm; //-- automaton
+ GString *gs; //-- needs to be freed by hand
+ gchar c;
+ guint32 u;
+ gfsmWeight w;
+}
+
+%token <c> TOK_UNKNOWN TOK_CHAR
+%token <u> TOK_UINT
+%token <gs> TOK_STRING
+%token <w> TOK_WEIGHT
+
+%type <u> label
+%type <w> weight
+%type <fsm> regex
+
+/*
+empty { $$=gfsm_regex_automaton_epsilon(my_compiler); }
+*/
+
+/*
+ | gfsmRETChar %prec LAB
+ { $$=gfsm_regex_automaton_lab(my_compiler, $1); }
+*/
+
+// -- Operator precedence and associativity
+%left CONCAT
+%left LABCONCAT
+%left WEIGHT
+%right '%' //-- non-AT&T: rmepsilon: % REGEX
+%right '$' //-- non-AT&T: determinize: $ REGEX
+%right '~' //-- non-AT&T: connect: ~ REGEX
+%left '*' '+' '?' '^'
+%right '!'
+%left '@'
+%left ':'
+%left '-'
+%left '&'
+%left '|'
+
+/*======================================================================
+ * Bison Rules
+ */
+%%
+
+regex: '('regex ')'
+ { $$=$2; }
+
+ | label
+ { $$=gfsm_regex_compiler_label_fsm(my_compiler, $1); }
+
+ | label regex %prec LABCONCAT
+ { $$=gfsm_regex_compiler_prepend_lab(my_compiler, $1, $2); }
+
+ | regex regex %prec CONCAT
+ { $$=gfsm_regex_compiler_concat(my_compiler, $1, $2); }
+
+ | '%' regex
+ { $$=gfsm_regex_compiler_rmepsilon(my_compiler, $2); /* non-ATT */ }
+
+ | '$' regex
+ { $$=gfsm_regex_compiler_determinize(my_compiler, $2); /* non-ATT */ }
+
+ | '~' regex
+ { $$=gfsm_regex_compiler_connect(my_compiler, $2); /* non-ATT */ }
+
+ | regex '*'
+ { $$=gfsm_regex_compiler_closure(my_compiler,$1,FALSE); }
+
+ | regex '+'
+ { $$=gfsm_regex_compiler_closure(my_compiler,$1,TRUE); }
+
+ | regex '^' TOK_UINT
+ { $$=gfsm_regex_compiler_power(my_compiler,$1,$3); }
+
+ | regex '?'
+ { $$=gfsm_regex_compiler_optional(my_compiler,$1); }
+
+ | '!' regex
+ { $$=gfsm_regex_compiler_complement(my_compiler,$2); }
+
+ | regex '|' regex
+ { $$=gfsm_regex_compiler_union(my_compiler,$1,$3); }
+
+ | regex '&' regex
+ { $$=gfsm_regex_compiler_intersect(my_compiler,$1,$3); }
+
+ | regex ':' regex
+ { $$=gfsm_regex_compiler_product(my_compiler,$1,$3); }
+
+ | regex '@' regex
+ { $$=gfsm_regex_compiler_compose(my_compiler,$1,$3); }
+
+ | regex '-' regex
+ { $$=gfsm_regex_compiler_difference(my_compiler,$1,$3); }
+
+ | regex weight %prec WEIGHT
+ { $$=gfsm_regex_compiler_weight(my_compiler,$1,$2); }
+ ;
+
+label: TOK_CHAR
+ { $$=gfsm_regex_compiler_char2label(my_compiler, $1); }
+
+ | TOK_STRING
+ { $$=gfsm_regex_compiler_gstring2label(my_compiler, $1); }
+
+ | '[' TOK_STRING ']'
+ { $$=gfsm_regex_compiler_gstring2label(my_compiler, $2); }
+ ;
+
+weight: '<' TOK_WEIGHT '>' { $$=$2; }
+ ;
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+int main (int argc, char **argv) {
+ gfsmRegexCompiler *reparser = g_new0(gfsmRegexCompiler,1);
+ gfsm_scanner_init((gfsmScanner*)reparser, "gfsmRegexCompiler", compretest_yy);
+
+
+ //-- initialization
+ reparser->srtype = gfsmSRTTropical;
+ reparser->gstr = g_string_new("");
+ reparser->abet = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(reparser->abet, "test.lab", &(reparser->scanner.err))) {
+ g_printerr("%s: load failed for labels file '%s': %s\n",
+ *argv, "test.lab", (reparser->scanner.err ? reparser->scanner.err->message : "?"));
+ exit(2);
+ }
+
+ //-- debug: lexer
+ reparser->scanner.emit_warnings = TRUE;
+
+ //-- parse
+ compretest_yyparse(reparser);
+
+ //-- sanity check
+ if (reparser->scanner.err) {
+ fprintf(stderr, "%s: %s\n", *argv, reparser->scanner.err->message);
+ }
+
+ if (reparser->fsm) {
+ gfsm_automaton_save_bin_file(reparser->fsm, stdout, NULL);
+ } else {
+ fprintf(stderr, "%s: Error: no fsm!\n", *argv);
+ }
+
+ gfsm_scanner_free((gfsmScanner*)reparser);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/ctest.c b/gfsm/gfsm/src/libgfsm/tests/ctest.c
new file mode 100644
index 0000000..78d9002
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/ctest.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+typedef struct testme_s {
+ int i : 1;
+ int j : 1;
+ int k : 1;
+} testme_t;
+
+int main (void) {
+ int x,y,z;
+ float f = +inf;
+ printf("sizeof(testme_t)=%u\n", sizeof(testme_t));
+
+ z = (x=42,y=24,17);
+ printf ("z = (x=42,y=24) = %d\n", z);
+ printf("f = %g\n", f);
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/dettest.c b/gfsm/gfsm/src/libgfsm/tests/dettest.c
new file mode 100644
index 0000000..278535c
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/dettest.c
@@ -0,0 +1,21 @@
+#include <gfsm.h>
+#include <stdio.h>
+
+int main (void) {
+ gfsmAutomaton *fsm = gfsm_automaton_new();
+
+ printf("##-- determinize()-1...\n");
+ gfsm_automaton_determinize(fsm);
+ gfsm_automaton_print_file(fsm,stdout,NULL);
+
+ printf("##-- determinize()-2...\n");
+ gfsm_automaton_determinize(fsm);
+ gfsm_automaton_print_file(fsm,stdout,NULL);
+
+ printf("##-- determinize()-3...\n");
+ gfsm_automaton_determinize(fsm);
+ gfsm_automaton_print_file(fsm,stdout,NULL);
+
+ printf("done.\n");
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/flex2test.l b/gfsm/gfsm/src/libgfsm/tests/flex2test.l
new file mode 100644
index 0000000..b81e7f7
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/flex2test.l
@@ -0,0 +1,174 @@
+/*======================================================================
+ * Flex Options
+ */
+%option outfile="flex2test.lex.c"
+%option header-file="flex2test.lex.h"
+%option prefix="testme_yy"
+%option reentrant
+%option 8bit
+%option yylineno
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+#include <gfsm.h>
+
+typedef enum {
+ T_EOF,
+ T_CHAR,
+ T_STRING,
+ T_WEIGHT,
+
+ T_OP_PROJ_1,
+ T_OP_PROJ_2,
+ T_OP_STAR,
+ T_OP_PLUS,
+ T_OP_POWER, //-- "^n"
+ T_OP_MINUS,
+ T_OP_OPTIONAL,
+ T_OP_UNION,
+ T_OP_COMPLEMENT,
+ T_OP_INTERSECT,
+ T_OP_PRODUCT,
+ T_OP_COMPOSE,
+
+ T_LPAREN,
+ T_RPAREN,
+ T_LBRACKET,
+ T_RBRACKET,
+
+ T_EQUAL,
+ T_SEMICOLON, //-- semicolon
+
+ T_OTHER
+} TokenType;
+
+#define GSTR_BUF ((GString*)((gfsmScanner*)yyextra)->data)
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+DIGIT [0-9]
+SPACE [[:space:]]
+WCHAR [^\\\[ \t\n\r\#\<]
+SCHAR [^\\\]]
+
+%x ESCAPE STRING SESCAPE COMMENT WEIGHT
+
+/*======================================================================
+ * Rules
+ */
+%%
+
+<INITIAL>{WCHAR} { return T_CHAR; }
+
+<INITIAL>{SPACE} { /* ignore */ }
+
+<INITIAL># { BEGIN(COMMENT); }
+
+<INITIAL>\\ { BEGIN(ESCAPE); }
+
+<INITIAL>\[ { BEGIN(STRING); GSTR_BUF->len = 0; }
+
+<INITIAL>\< { BEGIN(WEIGHT); }
+
+
+
+<WEIGHT>[^\>]+ { return WEIGHT; /* hack */ }
+
+<WEIGHT>\> { BEGIN(INITIAL); }
+
+
+
+<COMMENT>[^\n]*\n { BEGIN(INITIAL); }
+
+
+
+
+<ESCAPE>. { BEGIN(INITIAL); return T_CHAR; }
+
+
+
+
+<STRING>\] { BEGIN(INITIAL); return T_STRING; }
+
+<STRING>{SCHAR} { g_string_append_c(GSTR_BUF, yytext[0]); }
+
+<STRING>\\ { BEGIN(SESCAPE); }
+
+
+
+<SESCAPE>. { BEGIN(STRING); g_string_append_c(GSTR_BUF, yytext[0]); }
+
+
+
+<<EOF>> { return T_EOF; }
+
+
+<*>. {
+ gfsm_scanner_carp(yyextra, "bad character '%s'", yytext);
+ return T_OTHER;
+}
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+void testme(gfsmScanner *scanner) {
+ TokenType tok;
+ double weight;
+
+ while ((tok=testme_yylex(scanner->yyscanner)) != T_EOF) {
+ switch (tok) {
+ case T_CHAR:
+ printf("(char) '%s'\n", testme_yyget_text(scanner->yyscanner));
+ break;
+ case STRING:
+ printf("(string) \"%s\"\n", ((GString*)scanner->data)->str);
+ break;
+ case WEIGHT:
+ weight = strtod(testme_yyget_text(scanner->yyscanner),NULL);
+ printf("(weight) %g\n", weight);
+ break;
+ default:
+ printf("(other=%d): (%s)\n", tok, testme_yyget_text(scanner->yyscanner));
+ break;
+ }
+
+ if (scanner->err) {
+ fprintf(stderr, "Error: %s\n", scanner->err->message);
+ g_clear_error(&(scanner->err));
+ break;
+ }
+ }
+}
+
+int main(void) {
+ gfsmScanner *scanner = gfsm_scanner_new("myScanner",testme_yy);
+ scanner->data = g_string_new("");
+
+ //-- first, scan a string
+ /*
+ gfsm_scanner_scan_string(scanner, "line 1\nline 2\nline 3.");
+ scanner->filename = g_strdup("string");
+ testme(scanner);
+ */
+
+ //-- now scan stdin
+ gfsm_scanner_scan_filename(scanner, "-");
+ testme(scanner);
+
+ gfsm_scanner_free(scanner);
+
+ return 0;
+}
+
+//int testme_yywrap(yyscan_t yyscanner) { return 1; }
+GFSM_SCANNER_YYWRAP(testme_yy)
diff --git a/gfsm/gfsm/src/libgfsm/tests/flex3test.l b/gfsm/gfsm/src/libgfsm/tests/flex3test.l
new file mode 100644
index 0000000..27c1cc1
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/flex3test.l
@@ -0,0 +1,232 @@
+/*======================================================================
+ * Flex Options
+ */
+%option outfile="flex3test.lex.c"
+%option header-file="flex3test.lex.h"
+%option prefix="testme_yy"
+%option reentrant
+%option 8bit
+%option yylineno
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+#include <gfsm.h>
+
+typedef enum {
+ T_EOF = 256,
+ T_CHAR = 257,
+ T_BRACKETED = 258,
+ T_BSPACE = 259,
+ T_WEIGHT = 260,
+ T_UINT = 261,
+ T_UTF8 = 262,
+
+ T_LPAREN = '(',
+ T_RPAREN = ')',
+ T_LBRACKET = '[',
+ T_RBRACKET = ']',
+ T_LANGLE = '<',
+ T_RANGLE = '>',
+
+ T_BEQUAL = '=',
+
+ T_OTHER = 65535
+} TokenType;
+
+#define GSTR_BUF ((GString*)((gfsmScanner*)yyextra)->data)
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+DIGIT [0-9]
+SPACE [[:space:]]
+WCHAR [^\<\>\[\]\\ \t\n\r\#]
+BCHAR [^\\\]\ \t\n\r\=]
+UTF8PREFIX "Ã"
+
+%x ESCAPE BRACKETED BESCAPE COMMENT WEIGHT UINT UTF8 BUTF8
+
+/*======================================================================
+ * Rules
+ */
+%%
+
+{UTF8PREFIX} { BEGIN(UTF8); g_string_set_size(GSTR_BUF,1); GSTR_BUF->str[0] = yytext[0]; }
+
+"\\" { BEGIN(ESCAPE); }
+
+"#" { BEGIN(COMMENT); }
+
+"[" { BEGIN(BRACKETED); g_string_truncate(GSTR_BUF,0); return T_LBRACKET; }
+
+"<" { BEGIN(WEIGHT); return T_LANGLE; }
+
+
+"(" { return '('; }
+")" { return ')'; }
+
+"*" { return '*'; }
+"+" { return '+'; }
+"^" { BEGIN(UINT); return '|'; }
+"?" { return '?'; }
+"!" { return '!'; }
+"|" { return '|'; }
+"&" { return '&'; }
+":" { return ':'; }
+"@" { return '@'; }
+"-" { return '-'; }
+
+{SPACE} { /* ignore */ }
+
+{WCHAR} { return T_CHAR; }
+
+
+
+<UTF8>{UTF8PREFIX}+ { g_string_append(GSTR_BUF, yytext); }
+
+<UTF8>. { BEGIN(INITIAL); g_string_append_c(GSTR_BUF, yytext[0]); return T_UTF8; }
+
+
+<WEIGHT>([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? { return T_WEIGHT; /* hack */ }
+
+<WEIGHT>\> { BEGIN(INITIAL); return T_RANGLE; }
+
+
+
+<UINT>{DIGIT}+ { BEGIN(INITIAL); return T_UINT; }
+
+
+<COMMENT>[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ }
+
+
+
+
+<ESCAPE>. { BEGIN(INITIAL); return T_CHAR; }
+
+
+
+<BRACKETED>{UTF8PREFIX} { BEGIN(BUTF8); g_string_append_c(GSTR_BUF, yytext[0]); }
+
+<BRACKETED>\] { BEGIN(INITIAL); return T_RBRACKET; }
+
+<BRACKETED>{BCHAR} { g_string_append_c(GSTR_BUF, yytext[0]); }
+
+<BRACKETED>{SPACE} { return T_BSPACE; }
+
+<BRACKETED>"=" { return T_BEQUAL; }
+
+<BRACKETED>\\ { BEGIN(BESCAPE); }
+
+
+<BUTF8>{UTF8PREFIX}+ { g_string_append(GSTR_BUF, yytext); }
+
+<BUTF8>. { BEGIN(BRACKETED); g_string_append_c(GSTR_BUF, yytext[0]); }
+
+
+<BESCAPE>. { BEGIN(BRACKETED); g_string_append_c(GSTR_BUF, yytext[0]); }
+
+
+
+<<EOF>> { return T_EOF; }
+
+
+<*>. {
+ gfsm_scanner_carp(yyextra, "bad character '%s'", yytext);
+ return T_OTHER;
+}
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+void testme(gfsmScanner *scanner) {
+ TokenType tok;
+ double weight;
+ unsigned int uint;
+
+ while ((tok=testme_yylex(scanner->yyscanner)) != T_EOF) {
+ switch (tok) {
+ case T_CHAR:
+ printf("(char) '%s'\n", testme_yyget_text(scanner->yyscanner));
+ break;
+
+ case T_UTF8:
+ printf("(utf8) '%s'\n", ((GString*)scanner->data)->str);
+ break;
+
+ case T_LBRACKET:
+ printf("(lbracket)\n");
+ break;
+
+ case T_RBRACKET:
+ printf("(rbracket) gstr=\"%s\"\n", ((GString*)scanner->data)->str);
+ g_string_truncate(((GString*)scanner->data),0);
+ break;
+ case T_BSPACE:
+ printf("(bspace) gstr=\"%s\"\n", ((GString*)scanner->data)->str);
+ g_string_truncate(((GString*)scanner->data),0);
+ break;
+ case T_BEQUAL:
+ printf("(bequal) gstr=\"%s\"\n", ((GString*)scanner->data)->str);
+ g_string_truncate(((GString*)scanner->data),0);
+ break;
+
+ case T_LANGLE:
+ printf("(langle)\n");
+ break;
+ case T_RANGLE:
+ printf("(rangle)\n");
+ break;
+ case T_WEIGHT:
+ weight = strtod(testme_yyget_text(scanner->yyscanner),NULL);
+ printf("(weight) =%g\n", weight);
+ break;
+
+ case T_UINT:
+ uint = strtol(testme_yyget_text(scanner->yyscanner),NULL,0);
+ printf("(uint) =%d\n", uint);
+ break;
+
+ default:
+ printf("(other=%d~'%c'): (%s)\n", tok, tok, testme_yyget_text(scanner->yyscanner));
+ break;
+ }
+
+ if (scanner->err) {
+ fprintf(stderr, "Error: %s\n", scanner->err->message);
+ g_clear_error(&(scanner->err));
+ break;
+ }
+ }
+}
+
+int main(void) {
+ gfsmScanner *scanner = gfsm_scanner_new("myScanner",testme_yy);
+ scanner->data = g_string_new("");
+
+ //-- first, scan a string
+ /*
+ gfsm_scanner_scan_string(scanner, "line 1\nline 2\nline 3.");
+ scanner->filename = g_strdup("string");
+ testme(scanner);
+ */
+
+ //-- now scan stdin
+ gfsm_scanner_scan_filename(scanner, "-");
+ testme(scanner);
+
+ gfsm_scanner_free(scanner);
+
+ return 0;
+}
+
+//int testme_yywrap(yyscan_t yyscanner) { return 1; }
+GFSM_SCANNER_YYWRAP(testme_yy)
diff --git a/gfsm/gfsm/src/libgfsm/tests/flextest.l b/gfsm/gfsm/src/libgfsm/tests/flextest.l
new file mode 100644
index 0000000..c0d103d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/flextest.l
@@ -0,0 +1,59 @@
+/*======================================================================
+ * Flex Options
+ */
+%option outfile="flextest.c"
+%option header-file="flextest.h"
+%option prefix="testme_yy"
+%option reentrant
+%option 8bit
+
+%{
+/*======================================================================
+ * User C Header
+ */
+
+int nlines=0;
+
+%}
+
+/*======================================================================
+ * Flex Definitions
+ */
+
+
+/*======================================================================
+ * Rules
+ */
+%%
+
+\n { return 1; }
+
+<<EOF>> { return 0; }
+
+. { /* do nothing */; }
+
+%%
+
+/*======================================================================
+ * User C Code
+ */
+
+int main(void) {
+ yyscan_t scanner;
+ int nlines=0;
+ int tok;
+
+ testme_yylex_init(&scanner); //-- initialize reentrant flex scanner
+
+ while ((tok=testme_yylex(scanner))) {
+ //printf("tok=%d\n", tok);
+ nlines++;
+ }
+
+ testme_yylex_destroy(scanner); //-- cleanup reentrant flex scanner
+
+ printf("%d\n", nlines);
+ return 0;
+}
+
+int testme_yywrap(yyscan_t yyscanner) { return 1; }
diff --git a/gfsm/gfsm/src/libgfsm/tests/ftest.c b/gfsm/gfsm/src/libgfsm/tests/ftest.c
new file mode 100644
index 0000000..e571f31
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/ftest.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <glib.h>
+
+int main (int argc, char **argv) {
+ float f, f2;
+ gpointer p;
+ int i;
+
+ for (i=1; i<argc; i++) {
+ sscanf(argv[i], "%f", &f);
+ p = (gpointer)(*((int*)(&f)));
+ f2 = *((float*)(&p));
+ printf("argv[i=%d]='%s' ; f=%g ; f->p=%p ; p->f=%g\n", i, argv[i], f, p, f2);
+ }
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/gbtest.c b/gfsm/gfsm/src/libgfsm/tests/gbtest.c
new file mode 100644
index 0000000..e0e406d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/gbtest.c
@@ -0,0 +1,27 @@
+#include <glib.h>
+#include <stdio.h>
+
+GArray *ary1;
+GArray *ary2;
+GArray *ary3;
+guint esize = 8;
+guint nelts = 128;
+
+int main (void) {
+ int i;
+
+ ary1 = g_array_sized_new(FALSE, TRUE, esize, nelts);
+ ary2 = g_array_sized_new(FALSE, TRUE, esize, nelts);
+ ary3 = g_array_sized_new(FALSE, TRUE, esize, nelts);
+
+ for (i=0; i < 128; i++) {
+ g_array_free(ary2,TRUE);
+ ary2 = g_array_sized_new(FALSE,TRUE,esize,nelts*i);
+ }
+
+ g_array_free(ary1,TRUE);
+ g_array_free(ary2,TRUE);
+ g_array_free(ary3,TRUE);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/gfsm-chop.perl b/gfsm/gfsm/src/libgfsm/tests/gfsm-chop.perl
new file mode 100755
index 0000000..7f81bd8
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/gfsm-chop.perl
@@ -0,0 +1,40 @@
+#!/usr/bin/perl -w
+
+use Gfsm;
+
+our @want_states =
+ (
+ 5,
+ 4,
+ 11,
+ 98,
+ 5257,
+ 45623,
+ 290132,
+ 0
+ );
+
+push(@ARGV,'-') if (!@ARGV);
+
+$fsmfile = shift(@ARGV);
+our $fsm = Gfsm::Automaton->new();
+$fsm->load($fsmfile) or die("$0: load failed for fsm file '$fsmfile': $!");
+
+##-- chop it
+my %q2i = map { $want_states[$_]=>$_ } (0..$#want_states);
+my $qid_dummy = scalar(@want_states);
+$fsm2 = $fsm->shadow;
+$ai=Gfsm::ArcIter->new;
+
+foreach $qid_dst (0..$#want_states) {
+ $fsm2->ensure_state($qid_dst);
+ $qid_src = $want_states[$qid_dst];
+ for ($ai->open($fsm,$qid_src); $ai->ok; $ai->next) {
+ $fsm2->add_arc($qid_dst, $qid_dummy, $ai->lower, $ai->upper, $ai->weight);
+ }
+ $fsm2->add_arc($qid_dummy,$qid_dst,0,0,0);
+}
+$fsm2->root($qid_dummy);
+$fsm2->final_weight($qid_dummy,0);
+
+$fsm2->save('-');
diff --git a/gfsm/gfsm/src/libgfsm/tests/gfsm-out-degrees.perl b/gfsm/gfsm/src/libgfsm/tests/gfsm-out-degrees.perl
new file mode 100755
index 0000000..38caf2d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/gfsm-out-degrees.perl
@@ -0,0 +1,11 @@
+#!/usr/bin/perl -w
+
+use Gfsm;
+
+$fsmfile = @ARGV ? shift : '-';
+$fsm = Gfsm::Automaton->new();
+die("$0: load failed for '$fsmfile': $!") if (!$fsm->load($fsmfile));
+
+foreach $qid (0..($fsm->n_states-1)) {
+ print $qid, "\t", $fsm->out_degree($qid), "\n";
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.c b/gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.c
new file mode 100644
index 0000000..12495fa
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.c
@@ -0,0 +1,210 @@
+#include <gfsmRegexCompiler.h>
+#include <gfsmArith.h>
+#include <gfsmUtils.h>
+
+#define RETURN(rec,_rea) (rec)->rea=(_rea); return (_rea);
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_epsilon(gfsmRegexCompiler *rec)
+{
+ rec->rea.typ = gfsmREATEmpty;
+ rec->rea.val.lab = 0;
+ return rec->rea;
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_automaton_new_fsm(gfsmRegexCompiler *rec)
+{
+ gfsmAutomaton *fsm = gfsm_automaton_new_full(gfsmAutomatonDefaultFlags,
+ rec->srtype,
+ gfsmAutomatonDefaultSize);
+ fsm->flags.is_transducer = FALSE;
+ return fsm;
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_automaton_epsilon_fsm(gfsmRegexCompiler *rec)
+{
+ gfsmAutomaton *fsm = gfsm_regex_automaton_new_fsm(rec);
+ fsm->root_id = gfsm_automaton_add_state(fsm);
+ gfsm_automaton_set_final_state(fsm,fsm->root_id,TRUE);
+ return fsm;
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_automaton_label_fsm(gfsmRegexCompiler *rec, gfsmLabelVal lab)
+{
+ gfsmAutomaton *fsm = gfsm_regex_automaton_new_fsm(rec);
+ gfsmStateId labid;
+ fsm->root_id = gfsm_automaton_add_state(fsm);
+ labid = gfsm_automaton_add_state(fsm);
+ gfsm_automaton_add_arc(fsm, fsm->root_id, labid, lab, lab, fsm->sr->one);
+ gfsm_automaton_set_final_state(fsm,labid,TRUE);
+ return fsm;
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_automaton_fsm(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea)
+{
+ switch (rea.typ) {
+ case gfsmREATEmpty:
+ return gfsm_regex_automaton_epsilon_fsm(rec);
+ break;
+ case gfsmREATLabel:
+ return gfsm_regex_automaton_label_fsm(rec, rea.val.lab);
+ break;
+ case gfsmREATFull:
+ default:
+ return rea.val.fsm;
+ break;
+ }
+}
+
+//--------------------------------------------------------------
+gfsmAutomaton *gfsm_regex_automaton_expand(gfsmRegexCompiler *rec, gfsmRegexAutomaton *rea)
+{
+ rea->val.fsm = gfsm_regex_automaton_fsm(rec,*rea);
+ rea->typ = gfsmREATFull;
+ return rea->val.fsm;
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_label(gfsmRegexCompiler *rec, gfsmLabelVal lab)
+{
+ rec->rea.typ = gfsmREATLabel;
+ rec->rea.val.lab = lab;
+ return rec->rea;
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_concat(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmRegexAutomaton rea2)
+{
+ switch (rea2.typ) {
+ case gfsmREATEmpty:
+ break;
+ case gfsmREATLabel:
+ gfsm_regex_automaton_append_lab(rec, gfsm_regex_automaton_expand(rec,&rea1), rea2.val.lab);
+ break;
+ case gfsmREATFull:
+ default:
+ gfsm_automaton_concat(gfsm_regex_automaton_expand(rec,&rea1), rea2.val.fsm);
+ gfsm_automaton_free(rea2.val.fsm);
+ break;
+ }
+
+ RETURN(rec,rea1);
+}
+
+
+//--------------------------------------------------------------
+struct _gfsm_regex_append_lab_data {
+ gfsmAutomaton *fsm;
+ gfsmLabelVal lab;
+ gfsmStateId newid;
+};
+
+gboolean _gfsm_regex_append_lab_foreach_func(gfsmStateId qid, gpointer pw,
+ struct _gfsm_regex_append_lab_data *data)
+{
+ gfsm_automaton_get_state(data->fsm,qid)->is_final = FALSE;
+ gfsm_automaton_add_arc(data->fsm, qid, data->newid, data->lab, data->lab, gfsm_ptr2weight(pw));
+ return FALSE;
+}
+
+gfsmAutomaton *gfsm_regex_automaton_append_lab(gfsmRegexCompiler *rec, gfsmAutomaton *fsm, gfsmLabelVal lab)
+{
+ struct _gfsm_regex_append_lab_data data = { fsm, lab, gfsm_automaton_add_state(fsm) };
+ gfsm_weightmap_foreach(fsm->finals,
+ (GTraverseFunc)_gfsm_regex_append_lab_foreach_func,
+ &data);
+ gfsm_weightmap_clear(fsm->finals);
+ gfsm_automaton_set_final_state(fsm, data.newid, TRUE);
+ return fsm;
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_closure(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea, gboolean is_plus)
+{
+ gfsm_automaton_closure(gfsm_regex_automaton_expand(rec,&rea),is_plus);
+ RETURN(rec,rea);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_power(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea, guint32 n)
+{
+ gfsm_automaton_n_closure(gfsm_regex_automaton_expand(rec,&rea),n);
+ RETURN(rec,rea);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_project(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea,
+ gfsmLabelSide which)
+{
+ gfsm_automaton_project(gfsm_regex_automaton_expand(rec,&rea),which);
+ RETURN(rec,rea);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_optional(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea)
+{
+ gfsm_automaton_optional(gfsm_regex_automaton_expand(rec,&rea));
+ RETURN(rec,rea);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_complement(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea)
+{
+ gfsm_automaton_complement_full(gfsm_regex_automaton_expand(rec,&rea),rec->abet);
+ RETURN(rec,rea);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_union(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea1, gfsmRegexAutomaton rea2)
+{
+ gfsm_automaton_union(gfsm_regex_automaton_expand(rec,&rea1),gfsm_regex_automaton_expand(rec,&rea2));
+ gfsm_automaton_free(gfsm_regex_automaton_expand(rec,&rea2));
+ RETURN(rec,rea1);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_intersect(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea1, gfsmRegexAutomaton rea2)
+{
+ gfsm_automaton_intersect(gfsm_regex_automaton_expand(rec,&rea1),gfsm_regex_automaton_expand(rec,&rea2));
+ gfsm_automaton_free(gfsm_regex_automaton_expand(rec,&rea2));
+ RETURN(rec,rea1);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_product(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea1, gfsmRegexAutomaton rea2)
+{
+ _gfsm_automaton_product(gfsm_regex_automaton_expand(rec,&rea1),gfsm_regex_automaton_expand(rec,&rea2));
+ gfsm_automaton_free(gfsm_regex_automaton_expand(rec,&rea2));
+ RETURN(rec,rea1);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_compose(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea1, gfsmRegexAutomaton rea2)
+{
+ gfsm_automaton_compose(gfsm_regex_automaton_expand(rec,&rea1),gfsm_regex_automaton_expand(rec,&rea2));
+ gfsm_automaton_free(gfsm_regex_automaton_expand(rec,&rea2));
+ RETURN(rec,rea1);
+}
+
+//--------------------------------------------------------------
+gfsmRegexAutomaton gfsm_regex_automaton_difference(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea1, gfsmRegexAutomaton rea2)
+{
+ gfsm_automaton_difference(gfsm_regex_automaton_expand(rec,&rea1),gfsm_regex_automaton_expand(rec,&rea2));
+ gfsm_automaton_free(gfsm_regex_automaton_expand(rec,&rea2));
+ RETURN(rec,rea1);
+}
+
+//--------------------------------------------------------------
+/** Weight */
+gfsmRegexAutomaton gfsm_regex_automaton_weight(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea, gfsmWeight w)
+{
+ gfsm_automaton_arith_final(gfsm_regex_automaton_expand(rec,&rea), gfsmAOSRTimes, w, FALSE);
+ RETURN(rec,rea);
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.h b/gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.h
new file mode 100644
index 0000000..aefc1cc
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.h
@@ -0,0 +1,121 @@
+#ifndef _GFSM_REGEX_COMPILER_H
+#define _GFSM_REGEX_COMPILER_H
+
+#include <gfsmScanner.h>
+#include <gfsmAutomaton.h>
+#include <gfsmAlphabet.h>
+#include <gfsmAlgebra.h>
+
+/** Regex automaton type */
+typedef enum {
+ gfsmREATEmpty, ///< empty acceptor
+ gfsmREATLabel, ///< single label
+ gfsmREATFull ///< full automaton
+} gfsmRegexAutomatonType;
+
+/** Regex automaton value */
+typedef union {
+ gfsmLabelVal lab; ///< single label
+ gfsmAutomaton *fsm; ///< full automaton
+} gfsmRegexAutomatonValue;
+
+/** Regex automaton */
+typedef struct {
+ gfsmRegexAutomatonType typ; ///< regex type
+ gfsmRegexAutomatonValue val; ///< regex value
+} gfsmRegexAutomaton;
+
+/** Data structure for regex compiler */
+typedef struct {
+ gfsmScanner scanner; ///< scanner
+ gfsmSRType srtype; ///< semiring type
+ gfsmRegexAutomaton rea; ///< regex automaton under construction
+ gfsmAlphabet *abet; ///< alphabet
+ GString *gstr; ///< buffer
+ gboolean is_label : 1; ///< is this a singleton fsm? (if so, *fsm is a gfsmLabelVal)
+} gfsmRegexCompiler;
+
+/** New full-fleded automaton */
+gfsmAutomaton *gfsm_regex_automaton_new_fsm(gfsmRegexCompiler *rec);
+
+/** Get full-fledged automaton */
+gfsmAutomaton *gfsm_regex_automaton_fsm(gfsmRegexCompiler *rec, gfsmRegexAutomaton rea);
+
+/** Full Epsilon recognizer */
+gfsmAutomaton *gfsm_regex_automaton_epsilon_fsm(gfsmRegexCompiler *rec);
+
+/** Full single-character recognizer */
+gfsmAutomaton *gfsm_regex_automaton_label_fsm(gfsmRegexCompiler *rec, gfsmLabelVal lab);
+
+
+/** Single-label recognizer */
+gfsmRegexAutomaton gfsm_regex_automaton_label(gfsmRegexCompiler *rec, gfsmLabelVal lab);
+
+/** Single-label concatenation (low-level) */
+gfsmAutomaton *gfsm_regex_automaton_append_lab(gfsmRegexCompiler *rec,
+ gfsmAutomaton *fsm,
+ gfsmLabelVal lab);
+
+/** General concatenation */
+gfsmRegexAutomaton gfsm_regex_automaton_concat(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmRegexAutomaton rea2);
+
+/** Closure */
+gfsmRegexAutomaton gfsm_regex_automaton_closure(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea,
+ gboolean is_plus);
+
+/** Power (n-ary closure) */
+gfsmRegexAutomaton gfsm_regex_automaton_power(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea,
+ guint32 n);
+
+/** Projection */
+gfsmRegexAutomaton gfsm_regex_automaton_project(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea,
+ gfsmLabelSide which);
+
+
+/** Optionality */
+gfsmRegexAutomaton gfsm_regex_automaton_optional(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea);
+
+/** Complement */
+gfsmRegexAutomaton gfsm_regex_automaton_complement(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea);
+
+/** Union */
+gfsmRegexAutomaton gfsm_regex_automaton_union(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmRegexAutomaton rea2);
+
+/** Intersection */
+gfsmRegexAutomaton gfsm_regex_automaton_intersect(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmRegexAutomaton rea2);
+
+/** Product */
+gfsmRegexAutomaton gfsm_regex_automaton_product(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmRegexAutomaton rea2);
+
+/** Composition */
+gfsmRegexAutomaton gfsm_regex_automaton_compose(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmRegexAutomaton rea2);
+
+/** Difference */
+gfsmRegexAutomaton gfsm_regex_automaton_difference(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmRegexAutomaton rea2);
+
+/** Weight */
+gfsmRegexAutomaton gfsm_regex_automaton_weight(gfsmRegexCompiler *rec,
+ gfsmRegexAutomaton rea1,
+ gfsmWeight w);
+
+
+
+
+#endif /* _GFSM_REGEX_COMPILER_H */
diff --git a/gfsm/gfsm/src/libgfsm/tests/gfsmlabdump.c b/gfsm/gfsm/src/libgfsm/tests/gfsmlabdump.c
new file mode 100644
index 0000000..05916ac
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/gfsmlabdump.c
@@ -0,0 +1,73 @@
+#include <gfsm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main (int argc, char **argv) {
+ gfsmStringAlphabet *sa = (gfsmStringAlphabet*)gfsm_string_alphabet_new();
+ gfsmAlphabet *a = (gfsmAlphabet*)sa;
+ gfsmError *err = NULL;
+ char *filename= NULL;
+ gfsmLabelVal lv1,lv2;
+ char *key;
+
+ /*-- test: insert --*/
+ printf("testing insert: ");
+ lv1 = gfsm_alphabet_insert(a,"foo",gfsmNoLabel);
+ printf("%s\n", lv1 != gfsmNoLabel ? "ok" : "FAILED");
+
+ /*-- test: find --*/
+ printf("testing find_label: ");
+ lv2 = gfsm_alphabet_find_label(a,"foo");
+ printf("%s\n", lv1==lv2 ? "ok" : "FAILED");
+
+ /*-- test: find key --*/
+ printf("testing find_key: ");
+ key = gfsm_alphabet_find_key(a,lv1);
+ printf("%s\n", key != NULL && strcmp(key,"foo")==0 ? "ok" : "FAILED");
+
+ /*-- clear test --*/
+ printf("testing clear: ");
+ gfsm_alphabet_clear(a);
+ printf("%s\n", gfsm_alphabet_size(a)==0 ? "ok" : "FAILED");
+
+ /*-- load labels file --*/
+ if (argc > 0) { filename=argv[1]; }
+ else { filename="-"; }
+ printf("\nLoading alphabet from file %s: ", argc==0 ? "(stdin)" : filename);
+ if (!a || !gfsm_alphabet_load_filename(a, filename, &err)) {
+ g_printerr("couldn't load labels from stdin: %s\n", err->message);
+ exit(1);
+ }
+ printf("loaded.\n\n");
+
+ /*-- get some basic information --*/
+ printf("Basic Information:\n");
+ printf(" + gfsmAlphabet:\n");
+ printf(" type : %u (%s)\n", a->type,
+ (a->type==gfsmATString ? "string keys" : "weird type: tell moocow"));
+ printf(" lab_min: %u\n", a->lab_min);
+ printf(" lab_max: %u\n", a->lab_max);
+ printf(" + gfsmPointerAlphabet:\n");
+ printf(" labels2keys: %p [size=%u]\n",
+ sa->labels2keys, sa->labels2keys->len);
+ printf(" keys2labels: %p [size=%u]\n",
+ sa->keys2labels, g_hash_table_size(sa->keys2labels));
+ printf(" keydupfunc : %p (%s)\n",
+ sa->key_dup_func, (sa->key_dup_func == NULL
+ ? "no key copying: tell moocow"
+ : ((void*)sa->key_dup_func == (void*)gfsm_alphabet_strdup
+ ? "keys are copied: ok"
+ : "strangeness: tell moocow")));
+
+
+ /*-- dump it --*/
+ printf("\n--BEGIN dump--\n");
+ if (!gfsm_alphabet_save_file(a,stdout,&err)) {
+ g_printerr("couldn't save labels to stdout: %s\n", err->message);
+ exit(1);
+ }
+ printf("--END dump--\n\n");
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/gscantest.c b/gfsm/gfsm/src/libgfsm/tests/gscantest.c
new file mode 100644
index 0000000..199c414
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/gscantest.c
@@ -0,0 +1,51 @@
+#include <gfsm.h>
+#include <glib.h>
+#include <stdlib.h>
+
+#undef VERBOSE
+
+int main (int argc, char **argv) {
+ GScanner *scanner = g_scanner_new(&gfsm_automaton_scanner_config);
+ GTokenType typ;
+
+ scanner->input_name = *argv;
+ g_scanner_input_file(scanner, fileno(stdin));
+ while ((typ = g_scanner_get_next_token(scanner)) != G_TOKEN_EOF) {
+#ifdef VERBOSE
+ switch (typ) {
+ case G_TOKEN_INT:
+ printf("INT %ld\n", scanner->value.v_int);
+ break;
+ case G_TOKEN_FLOAT:
+ printf("FLOAT %g\n", scanner->value.v_float);
+ break;
+ case G_TOKEN_CHAR:
+ if (scanner->value.v_char == '\n') printf ("CHAR '\\n'\n");
+ else printf("CHAR '%c'\n", scanner->value.v_char);
+ break;
+ default:
+ printf("? (typ=%d)\n", typ);
+ break;
+ }
+#else // !VERBOSE
+ switch (typ) {
+ case G_TOKEN_INT:
+ printf("%ld\t", scanner->value.v_int);
+ break;
+ case G_TOKEN_FLOAT:
+ printf("%g\t", scanner->value.v_float);
+ break;
+ case G_TOKEN_CHAR:
+ if (scanner->value.v_char == '\n') fputc('\n',stdout);
+ else exit(1);
+ break;
+ default:
+ exit(1);
+ break;
+ }
+#endif // VERBOSE
+ }
+ g_scanner_destroy(scanner);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/intfloat.c b/gfsm/gfsm/src/libgfsm/tests/intfloat.c
new file mode 100644
index 0000000..098b860
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/intfloat.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+#define ptr2int(p) ((int)(p))
+#define int2ptr(i) ((void*)(i))
+#define ptr2float(p) (*((float*)(&(p))))
+#define int2float(i) (*((float*)(&(i))))
+
+#define float2int(f) (*((int*)(&(f))))
+#define float2ptr(f) (*((void**)(&(f))))
+
+int main(void) {
+ float f = 42.24;
+ int fi;
+ void *fp;
+ float fif, fpf;
+
+ printf("f=%f\n", f);
+ fi = float2int(f);
+ printf("->fi=%d\n", fi);
+
+ fif = int2float(fi);
+ printf("-->fif=%f\n", fif);
+
+ fp = float2ptr(f);
+ printf("->fp=%p\n", fp);
+
+ fpf=ptr2float(fp);
+ printf("-->fpf=%f\n", fpf);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/iotest.c b/gfsm/gfsm/src/libgfsm/tests/iotest.c
new file mode 100644
index 0000000..c218627
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/iotest.c
@@ -0,0 +1,180 @@
+#include <glib.h>
+#include <gfsmIO.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*---------------------------------------------------
+ * generic test: output
+ */
+void test_output_generic(gfsmIOHandle *io, const char *label)
+{
+ gboolean rc;
+ fprintf(stderr, "\n-------- I/O: %s: output\n", label);
+
+ fprintf(stderr, "+ write(\"foo\\n\",4):\n");
+ rc = gfsmio_write(io, "foo\n", 4);
+ gfsmio_flush(io);
+ fprintf(stderr, " --> %d\n", rc);
+
+ fprintf(stderr, "+ puts(\"bar\\n\"):\n");
+ rc = gfsmio_puts(io, "bar\n");
+ gfsmio_flush(io);
+ fprintf(stderr, " --> %d\n", rc);
+
+ fprintf(stderr, "+ putc('x'); putc('\\n'):\n");
+ rc = gfsmio_putc(io, 'x') && gfsmio_putc(io, '\n');
+ gfsmio_flush(io);
+ fprintf(stderr, " --> %d\n", rc);
+
+ fprintf(stderr, "+ printf(\"%%s%%s\\n\",\"foo\",\"bar\"):\n");
+ rc = gfsmio_printf(io, "%s%s\n", "foo", "bar");
+ gfsmio_flush(io);
+ fprintf(stderr, " --> %d\n", rc);
+}
+
+/*---------------------------------------------------
+ * generic test: input
+ */
+void test_input_generic(gfsmIOHandle *io, const char *label)
+{
+ char buf[2];
+ char *linebuf=NULL;
+ size_t n=0;
+ ssize_t nread=0;
+ gboolean rc;
+
+ fprintf(stderr, "\n-------- I/O: %s: input\n", label);
+
+ fprintf(stderr, "+ read(2)\n");
+ rc = gfsmio_read(io, buf, 2);
+ fprintf(stderr, " --> %d ; buf=\"%c%c\"\n", rc, buf[0], buf[1]);
+
+ fprintf(stderr, "+ getline()\n");
+ while ( (nread=gfsmio_getline(io, &linebuf, &n)) > 0) {
+ fprintf(stderr, " --> %d ; linebuf=\"%s\"\n", nread, linebuf);
+ fprintf(stderr, "+ getline()\n");
+ }
+ fprintf(stderr, " --> %d ; linebuf=\"%s\"\n", nread, linebuf);
+
+ if (linebuf) free(linebuf);
+}
+
+
+/*---------------------------------------------------
+ * test: FILE*
+ */
+void test_io_cfile(void) {
+ gfsmIOHandle *ioh=NULL;
+
+ //-- I/O to file: output
+ ioh = gfsmio_new_file(stdout);
+ test_output_generic(ioh, "FILE* (stdout)");
+ gfsmio_handle_free(ioh);
+
+ //-- I/O from file: input
+ ioh = gfsmio_new_file(stdin);
+ test_input_generic(ioh, "FILE* (stdin)");
+ gfsmio_handle_free(ioh);
+}
+
+/*---------------------------------------------------
+ * test: GString*
+ */
+void test_io_gstring(void) {
+ GString *gs = g_string_new("");
+ gfsmPosGString pgs = { gs, 0 };
+ gfsmIOHandle *ioh = NULL;
+
+ //-- I/O to GString*: output
+ ioh = gfsmio_new_gstring(&pgs);
+ test_output_generic(ioh, "GString*");
+ fprintf(stderr, "+ OUTPUT=\"%s\"\n", gs->str);
+
+ //-- I/O from GString*: input
+ pgs.pos = 0;
+ /*
+ g_string_assign(gs, "ab\ncde");
+ test_input_generic(ioh, "GString* \"ab\\nc\")");
+ */
+ /*
+ g_string_assign(gs, "a b c\nd e f");
+ test_input_generic(ioh, "GString* \"a b c\\nd e f\")");
+ */
+ /*
+ g_string_assign(gs, "abcde\nfghij\nklmnopqrstuvwxyz");
+ test_input_generic(ioh, "GString* \"...\")");
+ */
+ g_string_assign(gs, "abc\n\ndef\n");
+ test_input_generic(ioh, "GString* \"...\")");
+
+
+ gfsmio_handle_free(ioh);
+ g_string_free(gs,TRUE);
+}
+
+/*---------------------------------------------------
+ * test: gzFile
+ */
+void test_io_zfile(void) {
+ gfsmIOHandle *ioh=NULL;
+ gfsmError *err=NULL;
+
+ //-- I/O to gzGile: output
+ ioh = gfsmio_new_filename("iotest-out.gz", "wb", 0, &err);
+ test_output_generic(ioh, "gzFile (iotest-out.gz)");
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+
+ //-- I/O from gzFile: input
+ ioh = gfsmio_new_filename("iotest-in.gz", "rb", -1, &err);
+ test_input_generic(ioh, "gzFile (iotest-in.gz)");
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+}
+
+/*---------------------------------------------------
+ * test: gzFile from FILE*
+ */
+void test_io_zcfile(void) {
+ gfsmIOHandle *ioh=NULL;
+ int zlevel = -1;
+
+ //-- I/O to gzGile: output
+ ioh = gfsmio_new_zfile(stdout, "wb", zlevel);
+ test_output_generic(ioh, "gzFile(fileno(stdout))");
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+
+ //-- I/O from gzFile: input
+ ioh = gfsmio_new_zfile(stdin, "rb", zlevel);
+ test_input_generic(ioh, "gzFile(fileno(stdin))");
+ gfsmio_close(ioh);
+ gfsmio_handle_free(ioh);
+}
+
+
+/*---------------------------------------------------
+ * MAIN
+ */
+int main (void) {
+ /*
+ fprintf(stderr, "\n=================================\n");
+ test_io_cfile();
+ */
+
+ /*
+ fprintf(stderr, "\n=================================\n");
+ test_io_gstring();
+ */
+
+ /*
+ fprintf(stderr, "\n=================================\n");
+ test_io_zfile();
+ */
+
+ fprintf(stderr, "\n=================================\n");
+ test_io_zcfile();
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/lab2ary.c b/gfsm/gfsm/src/libgfsm/tests/lab2ary.c
new file mode 100644
index 0000000..e6dbee9
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/lab2ary.c
@@ -0,0 +1,62 @@
+#include <gfsm.h>
+#include <stdlib.h>
+
+
+gfsmAutomaton *fsm;
+gfsmAlphabet *ialph;
+const char *tfstname = "lab2ary.tfst";
+gfsmError *err = NULL;
+
+
+int main (int argc, char **argv) {
+ guint i;
+ ialph = gfsm_identity_alphabet_new();
+ //GArray *ary;
+ GPtrArray *ary;
+
+ fsm = gfsm_automaton_new();
+ if (!gfsm_automaton_compile_filename(fsm,tfstname,&err)) {
+ g_printerr("%s: compile failed for '%s': %s\n", *argv, tfstname, err->message);
+ exit(255);
+ }
+ printf("%s: compiled test automaton from '%s'\n", *argv, tfstname);
+
+ ialph = gfsm_automaton_get_alphabet(fsm, gfsmLSLower, ialph);
+
+ printf("--\n");
+ printf("alphabet size=%u ; min=%u ; max=%u\n",
+ gfsm_alphabet_size(ialph), ialph->lab_min, ialph->lab_max);
+
+ printf("--\n");
+ printf("alphabet array={");
+ /*-- ok
+ ary = g_array_new(FALSE,FALSE,sizeof(gfsmLabelVal));
+ gfsm_alphabet_labels_to_array(ialph,ary);
+ */
+ /*-- ok
+ ary = g_array_sized_new(FALSE,FALSE,sizeof(gfsmLabelVal),gfsm_alphabet_size(ialph));
+ gfsm_alphabet_labels_to_array(ialph,ary);
+ */
+ /*-- ok */
+ //ary = gfsm_alphabet_labels_to_array(ialph,NULL);
+
+ /*-- ptr_array */
+ ary = g_ptr_array_sized_new(gfsm_alphabet_size(ialph));
+ gfsm_alphabet_labels_to_array(ialph,ary);
+
+ for (i=0; i < ary->len; i++) {
+ //printf(" %u", g_array_index(ary,gfsmLabelVal,i));
+ printf(" %u", (gfsmLabelVal)g_ptr_array_index(ary,i));
+ }
+ printf(" }\n");
+
+ //-- cleanup
+ //g_array_free(ary,TRUE);
+ g_ptr_array_free(ary,TRUE);
+
+ gfsm_automaton_free(fsm);
+ gfsm_alphabet_free(ialph);
+
+ return 0;
+}
+
diff --git a/gfsm/gfsm/src/libgfsm/tests/labchurn.c b/gfsm/gfsm/src/libgfsm/tests/labchurn.c
new file mode 100644
index 0000000..b8f0a99
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/labchurn.c
@@ -0,0 +1,23 @@
+#include <gfsm.h>
+
+gfsmAlphabet *alph;
+
+int main (int argc, char **argv)
+{
+ char *infilename = (argc > 1 ? argv[1] : "-");
+
+ g_mem_set_vtable(glib_mem_profiler_table);
+
+ alph = gfsm_string_alphabet_new();
+ //g_mem_profile();
+
+ gfsm_alphabet_load_filename(alph,infilename,NULL);
+ //gfsm_alphabet_save_file(alph,stdout,NULL);
+
+
+ gfsm_alphabet_free(alph);
+
+ g_blow_chunks();
+ g_mem_profile();
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/labcount.perl b/gfsm/gfsm/src/libgfsm/tests/labcount.perl
new file mode 100755
index 0000000..4086797
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/labcount.perl
@@ -0,0 +1,28 @@
+#!/usr/bin/perl -w
+
+use Gfsm;
+
+if (!@ARGV) {
+ print STDERR "Usage: $0 LABFILE [DATA_FILE(s)...]\n";
+ exit 1;
+}
+
+$labfile = shift;
+$labs = Gfsm::Alphabet->new();
+$labs->load($labfile) or die("$0: load failed for labels file '$labfile': $!");
+$sym2id = $labs->asHash;
+
+##-- read data
+%labf = qw();
+$ftotal = 0;
+while (defined($line=<>)) {
+ chomp($line);
+ @labs = grep {defined($_)} @$sym2id{split(//,$line)};
+ $ftotal += scalar(@labs);
+ foreach (@labs) { ++$labf{$_}; }
+}
+
+##-- write data vector
+#print map { pack('d', (defined($_) ? $_ : 0)/$ftotal) } @labf;
+
+print map {pack('Sd',$_,$labf{$_}/$ftotal)} sort(keys(%labf));
diff --git a/gfsm/gfsm/src/libgfsm/tests/labprobs.h b/gfsm/gfsm/src/libgfsm/tests/labprobs.h
new file mode 100644
index 0000000..d8589d0
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/labprobs.h
@@ -0,0 +1,71 @@
+#include <gfsm.h>
+
+guint32 grand_seed = 42;
+const char *probfile = "tagh-probs.bin";
+
+extern gulong count_test;
+GArray *seekus = NULL; /*-- lab = g_array_index(seekus,i); 1<=i<=count_test --*/
+
+typedef struct {
+ gfsmLabelId lab;
+ double prob;
+} seekProb;
+GArray *labp=NULL; /*-- g_array_index(probs,seekProb,i) = (lab,p(lab)) --*/
+
+GRand *grand=NULL;
+
+/*======================================================================
+ * load_label_probs()
+ */
+void load_label_probs(void) {
+ seekProb sp;
+ double total=0, tmp;
+ FILE *f = fopen(probfile,"r");
+ if (!f) {
+ fprintf(stderr, "error: open failed for probability file '%s'\n", probfile);
+ exit(1);
+ }
+ labp = g_array_sized_new(FALSE,TRUE,sizeof(seekProb),256);
+ labp->len = 0;
+ while ( !feof(f) ) {
+ if (fread(&(sp.lab), sizeof(gfsmLabelId), 1, f) != 1
+ || fread(&(sp.prob), sizeof(double), 1, f) != 1)
+ {
+ break;
+ }
+ tmp = sp.prob;
+ sp.prob += total;
+ total += tmp;
+ g_array_append_val(labp,sp);
+
+ }
+ fclose(f);
+ fprintf(stderr, "[info]: read probability distribution over %d labels from '%s'\n",
+ labp->len, probfile);
+}
+
+/*======================================================================
+ * random_label()
+ */
+gfsmLabelId random_label(void) {
+ double w;
+ int i;
+ if (!grand) { grand = g_rand_new_with_seed(grand_seed); }
+ w = g_rand_double(grand);
+ for (i=0; i < labp->len && w > g_array_index(labp,seekProb,i).prob; i++) { ; }
+ if (i==labp->len) { --i; }
+ return g_array_index(labp,seekProb,i).lab;
+}
+
+/*======================================================================
+ * populate_seek_labels()
+ */
+void populate_seek_labels(void) {
+ int i;
+ gfsmLabelId lab;
+ seekus = g_array_sized_new(FALSE,TRUE,sizeof(gfsmLabelId),count_test);
+ for (i=0; i < count_test; i++) {
+ lab = random_label();
+ g_array_append_val(seekus,lab);
+ }
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/lkptest.tfst b/gfsm/gfsm/src/libgfsm/tests/lkptest.tfst
new file mode 100644
index 0000000..11f371e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/lkptest.tfst
@@ -0,0 +1,8 @@
+0 0 1 2 1
+0 0 2 3 1
+0 0 3 1 1
+0 1 2 2 1
+0 0
+1 2 2 2 1
+2 3 3 3 1
+3 0
diff --git a/gfsm/gfsm/src/libgfsm/tests/macrotest.i b/gfsm/gfsm/src/libgfsm/tests/macrotest.i
new file mode 100644
index 0000000..e540e43
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/macrotest.i
@@ -0,0 +1,11 @@
+#define _gfsm_bitvector_bits2bytes(nbits) ((nbits)>0 ? ((((nbits)-1)/8)+1) : 1)
+
+#define gfsm_bitvector_set(bv,i,v) \
+ ( (i >= gfsm_bitvector_size(bv) ? gfsm_bitvector_resize(bv,i) : 0), \
+ (v ? ( (bv)->data[ _gfsm_bitvector_bits2bytes(i)-1 ] |= (1<<((i)%8)) ) \
+ : ( (bv)->data[ _gfsm_bitvector_bits2bytes(i)-1 ] &= ~(1<<((i)%8)) ) ) )
+
+bits2bytes: _gfsm_bitvector_bits2bytes(MyBit)
+
+set: gfsm_bitvector_set(MyVector,MyBit,MyValue)
+
diff --git a/gfsm/gfsm/src/libgfsm/tests/memtest-alphabet.c b/gfsm/gfsm/src/libgfsm/tests/memtest-alphabet.c
new file mode 100644
index 0000000..edb1492
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/memtest-alphabet.c
@@ -0,0 +1,26 @@
+#include <glib.h>
+#include <gfsmAlphabet.h>
+
+void dofree (gpointer p) { g_free(p); }
+
+int main (void) {
+ gfsmAlphabet *a;
+ g_mem_set_vtable(glib_mem_profiler_table);
+
+ //a = (gfsmAlphabet*)g_new0(gfsmPointerAlphabet,1);
+ a = gfsm_string_alphabet_new();
+
+ gfsm_alphabet_insert(a,"foo",42);
+
+ gfsm_alphabet_free(a);
+
+ printf("<CHUNKS:1>--------\n");
+ //g_mem_chunk_info();
+
+
+
+ printf("<PROF:1>--------\n");
+ g_mem_profile();
+ g_blow_chunks();
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/memtest-automaton.c b/gfsm/gfsm/src/libgfsm/tests/memtest-automaton.c
new file mode 100644
index 0000000..ace1fbd
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/memtest-automaton.c
@@ -0,0 +1,20 @@
+#include <glib.h>
+#include <gfsm.h>
+
+void dofree (gpointer p) { g_free(p); }
+
+int main (void) {
+ gfsmAutomaton *fsm;
+ g_mem_set_vtable(glib_mem_profiler_table);
+
+ fsm = gfsm_automaton_new();
+ gfsm_automaton_free(fsm);
+
+ //printf("<CHUNKS:1>--------\n");
+ //g_mem_chunk_info();
+
+ printf("<PROF:1>--------\n");
+ g_blow_chunks();
+ g_mem_profile();
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/memtest-general.c b/gfsm/gfsm/src/libgfsm/tests/memtest-general.c
new file mode 100644
index 0000000..50fe42f
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/memtest-general.c
@@ -0,0 +1,168 @@
+#include <gfsm.h>
+#include <glib.h>
+
+#define VTABLE_PROFILE 1
+//#define VTABLE_LOCAL 1
+
+
+//#define USE_ALLOCATORS 1
+//#define DELAY_ALLOCATOR_FREE 1
+
+
+//#define NITEMS 0
+//#define NITEMS 1
+//#define NITEMS 10
+#define NITEMS 128
+//#define NITEMS 256
+//#define NITEMS 1024
+//#define NITEMS 65536
+//#define NITEMS 131072
+//#define NITEMS 262144
+//#define NITEMS 524288
+//#define NITEMS 1048576
+
+
+//#define NITERS
+//#define NITERS 1
+//#define NITERS 10
+#define NITERS 128
+//#define NITERS 1024
+//#define NITERS 65536
+//#define NITERS 131072
+//#define NITERS 262144
+//#define NITERS 524288
+//#define NITERS 1048576
+
+//#define PRINT_CHUNK_INFO 1
+//#define DO_PROFILE 1
+
+#define DO_GMALLOC 1
+#define GMALLOC_SIZE 45
+
+#define DO_GNEW 1
+#define GNEW_SIZE 70
+
+#define DO_SLIST 1
+
+#define DO_PTRARRAY 1
+#define PTRARRAY_SIZE 128
+
+
+/*--------------------------------------------------------------------
+ * mem table
+ */
+gpointer my_malloc(gsize n_bytes)
+{ return (gpointer)malloc(n_bytes); }
+
+gpointer my_realloc(gpointer mem, gsize n_bytes)
+{ return (gpointer)realloc(mem, n_bytes); }
+
+void my_free(gpointer mem)
+{ free(mem); }
+
+GMemVTable my_vtable =
+ {
+ my_malloc,
+ my_realloc,
+ my_free,
+ NULL,
+ NULL,
+ NULL
+ };
+
+/*--------------------------------------------------------------------
+ * operation macro
+ */
+#define MEMOP(code) \
+ printf("%s\n", #code); \
+ code;
+
+#define ITEMOP(code) \
+ for (i=0; i<NITEMS; i++) { code; }
+
+/*--------------------------------------------------------------------
+ * variables
+ */
+gpointer mallocp[NITERS];
+gpointer newp[NITERS];
+GSList *slist[NITERS];
+GPtrArray *ptrarray[NITERS];
+
+/*--------------------------------------------------------------------
+ * MAIN
+ */
+int main(int argc, char **argv) {
+ int i,j;
+
+
+ //-- memory debugging
+#if defined(VTABLE_PROFILE)
+ g_mem_set_vtable(glib_mem_profiler_table);
+#elif defined(VTABLE_LOCAL)
+ g_mem_set_vtable(&my_vtable);
+#endif
+
+ //-- setup gfsm allocators
+#if defined(USE_ALLOCATORS)
+ MEMOP(gfsm_allocators_enable());
+#endif
+
+
+ //--------------- iteration
+ for (j=0; j < NITERS; j++) {
+ //-- alloc
+# ifdef DO_GMALLOC
+ ITEMOP(mallocp[i]=g_malloc(GMALLOC_SIZE));
+# endif
+# ifdef DO_GNEW
+ ITEMOP(newp[i]=g_new(char,GNEW_SIZE));
+# endif
+# ifdef DO_SLIST
+ ITEMOP(slist[i]=g_slist_prepend(NULL,NULL));
+# endif
+# ifdef DO_PTRARRAY
+ ITEMOP(ptrarray[i]=g_ptr_array_sized_new(PTRARRAY_SIZE));
+# endif
+
+ //-- free
+# ifdef DO_GMALLOC
+ ITEMOP(g_free(mallocp[i]));
+# endif
+# ifdef DO_GNEW
+ ITEMOP(g_free(newp[i]));
+# endif
+# ifdef DO_SLIST
+ ITEMOP(g_slist_free(slist[i]));
+# endif
+# ifdef DO_PTRARRAY
+ ITEMOP(g_ptr_array_free(ptrarray[i],TRUE));
+# endif
+ }
+
+
+ //-- pop gfsm allocators
+#if defined(USE_ALLOCATORS) && !defined(DELAY_ALLOCATOR_FREE)
+ MEMOP(gfsm_allocators_free());
+#endif
+
+ //-- memory debugging
+#if defined(PRINT_CHUNK_INFO) && defined(VTABLE_PROFILE)
+ printf("\n<CHUNKS:1>--------\n");
+ g_blow_chunks();
+ g_mem_chunk_info();
+#endif
+ //
+#ifdef VTABLE_PROFILE
+ printf("\n<PROF:1>--------\n");
+ g_blow_chunks();
+ g_mem_profile();
+#endif
+
+ g_blow_chunks();
+
+#if defined(USE_ALLOCATORS) && defined(DELAY_ALLOCATOR_FREE)
+ MEMOP(gfsm_allocators_free());
+#endif
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/memtest.c b/gfsm/gfsm/src/libgfsm/tests/memtest.c
new file mode 100644
index 0000000..edb1492
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/memtest.c
@@ -0,0 +1,26 @@
+#include <glib.h>
+#include <gfsmAlphabet.h>
+
+void dofree (gpointer p) { g_free(p); }
+
+int main (void) {
+ gfsmAlphabet *a;
+ g_mem_set_vtable(glib_mem_profiler_table);
+
+ //a = (gfsmAlphabet*)g_new0(gfsmPointerAlphabet,1);
+ a = gfsm_string_alphabet_new();
+
+ gfsm_alphabet_insert(a,"foo",42);
+
+ gfsm_alphabet_free(a);
+
+ printf("<CHUNKS:1>--------\n");
+ //g_mem_chunk_info();
+
+
+
+ printf("<PROF:1>--------\n");
+ g_mem_profile();
+ g_blow_chunks();
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/module/.cvsignore b/gfsm/gfsm/src/libgfsm/tests/module/.cvsignore
new file mode 100644
index 0000000..58d248b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/module/.cvsignore
@@ -0,0 +1,18 @@
+*~
+.*~
+
+*.gfst
+*.output
+*.lex.c
+*.lex.h
+*.tab.c
+*.tab.h
+*.gz
+*.so
+*.o
+
+tagh*
+*.dat
+negra*
+
+mod1test
diff --git a/gfsm/gfsm/src/libgfsm/tests/module/Makefile b/gfsm/gfsm/src/libgfsm/tests/module/Makefile
new file mode 100644
index 0000000..c310837
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/module/Makefile
@@ -0,0 +1,39 @@
+TARGETS = mod1test libmod1a.so libmod1b.so
+KNOWN_TARGETS = mod1test libmod1a.so libmod1b.so
+
+CC = gcc
+#CC = ccmalloc --no-wrapper gcc
+LD = $(CC)
+
+CPPFLAGS = $(shell pkg-config --cflags-only-I gmodule-2.0)
+#CFLAGS ?= -O2 -pipe
+#CFLAGS ?= -Wall -g
+#CFLAGS += -Wall -g
+CFLAGS ?= -g
+CFLAGS += -Wall -fPIC -DPIC
+
+LDFLAGS = $(shell pkg-config --libs-only-L gmodule-2.0)
+LIBS = $(shell pkg-config --libs-only-l gmodule-2.0) -lm
+
+LDFLAGS_MODULE = -shared $(LDFLAGS)
+
+all: $(TARGETS)
+
+##-- keep intermediate files
+.SECONDARY:
+
+##-- PATTERN: .c -> .o
+%.o: %.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
+
+##-- clean
+clean:
+ rm -f *.o *.lo *.tab.[ch] *.lex.[ch] $(KNOWN_TARGETS)
+
+##-- modules
+lib%.so: %.o
+ $(LD) $(LDFLAGS_MODULE) -o $@ $^ $(LIBS)
+
+##-- Executables
+%test: %test.o
+ $(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
diff --git a/gfsm/gfsm/src/libgfsm/tests/module/mod1a.c b/gfsm/gfsm/src/libgfsm/tests/module/mod1a.c
new file mode 100644
index 0000000..69674c5
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/module/mod1a.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+void foo(void) {
+ printf("mod1a:foo() called.\n");
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/module/mod1b.c b/gfsm/gfsm/src/libgfsm/tests/module/mod1b.c
new file mode 100644
index 0000000..4705f7c
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/module/mod1b.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+void foo(void) {
+ printf("mod1b:foo() called.\n");
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/module/mod1test.c b/gfsm/gfsm/src/libgfsm/tests/module/mod1test.c
new file mode 100644
index 0000000..6389972
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/module/mod1test.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <glib.h>
+#include <gmodule.h>
+
+typedef void (*fooFunc) (void);
+
+int main(int argc, char **argv) {
+ int i;
+ const gchar *prog = argv[0];
+ //const gchar *moddir = g_getenv("PWD"); //-- get module directory (hack)
+ const gchar *moddir = ".";
+ gchar *modpath;
+ GModule *mod;
+ fooFunc foofunc;
+
+ g_assert(g_module_supported());
+
+ for (i=1; i < argc; i++) {
+ //-- build full module pathname
+ modpath = g_module_build_path(moddir,argv[i]);
+ printf("%s: argv[%d]='%s': moddir='%s', modpath='%s'\n", prog, i, moddir, argv[i], modpath);
+ //--
+ //modpath = argv[i];
+ //printf("%s: argv[%d]='%s': modfile='%s'\n", prog, i, argv[i], modpath);
+
+ //-- open module
+ if ( !(mod = g_module_open(modpath,G_MODULE_BIND_LOCAL)) ) {
+ g_printerr("%s: could not load module '%s': %s - skipping\n", prog, modpath, g_module_error());
+ if (modpath != argv[i]) g_free(modpath);
+ continue;
+ }
+ printf("-> open(): %p\n", mod);
+
+ //-- get symbol 'foo' from module
+ if (!g_module_symbol(mod,"foo",(gpointer *)&foofunc)) {
+ g_printerr("%s: could not load symbol 'foo' from module '%s': %s\n", prog, modpath, g_module_error());
+ g_module_close(mod);
+ if (modpath != argv[i]) g_free(modpath);
+ continue;
+ }
+ printf("-> symbol('foo'): %p\n", foofunc);
+
+ //-- call 'foo' as a foofunc
+ printf("-> calling foo(): ");
+ foofunc();
+
+ //-- cleanup
+ if (modpath != argv[i]) g_free(modpath);
+ g_module_close(mod);
+ }
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/nofinal.tfst b/gfsm/gfsm/src/libgfsm/tests/nofinal.tfst
new file mode 100644
index 0000000..ab866fa
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/nofinal.tfst
@@ -0,0 +1 @@
+0 0 1 1
diff --git a/gfsm/gfsm/src/libgfsm/tests/offsettest.c b/gfsm/gfsm/src/libgfsm/tests/offsettest.c
new file mode 100644
index 0000000..bec8e8f
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/offsettest.c
@@ -0,0 +1,101 @@
+#include <gfsm.h>
+#include <glib.h>
+#include <stdio.h>
+
+static const gulong count_test
+//= 1048576UL //== 2^20
+//= 16777216UL //== 2^24
+//= 33554432UL //==2^25
+= 268435456UL //==2^28
+//= 4294967295UL //== 2^32-1
+;
+
+//======================================================================
+// Basic bench subs
+
+inline gfsmLabelId get_lower(gfsmArc *a) { return a->lower; }
+inline gfsmLabelId get_upper(gfsmArc *a) { return a->upper; }
+inline gfsmLabelId get_label_offset(gfsmArc *a, gint offset) {
+ return *((gfsmLabelId*)G_STRUCT_MEMBER_P(&a,offset));
+}
+
+//======================================================================
+// Bench: literal: lower
+
+double bench_literal_lower(gfsmArc *a) {
+ gfsmLabelId l;
+ GTimer *timer = g_timer_new();
+ gulong i;
+ double elapsed;
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ l = get_lower(a);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+ g_timer_destroy(timer);
+ return elapsed;
+}
+
+//======================================================================
+// Bench: offset
+
+double bench_offset(gfsmArc *a, gint lab_offset) {
+ gfsmLabelId l;
+ GTimer *timer = g_timer_new();
+ gulong i;
+ double elapsed;
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ l = get_label_offset(a,lab_offset);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+ g_timer_destroy(timer);
+ return elapsed;
+}
+
+//======================================================================
+// Bench: offset: lower
+
+#define bench_offset_lower(a) bench_offset((a),G_STRUCT_OFFSET(gfsmArc, lower))
+
+
+//======================================================================
+// MAIN
+int main(int argc, char **argv) {
+ gfsmArc a = {0,1,2,3,4.5};
+ double elapsed_literal, elapsed_offset, count_dbl=count_test;
+
+ printf("G_STRUCT_OFFSET(gfsmArc, lower)=%d: *()=%d\n",
+ G_STRUCT_OFFSET(gfsmArc, lower),
+ *((gfsmLabelId*)G_STRUCT_MEMBER_P(&a,G_STRUCT_OFFSET(gfsmArc, lower)))
+ );
+
+ printf("G_STRUCT_OFFSET(gfsmArc, upper)=%d: *()=%d\n",
+ G_STRUCT_OFFSET(gfsmArc, upper),
+ *((gfsmLabelId*)G_STRUCT_MEMBER_P(&a,G_STRUCT_OFFSET(gfsmArc, upper)))
+ );
+
+ printf("G_STRUCT_OFFSET(gfsmArc, weight)=%d: *()=%g\n",
+ G_STRUCT_OFFSET(gfsmArc, weight),
+ *((gfsmWeight*)G_STRUCT_MEMBER_P(&a,G_STRUCT_OFFSET(gfsmArc, weight)))
+ );
+
+ //-- bench
+ elapsed_literal = bench_literal_lower(&a);
+ elapsed_literal = bench_literal_lower(&a);
+ //
+ elapsed_offset = bench_offset_lower(&a);
+ elapsed_offset = bench_offset_lower(&a);
+ //
+ //
+ fprintf(stderr, "%16s: %.2f sec, %ld iters, %.2e iter/sec\n",
+ "literal", elapsed_literal, count_test, count_dbl/elapsed_literal);
+ fprintf(stderr, "%16s: %.2f sec, %ld iters, %.2e iter/sec\n",
+ "offset", elapsed_offset, count_test, count_dbl/elapsed_offset);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/ortest.c b/gfsm/gfsm/src/libgfsm/tests/ortest.c
new file mode 100644
index 0000000..8327e0b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/ortest.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+int main(void) {
+ int x=0, y=-1;
+ int z = x||y;
+ printf("x||y=%d\n", z);
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/pathtest.c b/gfsm/gfsm/src/libgfsm/tests/pathtest.c
new file mode 100644
index 0000000..86a3ad3
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/pathtest.c
@@ -0,0 +1,289 @@
+#include <gfsm.h>
+
+
+//#define USE_VTABLE 1
+//#define USE_ALLOCATORS 1
+//#define DELAY_ALLOCATOR_FREE 1
+
+#define NEW_FST 1
+
+//#define MAKE_SLIST 1
+//#define MAKE_LIST 1
+//#define MAKE_FST 1
+//#define COMPILE_FST 1
+#define LOAD_FST 1
+//#define LOAD_EMPTY
+//#define LOAD_NOFINAL
+
+#define LOAD_NITERS 1
+//#define LOAD_NITERS 10
+//#define LOAD_NITERS 32768
+//#define LOAD_NITERS 65535
+//#define LOAD_NITERS 131072
+//#define LOAD_NITERS 262144
+//#define LOAD_NITERS 524288
+//#define LOAD_NITERS 1048576
+
+
+#define NEW_ABET 1
+#define LOAD_ABET 1
+
+//#define DO_INPUT 1
+//#define DO_LOOKUP 1
+//#define DO_PATHS 1
+//#define DO_STRINGS 1
+//#define DO_PTRARRAY 1
+
+#define NITERS 0
+//#define NITERS 1
+//#define NITERS 10
+//#define NITERS 1024
+//#define NITERS 65536
+//#define NITERS 131072
+//#define NITERS 262144
+//#define NITERS 524288
+//#define NITERS 1048576
+
+//#define PRINT_CHUNK_INFO 1
+//#define DO_PROFILE 1
+
+const char *progname = "pathtest";
+const char *labfile = "test.lab";
+
+#if defined(LOAD_EMPTY)
+const char *fstfile = "empty.gfst";
+const char *tfstfile = "empty.tfst";
+#elif defined(LOAD_NOFINAL)
+const char *fstfile = "nofinal.gfst";
+const char *tfstfile = "nofinal.tfst";
+#else
+const char *fstfile = "lkptest.gfst";
+const char *tfstfile = "lkptest.tfst";
+#endif
+
+
+gfsmLabelVector *input = NULL;
+gfsmAlphabet *abet = NULL;
+gfsmAutomaton *fst = NULL;
+gfsmAutomaton *result = NULL;
+gfsmSet *paths = NULL;
+GSList *strings = NULL;
+GPtrArray *ptrarray = NULL;
+gfsmError *err = NULL;
+GSList *sltmp = NULL;
+gfsmState *st = NULL;
+gfsmArc *arc=NULL;
+gfsmArcList *al=NULL;
+char line[256];
+
+
+gpointer my_malloc(gsize n_bytes)
+{
+ return (gpointer)malloc(n_bytes);
+}
+
+gpointer my_realloc(gpointer mem, gsize n_bytes)
+{
+ return (gpointer)realloc(mem, n_bytes);
+}
+
+void my_free(gpointer mem)
+{
+ free(mem);
+}
+
+GMemVTable my_vtable =
+ {
+ my_malloc,
+ my_realloc,
+ my_free,
+ NULL,
+ NULL,
+ NULL
+ };
+
+#define MEMOP(code) \
+ fprintf(stderr,"%s\n", #code); \
+ code;
+
+int main(int argc, char **argv) {
+ int i;
+
+ //-- memory debugging
+#if defined(DO_PROFILE)
+ g_mem_set_vtable(glib_mem_profiler_table);
+#elif defined(USE_VTABLE)
+ g_mem_set_vtable(&my_vtable);
+#endif
+
+ //-- setup gfsm allocators
+#if defined(USE_ALLOCATORS)
+ MEMOP(gfsm_allocators_enable());
+#endif
+
+ //-- load or make fst
+#ifdef NEW_FST
+ MEMOP(fst = gfsm_automaton_new(););
+
+#if defined(MAKE_SLIST)
+ //-- this is the culprit!
+ MEMOP(al = g_slist_prepend(NULL,NULL));
+ MEMOP(g_slist_free(al));
+#elif defined(MAKE_LIST)
+ {
+ GList *l=NULL;
+ MEMOP(l=g_list_prepend(NULL,NULL));
+ MEMOP(g_list_free(l));
+ }
+#elif defined(MAKE_FST)
+ MEMOP(st = gfsm_automaton_get_state(fst,0)); //-- ok
+ MEMOP(gfsm_automaton_set_final_state(fst, 0, TRUE)); //-- ok
+
+ MEMOP(gfsm_automaton_add_arc(fst,0,0,1,1,0)); //-- NOT ok!
+
+ //-- alloc
+ //MEMOP(arc=gfsm_arc_new_full(0,1,1,0)); //--ok
+ //MEMOP(st->arcs = g_slist_prepend((gpointer)arc,st->arcs)); //-- ok w/ allocator
+
+ //-- free
+ //MEMOP(g_slist_free(st->arcs); st->arcs=NULL;); //-- ok w/ allocator
+ //MEMOP(gfsm_arc_free(arc)); //-- /ok
+
+#elif defined(COMPILE_FST)
+ fprintf(stderr,"gfsm_automaton_compile_filename(\"%s\");\n", tfstfile);
+ if (!gfsm_automaton_compile_filename(fst,tfstfile,&err)) {
+ fprintf(stderr,"%s: compile failed for '%s': %s\n", progname, tfstfile, (err ? err->message : "?"));
+ exit(3);
+ }
+ //g_mem_profile();
+#elif defined(LOAD_FST)
+ fprintf(stderr,"gfsm_automaton_load_bin_filename(\"%s\"); //---[x %d]---\n", fstfile, LOAD_NITERS);
+ for (i=0; i < LOAD_NITERS; i++) {
+ if (fst) gfsm_automaton_free(fst);
+ fst = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(fst,fstfile,&err)) {
+ fprintf(stderr,"%s: load failed for '%s': %s\n", progname, fstfile, (err ? err->message : "?"));
+ exit(3);
+ }
+ g_blow_chunks();
+ }
+ //g_mem_profile();
+#endif // make or load FST
+#endif // NEW_FST
+
+ //-- load labels
+#ifdef NEW_ABET
+ MEMOP(abet = gfsm_string_alphabet_new(););
+#ifdef LOAD_ABET
+ fprintf(stderr,"gfsm_alphabet_load_filename(\"%s\");\n", labfile);
+ if (!gfsm_alphabet_load_filename(abet,labfile,&err)) {
+ fprintf(stderr,"%s: load failed for labels file '%s': %s\n",
+ progname, labfile, (err ? err->message : "?"));
+ exit(2);
+ }
+ //g_mem_profile();
+#endif //-- LOAD_ABET
+#endif //-- NEW_ABET
+
+ //-- setup input vector
+#ifdef DO_INPUT
+ MEMOP(input = g_ptr_array_new());
+ MEMOP(g_ptr_array_add(input,(gpointer)2));
+ MEMOP(g_ptr_array_add(input,(gpointer)2));
+ MEMOP(g_ptr_array_add(input,(gpointer)3));
+#endif //-- DEFINE_INPUT
+
+ //-- guts
+ fprintf(stderr, "\n--bench[%d] :lookup=%d, paths=%d, strings=%d, ptrarray=%d--\n\n",
+ NITERS,
+#ifdef DO_LOOKUP
+ 1
+#else
+ 0
+#endif
+ ,
+#ifdef DO_PATHS
+ 1
+#else
+ 0
+#endif
+ ,
+#ifdef DO_STRINGS
+ 1
+#else
+ 0
+#endif
+ ,
+#ifdef DO_PTRARRAY
+ 1
+#else
+ 0
+#endif
+ );
+
+ for (i=0; i < NITERS; i++) {
+#ifdef DO_LOOKUP
+ result = gfsm_automaton_lookup(fst, input, result);
+#endif
+#ifdef DO_PATHS
+ paths = gfsm_automaton_paths(result,paths);
+#endif
+#ifdef DO_STRINGS
+ strings = gfsm_paths_to_strings(paths, abet, NULL, fst->sr, TRUE, TRUE, strings);
+#endif
+#ifdef DO_PTRARRAY
+ ptrarray=g_ptr_array_sized_new(gfsm_set_size(paths));
+ gfsm_set_to_ptr_array(paths, ptrarray);
+#endif
+
+ //-- cleanup
+ for (sltmp=strings; sltmp; sltmp=sltmp->next) { g_free(sltmp->data); }
+ if (ptrarray) g_ptr_array_free(ptrarray,TRUE);
+ if (strings) g_slist_free(strings);
+ if (paths) gfsm_set_clear(paths);
+ g_blow_chunks();
+ }
+
+ //-- pop gfsm allocators (too early: segfaults)
+ /*
+#if defined(USE_ALLOCATORS) && !defined(DELAY_ALLOCATOR_FREE)
+ MEMOP(gfsm_allocators_disable());
+#endif
+ */
+
+ //-- cleanup
+ if (result) { MEMOP(gfsm_automaton_free(result)); }
+ if (paths) { MEMOP(gfsm_set_free(paths)); }
+ if (input) { MEMOP(g_ptr_array_free(input,TRUE)); }
+ if (fst) { MEMOP(gfsm_automaton_free(fst)); }
+ if (abet) { MEMOP(gfsm_alphabet_free(abet);); }
+
+ //-- pop gfsm allocators
+#if defined(USE_ALLOCATORS) && !defined(DELAY_ALLOCATOR_FREE)
+ MEMOP(gfsm_allocators_free());
+#endif
+
+ //-- memory debugging
+#ifdef PRINT_CHUNK_INFO
+ printf("\n<CHUNKS:1>--------\n");
+ g_blow_chunks();
+ g_mem_chunk_info();
+#endif
+ //
+#ifdef DO_PROFILE
+ printf("\n<PROF:1>--------\n");
+ g_blow_chunks();
+ g_mem_profile();
+#endif
+
+#if defined(USE_ALLOCATORS) && defined(DELAY_ALLOCATOR_FREE)
+ MEMOP(gfsm_allocators_free());
+#endif
+
+ {
+ printf("OK to exit? ");
+ scanf("%s", &line);
+ }
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/pathtest.tfst b/gfsm/gfsm/src/libgfsm/tests/pathtest.tfst
new file mode 100644
index 0000000..fd189c5
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/pathtest.tfst
@@ -0,0 +1,9 @@
+0 2 3 3 1
+0 1 2 2 1
+1 6 2 2 1
+2 4 3 3 1
+2 3 2 2 1
+4 5 1 1 1
+5 0
+6 7 3 3 1
+7 0
diff --git a/gfsm/gfsm/src/libgfsm/tests/priotest.c b/gfsm/gfsm/src/libgfsm/tests/priotest.c
new file mode 100644
index 0000000..c56a39e
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/priotest.c
@@ -0,0 +1,171 @@
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+
+const char *prog=NULL;
+
+//======================================================================
+// typedefs
+typedef enum {
+ gfsmAFNone = 0x0, /**< no sort field */
+ gfsmAFLower = 0x1, /**< sort by lower label */
+ gfsmAFUpper = 0x2, /**< sort by upper label */
+ gfsmAFWeight = 0x3, /**< sort by weight (refers to semiring) */
+ gfsmAFSource = 0x4, /**< sort by arc source (if supported and meaningful) */
+ gfsmAFTarget = 0x5, /**< sort by arc target (if supported and meaningful) */
+ gfsmAFUser = 0x6, /**< user-defined sort function */
+ gfsmAFAll = 0x7, /**< not really a sort field: mask of all valid sort fields */
+ gfsmAFReverse = 0x8, /**< not really a sort field: if set, indicates that arc comparisons should be reversed */
+ gfsmAFMask = 0xf /**< not really a sort field: mask of valid sort fields & reverse flag */
+} gfsmArcField;
+
+typedef enum {
+ gfsmAFNone = 0x0, /**< '_': no sort field */
+ gfsmAFLower = 0x1, /**< 'l': sort by lower label */
+ gfsmAFUpper = 0x2, /**< 'u': sort by upper label */
+ gfsmAFWeight = 0x3, /**< 'w': sort by weight (refers to semiring) */
+ gfsmAFSource = 0x4, /**< 's': sort by arc source (if supported and meaningful) */
+ gfsmAFTarget = 0x5, /**< 't': sort by arc target (if supported and meaningful) */
+ gfsmAFLowerR = 0x6, /**< 'L': reverse sort by lower label */
+ gfsmAFUpperR = 0x7, /**< 'U': reverse sort by upper label */
+ gfsmAFWeightR = 0x8, /**< 'W': reverse sort semiring weight */
+ gfsmAFSourceR = 0x9, /**< 'S': reverse sort source state (if supported and meaningful) */
+ gfsmAFTargetR = 0xa, /**< 'T': reverse sort target state (if supported and meaningful) */
+ gfsmAFUser = 0xf /**< 'x': pseudo-field for user-defined comparisons */
+} gfsmArcFieldId;
+
+#define gfsmArcFieldShift 4 //-- number of bits in a single logical ::gfsmArcField element
+const guint32 gfsmNArcFields = 5; //-- maximum 'nth' paramter supported by ::gfsmArcFieldMask
+
+typedef guint32 gfsmArcFieldMask; //-- mask of ::gfsmArcField values, left-shifted by ::gfsmArcFieldShift
+
+
+const guint32 gfsmAFM_L = gfsmAFLower;
+const guint32 gfsmAFM_LU = gfsmAFLower|(gfsmAFUpper<<gfsmArcFieldShift);
+const guint32 gfsmAFM_LUW = gfsmAFLower|(gfsmAFUpper<<gfsmArcFieldShift)|(gfsmAFWeight<<(2*gfsmArcFieldShift));
+
+gfsmArcFieldMask gfsm_arc_field_mask_new(guint nth, gfsmArcField field, gboolean reverse)
+{
+ gfsmArcFieldMask m = field;
+ if (reverse) m |= gfsmAFReverse;
+ return m << (nth*gfsmArcFieldShift);
+}
+
+gfsmArcFieldMask gfsm_arc_field_mask_add(gfsmArcFieldMask m, guint nth, gfsmArcField field, gboolean reverse)
+{ return (m | gfsm_arc_field_mask_new(nth,field,reverse)); }
+
+gfsmArcFieldMask gfsm_arc_field_mask_clear(gfsmArcFieldMask m, guint nth)
+{ return m & ((~gfsmAFMask)<<(nth*gfsmArcFieldShift)); }
+
+gfsmArcField gfsm_arc_field_mask_get_field(gfsmArcFieldMask m, guint nth)
+{ return (m>>(nth*gfsmArcFieldShift))&gfsmAFAll; }
+
+gboolean gfsm_arc_field_mask_get_reverse(gfsmArcFieldMask m, guint nth)
+{ return ((m>>(nth*gfsmArcFieldShift))&gfsmAFReverse) ? TRUE : FALSE; }
+
+
+//======================================================================
+// parse
+gfsmArcFieldMask parse_mask(const char *str)
+{
+ gfsmArcFieldMask m = 0;
+ gint i;
+ guint nth=0;
+ /*
+ gint max_tokens = 32;
+ gchar **toks = g_strsplit(str,",; \n\t",max_tokens);
+
+ //-- parse
+ for (i=0; toks[i] != NULL; i++) {
+ gchar *tok = toks[i];
+ g_strstrip(tok);
+ }
+ */
+ for (i=0; str[i] && nth < gfsmNArcFields; i++) {
+ switch (str[i]) {
+ case 'l' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFLower,0); break;
+ case 'L' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFLower,1); break;
+
+ case 'u' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFUpper,0); break;
+ case 'U' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFUpper,1); break;
+
+ case 'w' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFWeight,0); break;
+ case 'W' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFWeight,1); break;
+
+ case 's' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFSource,0); break;
+ case 'S' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFSource,1); break;
+
+ case 't' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFTarget,0); break;
+ case 'T' : m |= gfsm_arc_field_mask_new(nth++,gfsmAFTarget,1); break;
+
+ //-- silently ignore these
+ case 'x':
+ case 'X':
+ case '-':
+ case ',':
+ case ' ':
+ case '\t':
+ case '\n':
+ break;
+
+ default:
+ g_printerr("%s: character '%c' is not in [sStTlLuUwW] in field string '%s' - skipping\n", prog, str[i], str);
+ break;
+ }
+ }
+ if (str[i] && nth==gfsmNArcFields) {
+ g_printerr("%s: ignoring trailing characters '%s' in field string '%s'\n", prog, (str+i), str);
+ }
+
+ //-- cleanup
+ //g_strfreev(toks);
+
+ return m;
+}
+
+//======================================================================
+// dump
+
+const char *mask_field_str(gfsmArcFieldMask afm, guint nth)
+{
+ switch (gfsm_arc_field_mask_get_field(afm, nth)) {
+ case gfsmAFNone: return "none";
+ case gfsmAFLower: return "lower";
+ case gfsmAFUpper: return "upper";
+ case gfsmAFWeight: return "weight";
+ case gfsmAFSource: return "source";
+ case gfsmAFTarget: return "target";
+ default: return "?";
+ }
+ return "?";
+}
+const char *mask_reverse_str(gfsmArcFieldMask afm, guint nth)
+{
+ return gfsm_arc_field_mask_get_reverse(afm, nth) ? ">" : "<";
+}
+
+void dump_mask(gfsmArcFieldMask afm, const char *str)
+{
+ printf("%s: str='%s': priorities = %u = %#0.6x = { %s%s, %s%s, %s%s, %s%s, %s%s }\n",
+ prog, str, afm, afm,
+ mask_field_str(afm,0), mask_reverse_str(afm,0),
+ mask_field_str(afm,1), mask_reverse_str(afm,1),
+ mask_field_str(afm,2), mask_reverse_str(afm,2),
+ mask_field_str(afm,3), mask_reverse_str(afm,3),
+ mask_field_str(afm,4), mask_reverse_str(afm,4)
+ );
+}
+
+//======================================================================
+// MAIN
+int main(int argc, char **argv) {
+ int i;
+ gfsmArcFieldMask afm = 0;
+
+ prog = argv[0];
+ for (i=1; i < argc; i++) {
+ afm = parse_mask(argv[i]);
+ dump_mask(afm, argv[i]);
+ }
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/prtest.c b/gfsm/gfsm/src/libgfsm/tests/prtest.c
new file mode 100644
index 0000000..d93f207
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/prtest.c
@@ -0,0 +1,28 @@
+#include <gfsm.h>
+#include <stdlib.h>
+
+//char *fsmfile = "prtest.tfst";
+char *fsmfile = "prtest.gfst";
+gfsmError *errp = NULL;
+
+int main (int argc, char **argv) {
+ gfsmAutomaton *fsm=NULL;
+
+ if (argc > 1) fsmfile = argv[1];
+
+ fsm = gfsm_automaton_new();
+
+ //gfsm_automaton_compile_filename(fsm,fsmfile,&errp);
+ gfsm_automaton_load_bin_filename(fsm,fsmfile,&errp);
+ if (errp) { g_printerr("error: %s\n", errp->message); exit(1); }
+
+ gfsm_automaton_prune(fsm);
+ gfsm_automaton_renumber_states(fsm);
+
+ gfsm_automaton_print_file(fsm,stdout,&errp);
+ if (errp) { g_printerr("error: %s\n", errp->message); exit(1); }
+
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/prtest.tfst b/gfsm/gfsm/src/libgfsm/tests/prtest.tfst
new file mode 100644
index 0000000..f3ebd16
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/prtest.tfst
@@ -0,0 +1,8 @@
+0 1 1 1 0
+0 0
+1 0
+2 0
+3 0
+4 0
+5 0
+6 0
diff --git a/gfsm/gfsm/src/libgfsm/tests/ptest.c b/gfsm/gfsm/src/libgfsm/tests/ptest.c
new file mode 100644
index 0000000..44911cd
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/ptest.c
@@ -0,0 +1,25 @@
+#include <glib.h>
+#include <stdio.h>
+
+typedef struct _xstruc {
+ int x;
+ int y;
+} xstruc;
+
+int main (void) {
+ xstruc xs = {42,24};
+ xstruc *xsp = &xs;
+ void *vp = xsp;
+ char *s = NULL;
+ char *s2;
+
+ printf ("&xs =%p ; xsp =%p ; vp =%p\n", &xs, xsp, vp);
+ printf ("&xs.x =%p ; &xs.y =%p\n", &xs.x, &xs.y);
+ printf ("&xsp->x=%p ; &xsp->y=%p\n", &xsp->x, &xsp->y);
+ printf ("(vp)->x=%p ; (vp)->y=%p\n", &((xstruc*)vp)->x, &((xstruc*)vp)->y);
+
+ printf("\n");
+ printf("s=%p ; s2=%p\n", s, g_strdup(s));
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/rudtest.c b/gfsm/gfsm/src/libgfsm/tests/rudtest.c
new file mode 100644
index 0000000..7329b70
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/rudtest.c
@@ -0,0 +1,100 @@
+#include <gfsm.h>
+#include <gfsmDebug.h>
+#include <stdlib.h>
+
+//char *fsm1file = "rudtest.gfst";
+char *fsm1file = "rudtest2.gfst";
+char *fsm2file = "rudtest.gfst";
+
+gfsmError *errp = NULL;
+
+void hackme(gfsmAutomaton *fsm1, gfsmAutomaton *fsm2, char *label)
+{
+ printf("<%s>.a : reverse(fsm1)\n", label);
+ gfsm_automaton_reverse(fsm1);
+
+ printf("<%s>.b : union(fsm1,fsm2)\n", label);
+ gfsm_automaton_union(fsm1, fsm2);
+
+ printf("<%s>.c : determinize(fsm1)\n", label);
+ gfsm_automaton_determinize(fsm1);
+
+ printf("<%s> : done.\n", label);
+}
+
+void print_sizes(void)
+{
+ //-- show some memory sizes:
+ fprintf(stderr, "%-32s | %6s\n", "TYPE", "SIZE");
+#define PRINTSIZE(type) fprintf(stderr, "%-32s | %u\n", #type, sizeof(type))
+ PRINTSIZE(gfsmAlphabet);
+ PRINTSIZE(gfsmIdentityAlphabet);
+ PRINTSIZE(gfsmRangeAlphabet);
+
+ PRINTSIZE(gfsmArc);
+ PRINTSIZE(gfsmArcIter);
+ PRINTSIZE(gfsmArcList);
+ PRINTSIZE(gfsmAutomaton);
+ PRINTSIZE(gfsmAutomatonFlags);
+ PRINTSIZE(gfsmAutomatonHeader);
+ PRINTSIZE(gfsmSemiring);
+ //PRINTSIZE(gfsmSet);
+ //PRINTSIZE(gfsmSetUnionData);
+ PRINTSIZE(gfsmWeightedStateSet);
+ PRINTSIZE(gfsmState);
+ PRINTSIZE(gfsmStatePair);
+ PRINTSIZE(gfsmStateSet);
+ PRINTSIZE(gfsmStateSetIter);
+ PRINTSIZE(gfsmStoredState);
+ PRINTSIZE(gfsmStoredArc);
+ PRINTSIZE(gfsmVersionInfo);
+#undef PRINTSIZE
+}
+
+void rudtest_construct(gfsmAutomaton *fsm)
+{
+ gfsm_automaton_clear(fsm);
+ fsm->root_id = 0;
+ gfsm_automaton_add_state_full(fsm,0);
+ gfsm_automaton_add_state_full(fsm,1);
+ gfsm_automaton_add_state_full(fsm,2);
+ gfsm_automaton_set_final_state(fsm,2,TRUE);
+ gfsm_automaton_add_arc(fsm,0,1,1,1,0);
+}
+
+int main (int argc, char **argv) {
+ gfsmAutomaton *fsm1=NULL, *fsm2=NULL;
+
+ //g_thread_init(NULL);
+ GFSM_DEBUG_INIT();
+
+ //print_sizes();
+
+ if (argc > 1) fsm1file = argv[1];
+ if (argc > 2) fsm2file = argv[2];
+
+ fsm1 = gfsm_automaton_new();
+ fsm2 = gfsm_automaton_new();
+
+ gfsm_automaton_load_bin_filename(fsm1,fsm1file,&errp);
+ //rudtest_construct(fsm1);
+ if (errp) { g_printerr("error: %s\n", errp->message); exit(1); }
+
+ if (fsm2) gfsm_automaton_load_bin_filename(fsm2,fsm1file,&errp);
+ if (errp) { g_printerr("error: %s\n", errp->message); exit(1); }
+
+ hackme(fsm1,fsm2,"1");
+ hackme(fsm1,fsm2,"2");
+ hackme(fsm1,fsm2,"3");
+ hackme(fsm1,fsm2,"4");
+ /* */
+
+ if (fsm1) gfsm_automaton_free(fsm1);
+ if (fsm2) gfsm_automaton_free(fsm2);
+
+
+ GFSM_DEBUG_FINISH();
+ GFSM_DEBUG_PRINT();
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/rudtest.tfst b/gfsm/gfsm/src/libgfsm/tests/rudtest.tfst
new file mode 100644
index 0000000..ac8c248
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/rudtest.tfst
@@ -0,0 +1,3 @@
+0 1 1 1 0
+1 2 2 2 0
+2 0
diff --git a/gfsm/gfsm/src/libgfsm/tests/rudtest2.tfst b/gfsm/gfsm/src/libgfsm/tests/rudtest2.tfst
new file mode 100644
index 0000000..65261c9
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/rudtest2.tfst
@@ -0,0 +1,5 @@
+0 1 1 1 0
+1 2 2 2 0
+2 3 3 3 0
+3 4 4 4 0
+4 0
diff --git a/gfsm/gfsm/src/libgfsm/tests/seek2test.c b/gfsm/gfsm/src/libgfsm/tests/seek2test.c
new file mode 100644
index 0000000..cf12ac8
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/seek2test.c
@@ -0,0 +1,259 @@
+#include <gfsm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "labprobs.h"
+
+/*======================================================================
+ * Globals
+ */
+const char *prog = "seek2test";
+
+const char *fsmfile = "tagh-chopped.gfst";
+//const char *xfsmfile = "tagh-lo.gfstx";
+
+gfsmStateId qid_test = 0;
+guint out_degree_test = 0;
+gulong count_test =
+//1024
+//1048576
+4194304
+//16777216
+;
+
+//#define BENCH_SORTED 1
+#undef BENCH_SORTED
+
+/*======================================================================
+ * bench_seek_vanilla()
+ */
+double bench_seek_vanilla(gfsmAutomaton *fsm) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(gfsm_automaton_out_degree(fsm,qid_test));
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = qid_test;
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcIter ai;
+ ary->len=0;
+ for (gfsm_arciter_open(&ai,fsm,qid), gfsm_arciter_seek_lower(&ai,lab);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_lower(&ai,lab))
+ {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ if (fsm->flags.sort_mode==gfsmASMLower && a->lower!=lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_labx()
+ */
+#ifndef SEEK_LABX_BINSEARCH_CUTOFF
+#define SEEK_LABX_BINSEARCH_CUTOFF 0
+//#define SEEK_LABX_BINSEARCH_CUTOFF 4
+//#define SEEK_LABX_BINSEARCH_CUTOFF 8
+//#define SEEK_LABX_BINSEARCH_CUTOFF 16
+//#define SEEK_LABX_BINSEARCH_CUTOFF 32
+//#define SEEK_LABX_BINSEARCH_CUTOFF 64
+//#define SEEK_LABX_BINSEARCH_CUTOFF 128
+//#define SEEK_LABX_BINSEARCH_CUTOFF 256
+#endif
+
+double bench_seek_labx(gfsmArcLabelIndex *labx) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(gfsm_arc_label_index_out_degree(labx,qid_test));
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = qid_test;
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcRange range;
+ gfsmArc *a;
+ ary->len=0;
+ gfsm_arcrange_open_label_index(&range,labx,qid);
+ if ((range.max - range.min) <= SEEK_LABX_BINSEARCH_CUTOFF) {
+ for ( ; gfsm_arcrange_ok(&range); gfsm_arcrange_next(&range) ) {
+ a = gfsm_arcrange_arc(&range);
+ if (a->lower<lab) continue;
+ if (a->lower>lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ } else {
+ for (gfsm_arcrange_seek_lower(&range,lab); gfsm_arcrange_ok(&range); gfsm_arcrange_next(&range)) {
+ a = gfsm_arcrange_arc(&range);
+ if (a->lower!=lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ }
+ //gfsm_arcrange_close(&range);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+
+
+/*======================================================================
+ * Report
+ */
+GString *dat_header=NULL;
+GString *dat_data=NULL;
+gint dat_row=0;
+gint dat_col=0;
+
+void report_new_row(void) {
+ fprintf(stderr, "%s: qid=%u, out_degree=%u\n", prog, qid_test, out_degree_test);
+ //
+ //-- save data for gnuplot output
+ dat_col=0;
+ if (!dat_header) dat_header = g_string_new("");
+ if (!dat_data) dat_data = g_string_new("");
+ if (dat_row==0) {
+ g_string_append(dat_header,"#1:out_deg");
+ }
+ g_string_append_printf(dat_data, "%u", out_degree_test);
+}
+
+void report_column(char *label, double elapsed) {
+ double iters_per_sec = ((double)count_test)/elapsed;
+ //
+ //-- to stderr
+ fprintf(stderr, "BENCH[%16s]: %ld iters in %.2g sec: %.2g iters/sec\n",
+ label, count_test, elapsed, iters_per_sec);
+ fflush(stderr);
+ //
+ //-- to data strings
+ if (dat_row==0) {
+ g_string_append_printf(dat_header, "\t%d:%s_secs\t%d:%s_ips", (2*dat_col+2),label, (2*dat_col+3),label);
+ }
+ g_string_append_c(dat_data,'\t');
+ g_string_append_printf(dat_data,"\t%g\t%g", elapsed,iters_per_sec);
+ ++dat_col;
+}
+
+void report_end_row(void) {
+ ++dat_row;
+ g_string_append(dat_data,"\n");
+}
+
+void report_gnuplot(void) {
+ fflush(stderr);
+ printf("%s\n%s", dat_header->str, dat_data->str);
+}
+
+
+/*======================================================================
+ * Main
+ */
+int main(int argc, char **argv)
+{
+ char *qid_str="0";
+ gfsmError *err=NULL;
+ int argi;
+ //
+ gfsmAutomaton *fsm=NULL;
+ double elapsed_vanilla;
+#ifdef BENCH_SORTED
+ gfsmAutomaton *fsm_sorted=NULL;
+ double elapsed_sorted;
+#endif
+ gfsmArcLabelIndex *labx=NULL;
+ double elapsed_labx;
+
+ //-- sanity check
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [QID(s)...]\n", prog);
+ exit(1);
+ }
+
+ //-- load probabilities & initialize
+ load_label_probs();
+ populate_seek_labels();
+
+ //-- report
+ fprintf(stderr, "%s: count=%lu\n", prog, count_test);
+ fflush(stderr);
+
+ //-- load/create: vanilla
+ fprintf(stderr, "%s: loading vanilla automaton '%s'... ", prog, fsmfile); fflush(stderr);
+ fsm = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(fsm,fsmfile,&err)) {
+ fprintf(stderr,"%s: load failed for '%s': %s\n", prog, fsmfile, (err ? err->message : "?"));
+ exit(3);
+ }
+ fsm->flags.sort_mode = gfsmASMNone;
+ fprintf(stderr, "loaded.\n"); fflush(stderr);
+
+#ifdef BENCH_SORTED
+ //-- load/create: sorted
+ fprintf(stderr, "%s: sorting... ", prog); fflush(stderr);
+ fsm_sorted = gfsm_automaton_clone(fsm);
+ gfsm_automaton_arcsort(fsm_sorted,gfsmASMLower);
+ fprintf(stderr, "sorted.\n"); fflush(stderr);
+#endif
+
+ //-- load/create: labx
+ fprintf(stderr, "%s: indexing to gfsmArcLabelIndex... ", prog); fflush(stderr);
+ labx = gfsm_automaton_to_arc_label_index_lower(fsm,NULL);
+ fprintf(stderr, "indexed.\n"); fflush(stderr);
+
+ //-- main loop
+ for (argi=1; argi < argc; argi++) {
+ qid_str = argv[argi];
+ qid_test = strtol(qid_str,NULL,0);
+ out_degree_test = gfsm_automaton_out_degree(fsm,qid_test);
+
+ report_new_row();
+
+ //-- benchmark: vanilla
+ elapsed_vanilla = bench_seek_vanilla(fsm);
+ report_column("vanilla", elapsed_vanilla);
+
+#ifdef BENCH_SORTED
+ //-- benchmark: vanilla+sorted
+ gfsm_automaton_arcsort(fsm,gfsmASMLower);
+ elapsed_sorted = bench_seek_vanilla(fsm);
+ report_column("sorted", elapsed_sorted);
+#endif
+
+ //-- benchmark: indexed
+ elapsed_labx = bench_seek_labx(labx);
+ report_column("labx", elapsed_labx);
+
+ report_end_row();
+ }
+
+ //-- gnuplot output
+ report_gnuplot();
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+#ifdef BENCH_SORTED
+ if (fsm_sorted) gfsm_automaton_free(fsm_sorted);
+#endif
+ if (labx) gfsm_arc_label_index_free(labx);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/seek3test.c b/gfsm/gfsm/src/libgfsm/tests/seek3test.c
new file mode 100644
index 0000000..8c3e8af
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/seek3test.c
@@ -0,0 +1,611 @@
+#include <gfsm.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*======================================================================
+ * Globals
+ */
+const char *prog = "seek2test";
+
+gfsmStateId qid_test = 0;
+guint out_degree_test;
+gulong count_test_max =
+//1024UL //==2^10
+//1048576UL //==2^20
+2097152UL //==2^21
+//4194304UL //==2^22
+//16777216UL //==2^24
+//67108864UL //==2^26
+//268435456UL //==2^28
+;
+gulong count_test=0; //-- count_test_max/out_degree
+
+/*======================================================================
+ * Label population
+ */
+
+//--------------------------------------------------------------
+// globals
+GRand *grand = NULL;
+const guint32 grand_seed = 42;
+#define GRAND_USE_SEED 1
+//#undef GRAND_USE_SEED
+
+const guint32 n_labels = 128;
+const guint32 n_states = 8192;
+
+GArray *seekus = NULL; /*-- lab = g_array_index(seekus,i); 1<=i<=count_test --*/
+GArray *seekfrom = NULL; /*-- qid = g_array_index(seekus,i); 1<=i<=count_test --*/
+
+//--------------------------------------------------------------
+// random_label()
+gfsmLabelId random_label(void) {
+ if (!grand) {
+ grand = g_rand_new();
+#ifdef GRAND_USE_SEED
+ g_rand_set_seed(grand,grand_seed);
+#endif
+ }
+ return g_rand_int_range(grand,0,n_labels);
+}
+
+//--------------------------------------------------------------
+// populate_seek_labels()
+void populate_seek_labels(void) {
+ int i;
+ gfsmLabelId lab;
+ seekus = g_array_sized_new(FALSE,TRUE,sizeof(gfsmLabelId),count_test_max);
+ for (i=0; i < count_test_max; i++) {
+ lab = random_label();
+ g_array_append_val(seekus,lab);
+ }
+}
+
+//--------------------------------------------------------------
+// random_state()
+gfsmStateId random_state(void) {
+ if (!grand) { grand = g_rand_new_with_seed(grand_seed); }
+ return g_rand_int_range(grand,0,n_states);
+}
+
+//--------------------------------------------------------------
+// populate_seek_states()
+void populate_seek_states(void) {
+ int i;
+ seekfrom = g_array_sized_new(FALSE,TRUE,sizeof(gfsmStateId),count_test_max);
+ for (i=0; i < count_test_max; i++) {
+ gfsmStateId qid = random_state();
+ g_array_append_val(seekfrom,qid);
+ }
+}
+
+
+/*======================================================================
+ * bench_seek_vanilla()
+ */
+double bench_seek_vanilla(gfsmAutomaton *fsm) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId, i);
+ gfsmLabelId lab = g_array_index(seekus, gfsmLabelId, i);
+ gfsmArcIter ai;
+ ary->len=0;
+ for (gfsm_arciter_open(&ai,fsm,qid); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ if (a->lower != lab) continue;
+ g_ptr_array_add(ary, a);
+ }
+ gfsm_arciter_close(&ai);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_sorted()
+ */
+double bench_seek_sorted(gfsmAutomaton *fsm) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId,i);
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcIter ai;
+ ary->len=0;
+ for (gfsm_arciter_open(&ai,fsm,qid); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ if (a->lower < lab) continue;
+ if (a->lower > lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ gfsm_arciter_close(&ai);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_tabx_vanilla()
+ */
+double bench_seek_tabx_vanilla(gfsmArcTableIndex *tabx) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId,i);
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcRange range;
+ ary->len=0;
+ for (gfsm_arcrange_open_table_index(&range,tabx,qid); gfsm_arcrange_ok(&range); gfsm_arcrange_next(&range)) {
+ gfsmArc *a = gfsm_arcrange_arc(&range);
+ if (a->lower != lab) continue;
+ g_ptr_array_add(ary, a);
+ }
+ gfsm_arcrange_close(&range);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_tabx_sorted() : linear search
+ */
+double bench_seek_tabx_sorted(gfsmArcTableIndex *tabx) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId,i);
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcRange range;
+ ary->len=0;
+ for (gfsm_arcrange_open_table_index(&range,tabx,qid); gfsm_arcrange_ok(&range); gfsm_arcrange_next(&range)) {
+ gfsmArc *a = gfsm_arcrange_arc(&range);
+ if (a->lower < lab) continue;
+ if (a->lower > lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ gfsm_arcrange_close(&range);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_tabx_sorted_2() : linear search (v2) [identical to v1]
+ */
+double bench_seek_tabx_sorted_2(gfsmArcTableIndex *tabx) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId,i);
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcRange range;
+ ary->len=0;
+ for (gfsm_arcrange_open_table_index(&range,tabx,qid); range.min<range.max; ++range.min) {
+ if (range.min->lower < lab) continue;
+ if (range.min->lower > lab) break;
+ g_ptr_array_add(ary, range.min);
+ }
+ gfsm_arcrange_close(&range);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_tabx_seek_lib() : binary search: library function
+ */
+inline void gfsm_arcrange_seek_lower(gfsmArcRange *range, gfsmLabelId find)
+{
+ g_assert(range != NULL);
+ while (gfsm_arcrange_ok(range) && gfsm_arcrange_arc(range)->lower < find)
+ gfsm_arcrange_next(range);
+}
+
+double bench_seek_tabx_seek_lib(gfsmArcTableIndex *tabx) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId,i);
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcRange range;
+ ary->len=0;
+ for (gfsm_arcrange_open_table_index(&range,tabx,qid), gfsm_arcrange_seek_lower(&range,lab);
+ gfsm_arcrange_ok(&range);
+ gfsm_arcrange_next(&range))
+ {
+ gfsmArc *a = gfsm_arcrange_arc(&range);
+ if (a->lower > lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ gfsm_arcrange_close(&range);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_tabx_bsearch_inl() : binary search: inline function
+ */
+#define BSEARCH_CUTOFF 16
+static inline gfsmArc *bsearch_lower(gfsmArc *min, gfsmArc *max, gfsmLabelId find)
+{
+ while (min < max) {
+ gint diff = max-min;
+ if (diff < BSEARCH_CUTOFF) {
+ do {
+ if (min->lower >= find) break;
+ min++;
+ } while (min < max);
+ return min;
+ }
+ else {
+ gfsmArc *mid = min + diff/2;
+ if (mid->lower < find) min = mid+1;
+ else max = mid;
+ }
+ }
+ return min;
+}
+
+double bench_seek_tabx_bsearch_inl(gfsmArcTableIndex *tabx) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId,i);
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcRange range;
+ ary->len=0;
+ for (gfsm_arcrange_open_table_index(&range,tabx,qid), range.min=bsearch_lower(range.min,range.max,lab);
+ gfsm_arcrange_ok(&range);
+ gfsm_arcrange_next(&range))
+ {
+ gfsmArc *a = gfsm_arcrange_arc(&range);
+ if (a->lower > lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ gfsm_arcrange_close(&range);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * bench_seek_tabx_bsearch_func() : binary search: inline function
+ */
+static void bsearch_range_func(gfsmArcRange *range, gfsmLabelId find)
+{
+ gfsmArc *min=range->min, *max=range->max;
+ while (min < max) {
+ gfsmArc *mid = min + (max-min)/2;
+ if (mid->lower < find) min = mid+1;
+ else max = mid;
+ }
+ range->min = min;
+}
+
+double bench_seek_tabx_bsearch_func(gfsmArcTableIndex *tabx) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(out_degree_test);
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = g_array_index(seekfrom,gfsmStateId,i);
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcRange range;
+ ary->len=0;
+ for (gfsm_arcrange_open_table_index(&range,tabx,qid), bsearch_range_func(&range,lab);
+ gfsm_arcrange_ok(&range);
+ gfsm_arcrange_next(&range))
+ {
+ gfsmArc *a = gfsm_arcrange_arc(&range);
+ if (a->lower > lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ gfsm_arcrange_close(&range);
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+
+/*======================================================================
+ * Report
+ */
+GString *dat_header=NULL;
+GString *dat_data=NULL;
+gint dat_row=0;
+gint dat_col=0;
+
+void report_new_row(void) {
+ fprintf(stderr, "%s: n_states=%u, n_labels=%u, out_degree=%u\n", prog, n_states, n_labels, out_degree_test);
+ //
+ //-- save data for gnuplot output
+ dat_col=0;
+ if (!dat_header) dat_header = g_string_new("");
+ if (!dat_data) dat_data = g_string_new("");
+ if (dat_row==0) {
+ g_string_append(dat_header,"#1:out_deg");
+ }
+ g_string_append_printf(dat_data, "%u", out_degree_test);
+}
+
+void report_column(char *label, double elapsed) {
+ double iters_per_sec = ((double)count_test)/elapsed;
+ //
+ //-- to stderr
+ fprintf(stderr, "BENCH[%24s]: %ld iters in %5.3f sec: %7.2e iters/sec\n",
+ label, count_test, elapsed, iters_per_sec);
+ fflush(stderr);
+ //
+ //-- to data strings
+ if (dat_row==0) {
+ g_string_append_printf(dat_header, "\t%d:%s_secs\t%d:%s_ips", (2*dat_col+2),label, (2*dat_col+3),label);
+ }
+ g_string_append_c(dat_data,'\t');
+ g_string_append_printf(dat_data,"\t%g\t%g", elapsed,iters_per_sec);
+ ++dat_col;
+}
+
+void report_end_row(void) {
+ ++dat_row;
+ g_string_append(dat_data,"\n");
+}
+
+void report_gnuplot(void) {
+ fflush(stderr);
+ printf("%s\n%s", dat_header->str, dat_data->str);
+}
+
+
+/*======================================================================
+ * Main
+ */
+//#define BENCH_VANILLA 1
+//#define BENCH_SORTED 1
+//#define BENCH_TABX_VANILLA 1
+#define BENCH_TABX_SORTED 1
+//#define BENCH_TABX_SORTED_2 1
+//#define BENCH_TABX_SEEK_LIB 1
+#define BENCH_TABX_BSEARCH_FUNC 1
+//#define BENCH_TABX_BSEARCH_INL 1
+int main(int argc, char **argv)
+{
+ char *out_degree_str="32";
+ int argi, arci, qi;
+ //
+ gfsmAutomaton *fsm=NULL;
+ double elapsed_vanilla=0;
+ //
+ gfsmAutomaton *fsm_sorted=NULL;
+ double elapsed_sorted=0;
+ //
+ gfsmArcTableIndex *tabx=NULL;
+ double elapsed_tabx_vanilla=0;
+ //
+ gfsmArcTableIndex *tabx_sorted=NULL;
+ double elapsed_tabx_sorted=0;
+ //
+ gfsmArcTableIndex *tabx_sorted_2=NULL;
+ double elapsed_tabx_sorted_2=0;
+ //
+ gfsmArcTableIndex *tabx_seek_lib=NULL;
+ double elapsed_tabx_seek_lib=0;
+ //
+ gfsmArcTableIndex *tabx_bsearch_func=NULL;
+ double elapsed_tabx_bsearch_func=0;
+ //
+ gfsmArcTableIndex *tabx_bsearch_inl=NULL;
+ double elapsed_tabx_bsearch_inl=0;
+
+ //-- sanity check
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [OUT_DEGREE(s)...]\n", prog);
+ exit(1);
+ }
+
+ //-- initialize labels to seek
+ populate_seek_labels();
+ populate_seek_states();
+
+ //-- report
+ fprintf(stderr, "%s: count_test_max=%lu\n", prog, count_test_max);
+ fflush(stderr);
+
+ //-- create: vanilla
+ fsm = gfsm_automaton_new();
+
+ //-- main loop
+ for (argi=1; argi < argc; argi++) {
+ out_degree_str = argv[argi];
+ out_degree_test = strtol(out_degree_str,NULL,0);
+ //count_test = count_test_max / out_degree_test;
+ count_test = count_test_max;
+
+ //-- populate: vanilla
+ gfsm_automaton_clear(fsm);
+ gfsm_automaton_set_root(fsm,gfsm_automaton_ensure_state(fsm,0));
+ gfsm_automaton_set_final_state_full(fsm,0,TRUE,fsm->sr->one);
+ for (qi=1; qi < n_states; qi++) {
+ gfsm_automaton_ensure_state(fsm,qi);
+ for (arci=0; arci < out_degree_test; arci++) {
+ gfsmLabelId lo = random_label();
+ gfsmLabelId hi = random_label();
+ gfsmWeight w = arci + 1.0;
+ gfsm_automaton_add_arc(fsm,qi,qi, lo,hi, w);
+ }
+ }
+
+ //-------- bench
+ report_new_row();
+
+ //-- benchmark: vanilla (twice for cache optimization)
+#ifdef BENCH_VANILLA
+ elapsed_vanilla = bench_seek_vanilla(fsm);
+ elapsed_vanilla = bench_seek_vanilla(fsm);
+ report_column("vanilla", elapsed_vanilla);
+#endif
+
+#ifdef BENCH_SORTED
+ //-- benchmark: vanilla+sorted
+ fsm_sorted = gfsm_automaton_clone(fsm);
+ gfsm_automaton_arcsort(fsm_sorted,gfsmASMLower);
+ elapsed_sorted = bench_seek_sorted(fsm_sorted);
+ elapsed_sorted = bench_seek_sorted(fsm_sorted);
+ report_column("sorted", elapsed_sorted);
+#endif
+
+#ifdef BENCH_TABX_VANILLA
+ //-- benchmark: table: vanilla
+ tabx = gfsm_automaton_to_arc_table_index(fsm,tabx);
+ elapsed_tabx_vanilla = bench_seek_tabx_vanilla(tabx);
+ elapsed_tabx_vanilla = bench_seek_tabx_vanilla(tabx);
+ report_column("tabx_vanilla", elapsed_tabx_vanilla);
+#endif
+
+#ifdef BENCH_TABX_SORTED
+ //-- benchmark: table: sorted linear
+ tabx_sorted = gfsm_automaton_to_arc_table_index(fsm,tabx_sorted);
+ gfsm_arc_table_index_priority_sort(tabx_sorted, gfsmASP_LU, fsm->sr);
+ elapsed_tabx_sorted = bench_seek_tabx_sorted(tabx_sorted);
+ elapsed_tabx_sorted = bench_seek_tabx_sorted(tabx_sorted);
+ report_column("tabx_sorted", elapsed_tabx_sorted);
+#endif
+
+#ifdef BENCH_TABX_SORTED_2
+ //-- benchmark: table: sorted linear (v2)
+ tabx_sorted_2 = gfsm_automaton_to_arc_table_index(fsm,tabx_sorted_2);
+ gfsm_arc_table_index_priority_sort(tabx_sorted_2, gfsmASP_LU, fsm->sr);
+ elapsed_tabx_sorted_2 = bench_seek_tabx_sorted_2(tabx_sorted_2);
+ elapsed_tabx_sorted_2 = bench_seek_tabx_sorted_2(tabx_sorted_2);
+ report_column("tabx_sorted_2", elapsed_tabx_sorted_2);
+#endif
+
+#ifdef BENCH_TABX_SEEK_LIB
+ //-- benchmark: table: binary search: lib
+ tabx_seek_lib = gfsm_automaton_to_arc_table_index(fsm,tabx_seek_lib);
+ gfsm_arc_table_index_priority_sort(tabx_seek_lib, gfsmASP_LU, fsm->sr);
+ elapsed_tabx_seek_lib = bench_seek_tabx_seek_lib(tabx_seek_lib);
+ elapsed_tabx_seek_lib = bench_seek_tabx_seek_lib(tabx_seek_lib);
+ report_column("tabx_seek_lib", elapsed_tabx_seek_lib);
+#endif
+
+#ifdef BENCH_TABX_BSEARCH_FUNC
+ //-- benchmark: table: binary search: func
+ tabx_bsearch_func = gfsm_automaton_to_arc_table_index(fsm,tabx_bsearch_func);
+ gfsm_arc_table_index_priority_sort(tabx_bsearch_func, gfsmASP_LU, fsm->sr);
+ elapsed_tabx_bsearch_func = bench_seek_tabx_bsearch_func(tabx_bsearch_func);
+ elapsed_tabx_bsearch_func = bench_seek_tabx_bsearch_func(tabx_bsearch_func);
+ report_column("tabx_bsearch_func", elapsed_tabx_bsearch_func);
+#endif
+
+#ifdef BENCH_TABX_BSEARCH_INL
+ //-- benchmark: table: binary search: inline
+ tabx_bsearch_inl = gfsm_automaton_to_arc_table_index(fsm,tabx_bsearch_inl);
+ gfsm_arc_table_index_priority_sort(tabx_bsearch_inl, gfsmASP_LU, fsm->sr);
+ elapsed_tabx_bsearch_inl = bench_seek_tabx_bsearch_inl(tabx_bsearch_inl);
+ elapsed_tabx_bsearch_inl = bench_seek_tabx_bsearch_inl(tabx_bsearch_inl);
+ report_column("tabx_bsearch_inl", elapsed_tabx_bsearch_inl);
+#endif
+
+ report_end_row();
+ }
+
+ //-- gnuplot output
+ report_gnuplot();
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+ if (fsm_sorted) gfsm_automaton_free(fsm_sorted);
+ if (tabx) gfsm_arc_table_index_free(tabx);
+ if (tabx_sorted) gfsm_arc_table_index_free(tabx_sorted);
+ if (tabx_sorted_2) gfsm_arc_table_index_free(tabx_sorted_2);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/seektest.c b/gfsm/gfsm/src/libgfsm/tests/seektest.c
new file mode 100644
index 0000000..cc59874
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/seektest.c
@@ -0,0 +1,365 @@
+#include <gfsm.h>
+#include <gfsmIndexed2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "labprobs.h"
+
+/*======================================================================
+ * Globals
+ */
+const char *prog = "seektest";
+
+const char *fsmfile = "tagh-chopped.gfst";
+//const char *xfsmfile = "tagh-lo.gfstx";
+
+gfsmStateId qid_test = 0;
+guint out_degree_test = 0;
+gulong count_test =
+//1024
+//1048576
+4194304
+//16777216
+;
+
+//#define BENCH_SORTED 1
+#undef BENCH_SORTED
+
+/*======================================================================
+ * bench_seek_vanilla()
+ */
+double bench_seek_vanilla(gfsmAutomaton *fsm) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(gfsm_automaton_out_degree(fsm,qid_test));
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = qid_test;
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcIter ai;
+ ary->len=0;
+ for (gfsm_arciter_open(&ai,fsm,qid), gfsm_arciter_seek_lower(&ai,lab);
+ gfsm_arciter_ok(&ai);
+ gfsm_arciter_next(&ai), gfsm_arciter_seek_lower(&ai,lab))
+ {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ if (fsm->flags.sort_mode==gfsmASMLower && a->lower!=lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+/*======================================================================
+ * indexed_lower_lb()
+ */
+gfsmArcId indexed_lower_lb(gfsmIndexedAutomaton *fsm,
+ gfsmLabelId lab,
+ gfsmArcId aid_lo,
+ gfsmArcId aid_hi)
+
+{
+ /*
+ gfsmArcId aid_mid;
+ gfsmArc *a;
+ */
+
+ //if (!gfsm_indexed_automaton_has_state(fsm,qid)) return gfsmNoArc;
+ /*
+ aid_lo = g_array_index(fsm->state_first_arc, gfsmArcId, qid);
+ aid_hi = g_array_index(fsm->state_first_arc, gfsmArcId, qid+1);
+ */
+
+ while (aid_lo < aid_hi) {
+ gfsmArcId aid_mid = (aid_lo+aid_hi)/2;
+ gfsmArc *a = &g_array_index(fsm->arcs, gfsmArc, g_array_index(fsm->arcix_lower, gfsmArcId, aid_mid));
+ if (a->lower < lab) { aid_lo = aid_mid+1; }
+ else { aid_hi = aid_mid; }
+ }
+ //return aid_lo <= aid_hi ? aid_lo : gfsmNoArc;
+ return aid_lo;
+}
+
+
+/*======================================================================
+ * bench_seek_indexed()
+ */
+#ifndef SEEK_INDEXED_BINSEARCH_CUTOFF
+//#define SEEK_INDEXED_BINSEARCH_CUTOFF 0
+//#define SEEK_INDEXED_BINSEARCH_CUTOFF 4
+//#define SEEK_INDEXED_BINSEARCH_CUTOFF 8
+//#define SEEK_INDEXED_BINSEARCH_CUTOFF 16
+//#define SEEK_INDEXED_BINSEARCH_CUTOFF 32
+#define SEEK_INDEXED_BINSEARCH_CUTOFF 64
+#endif
+double bench_seek_indexed(gfsmIndexedAutomaton *fsm) {
+#if 1
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(gfsm_indexed_automaton_out_degree(fsm,qid_test));
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = qid_test;
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcId aid_lo = g_array_index(fsm->state_first_arc, gfsmArcId, qid);
+ gfsmArcId aid_hi = g_array_index(fsm->state_first_arc, gfsmArcId, qid+1);
+ gfsmArcId aid;
+ gfsmArc *a;
+ ary->len=0;
+ if (aid_hi-aid_lo >= SEEK_INDEXED_BINSEARCH_CUTOFF) {
+ for (aid=indexed_lower_lb(fsm,lab,aid_lo,aid_hi); aid<aid_hi; aid++) {
+ a = &g_array_index(fsm->arcs, gfsmArc, g_array_index(fsm->arcix_lower, gfsmArcId, aid));
+ if (a->lower!=lab) break;
+ g_ptr_array_add(ary, a);
+ }
+ } else {
+ for (a=((gfsmArc*)fsm->arcs->data)+aid_lo; a < ((gfsmArc*)fsm->arcs->data)+aid_hi; a++) {
+ if (a->lower==lab) g_ptr_array_add(ary,a);
+ }
+ }
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+#else
+ return 1e38; //-- dummy
+#endif
+}
+
+
+/*======================================================================
+ * indexed2_lower_lb()
+ */
+gfsmArcId indexed2_lower_lb(gfsmIndexedAutomaton2 *fsm,
+ gfsmLabelId lab,
+ gfsmArcId aid_lo,
+ gfsmArcId aid_hi)
+
+{
+ while (aid_lo < aid_hi) {
+ gfsmArcId aid_mid = (aid_lo+aid_hi)/2;
+ gfsmArc *a = g_ptr_array_index(fsm->arcix_lower, aid_mid);
+ if (a->lower < lab) { aid_lo = aid_mid+1; }
+ else { aid_hi = aid_mid; }
+ }
+ //return aid_lo <= aid_hi ? aid_lo : gfsmNoArc;
+ return aid_lo;
+}
+
+
+/*======================================================================
+ * bench_seek_indexed2()
+ */
+double bench_seek_indexed2(gfsmIndexedAutomaton2 *fsm) {
+ guint i;
+ double elapsed;
+ GPtrArray *ary = g_ptr_array_sized_new(gfsm_indexed_automaton2_out_degree(fsm,qid_test));
+ GTimer *timer = g_timer_new();
+
+ g_timer_start(timer);
+ for (i=0; i < count_test; i++) {
+ //-- BEGIN TEST CODE
+ gfsmStateId qid = qid_test;
+ gfsmLabelId lab = g_array_index(seekus,gfsmLabelId,i);
+ gfsmArcId aid_lo = g_array_index(fsm->state_first_arc, gfsmArcId, qid);
+ gfsmArcId aid_hi = g_array_index(fsm->state_first_arc, gfsmArcId, qid+1);
+ gfsmArcId aid;
+ gfsmArc **app;
+ ary->len=0;
+ if (aid_hi-aid_lo >= SEEK_INDEXED_BINSEARCH_CUTOFF) {
+ for (app = ((gfsmArc**)(fsm->arcix_lower->pdata)) + indexed2_lower_lb(fsm,lab,aid_lo,aid_hi);
+ app < ((gfsmArc**)(fsm->arcix_lower->pdata)) + aid_hi && (*app)->lower==lab;
+ app++)
+ {
+ g_ptr_array_add(ary, (*app));
+ }
+ } else {
+ for (app = ((gfsmArc**)(fsm->arcix_lower->pdata)) + aid_lo;
+ app < ((gfsmArc**)(fsm->arcix_lower->pdata)) + aid_hi;
+ app++)
+ {
+ if ((*app)->lower==lab) g_ptr_array_add(ary,(*app));
+ }
+ }
+ //-- END TEST CODE
+ }
+ elapsed = g_timer_elapsed(timer,NULL);
+
+ //-- cleanup
+ g_ptr_array_free(ary,TRUE);
+ g_timer_destroy(timer);
+
+ return elapsed;
+}
+
+
+/*======================================================================
+ * Report
+ */
+GString *dat_header=NULL;
+GString *dat_data=NULL;
+gint dat_row=0;
+gint dat_col=0;
+
+void report_new_row(void) {
+ fprintf(stderr, "%s: qid=%u, out_degree=%u\n", prog, qid_test, out_degree_test);
+ //
+ //-- save data for gnuplot output
+ dat_col=0;
+ if (!dat_header) dat_header = g_string_new("");
+ if (!dat_data) dat_data = g_string_new("");
+ if (dat_row==0) {
+ g_string_append(dat_header,"#1:out_deg");
+ }
+ g_string_append_printf(dat_data, "%u", out_degree_test);
+}
+
+void report_column(char *label, double elapsed) {
+ double iters_per_sec = ((double)count_test)/elapsed;
+ //
+ //-- to stderr
+ fprintf(stderr, "BENCH[%16s]: %ld iters in %.2g sec: %.2g iters/sec\n",
+ label, count_test, elapsed, iters_per_sec);
+ fflush(stderr);
+ //
+ //-- to data strings
+ if (dat_row==0) {
+ g_string_append_printf(dat_header, "\t%d:%s_secs\t%d:%s_ips", (2*dat_col+2),label, (2*dat_col+3),label);
+ }
+ g_string_append_c(dat_data,'\t');
+ g_string_append_printf(dat_data,"\t%g\t%g", elapsed,iters_per_sec);
+ ++dat_col;
+}
+
+void report_end_row(void) {
+ ++dat_row;
+ g_string_append(dat_data,"\n");
+}
+
+void report_gnuplot(void) {
+ fflush(stderr);
+ printf("%s\n%s", dat_header->str, dat_data->str);
+}
+
+
+/*======================================================================
+ * Main
+ */
+int main(int argc, char **argv)
+{
+ char *qid_str="0";
+ gfsmError *err=NULL;
+ int argi;
+ //
+ gfsmAutomaton *fsm=NULL;
+ double elapsed_vanilla;
+#ifdef BENCH_SORTED
+ gfsmAutomaton *fsm_sorted=NULL;
+ double elapsed_sorted;
+#endif
+ gfsmIndexedAutomaton *xfsm=NULL;
+ double elapsed_indexed;
+ gfsmIndexedAutomaton2 *xfsm2=NULL;
+ double elapsed_indexed2;
+
+ //-- sanity check
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [QID(s)...]\n", prog);
+ exit(1);
+ }
+
+ //-- load probabilities & initialize
+ load_label_probs();
+ populate_seek_labels();
+
+ //-- report
+ fprintf(stderr, "%s: count=%lu\n", prog, count_test);
+ fflush(stderr);
+
+ //-- load/create: vanilla
+ fprintf(stderr, "%s: loading vanilla automaton '%s'... ", prog, fsmfile); fflush(stderr);
+ fsm = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(fsm,fsmfile,&err)) {
+ fprintf(stderr,"%s: load failed for '%s': %s\n", prog, fsmfile, (err ? err->message : "?"));
+ exit(3);
+ }
+ fsm->flags.sort_mode = gfsmASMNone;
+ fprintf(stderr, "loaded.\n"); fflush(stderr);
+
+#ifdef BENCH_SORTED
+ //-- load/create: sorted
+ fprintf(stderr, "%s: sorting... ", prog); fflush(stderr);
+ fsm_sorted = gfsm_automaton_clone(fsm);
+ gfsm_automaton_arcsort(fsm_sorted,gfsmASMLower);
+ fprintf(stderr, "sorted.\n"); fflush(stderr);
+#endif
+
+ //-- load/create: indexed
+ fprintf(stderr, "%s: indexing... ", prog); fflush(stderr);
+ xfsm = gfsm_automaton_to_indexed(fsm,NULL);
+ fprintf(stderr, "indexed.\n"); fflush(stderr);
+
+ //-- load/create: indexed2
+ fprintf(stderr, "%s: indexing(2)... ", prog); fflush(stderr);
+ xfsm2 = gfsm_automaton_to_indexed2(fsm,NULL);
+ fprintf(stderr, "indexed.\n"); fflush(stderr);
+
+ //-- main loop
+ for (argi=1; argi < argc; argi++) {
+ qid_str = argv[argi];
+ qid_test = strtol(qid_str,NULL,0);
+ out_degree_test = gfsm_automaton_out_degree(fsm,qid_test);
+
+ report_new_row();
+
+ //-- benchmark: vanilla
+ elapsed_vanilla = bench_seek_vanilla(fsm);
+ report_column("vanilla", elapsed_vanilla);
+
+#ifdef BENCH_SORTED
+ //-- benchmark: vanilla+sorted
+ gfsm_automaton_arcsort(fsm,gfsmASMLower);
+ elapsed_sorted = bench_seek_vanilla(fsm);
+ report_column("sorted", elapsed_sorted);
+#endif
+
+ //-- benchmark: indexed
+ elapsed_indexed = bench_seek_indexed(xfsm);
+ report_column("indexed", elapsed_indexed);
+
+ //-- benchmark: indexed2
+ elapsed_indexed2 = bench_seek_indexed2(xfsm2);
+ report_column("indexed2", elapsed_indexed2);
+
+ report_end_row();
+ }
+
+ //-- gnuplot output
+ report_gnuplot();
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+#ifdef BENCH_SORTED
+ if (fsm_sorted) gfsm_automaton_free(fsm_sorted);
+#endif
+ if (xfsm) gfsm_indexed_automaton_free(xfsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/seektest.dat b/gfsm/gfsm/src/libgfsm/tests/seektest.dat
new file mode 100644
index 0000000..2f05a4b
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/seektest.dat
@@ -0,0 +1,9 @@
+#1:out_deg 2:vanilla_secs 3:vanilla_ips 4:indexed_secs 5:indexed_ips
+1 0.100445 4.17572e+07 0.057384 7.30919e+07
+2 0.108812 3.85463e+07 0.139554 3.00551e+07
+4 0.141588 2.96233e+07 0.148173 2.83068e+07
+8 0.195003 2.15089e+07 0.147859 2.83669e+07
+16 0.292195 1.43545e+07 0.21333 1.96611e+07
+32 0.539624 7.77264e+06 0.328515 1.27675e+07
+64 0.889506 4.71532e+06 0.394453 1.06332e+07
+148 1.79711 2.33392e+06 0.544203 7.70724e+06
diff --git a/gfsm/gfsm/src/libgfsm/tests/settest.c b/gfsm/gfsm/src/libgfsm/tests/settest.c
new file mode 100644
index 0000000..443f4d1
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/settest.c
@@ -0,0 +1,36 @@
+#include <glib.h>
+#include <gfsm.h>
+
+int main (void)
+{
+ gfsmSet *set;
+ GSList *setl;
+ GPtrArray *setary;
+ g_mem_set_vtable(glib_mem_profiler_table);
+
+ set = gfsm_set_new(gfsm_uint_compare);
+ gfsm_set_insert(set,(gpointer)2);
+
+ //gfsm_set_clear(set);
+
+ /*
+ fprintf(stderr,"**** set=");
+ gfsm_set_print_uint(set,stderr);
+ fprintf(stderr,"\n");
+ */
+ //setl = gfsm_set_to_slist(set);
+ //g_slist_free(setl);
+ /*
+ setl = g_slist_prepend(NULL,(gpointer)2);
+ g_slist_free(setl);
+ */
+ setary = g_ptr_array_sized_new(gfsm_set_size(set));
+ gfsm_set_to_ptr_array(set,setary);
+ g_ptr_array_free(setary,TRUE);
+
+ gfsm_set_free(set);
+
+ g_blow_chunks();
+ g_mem_profile();
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/sizes.bc b/gfsm/gfsm/src/libgfsm/tests/sizes.bc
new file mode 100644
index 0000000..28632e4
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/sizes.bc
@@ -0,0 +1,70 @@
+##-*- Mode: Shell-Script -*-
+
+##-- tagh size (carrot)
+tagh_carrot_n_states = 5345565;
+tagh_carrot_n_finals = 1;
+tagh_carrot_n_arcs = 9407741;
+
+##-- test constants (tagh, carrot)
+n_states = tagh_carrot_n_states;
+n_finals = tagh_carrot_n_finals;
+n_arcs = tagh_carrot_n_arcs;
+
+##-- basic type sizes
+size_ptr = 4;
+size_int32 = 4;
+size_float = 4;
+size_arc = 12;
+size_arc_src = 16;
+size_weight = size_float;
+
+##-- vanilla automaton sizes
+define size_vanilla_arcs(n_arcs) { return n_arcs*(size_arc+size_ptr); }
+define size_vanilla_states(n_states,n_finals) {
+ return (n_states*(size_int32+size_ptr)) + (n_finals*(size_float+size_int32));
+}
+define size_vanilla_full(n_states,n_finals,n_arcs) {
+ return size_vanilla_states(n_states,n_finals) + size_vanilla_arcs(n_arcs);
+}
+size_vanilla = size_vanilla_full(n_states,n_finals,n_arcs) / 2^20; ##== 184MB
+
+##-- basic index type sizes
+define size_arctab_ptr(n_arcs) { return (n_arcs*size_ptr); }
+define size_arctab(n_arcs) { return (n_arcs*size_arc); }
+define size_arcfirst(n_states) { return (n_states*size_ptr); }
+define size_finaltab(n_states) { return (n_states*size_weight); }
+define size_bitvec(n_bits) { return (n_bits/8); }
+
+##-- arcindex_ptr: auxilliary index: { arc*[] arc_ptrs_sorted; arc** first; }
+define size_arcindex_ptr_full(n_states,n_finals,n_arcs) {
+ return size_arctab_ptr(n_arcs) + size_arcfirst(n_states);
+}
+size_arcindex_ptr = size_arcindex_ptr_full(n_states,n_finals,n_arcs)/2^20; ##== 56MB
+
+##-- arcindex_tab: copy index: { arc[] arcs_sorted; arc* first; }
+define size_arcindex_tab_full(n_states,n_finals,n_arcs) {
+ return size_arctab(n_arcs) + size_arcfirst(n_states);
+}
+size_arcindex_tab = size_arcindex_tab_full(n_states,n_finals,n_arcs) / 2^20;
+
+##-- fsmtab: copy index: { arc[] arcs_sorted; arc* first; weight[] finals; }
+## --> SMALLEST, likely also MOST EFFICIENT!
+## + w/ finals: 149MB (vs. vanilla 184MB)
+## + w/o finals: 129MB
+define size_fsmtab_full(n_states,n_finals,n_arcs) {
+ return size_arctab(n_arcs) + size_arcfirst(n_states) + size_finaltab(n_states) + size_bitvec(n_states);
+}
+size_fsmtab = size_fsmtab_full(n_states,n_finals,n_arcs) / 2^20; ##== 149MB
+
+##-- fsmbitab: bi-indexed: { arc[] arcs; int32~arc*[] first; weight[] finals; int32[] ix_lo; int32[] ix_hi; }
+define size_ixtab(n_arcs) { return n_arcs*size_int32; }
+define size_fsmbitab_full(n_states,n_finals,n_arcs) {
+ return size_fsmtab_full(n_states,n_finals,n_arcs) + 2*size_ixtab(n_arcs);
+}
+size_fsmbitab = size_fsmbitab_full(n_states,n_finals,n_arcs) / 2^20; ##== 220MB
+
+##-- fsmbitab2: bi-indexed: { arc[] arcs~ix_lo; int32~arc*[] first; weight[] finals; int32[] ix_hi; }
+define size_fsmbitab2_full(n_states,n_finals,n_arcs) {
+ return size_fsmtab_full(n_states,n_finals,n_arcs) + size_ixtab(n_arcs);
+}
+size_fsmbitab2 = size_fsmbitab2_full(n_states,n_finals,n_arcs) / 2^20; ##== 185MB
diff --git a/gfsm/gfsm/src/libgfsm/tests/sizetest.c b/gfsm/gfsm/src/libgfsm/tests/sizetest.c
new file mode 100644
index 0000000..5e09070
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/sizetest.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+typedef struct {
+ int x1 : 1;
+ int x2 : 1;
+ int x3 : 30;
+} tstruc;
+
+int main (void) {
+ int i;
+ tstruc ts;
+
+ printf("sizeof(int)=%ld ; sizeof(tstruc)=%ld\n", sizeof(int), sizeof(tstruc));
+ printf("sizeof(float)=%ld, sizeof(void*)=%ld\n", sizeof(float), sizeof(void*));
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/sltest.c b/gfsm/gfsm/src/libgfsm/tests/sltest.c
new file mode 100644
index 0000000..8567e6a
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/sltest.c
@@ -0,0 +1,25 @@
+#include <glib.h>
+#include <stdio.h>
+
+int main (void) {
+ GSList *sl=NULL;
+ GAllocator *myalloc=NULL;
+
+ g_mem_set_vtable(glib_mem_profiler_table);
+
+ //-- allocator hack
+ myalloc = g_allocator_new("myAllocator", 128);
+ g_slist_push_allocator(myalloc);
+
+ sl = g_slist_prepend(NULL,(gpointer)2);
+ g_slist_free(sl);
+
+ //-- allocator hack
+ g_slist_pop_allocator();
+ g_allocator_free(myalloc);
+
+ g_blow_chunks();
+ g_mem_profile();
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/statetest.tfst b/gfsm/gfsm/src/libgfsm/tests/statetest.tfst
new file mode 100644
index 0000000..175575f
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/statetest.tfst
@@ -0,0 +1,8 @@
+0 1 0 0 0
+0 2 0 0 0
+0 3 0 0 0
+3 4 0 0 0
+0 99 99 99 0
+1
+2
+3
diff --git a/gfsm/gfsm/src/libgfsm/tests/structtest.c b/gfsm/gfsm/src/libgfsm/tests/structtest.c
new file mode 100644
index 0000000..6bb0558
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/structtest.c
@@ -0,0 +1,14 @@
+#include <glib.h>
+#include <stdio.h>
+
+typedef struct {
+ guint32 i1 : 1;
+ guint32 i2 : 31;
+} testme;
+
+int main (void) {
+
+ printf("guint32:%u ; testme=%u\n", sizeof(guint32), sizeof(testme));
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/tagh-lo.testus b/gfsm/gfsm/src/libgfsm/tests/tagh-lo.testus
new file mode 100644
index 0000000..b8eeec7
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/tagh-lo.testus
@@ -0,0 +1,8 @@
+5 out_deg=1
+4 out_deg=2
+11 out_deg=4
+98 out_deg=8
+5257 out_deg=16
+45623 out_deg=32
+290132 out_deg=64
+0 out_deg=148
diff --git a/gfsm/gfsm/src/libgfsm/tests/test-255.lab b/gfsm/gfsm/src/libgfsm/tests/test-255.lab
new file mode 100644
index 0000000..d2ad9fa
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/test-255.lab
@@ -0,0 +1,3 @@
+a 1
+ÿ 2
+b 3
diff --git a/gfsm/gfsm/src/libgfsm/tests/test-stateset.c b/gfsm/gfsm/src/libgfsm/tests/test-stateset.c
new file mode 100644
index 0000000..4e56112
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/test-stateset.c
@@ -0,0 +1,61 @@
+#include <gfsm.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+const char *progname = "test-stateset";
+const char *infilename = "statetest.tfst";
+
+gfsmAutomaton *fsm;
+gfsmError *err = NULL;
+
+gboolean stateset_print_func(gfsmStateId id, gpointer data)
+{
+ printf(" %u", id);
+ return FALSE;
+}
+
+void stateset_print(const char *label, gfsmStateSet *sset)
+{
+ gfsmStateSetIter ssi;
+ gfsmStateId ssid;
+
+ printf("%s: {", label);
+
+ //gfsm_stateset_foreach(sset, stateset_print_func, NULL);
+ for (ssi = gfsm_stateset_iter_begin(sset);
+ (ssid=gfsm_stateset_iter_id(ssi)) != gfsmNoState;
+ ssi = gfsm_stateset_iter_next(sset,ssi))
+ {
+ printf(" %u", ssid);
+ }
+
+ printf(" }\n");
+}
+
+int main (int argc, char **argv) {
+ int i;
+ gfsmStateId id;
+ gfsmStateSet *sset;
+
+ fsm = gfsm_automaton_new();
+ sset = gfsm_stateset_new();
+
+ if (!gfsm_automaton_compile_filename(fsm,infilename,&err)) {
+ g_printerr("%s: compile failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+ printf("%s: compiled test automaton from '%s'\n", *argv, infilename);
+
+ for (i=0; i < argc; i++) {
+ id = strtol(argv[i],NULL,10);
+ gfsm_stateset_clear(sset);
+ gfsm_stateset_populate(sset,fsm,id, gfsmEpsilon, gfsmEpsilon);
+
+ printf("--\nseed=%u\n", id);
+ stateset_print("equiv", sset);
+ }
+
+ gfsm_stateset_free(sset);
+ gfsm_automaton_free(fsm);
+ return 0;
+}
diff --git a/gfsm/gfsm/src/libgfsm/tests/test.lab b/gfsm/gfsm/src/libgfsm/tests/test.lab
new file mode 100644
index 0000000..ff5af08
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/test.lab
@@ -0,0 +1,10 @@
+<epsilon> 0
+a 1
+b 2
+c 3
+d 4
+e 5
+f 6
+foo 42
+bar 43
+baz 44
diff --git a/gfsm/gfsm/src/libgfsm/tests/test.txt b/gfsm/gfsm/src/libgfsm/tests/test.txt
new file mode 100644
index 0000000..c89f586
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/test.txt
@@ -0,0 +1,2 @@
+This is a test.
+This is ONLY a test.
diff --git a/gfsm/gfsm/src/libgfsm/tests/test2.lab b/gfsm/gfsm/src/libgfsm/tests/test2.lab
new file mode 100644
index 0000000..2398dad
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/test2.lab
@@ -0,0 +1,2 @@
+a 1
+b 2
diff --git a/gfsm/gfsm/src/libgfsm/tests/test2.txt b/gfsm/gfsm/src/libgfsm/tests/test2.txt
new file mode 100644
index 0000000..ed2c580
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/test2.txt
@@ -0,0 +1 @@
+a b c \ No newline at end of file
diff --git a/gfsm/gfsm/src/libgfsm/tests/testme.lab b/gfsm/gfsm/src/libgfsm/tests/testme.lab
new file mode 100644
index 0000000..78226ef
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/tests/testme.lab
@@ -0,0 +1,5 @@
+<eps> 0
+a 1
+b 2
+c 3
+answer 42
diff --git a/gfsm/gfsm/src/programs/.cvsignore b/gfsm/gfsm/src/programs/.cvsignore
new file mode 100644
index 0000000..ccc326d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/.cvsignore
@@ -0,0 +1,79 @@
+gfsmindex
+gfsmarith
+gfsmheader
+gfsmoptional
+gfsmreplace
+gfsmsigma
+gfsmarcsort
+gfsmclosure
+gfsmcompile
+gfsmcomplement
+gfsmcompose
+gfsmcompre
+gfsmconcat
+gfsmconnect
+gfsmconvert
+gfsmdeterminize
+gfsmdifference
+gfsmdraw
+gfsminfo
+gfsmintersect
+gfsminvert
+gfsmlabels
+gfsmlookup
+gfsmprint
+gfsmproduct
+gfsmproject
+gfsmprune
+gfsmrenumber
+gfsmreverse
+gfsmrmepsilon
+gfsmstrings
+gfsmunion
+gfsmviterbi
+
+*.out
+*.tmp
+tmp.*
+tmp
+SFST*
+
+*~
+.*~
+*.o
+*.lo
+*.la
+.libs
+*.a
+*.so
+.deps
+*.ps
+*.lfsa
+*.fst
+#*.tfst
+*.fsa
+#*.tfsa
+*.thfst
+*.afst
+*.afsa
+*.gfsa
+*.gfst
+*.dot
+#*.lab
+*.scl
+
+#*_cmdparser.c
+#*_cmdparser.h
+
+argh
+save
+tdata
+
+stamp-h*
+aclocal.m4
+Makefile
+Makefile.in
+README.txt
+configure
+
+ma-dwds-hacks
diff --git a/gfsm/gfsm/src/programs/Makefile.am b/gfsm/gfsm/src/programs/Makefile.am
new file mode 100644
index 0000000..b59e087
--- /dev/null
+++ b/gfsm/gfsm/src/programs/Makefile.am
@@ -0,0 +1,613 @@
+## File: src/programs/Makefile.am
+## Package: gfsm
+## Description:
+## + src-level automake file
+##
+## Process this file with Automake to create Makefile.in.
+##-----------------------------------------------------------------------
+
+##-----------------------------------------------------------------------
+## subdirectories
+##-----------------------------------------------------------------------
+#SUBDIRS =
+
+##-----------------------------------------------------------------------
+## primary targets
+##-----------------------------------------------------------------------
+
+## --- executable programs
+#bin_PROGRAMS = ${prog_1} ... ${prog_N}
+bin_PROGRAMS = \
+ gfsmarcsort \
+ gfsmarith \
+ gfsmclosure \
+ gfsmcompile \
+ gfsmcomplement \
+ gfsmcompose \
+ gfsmcompre \
+ gfsmconcat \
+ gfsmconnect \
+ gfsmconvert \
+ gfsmdeterminize \
+ gfsmdifference \
+ gfsmdraw \
+ gfsmheader \
+ gfsminfo \
+ gfsmintersect \
+ gfsminvert \
+ gfsmlabels \
+ gfsmlookup \
+ gfsmoptional \
+ gfsmprint \
+ gfsmproduct \
+ gfsmproject \
+ gfsmrenumber \
+ gfsmreplace \
+ gfsmreverse \
+ gfsmrmepsilon \
+ gfsmsigma \
+ gfsmstrings \
+ gfsmunion \
+ gfsmviterbi
+
+EXTRA_PROGRAMS = gfsmindex
+bin_PROGRAMS += gfsmindex
+
+EXTRA_DIST =
+
+#bin_SCRIPTS = ${script1} ... ${scriptN}
+
+## --- libtool libraries
+#lib_LTLIBRARIES = ${lib_1}.la ... ${lib_N}.la
+
+## --- shared data in @pkgdatadir@
+#pkgdata_DATA = ${data_1} ... ${data_N}
+
+## --- manpages -- section is auto-detected
+#man_MANS = ${man_1} ... ${man_N}
+
+##-----------------------------------------------------------------------
+## sources
+##-----------------------------------------------------------------------
+
+SUFFIXES = \
+ .gog _cmdparser.c _cmdparser.cc _cmdparser.h \
+ .pod .txt .1 .html .tex
+
+
+##-----------------------------------------------------------------------
+## individual programs
+##-----------------------------------------------------------------------
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+## --- Required sources
+#${prog_i}_SOURCES =
+##
+## --- Extra (possible)sources
+#EXTRA_${prog_i}_SOURCES =
+#EXTRA_${lib_i}_la_SOURCES =
+##
+## --- leftovers
+#mootconfig_SOURCES = mootconfig.cc
+##
+## --- Additional dependencies
+#gfsmcompile_main.o: gfsmcompile_cmdparser.h
+##
+## --- Linker flags
+#${prog_i}_LDFLAGS = -L. -static
+#${prog_i}_LDADD = ${non_src_file}.o -lsomelib
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#gfsmX_SOURCES = \
+# gfsmX_main.c \
+# gfsmX_cmdparser.c gfsmX_cmdparser.h
+#
+#gfsmX_main.o: gfsmX_cmdparser.h
+#
+#gfsmX_LDFLAGS = $(LDFLAGS_COMMON)
+#gfsmX_LDADD = $(LDADD_COMMON)
+#
+#EXTRA_DIST += gfsmX.gog
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmarith_SOURCES = \
+ gfsmarith_main.c \
+ gfsmarith_cmdparser.c gfsmarith_cmdparser.h
+
+gfsmarith_main.o: gfsmarith_cmdparser.h
+
+gfsmarith_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmarith_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmarith.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmcompile_SOURCES = \
+ gfsmcompile_main.c \
+ gfsmcompile_cmdparser.c gfsmcompile_cmdparser.h
+
+gfsmcompile_main.o: gfsmcompile_cmdparser.h
+
+gfsmcompile_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmcompile_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmcompile.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmconvert_SOURCES = \
+ gfsmconvert_main.c \
+ gfsmconvert_cmdparser.c gfsmconvert_cmdparser.h
+
+gfsmconvert_main.o: gfsmconvert_cmdparser.h
+
+gfsmconvert_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmconvert_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmconvert.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmprint_SOURCES = \
+ gfsmprint_main.c \
+ gfsmprint_cmdparser.c gfsmprint_cmdparser.h
+
+gfsmprint_main.o: gfsmprint_cmdparser.h
+
+gfsmprint_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmprint_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmprint.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmindex_SOURCES = \
+ gfsmindex_main.c \
+ gfsmindex_cmdparser.c gfsmindex_cmdparser.h
+
+gfsmindex_main.o: gfsmindex_cmdparser.h
+
+gfsmindex_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmindex_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmindex.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsminfo_SOURCES = \
+ gfsminfo_main.c \
+ gfsminfo_cmdparser.c gfsminfo_cmdparser.h
+
+gfsminfo_main.o: gfsminfo_cmdparser.h
+
+gfsminfo_LDFLAGS = $(LDFLAGS_COMMON)
+gfsminfo_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsminfo.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmarcsort_SOURCES = \
+ gfsmarcsort_main.c \
+ gfsmarcsort_cmdparser.c gfsmarcsort_cmdparser.h
+
+gfsmarcsort_main.o: gfsmarcsort_cmdparser.h
+
+gfsmarcsort_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmarcsort_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmarcsort.gog
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmcomplement_SOURCES = \
+ gfsmcomplement_main.c \
+ gfsmcomplement_cmdparser.c gfsmcomplement_cmdparser.h
+
+gfsmcomplement_main.o: gfsmcomplement_cmdparser.h
+
+gfsmcomplement_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmcomplement_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmcomplement.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmcompose_SOURCES = \
+ gfsmcompose_main.c \
+ gfsmcompose_cmdparser.c gfsmcompose_cmdparser.h
+
+gfsmcompose_main.o: gfsmcompose_cmdparser.h
+
+gfsmcompose_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmcompose_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmcompose.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmcompre_SOURCES = \
+ gfsmcompre_main.c \
+ gfsmcompre_cmdparser.c gfsmcompre_cmdparser.h
+
+gfsmcompre_main.o: gfsmcompre_cmdparser.h
+
+gfsmcompre_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmcompre_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmcompre.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmconcat_SOURCES = \
+ gfsmconcat_main.c \
+ gfsmconcat_cmdparser.c gfsmconcat_cmdparser.h
+
+gfsmconcat_main.o: gfsmconcat_cmdparser.h
+
+gfsmconcat_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmconcat_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmconcat.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmclosure_SOURCES = \
+ gfsmclosure_main.c \
+ gfsmclosure_cmdparser.c gfsmclosure_cmdparser.h
+
+gfsmclosure_main.o: gfsmclosure_cmdparser.h
+
+gfsmclosure_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmclosure_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmclosure.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmconnect_SOURCES = \
+ gfsmconnect_main.c \
+ gfsmconnect_cmdparser.c gfsmconnect_cmdparser.h
+
+gfsmconnect_main.o: gfsmconnect_cmdparser.h
+
+gfsmconnect_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmconnect_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmconnect.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmdeterminize_SOURCES = \
+ gfsmdeterminize_main.c \
+ gfsmdeterminize_cmdparser.c gfsmdeterminize_cmdparser.h
+
+gfsmdeterminize_main.o: gfsmdeterminize_cmdparser.h
+
+gfsmdeterminize_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmdeterminize_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmdeterminize.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmdifference_SOURCES = \
+ gfsmdifference_main.c \
+ gfsmdifference_cmdparser.c gfsmdifference_cmdparser.h
+
+gfsmdifference_main.o: gfsmdifference_cmdparser.h
+
+gfsmdifference_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmdifference_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmdifference.gog
+
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmdraw_SOURCES = \
+ gfsmdraw_main.c \
+ gfsmdraw_cmdparser.c gfsmdraw_cmdparser.h
+
+gfsmdraw_main.o: gfsmdraw_cmdparser.h
+
+gfsmdraw_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmdraw_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmdraw.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmheader_SOURCES = \
+ gfsmheader_main.c \
+ gfsmheader_cmdparser.c gfsmheader_cmdparser.h
+
+gfsmheader_main.o: gfsmheader_cmdparser.h
+
+gfsmheader_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmheader_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmheader.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmintersect_SOURCES = \
+ gfsmintersect_main.c \
+ gfsmintersect_cmdparser.c gfsmintersect_cmdparser.h
+
+gfsmintersect_main.o: gfsmintersect_cmdparser.h
+
+gfsmintersect_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmintersect_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmintersect.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsminvert_SOURCES = \
+ gfsminvert_main.c \
+ gfsminvert_cmdparser.c gfsminvert_cmdparser.h
+
+gfsminvert_main.o: gfsminvert_cmdparser.h
+
+gfsminvert_LDFLAGS = $(LDFLAGS_COMMON)
+gfsminvert_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsminvert.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmlabels_SOURCES = \
+ gfsmlabels_main.c \
+ gfsmlabels_cmdparser.c gfsmlabels_cmdparser.h
+
+gfsmlabels_main.o: gfsmlabels_cmdparser.h
+
+gfsmlabels_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmlabels_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmlabels.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmlookup_SOURCES = \
+ gfsmlookup_main.c \
+ gfsmlookup_cmdparser.c gfsmlookup_cmdparser.h
+
+gfsmlookup_main.o: gfsmlookup_cmdparser.h
+
+gfsmlookup_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmlookup_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmlookup.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmoptional_SOURCES = \
+ gfsmoptional_main.c \
+ gfsmoptional_cmdparser.c gfsmoptional_cmdparser.h
+
+gfsmoptional_main.o: gfsmoptional_cmdparser.h
+
+gfsmoptional_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmoptional_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmoptional.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmproduct_SOURCES = \
+ gfsmproduct_main.c \
+ gfsmproduct_cmdparser.c gfsmproduct_cmdparser.h
+
+gfsmproduct_main.o: gfsmproduct_cmdparser.h
+
+gfsmproduct_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmproduct_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmproduct.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmproject_SOURCES = \
+ gfsmproject_main.c \
+ gfsmproject_cmdparser.c gfsmproject_cmdparser.h
+
+gfsmproject_main.o: gfsmproject_cmdparser.h
+
+gfsmproject_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmproject_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmproject.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmrenumber_SOURCES = \
+ gfsmrenumber_main.c \
+ gfsmrenumber_cmdparser.c gfsmrenumber_cmdparser.h
+
+gfsmrenumber_main.o: gfsmrenumber_cmdparser.h
+
+gfsmrenumber_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmrenumber_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmrenumber.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmreplace_SOURCES = \
+ gfsmreplace_main.c \
+ gfsmreplace_cmdparser.c gfsmreplace_cmdparser.h
+
+gfsmreplace_main.o: gfsmreplace_cmdparser.h
+
+gfsmreplace_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmreplace_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmreplace.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmreverse_SOURCES = \
+ gfsmreverse_main.c \
+ gfsmreverse_cmdparser.c gfsmreverse_cmdparser.h
+
+gfsmreverse_main.o: gfsmreverse_cmdparser.h
+
+gfsmreverse_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmreverse_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmreverse.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmrmepsilon_SOURCES = \
+ gfsmrmepsilon_main.c \
+ gfsmrmepsilon_cmdparser.c gfsmrmepsilon_cmdparser.h
+
+gfsmrmepsilon_main.o: gfsmrmepsilon_cmdparser.h
+
+gfsmrmepsilon_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmrmepsilon_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmrmepsilon.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmsigma_SOURCES = \
+ gfsmsigma_main.c \
+ gfsmsigma_cmdparser.c gfsmsigma_cmdparser.h
+
+gfsmsigma_main.o: gfsmsigma_cmdparser.h
+
+gfsmsigma_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmsigma_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmsigma.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmstrings_SOURCES = \
+ gfsmstrings_main.c \
+ gfsmstrings_cmdparser.c gfsmstrings_cmdparser.h
+
+gfsmstrings_main.o: gfsmstrings_cmdparser.h
+
+gfsmstrings_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmstrings_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmstrings.gog
+
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmunion_SOURCES = \
+ gfsmunion_main.c \
+ gfsmunion_cmdparser.c gfsmunion_cmdparser.h
+
+gfsmunion_main.o: gfsmunion_cmdparser.h
+
+gfsmunion_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmunion_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmunion.gog
+
+##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gfsmviterbi_SOURCES = \
+ gfsmviterbi_main.c \
+ gfsmviterbi_cmdparser.c gfsmviterbi_cmdparser.h
+
+gfsmviterbi_main.o: gfsmviterbi_cmdparser.h
+
+gfsmviterbi_LDFLAGS = $(LDFLAGS_COMMON)
+gfsmviterbi_LDADD = $(LDADD_COMMON)
+
+EXTRA_DIST += gfsmviterbi.gog
+
+##-----------------------------------------------------------------------
+## headers
+##-----------------------------------------------------------------------
+
+## --- installable headers: @includedir@/@pkgname@
+#pkginclude_HEADERS = ${hfile_1} ... ${hfile_N}
+
+## --- no-install headers
+noinst_HEADERS = config.h
+
+##-----------------------------------------------------------------------
+## pre-compile rules: gengetopt
+##-----------------------------------------------------------------------
+
+##-----------------------------------------------------------------------
+## pre-compile rules: Getopt::Gen
+##-----------------------------------------------------------------------
+.SECONDARY:
+
+OPTGENFLAGS = -u -l --no-handle-rcfile
+
+if HAVE_OPTGEN
+
+.gog_cmdparser.h:
+ optgen.perl $(OPTGENFLAGS) --nopod -F $*_cmdparser $<
+
+.gog_cmdparser.c:
+ optgen.perl $(OPTGENFLAGS) --nopod -F $*_cmdparser $<
+
+.gog.pod:
+ optgen.perl $(OPTGENFLAGS) --nocfile --nohfile -F $* $<
+
+endif
+
+##-----------------------------------------------------------------------
+## compile flags
+##-----------------------------------------------------------------------
+
+## --- preprocessor flags
+AM_CPPFLAGS = -I@srcdir@/../libgfsm -I../libgfsm
+
+## --- compiler flags (c++)
+AM_CFLAGS = $(gfsm_WFLAGS) $(gfsm_OFLAGS)
+
+##-----------------------------------------------------------------------
+## linker flags
+## + library special handling of configure.in vars:
+##-----------------------------------------------------------------------
+#${prog_i}_LDFLAGS = -L. -static
+#${prog_i}_LDADD = ${non_src_file}.o -lsomelib
+
+LDFLAGS_COMMON = -L../libgfsm
+LDADD_COMMON = ../libgfsm/libgfsm.la @gfsm_LIBS@
+
+#${lib_i}_la_LDFLAGS = -L. -version-info ${lib_i_current}:${lib_i_rev}:${lib_i_age}
+#${lib_i}_LIBADD = -lotherlib
+
+##-----------------------------------------------------------------------
+## cleanup: fst
+##-----------------------------------------------------------------------
+
+fsmclean:
+ rm -f *.afsa *.afst *.gfsa *.gfst *.thfsa *.thfst
+
+##-----------------------------------------------------------------------
+## Variables: cleanup
+##-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+#CLEANFILES =
+
+## --- distclean: built by 'configure'
+#DISTCLEANFILES =
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = \
+ *~ .*~ Makefile Makefile.in \
+ *.man *.1 *.html *.txt *.tex \
+ *.afsa *.afst *.gfsa *.gfst *.thfst \
+ *.dot *.ps *.vcg
+
+# *_cmdparser.c *_cmdparser.h
+
+##-----------------------------------------------------------------------
+## Variables: distribution
+##-----------------------------------------------------------------------
+
+## --- extra distribution files
+#EXTRA_DIST =
+
+## --- recursion subdirectories for 'make dist'
+#DIST_SUBDIRS = $(SUBDIRS)
+
+## --- dist-hook: when another 'Makefile.am' is overkill
+#DISTHOOK_DIRS = foo
+#DISTHOOK_FILES = foo/bar.txt foo/baz.txt
+#dist-hook:
+# for d in $(DISTHOOK_DIRS); do\
+# mkdir -p $(distdir)/$$d ;\
+# done
+# for f in $(DISTHOOK_FILES); do\
+# cp -p $(srcdir)/$$f $(distdir)/$$f ;\
+# done
+
+##-----------------------------------------------------------------------
+## Rules: cleanup
+##-----------------------------------------------------------------------
+.PHONY: cvsclean
+
+cvsclean: maintainer-clean ;
diff --git a/gfsm/gfsm/src/programs/arith.tfst b/gfsm/gfsm/src/programs/arith.tfst
new file mode 100644
index 0000000..d7e7b72
--- /dev/null
+++ b/gfsm/gfsm/src/programs/arith.tfst
@@ -0,0 +1,9 @@
+0 1 1 1 1
+0 2 2 2 2
+0 3 3 3 -3
+0 4 4 4 inf
+0 0
+1 1
+2 2
+3 -3
+4 inf
diff --git a/gfsm/gfsm/src/programs/c1.tfst b/gfsm/gfsm/src/programs/c1.tfst
new file mode 100644
index 0000000..fef3d10
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c1.tfst
@@ -0,0 +1,5 @@
+0 0 1 2
+0 1 0 0
+1 1 1 3
+0
+1
diff --git a/gfsm/gfsm/src/programs/c2.lab b/gfsm/gfsm/src/programs/c2.lab
new file mode 100644
index 0000000..5288861
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c2.lab
@@ -0,0 +1,11 @@
+<eps> 0
+a 1
+b 2
+A 3
+B 4
+AA 5
+{A|B} 6
+{AA|B} 7
+{} 8
+[e2] 65533
+[e1] 65534
diff --git a/gfsm/gfsm/src/programs/c2.tfst b/gfsm/gfsm/src/programs/c2.tfst
new file mode 100644
index 0000000..c437b71
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c2.tfst
@@ -0,0 +1,4 @@
+0 0 2 3
+0 1 0 0
+1 1 3 1
+0
diff --git a/gfsm/gfsm/src/programs/c2a.tfst b/gfsm/gfsm/src/programs/c2a.tfst
new file mode 100644
index 0000000..d6c5236
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c2a.tfst
@@ -0,0 +1,10 @@
+0 1 a {A|B}
+1 2 <eps> a
+2 3 a {AA|B}
+3 2 <eps> a
+2 4 b {A|B}
+4 0 <eps> b
+0 5 b {A|B}
+5 0 <eps> b
+0
+2
diff --git a/gfsm/gfsm/src/programs/c2b.tfst b/gfsm/gfsm/src/programs/c2b.tfst
new file mode 100644
index 0000000..b16d00e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c2b.tfst
@@ -0,0 +1,22 @@
+0 1 <eps> <eps>
+0 2 <eps> <eps>
+0 3 <eps> <eps>
+3 4 {A|B} B
+3 4 {AA|B} B
+4 1 b <eps>
+2 5 {A|B} A
+2 5 {AA|B} AA
+5 1 a <eps>
+3 6 {A|B} B
+3 6 {AA|B} B
+6 2 b <eps>
+2 7 {A|B} A
+2 7 {AA|B} AA
+7 2 a <eps>
+3 8 {A|B} B
+3 8 {AA|B} B
+8 3 b <eps>
+2 9 {A|B} A
+2 9 {AA|B} AA
+9 3 a <eps>
+1
diff --git a/gfsm/gfsm/src/programs/c3a.tfst b/gfsm/gfsm/src/programs/c3a.tfst
new file mode 100644
index 0000000..d82ca52
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c3a.tfst
@@ -0,0 +1,8 @@
+0 1 a a
+1 0 <eps> A
+0 2 b b
+2 0 <eps> B
+0
+0 0 <eps> <eps1>
+1 1 <eps> <eps1>
+2 2 <eps> <eps1>
diff --git a/gfsm/gfsm/src/programs/c3b.tfst b/gfsm/gfsm/src/programs/c3b.tfst
new file mode 100644
index 0000000..4a4133f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c3b.tfst
@@ -0,0 +1,26 @@
+0 1 <eps1> <eps>
+1
+0 2 <eps1> <eps>
+2 4 a A
+4 1 A <eps>
+2 5 a A
+5 2 A <eps>
+2 6 a A
+6 3 A <eps>
+0 3 <eps1> <eps>
+3 7 b B
+7 1 B <eps>
+3 8 b B
+8 3 B <eps>
+3 9 b B
+9 2 B <eps>
+0 0 <eps2> <eps>
+1 1 <eps2> <eps>
+2 2 <eps2> <eps>
+3 3 <eps2> <eps>
+4 4 <eps2> <eps>
+5 5 <eps2> <eps>
+6 6 <eps2> <eps>
+7 7 <eps2> <eps>
+8 8 <eps2> <eps>
+9 9 <eps2> <eps>
diff --git a/gfsm/gfsm/src/programs/c3filt.tfst b/gfsm/gfsm/src/programs/c3filt.tfst
new file mode 100644
index 0000000..34cc982
--- /dev/null
+++ b/gfsm/gfsm/src/programs/c3filt.tfst
@@ -0,0 +1,20 @@
+0 0 <eps2> <eps1>
+0 0 a a
+0 0 b b
+0 0 A A
+0 0 B B
+0
+0 1 <eps1> <eps1>
+1 1 <eps1> <eps1>
+1 0 a a
+1 0 b b
+1 0 A A
+1 0 B B
+1
+0 2 <eps2> <eps2>
+2 2 <eps2> <eps2>
+2 0 a a
+2 0 b b
+2 0 A A
+2 0 B B
+2
diff --git a/gfsm/gfsm/src/programs/cat1.tfst b/gfsm/gfsm/src/programs/cat1.tfst
new file mode 100644
index 0000000..9a51daf
--- /dev/null
+++ b/gfsm/gfsm/src/programs/cat1.tfst
@@ -0,0 +1,3 @@
+0 1 1 1 1.0
+1 2 2 2 2.0
+2 20
diff --git a/gfsm/gfsm/src/programs/cat2.tfst b/gfsm/gfsm/src/programs/cat2.tfst
new file mode 100644
index 0000000..5e9e740
--- /dev/null
+++ b/gfsm/gfsm/src/programs/cat2.tfst
@@ -0,0 +1,4 @@
+0 1 3 3 30
+0 2 4 4 40
+1 100
+2 200
diff --git a/gfsm/gfsm/src/programs/comp1a.tfst b/gfsm/gfsm/src/programs/comp1a.tfst
new file mode 100644
index 0000000..c98130b
--- /dev/null
+++ b/gfsm/gfsm/src/programs/comp1a.tfst
@@ -0,0 +1,4 @@
+0 1 1 0 0
+1 2 0 0 0
+2 3 0 2 0
+3 0
diff --git a/gfsm/gfsm/src/programs/comp1b.tfst b/gfsm/gfsm/src/programs/comp1b.tfst
new file mode 100644
index 0000000..7818495
--- /dev/null
+++ b/gfsm/gfsm/src/programs/comp1b.tfst
@@ -0,0 +1,4 @@
+0 1 2 0 0
+1 2 0 0 0
+2 3 0 3 0
+3 0
diff --git a/gfsm/gfsm/src/programs/comp2.tfst b/gfsm/gfsm/src/programs/comp2.tfst
new file mode 100644
index 0000000..5eb2b86
--- /dev/null
+++ b/gfsm/gfsm/src/programs/comp2.tfst
@@ -0,0 +1,6 @@
+0 1 1 0 0
+1 2 0 0 0
+2 3 0 0 0
+3 4 0 0 0
+4 5 0 3 0
+5 0
diff --git a/gfsm/gfsm/src/programs/comp2a.tfst b/gfsm/gfsm/src/programs/comp2a.tfst
new file mode 100644
index 0000000..ed416e9
--- /dev/null
+++ b/gfsm/gfsm/src/programs/comp2a.tfst
@@ -0,0 +1,2 @@
+0 1 1 2 0
+1 0
diff --git a/gfsm/gfsm/src/programs/comp2b.tfst b/gfsm/gfsm/src/programs/comp2b.tfst
new file mode 100644
index 0000000..dbf6c01
--- /dev/null
+++ b/gfsm/gfsm/src/programs/comp2b.tfst
@@ -0,0 +1,3 @@
+0 1 2 0 0
+1 2 0 3 0
+2 0
diff --git a/gfsm/gfsm/src/programs/complement-in.tfst b/gfsm/gfsm/src/programs/complement-in.tfst
new file mode 100644
index 0000000..45e1e1b
--- /dev/null
+++ b/gfsm/gfsm/src/programs/complement-in.tfst
@@ -0,0 +1,4 @@
+0 1 1 1
+1 2 2 2
+2 2 2 2
+2 0
diff --git a/gfsm/gfsm/src/programs/compose-mohri-1.tfst b/gfsm/gfsm/src/programs/compose-mohri-1.tfst
new file mode 100644
index 0000000..ebf0277
--- /dev/null
+++ b/gfsm/gfsm/src/programs/compose-mohri-1.tfst
@@ -0,0 +1,5 @@
+0 1 1 1
+1 2 2 0
+2 3 3 0
+3 4 4 4
+4
diff --git a/gfsm/gfsm/src/programs/compose-mohri-2.tfst b/gfsm/gfsm/src/programs/compose-mohri-2.tfst
new file mode 100644
index 0000000..154e266
--- /dev/null
+++ b/gfsm/gfsm/src/programs/compose-mohri-2.tfst
@@ -0,0 +1,4 @@
+0 1 1 4
+1 2 0 5
+2 3 4 1
+3
diff --git a/gfsm/gfsm/src/programs/config.h b/gfsm/gfsm/src/programs/config.h
new file mode 100644
index 0000000..2b1cb3c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/config.h
@@ -0,0 +1,13 @@
+#include <gfsmConfig.h>
+
+/* Define this for verbose memory debugging */
+//#define GFSM_DEBUG_VERBOSE
+
+#ifdef GFSM_DEBUG_VERBOSE
+# include <gfsmDebug.h>
+# define GFSM_INIT gfsm_debug_init();
+# define GFSM_FINISH gfsm_debug_finish(); gfsm_debug_print();
+#else
+# define GFSM_INIT
+# define GFSM_FINISH
+#endif
diff --git a/gfsm/gfsm/src/programs/connect-in.tfst b/gfsm/gfsm/src/programs/connect-in.tfst
new file mode 100644
index 0000000..f160c6c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/connect-in.tfst
@@ -0,0 +1,7 @@
+0 1 0 1
+0 2 0 2
+1 3 1 3
+1 4 1 4
+2 4 2 4
+2 3 2 3
+3
diff --git a/gfsm/gfsm/src/programs/ctest.tfst b/gfsm/gfsm/src/programs/ctest.tfst
new file mode 100644
index 0000000..f160c6c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/ctest.tfst
@@ -0,0 +1,7 @@
+0 1 0 1
+0 2 0 2
+1 3 1 3
+1 4 1 4
+2 4 2 4
+2 3 2 3
+3
diff --git a/gfsm/gfsm/src/programs/ctest2.tfst b/gfsm/gfsm/src/programs/ctest2.tfst
new file mode 100644
index 0000000..b27f50a
--- /dev/null
+++ b/gfsm/gfsm/src/programs/ctest2.tfst
@@ -0,0 +1,6 @@
+0 1 0 1
+0 2 0 2
+1 3 1 3
+1 4 1 4
+2 4 2 4
+2 3 2 3
diff --git a/gfsm/gfsm/src/programs/det.tfst b/gfsm/gfsm/src/programs/det.tfst
new file mode 100644
index 0000000..f93e247
--- /dev/null
+++ b/gfsm/gfsm/src/programs/det.tfst
@@ -0,0 +1,5 @@
+0 1 1 1
+0 2 1 2
+2 3 3 3
+1
+3
diff --git a/gfsm/gfsm/src/programs/determinize-in.tfst b/gfsm/gfsm/src/programs/determinize-in.tfst
new file mode 100644
index 0000000..8a6d556
--- /dev/null
+++ b/gfsm/gfsm/src/programs/determinize-in.tfst
@@ -0,0 +1,7 @@
+0 1 1 1
+0 2 2 2
+0 2 1 1
+2 1 1 1
+2 3 3 3
+1 10
+3 30
diff --git a/gfsm/gfsm/src/programs/elookup.tfst b/gfsm/gfsm/src/programs/elookup.tfst
new file mode 100644
index 0000000..a7a0db1
--- /dev/null
+++ b/gfsm/gfsm/src/programs/elookup.tfst
@@ -0,0 +1,2 @@
+0 0 0 1 0
+0 0
diff --git a/gfsm/gfsm/src/programs/gfsmarcsort.gog b/gfsm/gfsm/src/programs/gfsmarcsort.gog
new file mode 100644
index 0000000..ab827d6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarcsort.gog
@@ -0,0 +1,107 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmarcsort"
+#program_version "0.01"
+
+purpose "Sort arcs of a finite state machine"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+flag "lower" l "Sort by (lower,upper,target) [default]."
+flag - i "Alias for -l"
+
+flag "upper" u "Sort by (upper,lower,target)."
+flag - o "Alias for '-u'"
+
+flag "weight" w "Sort by weight (ascending)."
+flag "cost" C "Alias for '-w'"
+
+string "mode" m "Sort by explicit mode string (overrides -l, -u, etc.)" \
+ arg="MODE" \
+ default="" \
+ details="
+Sort by a mode string over the characters \"luwstLUWST_\", as accepted
+by gfsm_acmask_from_chars(). Each character in the string represents
+a single elementary arc field comparison, and the comparison with the
+highest priority should occur leftmost in the string. Correspondence
+between characters in MODE and arc comparisons is:
+
+ CHAR : COMPARISON
+ l : sort by lower labels in ascending order
+ u : sort by upper labels in ascending order
+ w : sort by arc weight in semiring-ascending order
+ s : sort by source state in ascending order (useless here)
+ t : sort by target state in ascending order
+
+ L : sort by lower labels in descending order
+ U : sort by upper labels in descending order
+ W : sort by arc weight in semiring-descending order
+ S : sort by source state in descending order (useless here)
+ T : sort by target state in descending order
+
+ _ : no comparison at the corresponding priority level
+ x : user-specified comparison (useless here)
+
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.c b/gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.c
new file mode 100644
index 0000000..94f4f16
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.c
@@ -0,0 +1,595 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmarcsort_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.06
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmarcsort_cmdparser gfsmarcsort.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmarcsort"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmarcsort_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmarcsort (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Sort arcs of a finite state machine\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmarcsort");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -l --lower Sort by (lower,upper,target) [default].\n");
+ printf(" -i Alias for -l\n");
+ printf(" -u --upper Sort by (upper,lower,target).\n");
+ printf(" -o Alias for '-u'\n");
+ printf(" -w --weight Sort by weight (ascending).\n");
+ printf(" -C --cost Alias for '-w'\n");
+ printf(" -mMODE --mode=MODE Sort by explicit mode string (overrides -l, -u, etc.)\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->lower_flag = 0;
+ args_info->i_flag = 0;
+ args_info->upper_flag = 0;
+ args_info->o_flag = 0;
+ args_info->weight_flag = 0;
+ args_info->cost_flag = 0;
+ args_info->mode_arg = strdup("");
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->lower_given = 0;
+ args_info->i_given = 0;
+ args_info->upper_given = 0;
+ args_info->o_given = 0;
+ args_info->weight_given = 0;
+ args_info->cost_given = 0;
+ args_info->mode_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "lower", 0, NULL, 'l' },
+ { "upper", 0, NULL, 'u' },
+ { "weight", 0, NULL, 'w' },
+ { "cost", 0, NULL, 'C' },
+ { "mode", 1, NULL, 'm' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'l',
+ 'i',
+ 'u',
+ 'o',
+ 'w',
+ 'C',
+ 'm', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'l': /* Sort by (lower,upper,target) [default]. */
+ if (args_info->lower_given) {
+ fprintf(stderr, "%s: `--lower' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->lower_given++;
+ if (args_info->lower_given <= 1)
+ args_info->lower_flag = !(args_info->lower_flag);
+ break;
+
+ case 'i': /* Alias for -l */
+ if (args_info->i_given) {
+ fprintf(stderr, "%s: (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->i_given++;
+ if (args_info->i_given <= 1)
+ args_info->i_flag = !(args_info->i_flag);
+ break;
+
+ case 'u': /* Sort by (upper,lower,target). */
+ if (args_info->upper_given) {
+ fprintf(stderr, "%s: `--upper' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->upper_given++;
+ if (args_info->upper_given <= 1)
+ args_info->upper_flag = !(args_info->upper_flag);
+ break;
+
+ case 'o': /* Alias for '-u' */
+ if (args_info->o_given) {
+ fprintf(stderr, "%s: (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->o_given++;
+ if (args_info->o_given <= 1)
+ args_info->o_flag = !(args_info->o_flag);
+ break;
+
+ case 'w': /* Sort by weight (ascending). */
+ if (args_info->weight_given) {
+ fprintf(stderr, "%s: `--weight' (`-w') option given more than once\n", PROGRAM);
+ }
+ args_info->weight_given++;
+ if (args_info->weight_given <= 1)
+ args_info->weight_flag = !(args_info->weight_flag);
+ break;
+
+ case 'C': /* Alias for '-w' */
+ if (args_info->cost_given) {
+ fprintf(stderr, "%s: `--cost' (`-C') option given more than once\n", PROGRAM);
+ }
+ args_info->cost_given++;
+ if (args_info->cost_given <= 1)
+ args_info->cost_flag = !(args_info->cost_flag);
+ break;
+
+ case 'm': /* Sort by explicit mode string (overrides -l, -u, etc.) */
+ if (args_info->mode_given) {
+ fprintf(stderr, "%s: `--mode' (`-m') option given more than once\n", PROGRAM);
+ }
+ args_info->mode_given++;
+ if (args_info->mode_arg) free(args_info->mode_arg);
+ args_info->mode_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Sort by (lower,upper,target) [default]. */
+ else if (strcmp(olong, "lower") == 0) {
+ if (args_info->lower_given) {
+ fprintf(stderr, "%s: `--lower' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->lower_given++;
+ if (args_info->lower_given <= 1)
+ args_info->lower_flag = !(args_info->lower_flag);
+ }
+
+ /* Sort by (upper,lower,target). */
+ else if (strcmp(olong, "upper") == 0) {
+ if (args_info->upper_given) {
+ fprintf(stderr, "%s: `--upper' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->upper_given++;
+ if (args_info->upper_given <= 1)
+ args_info->upper_flag = !(args_info->upper_flag);
+ }
+
+ /* Sort by weight (ascending). */
+ else if (strcmp(olong, "weight") == 0) {
+ if (args_info->weight_given) {
+ fprintf(stderr, "%s: `--weight' (`-w') option given more than once\n", PROGRAM);
+ }
+ args_info->weight_given++;
+ if (args_info->weight_given <= 1)
+ args_info->weight_flag = !(args_info->weight_flag);
+ }
+
+ /* Alias for '-w' */
+ else if (strcmp(olong, "cost") == 0) {
+ if (args_info->cost_given) {
+ fprintf(stderr, "%s: `--cost' (`-C') option given more than once\n", PROGRAM);
+ }
+ args_info->cost_given++;
+ if (args_info->cost_given <= 1)
+ args_info->cost_flag = !(args_info->cost_flag);
+ }
+
+ /* Sort by explicit mode string (overrides -l, -u, etc.) */
+ else if (strcmp(olong, "mode") == 0) {
+ if (args_info->mode_given) {
+ fprintf(stderr, "%s: `--mode' (`-m') option given more than once\n", PROGRAM);
+ }
+ args_info->mode_given++;
+ if (args_info->mode_arg) free(args_info->mode_arg);
+ args_info->mode_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.h b/gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.h
new file mode 100644
index 0000000..29f5f6a
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmarcsort_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.06.
+ *
+ */
+
+#ifndef gfsmarcsort_cmdparser_h
+#define gfsmarcsort_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int lower_flag; /* Sort by (lower,upper,target) [default]. (default=0). */
+ int i_flag; /* Alias for -l (default=0). */
+ int upper_flag; /* Sort by (upper,lower,target). (default=0). */
+ int o_flag; /* Alias for '-u' (default=0). */
+ int weight_flag; /* Sort by weight (ascending). (default=0). */
+ int cost_flag; /* Alias for '-w' (default=0). */
+ char * mode_arg; /* Sort by explicit mode string (overrides -l, -u, etc.) (default=). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int lower_given; /* Whether lower was given */
+ int i_given; /* Whether - was given */
+ int upper_given; /* Whether upper was given */
+ int o_given; /* Whether - was given */
+ int weight_given; /* Whether weight was given */
+ int cost_given; /* Whether cost was given */
+ int mode_given; /* Whether mode was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmarcsort_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmarcsort_main.c b/gfsm/gfsm/src/programs/gfsmarcsort_main.c
new file mode 100644
index 0000000..ac3e48f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarcsort_main.c
@@ -0,0 +1,102 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004-2007 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmarcsort_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmarcsort";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs & vars
+gfsmAutomaton *fsm;
+gfsmArcCompMask mode = gfsmASMLower;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- mode?
+ if (args.mode_given) { mode = gfsm_acmask_from_chars(args.mode_arg); }
+ else if (args.lower_given || args.i_given) mode = gfsmASMLower;
+ else if (args.upper_given || args.o_given) mode = gfsmASMUpper;
+ else if (args.weight_given || args.cost_given) mode = gfsmASMWeight;
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- sort
+ gfsm_automaton_arcsort(fsm,mode);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmarith.gog b/gfsm/gfsm/src/programs/gfsmarith.gog
new file mode 100644
index 0000000..b2f14b9
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarith.gog
@@ -0,0 +1,132 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmarith"
+#program_version "0.01"
+
+purpose "Perform an elementary arithmetic operation on automaton weights"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "FSMFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+
+#-------------------------------------------------------
+# Basic Options
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-------------------------------------------------------
+# Operator Selection
+group "Operator Selection"
+
+flag "exp" E "Real exponentiation"
+
+flag "log" L "Real logarithm"
+
+float "multiply" m "Real multiplication by WEIGHT" \
+ arg="WEIGHT"
+
+float "add" a "Real addition of WEIGHT" \
+ arg="WEIGHT"
+
+flag "positive" p "Set real negative weights to zero"
+
+
+float "times" - "Semiring multiplication by WEIGHT" \
+ arg="WEIGHT"
+
+float "plus" - "Semiring addition of WEIGHT" \
+ arg="WEIGHT"
+
+flag "sr-positive" - "Set semiring-negative weights to semiring-zero"
+
+#-------------------------------------------------------
+# Weight Selection
+group "Weight Selection"
+
+flag "no-arcs" A "Exclude arc weights (default: include)"
+
+flag "no-finals" f "Exclude final weights (default: include)"
+
+#flag "potentials" P "Include potentials (default: include)" ##-- what the heck are 'potentials'?
+
+flag "zero" Z "Include semiring-zero weights (default: exclude)"
+
+#-------------------------------------------------------
+# State & Label Selection
+group "State & Label Selection"
+
+flag "initial" i "Select only initial state and its arcs/finality"
+
+int "state" s "Select only state ID and its arcs/finality (default=all)" \
+ arg="ID" \
+ default="-1"
+
+int "lower" l "Select only arcs with lower-label LO (default=any)" \
+ arg="LO" \
+ default="-1"
+
+int "upper" u "Select only arcs with upper-label HI (defualt=any)" \
+ arg="HI" \
+ default="-1"
+
+
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+Note that the --plus and --times operations are
+sensitive to the semiring associated with the stored FSM file, while
+the --add and --multiply operations have the usual real-number interpretations,
+regardless of the automaton semiring.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmarith_cmdparser.c b/gfsm/gfsm/src/programs/gfsmarith_cmdparser.c
new file mode 100644
index 0000000..7aade2f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarith_cmdparser.c
@@ -0,0 +1,773 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmarith_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmarith_cmdparser gfsmarith.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmarith"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmarith_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmarith (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Perform an elementary arithmetic operation on automaton weights\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... FSMFILE\n", "gfsmarith");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" FSMFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+ printf("\n");
+ printf(" Operator Selection:\n");
+ printf(" -E --exp Real exponentiation\n");
+ printf(" -L --log Real logarithm\n");
+ printf(" -mFLOAT --multiply=FLOAT Real multiplication by WEIGHT\n");
+ printf(" -aFLOAT --add=FLOAT Real addition of WEIGHT\n");
+ printf(" -p --positive Set real negative weights to zero\n");
+ printf(" --times=FLOAT Semiring multiplication by WEIGHT\n");
+ printf(" --plus=FLOAT Semiring addition of WEIGHT\n");
+ printf(" --sr-positive Set semiring-negative weights to semiring-zero\n");
+ printf("\n");
+ printf(" Weight Selection:\n");
+ printf(" -A --no-arcs Exclude arc weights (default: include)\n");
+ printf(" -f --no-finals Exclude final weights (default: include)\n");
+ printf(" -Z --zero Include semiring-zero weights (default: exclude)\n");
+ printf("\n");
+ printf(" State & Label Selection:\n");
+ printf(" -i --initial Select only initial state and its arcs/finality\n");
+ printf(" -sID --state=ID Select only state ID and its arcs/finality (default=all)\n");
+ printf(" -lLO --lower=LO Select only arcs with lower-label LO (default=any)\n");
+ printf(" -uHI --upper=HI Select only arcs with upper-label HI (defualt=any)\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+ args_info->exp_flag = 0;
+ args_info->log_flag = 0;
+ args_info->multiply_arg = 0;
+ args_info->add_arg = 0;
+ args_info->positive_flag = 0;
+ args_info->times_arg = 0;
+ args_info->plus_arg = 0;
+ args_info->sr_positive_flag = 0;
+ args_info->no_arcs_flag = 0;
+ args_info->no_finals_flag = 0;
+ args_info->zero_flag = 0;
+ args_info->initial_flag = 0;
+ args_info->state_arg = -1;
+ args_info->lower_arg = -1;
+ args_info->upper_arg = -1;
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+ args_info->exp_given = 0;
+ args_info->log_given = 0;
+ args_info->multiply_given = 0;
+ args_info->add_given = 0;
+ args_info->positive_given = 0;
+ args_info->times_given = 0;
+ args_info->plus_given = 0;
+ args_info->sr_positive_given = 0;
+ args_info->no_arcs_given = 0;
+ args_info->no_finals_given = 0;
+ args_info->zero_given = 0;
+ args_info->initial_given = 0;
+ args_info->state_given = 0;
+ args_info->lower_given = 0;
+ args_info->upper_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { "exp", 0, NULL, 'E' },
+ { "log", 0, NULL, 'L' },
+ { "multiply", 1, NULL, 'm' },
+ { "add", 1, NULL, 'a' },
+ { "positive", 0, NULL, 'p' },
+ { "times", 1, NULL, 0 },
+ { "plus", 1, NULL, 0 },
+ { "sr-positive", 0, NULL, 0 },
+ { "no-arcs", 0, NULL, 'A' },
+ { "no-finals", 0, NULL, 'f' },
+ { "zero", 0, NULL, 'Z' },
+ { "initial", 0, NULL, 'i' },
+ { "state", 1, NULL, 's' },
+ { "lower", 1, NULL, 'l' },
+ { "upper", 1, NULL, 'u' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ 'E',
+ 'L',
+ 'm', ':',
+ 'a', ':',
+ 'p',
+ 'A',
+ 'f',
+ 'Z',
+ 'i',
+ 's', ':',
+ 'l', ':',
+ 'u', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 'E': /* Real exponentiation */
+ if (args_info->exp_given) {
+ fprintf(stderr, "%s: `--exp' (`-E') option given more than once\n", PROGRAM);
+ }
+ args_info->exp_given++;
+ if (args_info->exp_given <= 1)
+ args_info->exp_flag = !(args_info->exp_flag);
+ break;
+
+ case 'L': /* Real logarithm */
+ if (args_info->log_given) {
+ fprintf(stderr, "%s: `--log' (`-L') option given more than once\n", PROGRAM);
+ }
+ args_info->log_given++;
+ if (args_info->log_given <= 1)
+ args_info->log_flag = !(args_info->log_flag);
+ break;
+
+ case 'm': /* Real multiplication by WEIGHT */
+ if (args_info->multiply_given) {
+ fprintf(stderr, "%s: `--multiply' (`-m') option given more than once\n", PROGRAM);
+ }
+ args_info->multiply_given++;
+ args_info->multiply_arg = (float)strtod(val, NULL);
+ break;
+
+ case 'a': /* Real addition of WEIGHT */
+ if (args_info->add_given) {
+ fprintf(stderr, "%s: `--add' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->add_given++;
+ args_info->add_arg = (float)strtod(val, NULL);
+ break;
+
+ case 'p': /* Set real negative weights to zero */
+ if (args_info->positive_given) {
+ fprintf(stderr, "%s: `--positive' (`-p') option given more than once\n", PROGRAM);
+ }
+ args_info->positive_given++;
+ if (args_info->positive_given <= 1)
+ args_info->positive_flag = !(args_info->positive_flag);
+ break;
+
+ case 'A': /* Exclude arc weights (default: include) */
+ if (args_info->no_arcs_given) {
+ fprintf(stderr, "%s: `--no-arcs' (`-A') option given more than once\n", PROGRAM);
+ }
+ args_info->no_arcs_given++;
+ if (args_info->no_arcs_given <= 1)
+ args_info->no_arcs_flag = !(args_info->no_arcs_flag);
+ break;
+
+ case 'f': /* Exclude final weights (default: include) */
+ if (args_info->no_finals_given) {
+ fprintf(stderr, "%s: `--no-finals' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->no_finals_given++;
+ if (args_info->no_finals_given <= 1)
+ args_info->no_finals_flag = !(args_info->no_finals_flag);
+ break;
+
+ case 'Z': /* Include semiring-zero weights (default: exclude) */
+ if (args_info->zero_given) {
+ fprintf(stderr, "%s: `--zero' (`-Z') option given more than once\n", PROGRAM);
+ }
+ args_info->zero_given++;
+ if (args_info->zero_given <= 1)
+ args_info->zero_flag = !(args_info->zero_flag);
+ break;
+
+ case 'i': /* Select only initial state and its arcs/finality */
+ if (args_info->initial_given) {
+ fprintf(stderr, "%s: `--initial' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->initial_given++;
+ if (args_info->initial_given <= 1)
+ args_info->initial_flag = !(args_info->initial_flag);
+ break;
+
+ case 's': /* Select only state ID and its arcs/finality (default=all) */
+ if (args_info->state_given) {
+ fprintf(stderr, "%s: `--state' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->state_given++;
+ args_info->state_arg = (int)atoi(val);
+ break;
+
+ case 'l': /* Select only arcs with lower-label LO (default=any) */
+ if (args_info->lower_given) {
+ fprintf(stderr, "%s: `--lower' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->lower_given++;
+ args_info->lower_arg = (int)atoi(val);
+ break;
+
+ case 'u': /* Select only arcs with upper-label HI (defualt=any) */
+ if (args_info->upper_given) {
+ fprintf(stderr, "%s: `--upper' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->upper_given++;
+ args_info->upper_arg = (int)atoi(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ /* Real exponentiation */
+ else if (strcmp(olong, "exp") == 0) {
+ if (args_info->exp_given) {
+ fprintf(stderr, "%s: `--exp' (`-E') option given more than once\n", PROGRAM);
+ }
+ args_info->exp_given++;
+ if (args_info->exp_given <= 1)
+ args_info->exp_flag = !(args_info->exp_flag);
+ }
+
+ /* Real logarithm */
+ else if (strcmp(olong, "log") == 0) {
+ if (args_info->log_given) {
+ fprintf(stderr, "%s: `--log' (`-L') option given more than once\n", PROGRAM);
+ }
+ args_info->log_given++;
+ if (args_info->log_given <= 1)
+ args_info->log_flag = !(args_info->log_flag);
+ }
+
+ /* Real multiplication by WEIGHT */
+ else if (strcmp(olong, "multiply") == 0) {
+ if (args_info->multiply_given) {
+ fprintf(stderr, "%s: `--multiply' (`-m') option given more than once\n", PROGRAM);
+ }
+ args_info->multiply_given++;
+ args_info->multiply_arg = (float)strtod(val, NULL);
+ }
+
+ /* Real addition of WEIGHT */
+ else if (strcmp(olong, "add") == 0) {
+ if (args_info->add_given) {
+ fprintf(stderr, "%s: `--add' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->add_given++;
+ args_info->add_arg = (float)strtod(val, NULL);
+ }
+
+ /* Set real negative weights to zero */
+ else if (strcmp(olong, "positive") == 0) {
+ if (args_info->positive_given) {
+ fprintf(stderr, "%s: `--positive' (`-p') option given more than once\n", PROGRAM);
+ }
+ args_info->positive_given++;
+ if (args_info->positive_given <= 1)
+ args_info->positive_flag = !(args_info->positive_flag);
+ }
+
+ /* Semiring multiplication by WEIGHT */
+ else if (strcmp(olong, "times") == 0) {
+ if (args_info->times_given) {
+ fprintf(stderr, "%s: `--times' option given more than once\n", PROGRAM);
+ }
+ args_info->times_given++;
+ args_info->times_arg = (float)strtod(val, NULL);
+ }
+
+ /* Semiring addition of WEIGHT */
+ else if (strcmp(olong, "plus") == 0) {
+ if (args_info->plus_given) {
+ fprintf(stderr, "%s: `--plus' option given more than once\n", PROGRAM);
+ }
+ args_info->plus_given++;
+ args_info->plus_arg = (float)strtod(val, NULL);
+ }
+
+ /* Set semiring-negative weights to semiring-zero */
+ else if (strcmp(olong, "sr-positive") == 0) {
+ if (args_info->sr_positive_given) {
+ fprintf(stderr, "%s: `--sr-positive' option given more than once\n", PROGRAM);
+ }
+ args_info->sr_positive_given++;
+ if (args_info->sr_positive_given <= 1)
+ args_info->sr_positive_flag = !(args_info->sr_positive_flag);
+ }
+
+ /* Exclude arc weights (default: include) */
+ else if (strcmp(olong, "no-arcs") == 0) {
+ if (args_info->no_arcs_given) {
+ fprintf(stderr, "%s: `--no-arcs' (`-A') option given more than once\n", PROGRAM);
+ }
+ args_info->no_arcs_given++;
+ if (args_info->no_arcs_given <= 1)
+ args_info->no_arcs_flag = !(args_info->no_arcs_flag);
+ }
+
+ /* Exclude final weights (default: include) */
+ else if (strcmp(olong, "no-finals") == 0) {
+ if (args_info->no_finals_given) {
+ fprintf(stderr, "%s: `--no-finals' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->no_finals_given++;
+ if (args_info->no_finals_given <= 1)
+ args_info->no_finals_flag = !(args_info->no_finals_flag);
+ }
+
+ /* Include semiring-zero weights (default: exclude) */
+ else if (strcmp(olong, "zero") == 0) {
+ if (args_info->zero_given) {
+ fprintf(stderr, "%s: `--zero' (`-Z') option given more than once\n", PROGRAM);
+ }
+ args_info->zero_given++;
+ if (args_info->zero_given <= 1)
+ args_info->zero_flag = !(args_info->zero_flag);
+ }
+
+ /* Select only initial state and its arcs/finality */
+ else if (strcmp(olong, "initial") == 0) {
+ if (args_info->initial_given) {
+ fprintf(stderr, "%s: `--initial' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->initial_given++;
+ if (args_info->initial_given <= 1)
+ args_info->initial_flag = !(args_info->initial_flag);
+ }
+
+ /* Select only state ID and its arcs/finality (default=all) */
+ else if (strcmp(olong, "state") == 0) {
+ if (args_info->state_given) {
+ fprintf(stderr, "%s: `--state' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->state_given++;
+ args_info->state_arg = (int)atoi(val);
+ }
+
+ /* Select only arcs with lower-label LO (default=any) */
+ else if (strcmp(olong, "lower") == 0) {
+ if (args_info->lower_given) {
+ fprintf(stderr, "%s: `--lower' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->lower_given++;
+ args_info->lower_arg = (int)atoi(val);
+ }
+
+ /* Select only arcs with upper-label HI (defualt=any) */
+ else if (strcmp(olong, "upper") == 0) {
+ if (args_info->upper_given) {
+ fprintf(stderr, "%s: `--upper' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->upper_given++;
+ args_info->upper_arg = (int)atoi(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmarith_cmdparser.h b/gfsm/gfsm/src/programs/gfsmarith_cmdparser.h
new file mode 100644
index 0000000..0f8b5c4
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarith_cmdparser.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmarith_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmarith_cmdparser_h
+#define gfsmarith_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+ int exp_flag; /* Real exponentiation (default=0). */
+ int log_flag; /* Real logarithm (default=0). */
+ float multiply_arg; /* Real multiplication by WEIGHT (default=0). */
+ float add_arg; /* Real addition of WEIGHT (default=0). */
+ int positive_flag; /* Set real negative weights to zero (default=0). */
+ float times_arg; /* Semiring multiplication by WEIGHT (default=0). */
+ float plus_arg; /* Semiring addition of WEIGHT (default=0). */
+ int sr_positive_flag; /* Set semiring-negative weights to semiring-zero (default=0). */
+ int no_arcs_flag; /* Exclude arc weights (default: include) (default=0). */
+ int no_finals_flag; /* Exclude final weights (default: include) (default=0). */
+ int zero_flag; /* Include semiring-zero weights (default: exclude) (default=0). */
+ int initial_flag; /* Select only initial state and its arcs/finality (default=0). */
+ int state_arg; /* Select only state ID and its arcs/finality (default=all) (default=-1). */
+ int lower_arg; /* Select only arcs with lower-label LO (default=any) (default=-1). */
+ int upper_arg; /* Select only arcs with upper-label HI (defualt=any) (default=-1). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+ int exp_given; /* Whether exp was given */
+ int log_given; /* Whether log was given */
+ int multiply_given; /* Whether multiply was given */
+ int add_given; /* Whether add was given */
+ int positive_given; /* Whether positive was given */
+ int times_given; /* Whether times was given */
+ int plus_given; /* Whether plus was given */
+ int sr_positive_given; /* Whether sr-positive was given */
+ int no_arcs_given; /* Whether no-arcs was given */
+ int no_finals_given; /* Whether no-finals was given */
+ int zero_given; /* Whether zero was given */
+ int initial_given; /* Whether initial was given */
+ int state_given; /* Whether state was given */
+ int lower_given; /* Whether lower was given */
+ int upper_given; /* Whether upper was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmarith_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmarith_main.c b/gfsm/gfsm/src/programs/gfsmarith_main.c
new file mode 100644
index 0000000..53f5708
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmarith_main.c
@@ -0,0 +1,132 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gfsm.h>
+
+#include "gfsmarith_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmarith";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+gfsmError *err = NULL;
+
+//-- arithmetic operation
+gfsmArithOp op=gfsmAONone;
+gfsmWeight arg=0;
+
+//-- weight selection
+gboolean do_arcs;
+gboolean do_finals;
+gboolean do_zero;
+
+//-- state & label selection
+gfsmStateId qid;
+gfsmLabelVal lo;
+gfsmLabelVal hi;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ outfilename = args.output_arg;
+
+ //-- operator selection
+ if (args.exp_given) { op = gfsmAOExp; }
+ else if (args.log_given) { op = gfsmAOLog; }
+ else if (args.multiply_given) { op = gfsmAOMult; arg=args.multiply_arg; }
+ else if (args.add_given) { op = gfsmAOAdd; arg=args.add_arg; }
+ else if (args.positive_given) { op = gfsmAONoNeg; }
+ else if (args.times_given) { op = gfsmAOSRTimes; arg=args.times_arg; }
+ else if (args.plus_given) { op = gfsmAOSRPlus; arg=args.plus_arg; }
+ else if (args.sr_positive_given) { op = gfsmAOSRNoNeg; }
+
+ //-- weight selection
+ do_arcs = !args.no_arcs_given;
+ do_finals = !args.no_finals_given;
+ do_zero = args.zero_given;
+
+ //-- state & label selection
+ qid = args.state_given ? args.state_arg : gfsmNoState;
+ lo = args.lower_given ? args.lower_arg : gfsmNoLabel;
+ hi = args.upper_given ? args.upper_arg : gfsmNoLabel;
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(3);
+ }
+
+ //-- hack: initial-state selection
+ if (args.initial_flag) qid=fsm->root_id;
+
+ //-- perform weight aritmetic
+ gfsm_automaton_arith_state(fsm, qid, op, arg, lo, hi, do_arcs, do_finals, do_zero);
+
+ //-- store automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmclosure.gog b/gfsm/gfsm/src/programs/gfsmclosure.gog
new file mode 100644
index 0000000..77b5884
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmclosure.gog
@@ -0,0 +1,79 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmclosure"
+#program_version "0.01"
+
+purpose "Compute Kleene closure of a finite state machine"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "times" n "Compute n-ary (^n) closure." \
+ arg="N" \
+ default="0"
+
+flag "plus" p "Compute transitive (+) closure." \
+ details="
+Alias for '-n 1'.
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmclosure_cmdparser.c b/gfsm/gfsm/src/programs/gfsmclosure_cmdparser.c
new file mode 100644
index 0000000..11f7bfd
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmclosure_cmdparser.c
@@ -0,0 +1,495 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmclosure_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmclosure_cmdparser gfsmclosure.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmclosure"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmclosure_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmclosure (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compute Kleene closure of a finite state machine\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmclosure");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -nN --times=N Compute n-ary (^n) closure.\n");
+ printf(" -p --plus Compute transitive (+) closure.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->times_arg = 0;
+ args_info->plus_flag = 0;
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->times_given = 0;
+ args_info->plus_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "times", 1, NULL, 'n' },
+ { "plus", 0, NULL, 'p' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'n', ':',
+ 'p',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'n': /* Compute n-ary (^n) closure. */
+ if (args_info->times_given) {
+ fprintf(stderr, "%s: `--times' (`-n') option given more than once\n", PROGRAM);
+ }
+ args_info->times_given++;
+ args_info->times_arg = (int)atoi(val);
+ break;
+
+ case 'p': /* Compute transitive (+) closure. */
+ if (args_info->plus_given) {
+ fprintf(stderr, "%s: `--plus' (`-p') option given more than once\n", PROGRAM);
+ }
+ args_info->plus_given++;
+ if (args_info->plus_given <= 1)
+ args_info->plus_flag = !(args_info->plus_flag);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Compute n-ary (^n) closure. */
+ else if (strcmp(olong, "times") == 0) {
+ if (args_info->times_given) {
+ fprintf(stderr, "%s: `--times' (`-n') option given more than once\n", PROGRAM);
+ }
+ args_info->times_given++;
+ args_info->times_arg = (int)atoi(val);
+ }
+
+ /* Compute transitive (+) closure. */
+ else if (strcmp(olong, "plus") == 0) {
+ if (args_info->plus_given) {
+ fprintf(stderr, "%s: `--plus' (`-p') option given more than once\n", PROGRAM);
+ }
+ args_info->plus_given++;
+ if (args_info->plus_given <= 1)
+ args_info->plus_flag = !(args_info->plus_flag);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmclosure_cmdparser.h b/gfsm/gfsm/src/programs/gfsmclosure_cmdparser.h
new file mode 100644
index 0000000..0837b6a
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmclosure_cmdparser.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmclosure_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmclosure_cmdparser_h
+#define gfsmclosure_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int times_arg; /* Compute n-ary (^n) closure. (default=0). */
+ int plus_flag; /* Compute transitive (+) closure. (default=0). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int times_given; /* Whether times was given */
+ int plus_given; /* Whether plus was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmclosure_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmclosure_main.c b/gfsm/gfsm/src/programs/gfsmclosure_main.c
new file mode 100644
index 0000000..8b8d029
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmclosure_main.c
@@ -0,0 +1,100 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmclosure_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmclosure";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsm=NULL;
+guint times = 0;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- get closure length
+ if (args.plus_given) times = 1;
+ else times = args.times_arg;
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- compute closure
+ gfsm_automaton_n_closure(fsm, times);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcompile.gog b/gfsm/gfsm/src/programs/gfsmcompile.gog
new file mode 100644
index 0000000..e53307b
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompile.gog
@@ -0,0 +1,102 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmcompile"
+#program_version "0.01"
+
+purpose "Compile text format gfsm files to binary"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "TXTFILE" "Input text file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#argument "BINFILE" "Output binary gfsm file" \
+# details="
+#If unspecified, output will be written to standard output.
+#"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+flag "acceptor" a "Compile as acceptor (default=transducer)" \
+ default=0
+
+string "ilabels" i "Specify input (lower) labels file." \
+ arg="LABELS"
+
+string "olabels" o "Specify output (upper) labels file." \
+ arg="LABELS"
+
+string "slabels" S "Specify state labels file." \
+ arg="LABELS"
+
+string "semiring" s "Specify semiring type." \
+ arg="SRTYPE" \
+ default="tropical" \
+ details="
+Specify one of the following:
+
+ boolean
+ log
+ plog
+ real
+ trivial
+ tropical
+
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmcompile_cmdparser.c b/gfsm/gfsm/src/programs/gfsmcompile_cmdparser.c
new file mode 100644
index 0000000..ea17d5d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompile_cmdparser.c
@@ -0,0 +1,569 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcompile_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmcompile_cmdparser gfsmcompile.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmcompile"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmcompile_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmcompile (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compile text format gfsm files to binary\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... TXTFILE\n", "gfsmcompile");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" TXTFILE Input text file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -a --acceptor Compile as acceptor (default=transducer)\n");
+ printf(" -iLABELS --ilabels=LABELS Specify input (lower) labels file.\n");
+ printf(" -oLABELS --olabels=LABELS Specify output (upper) labels file.\n");
+ printf(" -SLABELS --slabels=LABELS Specify state labels file.\n");
+ printf(" -sSRTYPE --semiring=SRTYPE Specify semiring type.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->acceptor_flag = 0;
+ args_info->ilabels_arg = NULL;
+ args_info->olabels_arg = NULL;
+ args_info->slabels_arg = NULL;
+ args_info->semiring_arg = strdup("tropical");
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->acceptor_given = 0;
+ args_info->ilabels_given = 0;
+ args_info->olabels_given = 0;
+ args_info->slabels_given = 0;
+ args_info->semiring_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "acceptor", 0, NULL, 'a' },
+ { "ilabels", 1, NULL, 'i' },
+ { "olabels", 1, NULL, 'o' },
+ { "slabels", 1, NULL, 'S' },
+ { "semiring", 1, NULL, 's' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'a',
+ 'i', ':',
+ 'o', ':',
+ 'S', ':',
+ 's', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'a': /* Compile as acceptor (default=transducer) */
+ if (args_info->acceptor_given) {
+ fprintf(stderr, "%s: `--acceptor' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->acceptor_given++;
+ if (args_info->acceptor_given <= 1)
+ args_info->acceptor_flag = !(args_info->acceptor_flag);
+ break;
+
+ case 'i': /* Specify input (lower) labels file. */
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ break;
+
+ case 'o': /* Specify output (upper) labels file. */
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ break;
+
+ case 'S': /* Specify state labels file. */
+ if (args_info->slabels_given) {
+ fprintf(stderr, "%s: `--slabels' (`-S') option given more than once\n", PROGRAM);
+ }
+ args_info->slabels_given++;
+ if (args_info->slabels_arg) free(args_info->slabels_arg);
+ args_info->slabels_arg = strdup(val);
+ break;
+
+ case 's': /* Specify semiring type. */
+ if (args_info->semiring_given) {
+ fprintf(stderr, "%s: `--semiring' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->semiring_given++;
+ if (args_info->semiring_arg) free(args_info->semiring_arg);
+ args_info->semiring_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Compile as acceptor (default=transducer) */
+ else if (strcmp(olong, "acceptor") == 0) {
+ if (args_info->acceptor_given) {
+ fprintf(stderr, "%s: `--acceptor' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->acceptor_given++;
+ if (args_info->acceptor_given <= 1)
+ args_info->acceptor_flag = !(args_info->acceptor_flag);
+ }
+
+ /* Specify input (lower) labels file. */
+ else if (strcmp(olong, "ilabels") == 0) {
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ }
+
+ /* Specify output (upper) labels file. */
+ else if (strcmp(olong, "olabels") == 0) {
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ }
+
+ /* Specify state labels file. */
+ else if (strcmp(olong, "slabels") == 0) {
+ if (args_info->slabels_given) {
+ fprintf(stderr, "%s: `--slabels' (`-S') option given more than once\n", PROGRAM);
+ }
+ args_info->slabels_given++;
+ if (args_info->slabels_arg) free(args_info->slabels_arg);
+ args_info->slabels_arg = strdup(val);
+ }
+
+ /* Specify semiring type. */
+ else if (strcmp(olong, "semiring") == 0) {
+ if (args_info->semiring_given) {
+ fprintf(stderr, "%s: `--semiring' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->semiring_given++;
+ if (args_info->semiring_arg) free(args_info->semiring_arg);
+ args_info->semiring_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcompile_cmdparser.h b/gfsm/gfsm/src/programs/gfsmcompile_cmdparser.h
new file mode 100644
index 0000000..53c4d59
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompile_cmdparser.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcompile_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmcompile_cmdparser_h
+#define gfsmcompile_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int acceptor_flag; /* Compile as acceptor (default=transducer) (default=0). */
+ char * ilabels_arg; /* Specify input (lower) labels file. (default=NULL). */
+ char * olabels_arg; /* Specify output (upper) labels file. (default=NULL). */
+ char * slabels_arg; /* Specify state labels file. (default=NULL). */
+ char * semiring_arg; /* Specify semiring type. (default=tropical). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int acceptor_given; /* Whether acceptor was given */
+ int ilabels_given; /* Whether ilabels was given */
+ int olabels_given; /* Whether olabels was given */
+ int slabels_given; /* Whether slabels was given */
+ int semiring_given; /* Whether semiring was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmcompile_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmcompile_main.c b/gfsm/gfsm/src/programs/gfsmcompile_main.c
new file mode 100644
index 0000000..feeba69
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompile_main.c
@@ -0,0 +1,132 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gfsm.h>
+
+#include "gfsmcompile_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmcompile";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+gfsmAlphabet *ilabels=NULL, *olabels=NULL, *slabels=NULL;
+gfsmError *err = NULL;
+gfsmSRType srtype = gfsmSRTUnknown;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ outfilename = args.output_arg;
+
+ //-- labels: input
+ if (args.ilabels_given) {
+ ilabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(ilabels,args.ilabels_arg,&err)) {
+ g_printerr("%s: load failed for input-labels file '%s': %s\n",
+ progname, args.ilabels_arg, err->message);
+ exit(2);
+ }
+ }
+ //-- labels: output
+ if (args.olabels_given) {
+ olabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(olabels,args.olabels_arg,&err)) {
+ g_printerr("%s: load failed for output-labels file '%s': %s\n",
+ progname, args.olabels_arg, err->message);
+ exit(2);
+ }
+ }
+ //-- labels: state
+ if (args.slabels_given) {
+ slabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(slabels,args.slabels_arg,&err)) {
+ g_printerr("%s: load failed for state-labels file '%s': %s\n",
+ progname, args.slabels_arg, err->message);
+ exit(2);
+ }
+ }
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+ if (args.acceptor_given) fsm->flags.is_transducer = FALSE;
+
+ //-- set semiring
+ srtype = gfsm_sr_name_to_type(args.semiring_arg);
+ if (srtype != fsm->sr->type) {
+ gfsm_automaton_set_semiring(fsm, gfsm_semiring_new(srtype));
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- compile automaton
+ if (!gfsm_automaton_compile_filename_full(fsm,infilename,ilabels,olabels,slabels,&err)) {
+ g_printerr("%s: compile failed for '%s': %s\n", progname, infilename, err->message);
+ exit(3);
+ }
+
+ //-- store automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (ilabels) gfsm_alphabet_free(ilabels);
+ if (olabels) gfsm_alphabet_free(olabels);
+ if (slabels) gfsm_alphabet_free(slabels);
+ gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcomplement.gog b/gfsm/gfsm/src/programs/gfsmcomplement.gog
new file mode 100644
index 0000000..7712b3c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcomplement.gog
@@ -0,0 +1,73 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmcomplement"
+#program_version "0.01"
+
+purpose "Compute complement of finite state acceptors"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+string "ilabels" i "Specify input (lower) labels file for alphabet." \
+ arg="LABELS"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+Epsilon arcs are not handled correctly.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.c b/gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.c
new file mode 100644
index 0000000..d697579
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.c
@@ -0,0 +1,473 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcomplement_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmcomplement_cmdparser gfsmcomplement.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmcomplement"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmcomplement_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmcomplement (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compute complement of finite state acceptors\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmcomplement");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -iLABELS --ilabels=LABELS Specify input (lower) labels file for alphabet.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->ilabels_arg = NULL;
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->ilabels_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "ilabels", 1, NULL, 'i' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'i', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'i': /* Specify input (lower) labels file for alphabet. */
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify input (lower) labels file for alphabet. */
+ else if (strcmp(olong, "ilabels") == 0) {
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.h b/gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.h
new file mode 100644
index 0000000..4b3d57d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcomplement_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmcomplement_cmdparser_h
+#define gfsmcomplement_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * ilabels_arg; /* Specify input (lower) labels file for alphabet. (default=NULL). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int ilabels_given; /* Whether ilabels was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmcomplement_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmcomplement_main.c b/gfsm/gfsm/src/programs/gfsmcomplement_main.c
new file mode 100644
index 0000000..227b963
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcomplement_main.c
@@ -0,0 +1,105 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmcomplement_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmcomplement";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+gfsmAlphabet *ilabels=NULL;
+gfsmError *err=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- labels: input
+ if (args.ilabels_given) {
+ ilabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(ilabels,args.ilabels_arg,&err)) {
+ g_printerr("%s: load failed for input-labels file '%s': %s\n",
+ progname, args.ilabels_arg, err->message);
+ exit(2);
+ }
+ }
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- complement
+ if (ilabels) gfsm_automaton_complement_full(fsm,ilabels);
+ else gfsm_automaton_complement(fsm);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (ilabels) gfsm_alphabet_free(ilabels);
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcompose.gog b/gfsm/gfsm/src/programs/gfsmcompose.gog
new file mode 100644
index 0000000..c4e34f3
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompose.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmcompose"
+#program_version "0.01"
+
+purpose "Compute composition of finite-state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE(s)" "Stored binary gfsm file(s)" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+Probably many.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmcompose_cmdparser.c b/gfsm/gfsm/src/programs/gfsmcompose_cmdparser.c
new file mode 100644
index 0000000..5a82199
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompose_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcompose_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmcompose_cmdparser gfsmcompose.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmcompose"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmcompose_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmcompose (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compute composition of finite-state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE(s)\n", "gfsmcompose");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE(s) Stored binary gfsm file(s)\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcompose_cmdparser.h b/gfsm/gfsm/src/programs/gfsmcompose_cmdparser.h
new file mode 100644
index 0000000..a99342e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompose_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcompose_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmcompose_cmdparser_h
+#define gfsmcompose_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmcompose_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmcompose_main.c b/gfsm/gfsm/src/programs/gfsmcompose_main.c
new file mode 100644
index 0000000..232c5e6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompose_main.c
@@ -0,0 +1,123 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005-2007 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmcompose_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmcompose";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename;
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsmOut=NULL, *fsmIn=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- require at least one file argument
+ if (args.inputs_num < 1) {
+ cmdline_parser_print_help();
+ exit(2);
+ }
+
+ //-- output
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsmIn = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * compute_operation()
+ * + utility routine
+ */
+void compute_operation(const char *infilename)
+{
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsmIn,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- compute underlying FSM operation
+ if (fsmOut == NULL) {
+ fsmOut = fsmIn;
+ fsmIn = gfsm_automaton_new();
+ } else {
+ gfsm_automaton_compose(fsmOut,fsmIn);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ int i;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ for (i = 0; i < args.inputs_num; i++) {
+ compute_operation(args.inputs[i]);
+ }
+ if (args.inputs_num == 1) compute_operation("-");
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsmOut,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsmIn) gfsm_automaton_free(fsmIn);
+ if (fsmOut) gfsm_automaton_free(fsmOut);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcompre.gog b/gfsm/gfsm/src/programs/gfsmcompre.gog
new file mode 100644
index 0000000..7e4058f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompre.gog
@@ -0,0 +1,94 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmcompre"
+#program_version "0.01"
+
+purpose "Compile an automaton from a regular expression"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+#argument "LABELID..." "Input label IDs" \
+# details="
+#In ASCII decimal notation.
+#"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+string "labels" l "Basic label alphabet" \
+ arg="LABFILE"
+
+string "regex" s "Regular expression to compile" \
+ arg="REGEX"
+
+flag "string" x "Compile as string, not regex" \
+ default=0
+
+string "semiring" r "Specify semiring type" \
+ arg="SRTYPE" \
+ default="tropical" \
+ details="
+Specify one of the following:
+
+ boolean
+ log
+ plog
+ real
+ trivial
+ tropical
+
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmcompre_cmdparser.c b/gfsm/gfsm/src/programs/gfsmcompre_cmdparser.c
new file mode 100644
index 0000000..75f5810
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompre_cmdparser.c
@@ -0,0 +1,542 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcompre_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmcompre_cmdparser gfsmcompre.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmcompre"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmcompre_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmcompre (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compile an automaton from a regular expression\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... [FILES]...\n", "gfsmcompre");
+
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -lLABFILE --labels=LABFILE Basic label alphabet\n");
+ printf(" -sREGEX --regex=REGEX Regular expression to compile\n");
+ printf(" -x --string Compile as string, not regex\n");
+ printf(" -rSRTYPE --semiring=SRTYPE Specify semiring type\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->labels_arg = NULL;
+ args_info->regex_arg = NULL;
+ args_info->string_flag = 0;
+ args_info->semiring_arg = strdup("tropical");
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->labels_given = 0;
+ args_info->regex_given = 0;
+ args_info->string_given = 0;
+ args_info->semiring_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "labels", 1, NULL, 'l' },
+ { "regex", 1, NULL, 's' },
+ { "string", 0, NULL, 'x' },
+ { "semiring", 1, NULL, 'r' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'l', ':',
+ 's', ':',
+ 'x',
+ 'r', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'l': /* Basic label alphabet */
+ if (args_info->labels_given) {
+ fprintf(stderr, "%s: `--labels' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->labels_given++;
+ if (args_info->labels_arg) free(args_info->labels_arg);
+ args_info->labels_arg = strdup(val);
+ break;
+
+ case 's': /* Regular expression to compile */
+ if (args_info->regex_given) {
+ fprintf(stderr, "%s: `--regex' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->regex_given++;
+ if (args_info->regex_arg) free(args_info->regex_arg);
+ args_info->regex_arg = strdup(val);
+ break;
+
+ case 'x': /* Compile as string, not regex */
+ if (args_info->string_given) {
+ fprintf(stderr, "%s: `--string' (`-x') option given more than once\n", PROGRAM);
+ }
+ args_info->string_given++;
+ if (args_info->string_given <= 1)
+ args_info->string_flag = !(args_info->string_flag);
+ break;
+
+ case 'r': /* Specify semiring type */
+ if (args_info->semiring_given) {
+ fprintf(stderr, "%s: `--semiring' (`-r') option given more than once\n", PROGRAM);
+ }
+ args_info->semiring_given++;
+ if (args_info->semiring_arg) free(args_info->semiring_arg);
+ args_info->semiring_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Basic label alphabet */
+ else if (strcmp(olong, "labels") == 0) {
+ if (args_info->labels_given) {
+ fprintf(stderr, "%s: `--labels' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->labels_given++;
+ if (args_info->labels_arg) free(args_info->labels_arg);
+ args_info->labels_arg = strdup(val);
+ }
+
+ /* Regular expression to compile */
+ else if (strcmp(olong, "regex") == 0) {
+ if (args_info->regex_given) {
+ fprintf(stderr, "%s: `--regex' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->regex_given++;
+ if (args_info->regex_arg) free(args_info->regex_arg);
+ args_info->regex_arg = strdup(val);
+ }
+
+ /* Compile as string, not regex */
+ else if (strcmp(olong, "string") == 0) {
+ if (args_info->string_given) {
+ fprintf(stderr, "%s: `--string' (`-x') option given more than once\n", PROGRAM);
+ }
+ args_info->string_given++;
+ if (args_info->string_given <= 1)
+ args_info->string_flag = !(args_info->string_flag);
+ }
+
+ /* Specify semiring type */
+ else if (strcmp(olong, "semiring") == 0) {
+ if (args_info->semiring_given) {
+ fprintf(stderr, "%s: `--semiring' (`-r') option given more than once\n", PROGRAM);
+ }
+ args_info->semiring_given++;
+ if (args_info->semiring_arg) free(args_info->semiring_arg);
+ args_info->semiring_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmcompre_cmdparser.h b/gfsm/gfsm/src/programs/gfsmcompre_cmdparser.h
new file mode 100644
index 0000000..32361ea
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompre_cmdparser.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmcompre_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmcompre_cmdparser_h
+#define gfsmcompre_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * labels_arg; /* Basic label alphabet (default=NULL). */
+ char * regex_arg; /* Regular expression to compile (default=NULL). */
+ int string_flag; /* Compile as string, not regex (default=0). */
+ char * semiring_arg; /* Specify semiring type (default=tropical). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int labels_given; /* Whether labels was given */
+ int regex_given; /* Whether regex was given */
+ int string_given; /* Whether string was given */
+ int semiring_given; /* Whether semiring was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmcompre_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmcompre_main.c b/gfsm/gfsm/src/programs/gfsmcompre_main.c
new file mode 100644
index 0000000..78e7721
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmcompre_main.c
@@ -0,0 +1,143 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <gfsm.h>
+
+#include "gfsmcompre_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmcompre";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *fstfilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmRegexCompiler *rec = NULL;
+gfsmAlphabet *abet = NULL;
+gfsmError *err = NULL;
+gboolean emit_warnings = TRUE;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- sanity checks
+ if (!args.regex_given) {
+ g_printerr("%s: no regex specified!\n", progname);
+ cmdline_parser_print_help();
+ exit(-1);
+ }
+
+ //-- filenames
+ outfilename = args.output_arg;
+
+ //-- alphabet: basic labels
+ abet = gfsm_string_alphabet_new();
+ if (args.labels_given) {
+ if (!gfsm_alphabet_load_filename(abet, args.labels_arg, &err)) {
+ g_printerr("%s: load failed for labels file '%s': %s\n",
+ progname, args.labels_arg, err->message);
+ exit(2);
+ }
+ }
+
+ //-- options for regex compiler
+ rec = gfsm_regex_compiler_new_full("gfsmRegexCompiler",
+ abet,
+ gfsm_sr_name_to_type(args.semiring_arg),
+ emit_warnings);
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmAutomaton *fsm;
+ char *regex=NULL;
+
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- string-compile hack: escape everything
+ if (args.string_flag) {
+ GString *tmp = g_string_new("");
+ int i;
+ for (i=0; i < strlen(args.regex_arg); i++) {
+ g_string_append_c(tmp,'\\');
+ g_string_append_c(tmp,args.regex_arg[i]);
+ }
+ regex = tmp->str;
+ g_string_free(tmp,FALSE);
+ } else {
+ regex = args.regex_arg;
+ }
+
+ //-- parse regex string
+ gfsm_scanner_scan_string(&(rec->scanner), regex);
+ fsm = gfsm_regex_compiler_parse(rec);
+
+ //-- check for errors
+ if (rec->scanner.err) {
+ g_printerr("%s: %s\n", progname, err->message);
+ exit(3);
+ }
+ if (!fsm) {
+ g_printerr("%s: no automaton!\n", progname);
+ exit(4);
+ }
+
+
+ //-- save output fsm
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(5);
+ }
+
+ //-- cleanup
+ gfsm_regex_compiler_free(rec,TRUE,TRUE);
+
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmconcat.gog b/gfsm/gfsm/src/programs/gfsmconcat.gog
new file mode 100644
index 0000000..f9b1e47
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconcat.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmconcat"
+#program_version "0.01"
+
+purpose "Concatenate finite state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE(s)" "Stored binary gfsm file(s)" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmconcat_cmdparser.c b/gfsm/gfsm/src/programs/gfsmconcat_cmdparser.c
new file mode 100644
index 0000000..617a630
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconcat_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmconcat_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmconcat_cmdparser gfsmconcat.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmconcat"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmconcat_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmconcat (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Concatenate finite state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE(s)\n", "gfsmconcat");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE(s) Stored binary gfsm file(s)\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmconcat_cmdparser.h b/gfsm/gfsm/src/programs/gfsmconcat_cmdparser.h
new file mode 100644
index 0000000..43125dd
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconcat_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmconcat_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmconcat_cmdparser_h
+#define gfsmconcat_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmconcat_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmconcat_main.c b/gfsm/gfsm/src/programs/gfsmconcat_main.c
new file mode 100644
index 0000000..9d63792
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconcat_main.c
@@ -0,0 +1,118 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmconcat_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmconcat";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename;
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsmOut=NULL, *fsmIn=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- require at least one file argument
+ if (args.inputs_num < 1) {
+ cmdline_parser_print_help();
+ exit(2);
+ }
+
+ //-- output
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsmIn = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * compute_operation()
+ * + utility routine
+ */
+void compute_operation(const char *infilename)
+{
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsmIn,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- compute concat
+ if (fsmOut == NULL) {
+ fsmOut = fsmIn;
+ fsmIn = gfsm_automaton_new();
+ } else {
+ gfsm_automaton_concat(fsmOut,fsmIn);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ int i;
+ get_my_options(argc,argv);
+
+ for (i = 0; i < args.inputs_num; i++) {
+ compute_operation(args.inputs[i]);
+ }
+ if (args.inputs_num == 1) compute_operation("-");
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsmOut,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsmIn) gfsm_automaton_free(fsmIn);
+ if (fsmOut) gfsm_automaton_free(fsmOut);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmconnect.gog b/gfsm/gfsm/src/programs/gfsmconnect.gog
new file mode 100644
index 0000000..2de8230
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconnect.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmconnect"
+#program_version "0.01"
+
+purpose "Remove non-coaccessible states from finite state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmconnect_cmdparser.c b/gfsm/gfsm/src/programs/gfsmconnect_cmdparser.c
new file mode 100644
index 0000000..a3f30cb
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconnect_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmconnect_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmconnect_cmdparser gfsmconnect.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmconnect"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmconnect_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmconnect (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Remove non-coaccessible states from finite state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmconnect");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmconnect_cmdparser.h b/gfsm/gfsm/src/programs/gfsmconnect_cmdparser.h
new file mode 100644
index 0000000..08f42e0
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconnect_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmconnect_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmconnect_cmdparser_h
+#define gfsmconnect_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmconnect_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmconnect_main.c b/gfsm/gfsm/src/programs/gfsmconnect_main.c
new file mode 100644
index 0000000..82c9c22
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconnect_main.c
@@ -0,0 +1,99 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmconnect_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmconnect";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ int rc = 0;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- connect
+ gfsm_automaton_connect(fsm);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- get exit status: 255 if no root state
+ if (fsm->root_id == gfsmNoState) rc=255;
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return rc;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmconvert.gog b/gfsm/gfsm/src/programs/gfsmconvert.gog
new file mode 100644
index 0000000..4bb24af
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconvert.gog
@@ -0,0 +1,89 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmconvert"
+#program_version "0.01"
+
+purpose "Convert binary format gfsm files"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "FSMFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "transducer" t "Specify whether automaton is a transducer" \
+ arg="BOOL"
+
+int "weighted" w "Specify whether automaton is weighted" \
+ arg="BOOL"
+
+string "semiring" s "Specify semiring type." \
+ arg="SRTYPE" \
+ details="
+Specify one of the following:
+
+ boolean
+ log
+ real
+ trivial
+ tropical
+
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmconvert_cmdparser.c b/gfsm/gfsm/src/programs/gfsmconvert_cmdparser.c
new file mode 100644
index 0000000..3e77ce5
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconvert_cmdparser.c
@@ -0,0 +1,517 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmconvert_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmconvert_cmdparser gfsmconvert.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmconvert"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmconvert_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmconvert (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Convert binary format gfsm files\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... FSMFILE\n", "gfsmconvert");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" FSMFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -tBOOL --transducer=BOOL Specify whether automaton is a transducer\n");
+ printf(" -wBOOL --weighted=BOOL Specify whether automaton is weighted\n");
+ printf(" -sSRTYPE --semiring=SRTYPE Specify semiring type.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->transducer_arg = 0;
+ args_info->weighted_arg = 0;
+ args_info->semiring_arg = NULL;
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->transducer_given = 0;
+ args_info->weighted_given = 0;
+ args_info->semiring_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "transducer", 1, NULL, 't' },
+ { "weighted", 1, NULL, 'w' },
+ { "semiring", 1, NULL, 's' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 't', ':',
+ 'w', ':',
+ 's', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 't': /* Specify whether automaton is a transducer */
+ if (args_info->transducer_given) {
+ fprintf(stderr, "%s: `--transducer' (`-t') option given more than once\n", PROGRAM);
+ }
+ args_info->transducer_given++;
+ args_info->transducer_arg = (int)atoi(val);
+ break;
+
+ case 'w': /* Specify whether automaton is weighted */
+ if (args_info->weighted_given) {
+ fprintf(stderr, "%s: `--weighted' (`-w') option given more than once\n", PROGRAM);
+ }
+ args_info->weighted_given++;
+ args_info->weighted_arg = (int)atoi(val);
+ break;
+
+ case 's': /* Specify semiring type. */
+ if (args_info->semiring_given) {
+ fprintf(stderr, "%s: `--semiring' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->semiring_given++;
+ if (args_info->semiring_arg) free(args_info->semiring_arg);
+ args_info->semiring_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify whether automaton is a transducer */
+ else if (strcmp(olong, "transducer") == 0) {
+ if (args_info->transducer_given) {
+ fprintf(stderr, "%s: `--transducer' (`-t') option given more than once\n", PROGRAM);
+ }
+ args_info->transducer_given++;
+ args_info->transducer_arg = (int)atoi(val);
+ }
+
+ /* Specify whether automaton is weighted */
+ else if (strcmp(olong, "weighted") == 0) {
+ if (args_info->weighted_given) {
+ fprintf(stderr, "%s: `--weighted' (`-w') option given more than once\n", PROGRAM);
+ }
+ args_info->weighted_given++;
+ args_info->weighted_arg = (int)atoi(val);
+ }
+
+ /* Specify semiring type. */
+ else if (strcmp(olong, "semiring") == 0) {
+ if (args_info->semiring_given) {
+ fprintf(stderr, "%s: `--semiring' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->semiring_given++;
+ if (args_info->semiring_arg) free(args_info->semiring_arg);
+ args_info->semiring_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmconvert_cmdparser.h b/gfsm/gfsm/src/programs/gfsmconvert_cmdparser.h
new file mode 100644
index 0000000..93a2291
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconvert_cmdparser.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmconvert_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmconvert_cmdparser_h
+#define gfsmconvert_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int transducer_arg; /* Specify whether automaton is a transducer (default=0). */
+ int weighted_arg; /* Specify whether automaton is weighted (default=0). */
+ char * semiring_arg; /* Specify semiring type. (default=NULL). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int transducer_given; /* Whether transducer was given */
+ int weighted_given; /* Whether weighted was given */
+ int semiring_given; /* Whether semiring was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmconvert_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmconvert_main.c b/gfsm/gfsm/src/programs/gfsmconvert_main.c
new file mode 100644
index 0000000..7c09f08
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmconvert_main.c
@@ -0,0 +1,110 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gfsm.h>
+
+#include "gfsmconvert_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmconvert";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+gfsmError *err = NULL;
+gfsmSRType srtype = gfsmSRTUnknown;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ outfilename = args.output_arg;
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(3);
+ }
+
+ //-- set flags
+ if (args.transducer_given) fsm->flags.is_transducer = args.transducer_arg;
+ if (args.weighted_given) fsm->flags.is_weighted = args.weighted_arg;
+
+ //-- set semiring
+ if (args.semiring_given) {
+ srtype = gfsm_sr_name_to_type(args.semiring_arg);
+ if (srtype == gfsmSRTUnknown) {
+ g_printerr("%s: Warning: unknown semiring name '%s' defaults to type 'tropical'.\n",
+ progname, args.semiring_arg);
+ srtype = gfsmSRTTropical;
+ }
+ if (srtype != fsm->sr->type) {
+ gfsm_automaton_set_semiring(fsm, gfsm_semiring_new(srtype));
+ }
+ }
+
+ //-- store automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmdeterminize.gog b/gfsm/gfsm/src/programs/gfsmdeterminize.gog
new file mode 100644
index 0000000..1fed7e8
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdeterminize.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmdeterminize"
+#program_version "0.01"
+
+purpose "Determinize a finite state machine"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.c b/gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.c
new file mode 100644
index 0000000..0ce40e9
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmdeterminize_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmdeterminize_cmdparser gfsmdeterminize.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmdeterminize"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmdeterminize_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmdeterminize (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Determinize a finite state machine\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmdeterminize");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.h b/gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.h
new file mode 100644
index 0000000..a0324f4
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmdeterminize_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmdeterminize_cmdparser_h
+#define gfsmdeterminize_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmdeterminize_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmdeterminize_main.c b/gfsm/gfsm/src/programs/gfsmdeterminize_main.c
new file mode 100644
index 0000000..66ba402
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdeterminize_main.c
@@ -0,0 +1,100 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmdeterminize_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmdeterminize";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- determinize
+ gfsm_automaton_determinize(fsm);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm, outfilename, args.compress_arg, &err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmdifference.gog b/gfsm/gfsm/src/programs/gfsmdifference.gog
new file mode 100644
index 0000000..9bdb612
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdifference.gog
@@ -0,0 +1,71 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmdifference"
+#program_version "0.01"
+
+purpose "Compute difference of epsilon-free finite state acceptors"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE(s)" "Stored binary gfsm file(s)" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+Epsilon arcs are not handled correctly.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmdifference_cmdparser.c b/gfsm/gfsm/src/programs/gfsmdifference_cmdparser.c
new file mode 100644
index 0000000..80c51f7
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdifference_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmdifference_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmdifference_cmdparser gfsmdifference.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmdifference"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmdifference_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmdifference (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compute difference of epsilon-free finite state acceptors\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE(s)\n", "gfsmdifference");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE(s) Stored binary gfsm file(s)\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmdifference_cmdparser.h b/gfsm/gfsm/src/programs/gfsmdifference_cmdparser.h
new file mode 100644
index 0000000..b61aa90
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdifference_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmdifference_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmdifference_cmdparser_h
+#define gfsmdifference_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmdifference_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmdifference_main.c b/gfsm/gfsm/src/programs/gfsmdifference_main.c
new file mode 100644
index 0000000..19aaedf
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdifference_main.c
@@ -0,0 +1,123 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmdifference_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmdifference";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename;
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsmOut=NULL, *fsmIn=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- require at least one file argument
+ if (args.inputs_num < 1) {
+ cmdline_parser_print_help();
+ exit(2);
+ }
+
+ //-- output
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsmIn = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * compute_operation()
+ * + utility routine
+ */
+void compute_operation(const char *infilename)
+{
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsmIn,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- compute difference
+ if (fsmOut == NULL) {
+ fsmOut = fsmIn;
+ fsmIn = gfsm_automaton_new();
+ } else {
+ gfsm_automaton_difference(fsmOut,fsmIn);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ int i;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ for (i = 0; i < args.inputs_num; i++) {
+ compute_operation(args.inputs[i]);
+ }
+ if (args.inputs_num == 1) compute_operation("-");
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsmOut,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsmIn) gfsm_automaton_free(fsmIn);
+ if (fsmOut) gfsm_automaton_free(fsmOut);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmdraw.gog b/gfsm/gfsm/src/programs/gfsmdraw.gog
new file mode 100644
index 0000000..63fbb4f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdraw.gog
@@ -0,0 +1,138 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmdraw"
+#program_version "0.01"
+
+purpose "Generate graph specifications from binary gfsm files"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details "
+gfsmdraw reads a binary GFSM file file and produces a graph specification
+in either dot(1) or vcg(1) format.
+"
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Common Options
+#-----------------------------------------------------------------------------
+group "Common Options"
+
+string "ilabels" i "Specify input (lower) labels file." \
+ arg="LABELS"
+
+string "olabels" o "Specify output (upper) labels file." \
+ arg="LABELS"
+
+string "slabels" s "Specify state labels file." \
+ arg="LABELS"
+
+string "title" t "Specify output title." \
+ arg="TITLE" \
+ details="Default is input filename."
+
+flag "vertical" v "Draw vertically." \
+ details="Default mode is top-to-bottom"
+
+string "output" F "Output graph specification." \
+ arg="DOTFILE" \
+ details="
+Default behavior is to write to stdout.
+"
+
+#-----------------------------------------------------------------------------
+# dot Options
+#-----------------------------------------------------------------------------
+group "dot Options"
+
+flag "dot" d "Request dot output (default)"
+
+float "width" W "Specify output width (default=bbox)." \
+ arg="WIDTH" \
+ default="8.5"
+float "height" H "Specify output height (default=bbox)." \
+ arg="HEIGHT" \
+ default="11"
+
+int "fontsize" f "Set output font size." \
+ arg="POINTS" \
+ default="14"
+string "font" - "Set output font name." \
+ arg="FONT"
+
+float "nodesep" n "Set min node separation." \
+ default="0.25"
+float "ranksep" r "Set min rank separation." \
+ default="0.40"
+
+flag "portrait" p "Generate in portrait mode." \
+ details="Default mode is landscape."
+
+#-----------------------------------------------------------------------------
+# VCG Options
+#-----------------------------------------------------------------------------
+group "VCG Options"
+
+flag "vcg" g "Request VCG output."
+
+int "xspace" x "Set xspace graph parameter." \
+ default="40"
+int "yspace" y "Set yspace graph parameter." \
+ default="20"
+
+string "state-shape" - "Set shape for state nodes." \
+ arg="SHAPE" \
+ default="box"
+
+string "state-color" - "Set default state color." \
+ arg="COLOR" \
+ default="white"
+
+string "final-color" - "Set color for final states." \
+ arg="COLOR" \
+ default="lightgrey"
+
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>,
+dot(1),
+vcg(1),
+xvcg(1)
+"
diff --git a/gfsm/gfsm/src/programs/gfsmdraw_cmdparser.c b/gfsm/gfsm/src/programs/gfsmdraw_cmdparser.c
new file mode 100644
index 0000000..40b52e6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdraw_cmdparser.c
@@ -0,0 +1,835 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmdraw_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmdraw_cmdparser gfsmdraw.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmdraw"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmdraw_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmdraw (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Generate graph specifications from binary gfsm files\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmdraw");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf("\n");
+ printf(" Common Options:\n");
+ printf(" -iLABELS --ilabels=LABELS Specify input (lower) labels file.\n");
+ printf(" -oLABELS --olabels=LABELS Specify output (upper) labels file.\n");
+ printf(" -sLABELS --slabels=LABELS Specify state labels file.\n");
+ printf(" -tTITLE --title=TITLE Specify output title.\n");
+ printf(" -v --vertical Draw vertically.\n");
+ printf(" -FDOTFILE --output=DOTFILE Output graph specification.\n");
+ printf("\n");
+ printf(" dot Options:\n");
+ printf(" -d --dot Request dot output (default)\n");
+ printf(" -WFLOAT --width=FLOAT Specify output width (default=bbox).\n");
+ printf(" -HFLOAT --height=FLOAT Specify output height (default=bbox).\n");
+ printf(" -fPOINTS --fontsize=POINTS Set output font size.\n");
+ printf(" --font=FONT Set output font name.\n");
+ printf(" -nFLOAT --nodesep=FLOAT Set min node separation.\n");
+ printf(" -rFLOAT --ranksep=FLOAT Set min rank separation.\n");
+ printf(" -p --portrait Generate in portrait mode.\n");
+ printf("\n");
+ printf(" VCG Options:\n");
+ printf(" -g --vcg Request VCG output.\n");
+ printf(" -xINT --xspace=INT Set xspace graph parameter.\n");
+ printf(" -yINT --yspace=INT Set yspace graph parameter.\n");
+ printf(" --state-shape=SHAPE Set shape for state nodes.\n");
+ printf(" --state-color=COLOR Set default state color.\n");
+ printf(" --final-color=COLOR Set color for final states.\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->ilabels_arg = NULL;
+ args_info->olabels_arg = NULL;
+ args_info->slabels_arg = NULL;
+ args_info->title_arg = NULL;
+ args_info->vertical_flag = 0;
+ args_info->output_arg = NULL;
+ args_info->dot_flag = 0;
+ args_info->width_arg = 8.5;
+ args_info->height_arg = 11;
+ args_info->fontsize_arg = 14;
+ args_info->font_arg = NULL;
+ args_info->nodesep_arg = 0.25;
+ args_info->ranksep_arg = 0.40;
+ args_info->portrait_flag = 0;
+ args_info->vcg_flag = 0;
+ args_info->xspace_arg = 40;
+ args_info->yspace_arg = 20;
+ args_info->state_shape_arg = strdup("box");
+ args_info->state_color_arg = strdup("white");
+ args_info->final_color_arg = strdup("lightgrey");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->ilabels_given = 0;
+ args_info->olabels_given = 0;
+ args_info->slabels_given = 0;
+ args_info->title_given = 0;
+ args_info->vertical_given = 0;
+ args_info->output_given = 0;
+ args_info->dot_given = 0;
+ args_info->width_given = 0;
+ args_info->height_given = 0;
+ args_info->fontsize_given = 0;
+ args_info->font_given = 0;
+ args_info->nodesep_given = 0;
+ args_info->ranksep_given = 0;
+ args_info->portrait_given = 0;
+ args_info->vcg_given = 0;
+ args_info->xspace_given = 0;
+ args_info->yspace_given = 0;
+ args_info->state_shape_given = 0;
+ args_info->state_color_given = 0;
+ args_info->final_color_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "ilabels", 1, NULL, 'i' },
+ { "olabels", 1, NULL, 'o' },
+ { "slabels", 1, NULL, 's' },
+ { "title", 1, NULL, 't' },
+ { "vertical", 0, NULL, 'v' },
+ { "output", 1, NULL, 'F' },
+ { "dot", 0, NULL, 'd' },
+ { "width", 1, NULL, 'W' },
+ { "height", 1, NULL, 'H' },
+ { "fontsize", 1, NULL, 'f' },
+ { "font", 1, NULL, 0 },
+ { "nodesep", 1, NULL, 'n' },
+ { "ranksep", 1, NULL, 'r' },
+ { "portrait", 0, NULL, 'p' },
+ { "vcg", 0, NULL, 'g' },
+ { "xspace", 1, NULL, 'x' },
+ { "yspace", 1, NULL, 'y' },
+ { "state-shape", 1, NULL, 0 },
+ { "state-color", 1, NULL, 0 },
+ { "final-color", 1, NULL, 0 },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'i', ':',
+ 'o', ':',
+ 's', ':',
+ 't', ':',
+ 'v',
+ 'F', ':',
+ 'd',
+ 'W', ':',
+ 'H', ':',
+ 'f', ':',
+ 'n', ':',
+ 'r', ':',
+ 'p',
+ 'g',
+ 'x', ':',
+ 'y', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'i': /* Specify input (lower) labels file. */
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ break;
+
+ case 'o': /* Specify output (upper) labels file. */
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ break;
+
+ case 's': /* Specify state labels file. */
+ if (args_info->slabels_given) {
+ fprintf(stderr, "%s: `--slabels' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->slabels_given++;
+ if (args_info->slabels_arg) free(args_info->slabels_arg);
+ args_info->slabels_arg = strdup(val);
+ break;
+
+ case 't': /* Specify output title. */
+ if (args_info->title_given) {
+ fprintf(stderr, "%s: `--title' (`-t') option given more than once\n", PROGRAM);
+ }
+ args_info->title_given++;
+ if (args_info->title_arg) free(args_info->title_arg);
+ args_info->title_arg = strdup(val);
+ break;
+
+ case 'v': /* Draw vertically. */
+ if (args_info->vertical_given) {
+ fprintf(stderr, "%s: `--vertical' (`-v') option given more than once\n", PROGRAM);
+ }
+ args_info->vertical_given++;
+ if (args_info->vertical_given <= 1)
+ args_info->vertical_flag = !(args_info->vertical_flag);
+ break;
+
+ case 'F': /* Output graph specification. */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 'd': /* Request dot output (default) */
+ if (args_info->dot_given) {
+ fprintf(stderr, "%s: `--dot' (`-d') option given more than once\n", PROGRAM);
+ }
+ args_info->dot_given++;
+ if (args_info->dot_given <= 1)
+ args_info->dot_flag = !(args_info->dot_flag);
+ break;
+
+ case 'W': /* Specify output width (default=bbox). */
+ if (args_info->width_given) {
+ fprintf(stderr, "%s: `--width' (`-W') option given more than once\n", PROGRAM);
+ }
+ args_info->width_given++;
+ args_info->width_arg = (float)strtod(val, NULL);
+ break;
+
+ case 'H': /* Specify output height (default=bbox). */
+ if (args_info->height_given) {
+ fprintf(stderr, "%s: `--height' (`-H') option given more than once\n", PROGRAM);
+ }
+ args_info->height_given++;
+ args_info->height_arg = (float)strtod(val, NULL);
+ break;
+
+ case 'f': /* Set output font size. */
+ if (args_info->fontsize_given) {
+ fprintf(stderr, "%s: `--fontsize' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->fontsize_given++;
+ args_info->fontsize_arg = (int)atoi(val);
+ break;
+
+ case 'n': /* Set min node separation. */
+ if (args_info->nodesep_given) {
+ fprintf(stderr, "%s: `--nodesep' (`-n') option given more than once\n", PROGRAM);
+ }
+ args_info->nodesep_given++;
+ args_info->nodesep_arg = (float)strtod(val, NULL);
+ break;
+
+ case 'r': /* Set min rank separation. */
+ if (args_info->ranksep_given) {
+ fprintf(stderr, "%s: `--ranksep' (`-r') option given more than once\n", PROGRAM);
+ }
+ args_info->ranksep_given++;
+ args_info->ranksep_arg = (float)strtod(val, NULL);
+ break;
+
+ case 'p': /* Generate in portrait mode. */
+ if (args_info->portrait_given) {
+ fprintf(stderr, "%s: `--portrait' (`-p') option given more than once\n", PROGRAM);
+ }
+ args_info->portrait_given++;
+ if (args_info->portrait_given <= 1)
+ args_info->portrait_flag = !(args_info->portrait_flag);
+ break;
+
+ case 'g': /* Request VCG output. */
+ if (args_info->vcg_given) {
+ fprintf(stderr, "%s: `--vcg' (`-g') option given more than once\n", PROGRAM);
+ }
+ args_info->vcg_given++;
+ if (args_info->vcg_given <= 1)
+ args_info->vcg_flag = !(args_info->vcg_flag);
+ break;
+
+ case 'x': /* Set xspace graph parameter. */
+ if (args_info->xspace_given) {
+ fprintf(stderr, "%s: `--xspace' (`-x') option given more than once\n", PROGRAM);
+ }
+ args_info->xspace_given++;
+ args_info->xspace_arg = (int)atoi(val);
+ break;
+
+ case 'y': /* Set yspace graph parameter. */
+ if (args_info->yspace_given) {
+ fprintf(stderr, "%s: `--yspace' (`-y') option given more than once\n", PROGRAM);
+ }
+ args_info->yspace_given++;
+ args_info->yspace_arg = (int)atoi(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify input (lower) labels file. */
+ else if (strcmp(olong, "ilabels") == 0) {
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ }
+
+ /* Specify output (upper) labels file. */
+ else if (strcmp(olong, "olabels") == 0) {
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ }
+
+ /* Specify state labels file. */
+ else if (strcmp(olong, "slabels") == 0) {
+ if (args_info->slabels_given) {
+ fprintf(stderr, "%s: `--slabels' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->slabels_given++;
+ if (args_info->slabels_arg) free(args_info->slabels_arg);
+ args_info->slabels_arg = strdup(val);
+ }
+
+ /* Specify output title. */
+ else if (strcmp(olong, "title") == 0) {
+ if (args_info->title_given) {
+ fprintf(stderr, "%s: `--title' (`-t') option given more than once\n", PROGRAM);
+ }
+ args_info->title_given++;
+ if (args_info->title_arg) free(args_info->title_arg);
+ args_info->title_arg = strdup(val);
+ }
+
+ /* Draw vertically. */
+ else if (strcmp(olong, "vertical") == 0) {
+ if (args_info->vertical_given) {
+ fprintf(stderr, "%s: `--vertical' (`-v') option given more than once\n", PROGRAM);
+ }
+ args_info->vertical_given++;
+ if (args_info->vertical_given <= 1)
+ args_info->vertical_flag = !(args_info->vertical_flag);
+ }
+
+ /* Output graph specification. */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ /* Request dot output (default) */
+ else if (strcmp(olong, "dot") == 0) {
+ if (args_info->dot_given) {
+ fprintf(stderr, "%s: `--dot' (`-d') option given more than once\n", PROGRAM);
+ }
+ args_info->dot_given++;
+ if (args_info->dot_given <= 1)
+ args_info->dot_flag = !(args_info->dot_flag);
+ }
+
+ /* Specify output width (default=bbox). */
+ else if (strcmp(olong, "width") == 0) {
+ if (args_info->width_given) {
+ fprintf(stderr, "%s: `--width' (`-W') option given more than once\n", PROGRAM);
+ }
+ args_info->width_given++;
+ args_info->width_arg = (float)strtod(val, NULL);
+ }
+
+ /* Specify output height (default=bbox). */
+ else if (strcmp(olong, "height") == 0) {
+ if (args_info->height_given) {
+ fprintf(stderr, "%s: `--height' (`-H') option given more than once\n", PROGRAM);
+ }
+ args_info->height_given++;
+ args_info->height_arg = (float)strtod(val, NULL);
+ }
+
+ /* Set output font size. */
+ else if (strcmp(olong, "fontsize") == 0) {
+ if (args_info->fontsize_given) {
+ fprintf(stderr, "%s: `--fontsize' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->fontsize_given++;
+ args_info->fontsize_arg = (int)atoi(val);
+ }
+
+ /* Set output font name. */
+ else if (strcmp(olong, "font") == 0) {
+ if (args_info->font_given) {
+ fprintf(stderr, "%s: `--font' option given more than once\n", PROGRAM);
+ }
+ args_info->font_given++;
+ if (args_info->font_arg) free(args_info->font_arg);
+ args_info->font_arg = strdup(val);
+ }
+
+ /* Set min node separation. */
+ else if (strcmp(olong, "nodesep") == 0) {
+ if (args_info->nodesep_given) {
+ fprintf(stderr, "%s: `--nodesep' (`-n') option given more than once\n", PROGRAM);
+ }
+ args_info->nodesep_given++;
+ args_info->nodesep_arg = (float)strtod(val, NULL);
+ }
+
+ /* Set min rank separation. */
+ else if (strcmp(olong, "ranksep") == 0) {
+ if (args_info->ranksep_given) {
+ fprintf(stderr, "%s: `--ranksep' (`-r') option given more than once\n", PROGRAM);
+ }
+ args_info->ranksep_given++;
+ args_info->ranksep_arg = (float)strtod(val, NULL);
+ }
+
+ /* Generate in portrait mode. */
+ else if (strcmp(olong, "portrait") == 0) {
+ if (args_info->portrait_given) {
+ fprintf(stderr, "%s: `--portrait' (`-p') option given more than once\n", PROGRAM);
+ }
+ args_info->portrait_given++;
+ if (args_info->portrait_given <= 1)
+ args_info->portrait_flag = !(args_info->portrait_flag);
+ }
+
+ /* Request VCG output. */
+ else if (strcmp(olong, "vcg") == 0) {
+ if (args_info->vcg_given) {
+ fprintf(stderr, "%s: `--vcg' (`-g') option given more than once\n", PROGRAM);
+ }
+ args_info->vcg_given++;
+ if (args_info->vcg_given <= 1)
+ args_info->vcg_flag = !(args_info->vcg_flag);
+ }
+
+ /* Set xspace graph parameter. */
+ else if (strcmp(olong, "xspace") == 0) {
+ if (args_info->xspace_given) {
+ fprintf(stderr, "%s: `--xspace' (`-x') option given more than once\n", PROGRAM);
+ }
+ args_info->xspace_given++;
+ args_info->xspace_arg = (int)atoi(val);
+ }
+
+ /* Set yspace graph parameter. */
+ else if (strcmp(olong, "yspace") == 0) {
+ if (args_info->yspace_given) {
+ fprintf(stderr, "%s: `--yspace' (`-y') option given more than once\n", PROGRAM);
+ }
+ args_info->yspace_given++;
+ args_info->yspace_arg = (int)atoi(val);
+ }
+
+ /* Set shape for state nodes. */
+ else if (strcmp(olong, "state-shape") == 0) {
+ if (args_info->state_shape_given) {
+ fprintf(stderr, "%s: `--state-shape' option given more than once\n", PROGRAM);
+ }
+ args_info->state_shape_given++;
+ if (args_info->state_shape_arg) free(args_info->state_shape_arg);
+ args_info->state_shape_arg = strdup(val);
+ }
+
+ /* Set default state color. */
+ else if (strcmp(olong, "state-color") == 0) {
+ if (args_info->state_color_given) {
+ fprintf(stderr, "%s: `--state-color' option given more than once\n", PROGRAM);
+ }
+ args_info->state_color_given++;
+ if (args_info->state_color_arg) free(args_info->state_color_arg);
+ args_info->state_color_arg = strdup(val);
+ }
+
+ /* Set color for final states. */
+ else if (strcmp(olong, "final-color") == 0) {
+ if (args_info->final_color_given) {
+ fprintf(stderr, "%s: `--final-color' option given more than once\n", PROGRAM);
+ }
+ args_info->final_color_given++;
+ if (args_info->final_color_arg) free(args_info->final_color_arg);
+ args_info->final_color_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmdraw_cmdparser.h b/gfsm/gfsm/src/programs/gfsmdraw_cmdparser.h
new file mode 100644
index 0000000..b494e48
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdraw_cmdparser.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmdraw_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmdraw_cmdparser_h
+#define gfsmdraw_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * ilabels_arg; /* Specify input (lower) labels file. (default=NULL). */
+ char * olabels_arg; /* Specify output (upper) labels file. (default=NULL). */
+ char * slabels_arg; /* Specify state labels file. (default=NULL). */
+ char * title_arg; /* Specify output title. (default=NULL). */
+ int vertical_flag; /* Draw vertically. (default=0). */
+ char * output_arg; /* Output graph specification. (default=NULL). */
+ int dot_flag; /* Request dot output (default) (default=0). */
+ float width_arg; /* Specify output width (default=bbox). (default=8.5). */
+ float height_arg; /* Specify output height (default=bbox). (default=11). */
+ int fontsize_arg; /* Set output font size. (default=14). */
+ char * font_arg; /* Set output font name. (default=NULL). */
+ float nodesep_arg; /* Set min node separation. (default=0.25). */
+ float ranksep_arg; /* Set min rank separation. (default=0.40). */
+ int portrait_flag; /* Generate in portrait mode. (default=0). */
+ int vcg_flag; /* Request VCG output. (default=0). */
+ int xspace_arg; /* Set xspace graph parameter. (default=40). */
+ int yspace_arg; /* Set yspace graph parameter. (default=20). */
+ char * state_shape_arg; /* Set shape for state nodes. (default=box). */
+ char * state_color_arg; /* Set default state color. (default=white). */
+ char * final_color_arg; /* Set color for final states. (default=lightgrey). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int ilabels_given; /* Whether ilabels was given */
+ int olabels_given; /* Whether olabels was given */
+ int slabels_given; /* Whether slabels was given */
+ int title_given; /* Whether title was given */
+ int vertical_given; /* Whether vertical was given */
+ int output_given; /* Whether output was given */
+ int dot_given; /* Whether dot was given */
+ int width_given; /* Whether width was given */
+ int height_given; /* Whether height was given */
+ int fontsize_given; /* Whether fontsize was given */
+ int font_given; /* Whether font was given */
+ int nodesep_given; /* Whether nodesep was given */
+ int ranksep_given; /* Whether ranksep was given */
+ int portrait_given; /* Whether portrait was given */
+ int vcg_given; /* Whether vcg was given */
+ int xspace_given; /* Whether xspace was given */
+ int yspace_given; /* Whether yspace was given */
+ int state_shape_given; /* Whether state-shape was given */
+ int state_color_given; /* Whether state-color was given */
+ int final_color_given; /* Whether final-color was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmdraw_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmdraw_main.c b/gfsm/gfsm/src/programs/gfsmdraw_main.c
new file mode 100644
index 0000000..7748419
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmdraw_main.c
@@ -0,0 +1,166 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmdraw_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmdraw";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+gfsmAlphabet *ilabels=NULL, *olabels=NULL, *slabels=NULL;
+gfsmError *err = NULL;
+
+typedef enum _gfsmDrawMode {
+ gfsmDMNone,
+ gfsmDMDot,
+ gfsmDMVCG
+} gfsmDrawMode;
+gfsmDrawMode mode = gfsmDMDot; //-- default mode
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ if (args.output_given) outfilename = args.output_arg;
+
+ //-- labels: input
+ if (args.ilabels_given) {
+ ilabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(ilabels,args.ilabels_arg,&err)) {
+ g_printerr("%s: load failed for input-labels file '%s': %s\n",
+ progname, args.ilabels_arg, (err ? err->message : "?"));
+ exit(2);
+ }
+ }
+ //-- labels: output
+ if (args.olabels_given) {
+ olabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(olabels,args.olabels_arg,&err)) {
+ g_printerr("%s: load failed for output-labels file '%s': %s\n",
+ progname, args.olabels_arg, (err ? err->message : "?"));
+ exit(2);
+ }
+ }
+ //-- labels: state
+ if (args.slabels_given) {
+ slabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(slabels,args.slabels_arg,&err)) {
+ g_printerr("%s: load failed for state-labels file '%s': %s\n",
+ progname, args.slabels_arg, (err ? err->message : "?"));
+ exit(2);
+ }
+ }
+
+ //-- draw mode
+ if (args.dot_given) mode = gfsmDMDot;
+ else if (args.vcg_given) mode = gfsmDMVCG;
+
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gboolean rc = FALSE;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, (err ? err->message : "?"));
+ exit(3);
+ }
+
+ //-- draw automaton
+ if (mode==gfsmDMDot)
+ rc = gfsm_automaton_draw_dot_filename_full(fsm,
+ outfilename,
+ ilabels,
+ olabels,
+ slabels,
+ (args.title_given ? args.title_arg : infilename),
+ args.width_arg,
+ args.height_arg,
+ args.fontsize_arg,
+ args.font_arg,
+ args.portrait_given,
+ args.vertical_given,
+ args.nodesep_arg,
+ args.ranksep_arg,
+ &err);
+ else if (mode==gfsmDMVCG)
+ rc = gfsm_automaton_draw_vcg_filename_full(fsm,
+ outfilename,
+ ilabels,
+ olabels,
+ slabels,
+ (args.title_given ? args.title_arg : infilename),
+ args.xspace_arg,
+ args.yspace_arg,
+ (args.vertical_given ? "top_to_bottom" : "left_to_right"),
+ args.state_shape_arg,
+ args.state_color_arg,
+ args.final_color_arg,
+ &err);
+
+ if (!rc) {
+ g_printerr("%s: store failed to '%s': %s\n",
+ progname, outfilename, (err ? err->message : "?"));
+ exit(4);
+ }
+
+ //-- cleanup
+ if (ilabels) gfsm_alphabet_free(ilabels);
+ if (olabels) gfsm_alphabet_free(olabels);
+ if (slabels) gfsm_alphabet_free(slabels);
+ gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmheader.gog b/gfsm/gfsm/src/programs/gfsmheader.gog
new file mode 100644
index 0000000..c3555ee
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmheader.gog
@@ -0,0 +1,57 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmheader"
+#program_version "0.01"
+
+purpose "Show header information from stored gfsm files"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmheader_cmdparser.c b/gfsm/gfsm/src/programs/gfsmheader_cmdparser.c
new file mode 100644
index 0000000..58f982f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmheader_cmdparser.c
@@ -0,0 +1,403 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmheader_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmheader_cmdparser gfsmheader.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmheader"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmheader_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmheader (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Show header information from stored gfsm files\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmheader");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmheader_cmdparser.h b/gfsm/gfsm/src/programs/gfsmheader_cmdparser.h
new file mode 100644
index 0000000..b9e0baa
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmheader_cmdparser.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmheader_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmheader_cmdparser_h
+#define gfsmheader_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmheader_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmheader_main.c b/gfsm/gfsm/src/programs/gfsmheader_main.c
new file mode 100644
index 0000000..5ba0a87
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmheader_main.c
@@ -0,0 +1,129 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmheader_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmheader";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+
+//-- global structs
+gfsmAutomatonHeader hdr;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+
+ //-- initialize header
+ memset(&hdr, 0, sizeof(gfsmAutomatonHeader));
+}
+
+/*--------------------------------------------------------------------------
+ * Utilities
+ *--------------------------------------------------------------------------*/
+#define bool2char(b) (b ? 'y' : 'n')
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ gfsmIOHandle *ioh = NULL;
+ GString *modestr = NULL;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ //-- open file
+ if (!(ioh = gfsmio_new_filename(infilename,"rb",-1,&err)) || err) {
+ g_printerr("%s: open failed for '%s': %s\n", progname, infilename, err->message);
+ exit(2);
+ }
+
+ //-- read header
+ if (!gfsmio_read(ioh, &hdr, sizeof(gfsmAutomatonHeader))) {
+ g_printerr("%s: failed to read header!\n", progname);
+ exit(3);
+ }
+ gfsmio_close(ioh);
+
+ //-- print header information
+ printf("%-24s: %s\n", "Filename", infilename);
+ printf("%-24s: %s\n", "magic", hdr.magic);
+ printf("%-24s: %d.%d.%d\n", "version",
+ hdr.version.major, hdr.version.minor, hdr.version.micro);
+ printf("%-24s: %d.%d.%d\n", "version_min",
+ hdr.version_min.major, hdr.version_min.minor, hdr.version_min.micro);
+
+ printf("%-24s: %d\n", "flags.is_transducer", hdr.flags.is_transducer);
+ printf("%-24s: %d\n", "flags.is_weighted", hdr.flags.is_transducer);
+#if 0
+ printf("%-24s: %d (%s)\n", "flags.sort_mode",
+ hdr.flags.sort_mode, gfsm_arc_sortmode_to_name(hdr.flags.sort_mode));
+#else
+ modestr = gfsm_acmask_to_gstring(hdr.flags.sort_mode, modestr);
+ printf("%-24s: %d (%s)\n", "flags.sort_mode", hdr.flags.sort_mode, modestr->str);
+ g_string_free(modestr,TRUE);
+#endif
+ printf("%-24s: %d\n", "flags.is_deterministic", hdr.flags.is_deterministic);
+ printf("%-24s: %d\n", "flags.unused", hdr.flags.unused);
+
+ printf("%-24s: %u\n", "root_id", hdr.root_id);
+ printf("%-24s: %u\n", "n_states", hdr.n_states);
+ printf("%-24s: %u\n", "n_arcs", hdr.n_arcs_007);
+ printf("%-24s: %u (%s)\n", "srtype", hdr.srtype, gfsm_sr_type_to_name(hdr.srtype));
+
+ printf("%-24s: %u\n", "unused1", hdr.unused1);
+ printf("%-24s: %u\n", "unused2", hdr.unused2);
+ printf("%-24s: %u\n", "unused3", hdr.unused3);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmindex.gog b/gfsm/gfsm/src/programs/gfsmindex.gog
new file mode 100644
index 0000000..53c2a14
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmindex.gog
@@ -0,0 +1,75 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmindex"
+#program_version "0.01"
+
+purpose "Convert between indexed and un-indexed binary gfsm automata"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "FSMFILE" "Stored binary gfsm automaton file or index" \
+ details="
+If unspecified, standard input will be read.
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+flag "unindex" u "Convert indexed automaton to unindexed format" \
+ details="
+Default behavior is to convert a plain unindexed automaton to an indexed automaton.
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmindex_cmdparser.c b/gfsm/gfsm/src/programs/gfsmindex_cmdparser.c
new file mode 100644
index 0000000..8de1602
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmindex_cmdparser.c
@@ -0,0 +1,473 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmindex_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.06
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmindex_cmdparser gfsmindex.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmindex"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmindex_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmindex (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Convert between indexed and un-indexed binary gfsm automata\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... FSMFILE\n", "gfsmindex");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" FSMFILE Stored binary gfsm automaton file or index\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -u --unindex Convert indexed automaton to unindexed format\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->unindex_flag = 0;
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->unindex_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "unindex", 0, NULL, 'u' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'u',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'u': /* Convert indexed automaton to unindexed format */
+ if (args_info->unindex_given) {
+ fprintf(stderr, "%s: `--unindex' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->unindex_given++;
+ if (args_info->unindex_given <= 1)
+ args_info->unindex_flag = !(args_info->unindex_flag);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Convert indexed automaton to unindexed format */
+ else if (strcmp(olong, "unindex") == 0) {
+ if (args_info->unindex_given) {
+ fprintf(stderr, "%s: `--unindex' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->unindex_given++;
+ if (args_info->unindex_given <= 1)
+ args_info->unindex_flag = !(args_info->unindex_flag);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmindex_cmdparser.h b/gfsm/gfsm/src/programs/gfsmindex_cmdparser.h
new file mode 100644
index 0000000..7dbcfb6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmindex_cmdparser.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmindex_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.06.
+ *
+ */
+
+#ifndef gfsmindex_cmdparser_h
+#define gfsmindex_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int unindex_flag; /* Convert indexed automaton to unindexed format (default=0). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int unindex_given; /* Whether unindex was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmindex_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmindex_main.c b/gfsm/gfsm/src/programs/gfsmindex_main.c
new file mode 100644
index 0000000..76adf26
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmindex_main.c
@@ -0,0 +1,124 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2007 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gfsm.h>
+
+#include "gfsmindex_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmindex";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm=NULL;
+gfsmIndexedAutomaton *xfsm=NULL;
+gfsmError *err=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ outfilename = args.output_arg;
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- dispatch
+ if (args.unindex_given) {
+ //-- convert indexed --> vanilla
+
+ //-- load index
+ xfsm = gfsm_indexed_automaton_new();
+ if (!gfsm_indexed_automaton_load_bin_filename(xfsm,infilename,&err)) {
+ g_printerr("%s: load failed for indexed automaton from '%s': %s\n", progname, infilename,
+ (err ? err->message : "?"));
+ exit(3);
+ }
+
+ //-- unindex
+ fsm = gfsm_indexed_to_automaton(xfsm,NULL);
+
+ //-- store vanilla
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed for vanilla automaton to '%s': %s\n", progname, outfilename,
+ (err ? err->message : "?"));
+ exit(4);
+ }
+ }
+ else {
+ //-- convert vanilla --> indexed
+
+ //-- load vanilla
+ fsm = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for vanilla automaton from '%s': %s\n", progname, infilename,
+ (err ? err->message : "?"));
+ exit(3);
+ }
+
+ //-- index & sort
+ xfsm = gfsm_automaton_to_indexed(fsm,NULL);
+ //gfsm_indexed_automaton_sort(xfsm, gfsm_acmask_from_args(gfsmACLower,gfsmACWeight)); //-- TODO: make these options!
+
+ //-- store indexed
+ if (!gfsm_indexed_automaton_save_bin_filename(xfsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed for indexed automaton to '%s': %s\n", progname, outfilename,
+ (err ? err->message : "?"));
+ exit(4);
+ }
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+ if (xfsm) gfsm_indexed_automaton_free(xfsm);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsminfo.gog b/gfsm/gfsm/src/programs/gfsminfo.gog
new file mode 100644
index 0000000..22ddbec
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminfo.gog
@@ -0,0 +1,57 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsminfo"
+#program_version "0.01"
+
+purpose "Show basic information about stored gfsm files"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsminfo_cmdparser.c b/gfsm/gfsm/src/programs/gfsminfo_cmdparser.c
new file mode 100644
index 0000000..79e978f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminfo_cmdparser.c
@@ -0,0 +1,403 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsminfo_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsminfo_cmdparser gfsminfo.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsminfo"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsminfo_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsminfo (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Show basic information about stored gfsm files\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsminfo");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsminfo_cmdparser.h b/gfsm/gfsm/src/programs/gfsminfo_cmdparser.h
new file mode 100644
index 0000000..8aa6727
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminfo_cmdparser.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsminfo_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsminfo_cmdparser_h
+#define gfsminfo_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsminfo_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsminfo_main.c b/gfsm/gfsm/src/programs/gfsminfo_main.c
new file mode 100644
index 0000000..7c6377d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminfo_main.c
@@ -0,0 +1,123 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsminfo_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsminfo";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * Utilities
+ *--------------------------------------------------------------------------*/
+#define bool2char(b) (b ? 'y' : 'n')
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ GString *modestr = NULL;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+ guint n_eps_i, n_eps_o, n_eps_io;
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(2);
+ }
+
+ //-- print information
+ printf("%-24s: %s\n", "Filename", infilename);
+ printf("%-24s: %s\n", "Semiring", gfsm_sr_type_to_name(fsm->sr->type));
+ printf("%-24s: %c\n", "Transducer?", bool2char(gfsm_automaton_is_transducer(fsm)));
+ printf("%-24s: %c\n", "Weighted?", bool2char(gfsm_automaton_is_weighted(fsm)));
+ printf("%-24s: %c\n", "Deterministic?", bool2char(fsm->flags.is_deterministic));
+#if 0
+ printf("%-24s: %s\n", "Sort Mode", gfsm_arc_sortmode_to_name(gfsm_automaton_sortmode(fsm)));
+#else
+ modestr = gfsm_acmask_to_gstring(fsm->flags.sort_mode, modestr);
+ printf("%-24s: %s\n", "Sort Mode", modestr->str);
+ g_string_free(modestr,TRUE);
+#endif
+ if (fsm->root_id != gfsmNoState) {
+ printf("%-24s: %u\n", "Initial state", fsm->root_id);
+ } else {
+ printf("%-24s: %s\n", "Initial state", "none");
+ }
+ printf("%-24s: %u\n", "# of states", gfsm_automaton_n_states(fsm));
+ printf("%-24s: %u\n", "# of final states", gfsm_automaton_n_final_states(fsm));
+ printf("%-24s: %u\n", "# of arcs", gfsm_automaton_n_arcs_full(fsm, &n_eps_i, &n_eps_o, &n_eps_io));
+ printf("%-24s: %u\n", "# of i/o epsilon arcs", n_eps_io);
+ printf("%-24s: %u\n", "# of input epsilon arcs", n_eps_i);
+ printf("%-24s: %u\n", "# of output epsilon arcs", n_eps_o);
+
+ printf("%-24s: %c\n", "cyclic?", bool2char(gfsm_automaton_is_cyclic(fsm)));
+ //...
+
+ //-- cleanup
+ gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmintersect.gog b/gfsm/gfsm/src/programs/gfsmintersect.gog
new file mode 100644
index 0000000..9ce5f79
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmintersect.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmintersect"
+#program_version "0.01"
+
+purpose "Compute intersection of finite state acceptors"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE(s)" "Stored binary gfsm file(s)" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+Probably many.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmintersect_cmdparser.c b/gfsm/gfsm/src/programs/gfsmintersect_cmdparser.c
new file mode 100644
index 0000000..28b385e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmintersect_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmintersect_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmintersect_cmdparser gfsmintersect.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmintersect"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmintersect_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmintersect (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compute intersection of finite state acceptors\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE(s)\n", "gfsmintersect");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE(s) Stored binary gfsm file(s)\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmintersect_cmdparser.h b/gfsm/gfsm/src/programs/gfsmintersect_cmdparser.h
new file mode 100644
index 0000000..4ff1144
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmintersect_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmintersect_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmintersect_cmdparser_h
+#define gfsmintersect_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmintersect_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmintersect_main.c b/gfsm/gfsm/src/programs/gfsmintersect_main.c
new file mode 100644
index 0000000..4fd05ff
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmintersect_main.c
@@ -0,0 +1,123 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmintersect_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmintersect";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename;
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsmOut=NULL, *fsmIn=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- require at least one file argument
+ if (args.inputs_num < 1) {
+ cmdline_parser_print_help();
+ exit(2);
+ }
+
+ //-- output
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsmIn = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * compute_operation()
+ * + utility routine
+ */
+void compute_operation(const char *infilename)
+{
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsmIn,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- compute underlying FSM operation
+ if (fsmOut == NULL) {
+ fsmOut = fsmIn;
+ fsmIn = gfsm_automaton_new();
+ } else {
+ gfsm_automaton_intersect(fsmOut,fsmIn);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ int i;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ for (i = 0; i < args.inputs_num; i++) {
+ compute_operation(args.inputs[i]);
+ }
+ if (args.inputs_num == 1) compute_operation("-");
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsmOut,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsmIn) gfsm_automaton_free(fsmIn);
+ if (fsmOut) gfsm_automaton_free(fsmOut);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsminvert.gog b/gfsm/gfsm/src/programs/gfsminvert.gog
new file mode 100644
index 0000000..4bb0f2e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminvert.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsminvert"
+#program_version "0.01"
+
+purpose "Invert input/output tapes of finite state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsminvert_cmdparser.c b/gfsm/gfsm/src/programs/gfsminvert_cmdparser.c
new file mode 100644
index 0000000..04d03c1
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminvert_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsminvert_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsminvert_cmdparser gfsminvert.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsminvert"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsminvert_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsminvert (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Invert input/output tapes of finite state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsminvert");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsminvert_cmdparser.h b/gfsm/gfsm/src/programs/gfsminvert_cmdparser.h
new file mode 100644
index 0000000..47b8bad
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminvert_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsminvert_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsminvert_cmdparser_h
+#define gfsminvert_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsminvert_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsminvert_main.c b/gfsm/gfsm/src/programs/gfsminvert_main.c
new file mode 100644
index 0000000..acb285c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsminvert_main.c
@@ -0,0 +1,95 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsminvert_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsminvert";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- invert
+ gfsm_automaton_invert(fsm);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmlabels.gog b/gfsm/gfsm/src/programs/gfsmlabels.gog
new file mode 100644
index 0000000..56642da
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlabels.gog
@@ -0,0 +1,78 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmlabels"
+#program_version "0.01"
+
+purpose "Map input text characters to gfsm labels"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "TXTFILE" "Input text file" \
+ details="
+If unspecified, standard input will be read.
+"
+
+#argument "BINFILE" "Output binary gfsm file" \
+# details="
+#If unspecified, output will be written to standard output.
+#"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+string "labels" l "Specify input alphabet (labels) file." \
+ arg="LABELS"
+
+flag "att-mode" a "Parse string(s) in AT&T-compatible mode." \
+ default="0"
+
+flag "map-mode" m "Output original strings in addition to label vectors." \
+ default="0"
+
+flag "quiet" q "Suppress warnings about undefined symbols." \
+ default="0"
+
+string "output" o "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmlabels_cmdparser.c b/gfsm/gfsm/src/programs/gfsmlabels_cmdparser.c
new file mode 100644
index 0000000..078f4e5
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlabels_cmdparser.c
@@ -0,0 +1,523 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmlabels_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.06
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmlabels_cmdparser gfsmlabels.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmlabels"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmlabels_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmlabels (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Map input text characters to gfsm labels\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... TXTFILE\n", "gfsmlabels");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" TXTFILE Input text file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -lLABELS --labels=LABELS Specify input alphabet (labels) file.\n");
+ printf(" -a --att-mode Parse string(s) in AT&T-compatible mode.\n");
+ printf(" -m --map-mode Output original strings in addition to label vectors.\n");
+ printf(" -q --quiet Suppress warnings about undefined symbols.\n");
+ printf(" -oFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->labels_arg = NULL;
+ args_info->att_mode_flag = 0;
+ args_info->map_mode_flag = 0;
+ args_info->quiet_flag = 0;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->labels_given = 0;
+ args_info->att_mode_given = 0;
+ args_info->map_mode_given = 0;
+ args_info->quiet_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "labels", 1, NULL, 'l' },
+ { "att-mode", 0, NULL, 'a' },
+ { "map-mode", 0, NULL, 'm' },
+ { "quiet", 0, NULL, 'q' },
+ { "output", 1, NULL, 'o' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'l', ':',
+ 'a',
+ 'm',
+ 'q',
+ 'o', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'l': /* Specify input alphabet (labels) file. */
+ if (args_info->labels_given) {
+ fprintf(stderr, "%s: `--labels' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->labels_given++;
+ if (args_info->labels_arg) free(args_info->labels_arg);
+ args_info->labels_arg = strdup(val);
+ break;
+
+ case 'a': /* Parse string(s) in AT&T-compatible mode. */
+ if (args_info->att_mode_given) {
+ fprintf(stderr, "%s: `--att-mode' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->att_mode_given++;
+ if (args_info->att_mode_given <= 1)
+ args_info->att_mode_flag = !(args_info->att_mode_flag);
+ break;
+
+ case 'm': /* Output original strings in addition to label vectors. */
+ if (args_info->map_mode_given) {
+ fprintf(stderr, "%s: `--map-mode' (`-m') option given more than once\n", PROGRAM);
+ }
+ args_info->map_mode_given++;
+ if (args_info->map_mode_given <= 1)
+ args_info->map_mode_flag = !(args_info->map_mode_flag);
+ break;
+
+ case 'q': /* Suppress warnings about undefined symbols. */
+ if (args_info->quiet_given) {
+ fprintf(stderr, "%s: `--quiet' (`-q') option given more than once\n", PROGRAM);
+ }
+ args_info->quiet_given++;
+ if (args_info->quiet_given <= 1)
+ args_info->quiet_flag = !(args_info->quiet_flag);
+ break;
+
+ case 'o': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify input alphabet (labels) file. */
+ else if (strcmp(olong, "labels") == 0) {
+ if (args_info->labels_given) {
+ fprintf(stderr, "%s: `--labels' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->labels_given++;
+ if (args_info->labels_arg) free(args_info->labels_arg);
+ args_info->labels_arg = strdup(val);
+ }
+
+ /* Parse string(s) in AT&T-compatible mode. */
+ else if (strcmp(olong, "att-mode") == 0) {
+ if (args_info->att_mode_given) {
+ fprintf(stderr, "%s: `--att-mode' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->att_mode_given++;
+ if (args_info->att_mode_given <= 1)
+ args_info->att_mode_flag = !(args_info->att_mode_flag);
+ }
+
+ /* Output original strings in addition to label vectors. */
+ else if (strcmp(olong, "map-mode") == 0) {
+ if (args_info->map_mode_given) {
+ fprintf(stderr, "%s: `--map-mode' (`-m') option given more than once\n", PROGRAM);
+ }
+ args_info->map_mode_given++;
+ if (args_info->map_mode_given <= 1)
+ args_info->map_mode_flag = !(args_info->map_mode_flag);
+ }
+
+ /* Suppress warnings about undefined symbols. */
+ else if (strcmp(olong, "quiet") == 0) {
+ if (args_info->quiet_given) {
+ fprintf(stderr, "%s: `--quiet' (`-q') option given more than once\n", PROGRAM);
+ }
+ args_info->quiet_given++;
+ if (args_info->quiet_given <= 1)
+ args_info->quiet_flag = !(args_info->quiet_flag);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmlabels_cmdparser.h b/gfsm/gfsm/src/programs/gfsmlabels_cmdparser.h
new file mode 100644
index 0000000..71f8d95
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlabels_cmdparser.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmlabels_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.06.
+ *
+ */
+
+#ifndef gfsmlabels_cmdparser_h
+#define gfsmlabels_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * labels_arg; /* Specify input alphabet (labels) file. (default=NULL). */
+ int att_mode_flag; /* Parse string(s) in AT&T-compatible mode. (default=0). */
+ int map_mode_flag; /* Output original strings in addition to label vectors. (default=0). */
+ int quiet_flag; /* Suppress warnings about undefined symbols. (default=0). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int labels_given; /* Whether labels was given */
+ int att_mode_given; /* Whether att-mode was given */
+ int map_mode_given; /* Whether map-mode was given */
+ int quiet_given; /* Whether quiet was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmlabels_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmlabels_main.c b/gfsm/gfsm/src/programs/gfsmlabels_main.c
new file mode 100644
index 0000000..0e25c78
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlabels_main.c
@@ -0,0 +1,208 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005-2008 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <gfsm.h>
+
+/*-- use gnulib --*/
+#include "gnulib/getdelim.h"
+
+#include "gfsmlabels_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmlabels";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+FILE *outfile = NULL;
+
+//-- global structs
+gfsmAlphabet *labels=NULL;
+gfsmError *err = NULL;
+gboolean att_mode = FALSE;
+gboolean map_mode = FALSE;
+gboolean warn_on_undef = TRUE;
+
+/* HACK */
+//extern ssize_t getline(char **LINEPTR, size_t *N, FILE *STREAM);
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ outfilename = args.output_arg;
+
+ //-- open output file
+ if (args.output_given) {
+ outfilename = args.output_arg;
+ outfile = gfsm_open_filename(outfilename,"w",&err);
+ if (!outfile) {
+ g_printerr("%s: open failed for output file '%s': %s\n",
+ progname, outfilename, strerror(errno));
+ exit(2);
+ }
+ }
+ else {
+ outfile = stdout;
+ }
+
+ //-- labels
+ if (args.labels_given) {
+ labels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(labels, args.labels_arg, &err)) {
+ g_printerr("%s: load failed for labels file '%s': %s\n",
+ progname, args.labels_arg, err->message);
+ exit(3);
+ }
+ } else {
+ g_printerr("%s: no labels file specified!\n", progname);
+ exit(3);
+ }
+
+ //-- mode flags
+ att_mode = args.att_mode_flag;
+ map_mode = args.map_mode_flag;
+ warn_on_undef = !args.quiet_flag;
+}
+
+/*--------------------------------------------------------------------------
+ * apply_labels_file()
+ */
+void apply_labels_file(gfsmAlphabet *labels, FILE *infile, FILE *outfile)
+{
+ char *str = NULL;
+ size_t buflen = 0;
+ ssize_t linelen = 0;
+ ssize_t i;
+ gfsmLabelVal lab;
+ gfsmLabelVector *vec = g_ptr_array_new();
+
+ while (!feof(infile)) {
+ linelen = getdelim(&str,&buflen,'\n',infile);
+ if (linelen<0) { break; } //-- EOF
+
+ //-- truncate terminating newline character
+ if (str[linelen-1] == '\n') { str[linelen-1] = 0; }
+
+ //-- map mode?
+ if (map_mode) { fprintf(outfile, "%s\t", str); }
+
+ //-- convert
+ vec = gfsm_alphabet_generic_string_to_labels(labels,str,vec,warn_on_undef,att_mode);
+
+ //-- dump labels
+ for (i=0; i<vec->len; i++) {
+ lab = GPOINTER_TO_UINT(vec->pdata[i]);
+ if (i>0) { fputc(' ',outfile); }
+ fprintf(outfile, "%d", lab);
+ }
+ fputc('\n', outfile);
+ }
+
+ if (str) free(str);
+ if (vec) g_ptr_array_free(vec,TRUE);
+}
+
+void apply_labels_file_0(gfsmAlphabet *labels, FILE *infile, FILE *outfile)
+{
+ char *str = NULL;
+ size_t buflen = 0;
+ ssize_t linelen = 0;
+ ssize_t i;
+ gfsmLabelVal lab;
+ char cs[2] = {'\0', '\0'};
+
+ while (!feof(infile)) {
+ /*linelen = getline(&str,&buflen,infile);*/
+ linelen = getdelim(&str,&buflen,'\n',infile);
+ for (i=0; i < linelen; i++) {
+ if (isspace(str[i])) continue;
+ cs[0] = str[i];
+ lab = gfsm_alphabet_find_label(labels,cs);
+
+ if (lab==gfsmNoLabel) {
+ g_printerr("%s: Warning: no label for character '%c' -- skipping.\n",
+ progname, cs[0]);
+ continue;
+ }
+
+ fprintf(outfile, "%d ", lab);
+ }
+ fputs("\n", outfile);
+ }
+
+ if (str) free(str);
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ int i;
+
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- process input(s)
+ if (args.inputs_num==0) {
+ apply_labels_file(labels,stdin,outfile);
+ }
+ for (i=0; i < args.inputs_num; i++) {
+ FILE *infile = (strcmp(args.inputs[i],"-")==0 ? stdin : fopen(args.inputs[i], "r"));
+ if (!infile) {
+ g_printerr("%s: load failed for input file '%s': %s\n", progname, args.inputs[i], strerror(errno));
+ exit(255);
+ }
+ apply_labels_file(labels,infile,outfile);
+ if (infile != stdin) fclose(infile);
+ }
+
+
+ //-- cleanup
+ if (labels) gfsm_alphabet_free(labels);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmlookup.gog b/gfsm/gfsm/src/programs/gfsmlookup.gog
new file mode 100644
index 0000000..500108f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlookup.gog
@@ -0,0 +1,77 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmlookup"
+#program_version "0.01"
+
+purpose "Apply a transducer to a linear label sequence"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "LABELID..." "Input label IDs" \
+ details="
+In ASCII decimal notation.
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+string "fst" f "Transducer to apply (default=stdin)." \
+ arg="FSTFILE" \
+ default="-" \
+ details="
+If unspecified, standard input will be read.
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmlookup_cmdparser.c b/gfsm/gfsm/src/programs/gfsmlookup_cmdparser.c
new file mode 100644
index 0000000..ae36643
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlookup_cmdparser.c
@@ -0,0 +1,473 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmlookup_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmlookup_cmdparser gfsmlookup.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmlookup"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmlookup_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmlookup (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Apply a transducer to a linear label sequence\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... LABELID...\n", "gfsmlookup");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" LABELID... Input label IDs\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -fFSTFILE --fst=FSTFILE Transducer to apply (default=stdin).\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->fst_arg = strdup("-");
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->fst_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "fst", 1, NULL, 'f' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'f', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'f': /* Transducer to apply (default=stdin). */
+ if (args_info->fst_given) {
+ fprintf(stderr, "%s: `--fst' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->fst_given++;
+ if (args_info->fst_arg) free(args_info->fst_arg);
+ args_info->fst_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Transducer to apply (default=stdin). */
+ else if (strcmp(olong, "fst") == 0) {
+ if (args_info->fst_given) {
+ fprintf(stderr, "%s: `--fst' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->fst_given++;
+ if (args_info->fst_arg) free(args_info->fst_arg);
+ args_info->fst_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmlookup_cmdparser.h b/gfsm/gfsm/src/programs/gfsmlookup_cmdparser.h
new file mode 100644
index 0000000..3b20b24
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlookup_cmdparser.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmlookup_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmlookup_cmdparser_h
+#define gfsmlookup_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * fst_arg; /* Transducer to apply (default=stdin). (default=-). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int fst_given; /* Whether fst was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmlookup_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmlookup_main.c b/gfsm/gfsm/src/programs/gfsmlookup_main.c
new file mode 100644
index 0000000..39dd8a2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmlookup_main.c
@@ -0,0 +1,125 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <gfsm.h>
+
+#include "gfsmlookup_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmlookup";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *fstfilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fst = NULL;
+gfsmError *err = NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.fst_given) fstfilename = args.fst_arg;
+ outfilename = args.output_arg;
+
+ //-- load FST
+ fst = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(fst, fstfilename, &err)) {
+ g_printerr("%s: load failed for FST file '%s': %s\n", progname, fstfilename, err->message);
+ exit(255);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * lookup_labels()
+ */
+gfsmAutomaton *lookup_labels(gfsmAutomaton *fst, int argc, char **argv)
+{
+ gfsmLabelVector *vec = g_ptr_array_sized_new(argc);
+ char *s=NULL, *tail=NULL;
+ gfsmLabelVal lab;
+ gfsmAutomaton *result = NULL;
+ int i;
+
+ //-- fill input vector
+ for (i=0; i < argc; i++) {
+ for (s=argv[i], lab=strtol(s,&tail,0); s != tail; s=tail, lab=strtol(s,&tail,0)) {
+ g_ptr_array_add(vec, (gpointer)lab);
+ }
+ }
+
+ //-- actual lookup
+ result = gfsm_automaton_lookup(fst, vec, result);
+
+ //-- cleanup
+ g_ptr_array_free(vec,TRUE);
+
+ return result;
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmAutomaton *result;
+
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- process input
+ result = lookup_labels(fst, args.inputs_num, args.inputs);
+
+ //-- save output
+ if (!gfsm_automaton_save_bin_filename(result,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fst) gfsm_automaton_free(fst);
+ if (result) gfsm_automaton_free(result);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmoptional.gog b/gfsm/gfsm/src/programs/gfsmoptional.gog
new file mode 100644
index 0000000..3bf6102
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmoptional.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmoptional"
+#program_version "0.01"
+
+purpose "Make a an automaton optional"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmoptional_cmdparser.c b/gfsm/gfsm/src/programs/gfsmoptional_cmdparser.c
new file mode 100644
index 0000000..0f90ca4
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmoptional_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmoptional_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmoptional_cmdparser gfsmoptional.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmoptional"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmoptional_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmoptional (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Make a an automaton optional\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmoptional");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmoptional_cmdparser.h b/gfsm/gfsm/src/programs/gfsmoptional_cmdparser.h
new file mode 100644
index 0000000..566495e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmoptional_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmoptional_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmoptional_cmdparser_h
+#define gfsmoptional_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmoptional_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmoptional_main.c b/gfsm/gfsm/src/programs/gfsmoptional_main.c
new file mode 100644
index 0000000..73c442c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmoptional_main.c
@@ -0,0 +1,101 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmoptional_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmoptional";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * Utilities
+ *--------------------------------------------------------------------------*/
+#define bool2char(b) (b ? 'y' : 'n')
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(2);
+ }
+
+ //-- make optional
+ gfsm_automaton_optional(fsm);
+
+ //-- store automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,args.output_arg,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, args.output_arg, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmprint.gog b/gfsm/gfsm/src/programs/gfsmprint.gog
new file mode 100644
index 0000000..4a01ef2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmprint.gog
@@ -0,0 +1,80 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmprint"
+#program_version "0.01"
+
+purpose "Convert binary format gfsm files to text"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+argument "TXTFILE" "Output text file" \
+ details="
+If unspecified, output will be written to standard output.
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+string "ilabels" i "Specify input (lower) labels file." \
+ arg="LABELS"
+
+string "olabels" o "Specify output (upper) labels file." \
+ arg="LABELS"
+
+string "slabels" s "Specify state labels file." \
+ arg="LABELS"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="0" \
+ details="
+Specify zlib compression level of output file. -1 indicates
+the library default compression level, 0 (default) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmprint_cmdparser.c b/gfsm/gfsm/src/programs/gfsmprint_cmdparser.c
new file mode 100644
index 0000000..253eb1d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmprint_cmdparser.c
@@ -0,0 +1,498 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmprint_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmprint_cmdparser gfsmprint.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmprint"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmprint_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmprint (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Convert binary format gfsm files to text\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE TXTFILE\n", "gfsmprint");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+ printf(" TXTFILE Output text file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -iLABELS --ilabels=LABELS Specify input (lower) labels file.\n");
+ printf(" -oLABELS --olabels=LABELS Specify output (upper) labels file.\n");
+ printf(" -sLABELS --slabels=LABELS Specify state labels file.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->ilabels_arg = NULL;
+ args_info->olabels_arg = NULL;
+ args_info->slabels_arg = NULL;
+ args_info->compress_arg = 0;
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->ilabels_given = 0;
+ args_info->olabels_given = 0;
+ args_info->slabels_given = 0;
+ args_info->compress_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "ilabels", 1, NULL, 'i' },
+ { "olabels", 1, NULL, 'o' },
+ { "slabels", 1, NULL, 's' },
+ { "compress", 1, NULL, 'z' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'i', ':',
+ 'o', ':',
+ 's', ':',
+ 'z', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'i': /* Specify input (lower) labels file. */
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ break;
+
+ case 'o': /* Specify output (upper) labels file. */
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ break;
+
+ case 's': /* Specify state labels file. */
+ if (args_info->slabels_given) {
+ fprintf(stderr, "%s: `--slabels' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->slabels_given++;
+ if (args_info->slabels_arg) free(args_info->slabels_arg);
+ args_info->slabels_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify input (lower) labels file. */
+ else if (strcmp(olong, "ilabels") == 0) {
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ }
+
+ /* Specify output (upper) labels file. */
+ else if (strcmp(olong, "olabels") == 0) {
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ }
+
+ /* Specify state labels file. */
+ else if (strcmp(olong, "slabels") == 0) {
+ if (args_info->slabels_given) {
+ fprintf(stderr, "%s: `--slabels' (`-s') option given more than once\n", PROGRAM);
+ }
+ args_info->slabels_given++;
+ if (args_info->slabels_arg) free(args_info->slabels_arg);
+ args_info->slabels_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmprint_cmdparser.h b/gfsm/gfsm/src/programs/gfsmprint_cmdparser.h
new file mode 100644
index 0000000..0b06787
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmprint_cmdparser.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmprint_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmprint_cmdparser_h
+#define gfsmprint_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * ilabels_arg; /* Specify input (lower) labels file. (default=NULL). */
+ char * olabels_arg; /* Specify output (upper) labels file. (default=NULL). */
+ char * slabels_arg; /* Specify state labels file. (default=NULL). */
+ int compress_arg; /* Specify compression level of output file. (default=0). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int ilabels_given; /* Whether ilabels was given */
+ int olabels_given; /* Whether olabels was given */
+ int slabels_given; /* Whether slabels was given */
+ int compress_given; /* Whether compress was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmprint_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmprint_main.c b/gfsm/gfsm/src/programs/gfsmprint_main.c
new file mode 100644
index 0000000..fe6d7f3
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmprint_main.c
@@ -0,0 +1,125 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmprint_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmprint";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+gfsmAlphabet *ilabels=NULL, *olabels=NULL, *slabels=NULL;
+gfsmError *err = NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ if (args.inputs_num > 1) outfilename = args.inputs[1];
+
+ //-- labels: input
+ if (args.ilabels_given) {
+ ilabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(ilabels,args.ilabels_arg,&err)) {
+ g_printerr("%s: load failed for input-labels file '%s': %s\n",
+ progname, args.ilabels_arg, err->message);
+ exit(2);
+ }
+ }
+ //-- labels: output
+ if (args.olabels_given) {
+ olabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(olabels,args.olabels_arg,&err)) {
+ g_printerr("%s: load failed for output-labels file '%s': %s\n",
+ progname, args.olabels_arg, err->message);
+ exit(2);
+ }
+ }
+ //-- labels: state
+ if (args.slabels_given) {
+ slabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(slabels,args.slabels_arg,&err)) {
+ g_printerr("%s: load failed for state-labels file '%s': %s\n",
+ progname, args.slabels_arg, err->message);
+ exit(2);
+ }
+ }
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(3);
+ }
+
+ //-- print automaton
+ if (!gfsm_automaton_print_filename_full(fsm,outfilename,ilabels,olabels,slabels,args.compress_arg,&err)) {
+ g_printerr("%s: print failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(3);
+ }
+
+ //-- cleanup
+ if (ilabels) gfsm_alphabet_free(ilabels);
+ if (olabels) gfsm_alphabet_free(olabels);
+ if (slabels) gfsm_alphabet_free(slabels);
+ gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmproduct.gog b/gfsm/gfsm/src/programs/gfsmproduct.gog
new file mode 100644
index 0000000..120c823
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproduct.gog
@@ -0,0 +1,78 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmproduct"
+#program_version "0.01"
+
+purpose "Compute Cartesian product of finite state acceptors"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "LOWER" "Stored binary gfsm file" \
+ required=1 \
+ details="
+FSM accepting the lower side of the output FST.
+Required argument.
+"
+
+argument "UPPER" "Stored binary gfsm file" \
+ details="
+FSM accepting the upper side of the output FST.
+If unspecified, standard input will be read.
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmproduct_cmdparser.c b/gfsm/gfsm/src/programs/gfsmproduct_cmdparser.c
new file mode 100644
index 0000000..27fd759
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproduct_cmdparser.c
@@ -0,0 +1,450 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmproduct_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmproduct_cmdparser gfsmproduct.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmproduct"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmproduct_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmproduct (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compute Cartesian product of finite state acceptors\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... LOWER UPPER\n", "gfsmproduct");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" LOWER Stored binary gfsm file\n");
+ printf(" UPPER Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmproduct_cmdparser.h b/gfsm/gfsm/src/programs/gfsmproduct_cmdparser.h
new file mode 100644
index 0000000..527630e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproduct_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmproduct_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmproduct_cmdparser_h
+#define gfsmproduct_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmproduct_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmproduct_main.c b/gfsm/gfsm/src/programs/gfsmproduct_main.c
new file mode 100644
index 0000000..446e875
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproduct_main.c
@@ -0,0 +1,123 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmproduct_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmproduct";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename;
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsmOut=NULL, *fsmIn=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- require at least one file argument
+ if (args.inputs_num < 1) {
+ cmdline_parser_print_help();
+ exit(2);
+ }
+
+ //-- output
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsmIn = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * compute_operation()
+ * + utility routine
+ */
+void compute_operation(const char *infilename)
+{
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsmIn,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- compute product
+ if (fsmOut == NULL) {
+ fsmOut = fsmIn;
+ fsmIn = gfsm_automaton_new();
+ } else {
+ gfsm_automaton_product2(fsmOut,fsmIn); //-- dual-destructive version
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ int i;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ for (i = 0; i < args.inputs_num && i < 2; i++) {
+ compute_operation(args.inputs[i]);
+ }
+ if (args.inputs_num == 1) compute_operation("-");
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsmOut,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsmIn) gfsm_automaton_free(fsmIn);
+ if (fsmOut) gfsm_automaton_free(fsmOut);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmproject.gog b/gfsm/gfsm/src/programs/gfsmproject.gog
new file mode 100644
index 0000000..42fcb6c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproject.gog
@@ -0,0 +1,76 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmproject"
+#program_version "0.01"
+
+purpose "Project one side of finite state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+flag "first" 1 "Project lower side [default]."
+flag - i "Project input tape (alias for -1)"
+
+flag "second" 2 "Project upper side."
+flag - o "Project output side (alias for -2)"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmproject_cmdparser.c b/gfsm/gfsm/src/programs/gfsmproject_cmdparser.c
new file mode 100644
index 0000000..5905210
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproject_cmdparser.c
@@ -0,0 +1,523 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmproject_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmproject_cmdparser gfsmproject.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmproject"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmproject_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmproject (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Project one side of finite state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmproject");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -1 --first Project lower side [default].\n");
+ printf(" -i Project input tape (alias for -1)\n");
+ printf(" -2 --second Project upper side.\n");
+ printf(" -o Project output side (alias for -2)\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->first_flag = 0;
+ args_info->i_flag = 0;
+ args_info->second_flag = 0;
+ args_info->o_flag = 0;
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->first_given = 0;
+ args_info->i_given = 0;
+ args_info->second_given = 0;
+ args_info->o_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "first", 0, NULL, '1' },
+ { "second", 0, NULL, '2' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ '1',
+ 'i',
+ '2',
+ 'o',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case '1': /* Project lower side [default]. */
+ if (args_info->first_given) {
+ fprintf(stderr, "%s: `--first' (`-1') option given more than once\n", PROGRAM);
+ }
+ args_info->first_given++;
+ if (args_info->first_given <= 1)
+ args_info->first_flag = !(args_info->first_flag);
+ break;
+
+ case 'i': /* Project input tape (alias for -1) */
+ if (args_info->i_given) {
+ fprintf(stderr, "%s: (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->i_given++;
+ if (args_info->i_given <= 1)
+ args_info->i_flag = !(args_info->i_flag);
+ break;
+
+ case '2': /* Project upper side. */
+ if (args_info->second_given) {
+ fprintf(stderr, "%s: `--second' (`-2') option given more than once\n", PROGRAM);
+ }
+ args_info->second_given++;
+ if (args_info->second_given <= 1)
+ args_info->second_flag = !(args_info->second_flag);
+ break;
+
+ case 'o': /* Project output side (alias for -2) */
+ if (args_info->o_given) {
+ fprintf(stderr, "%s: (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->o_given++;
+ if (args_info->o_given <= 1)
+ args_info->o_flag = !(args_info->o_flag);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Project lower side [default]. */
+ else if (strcmp(olong, "first") == 0) {
+ if (args_info->first_given) {
+ fprintf(stderr, "%s: `--first' (`-1') option given more than once\n", PROGRAM);
+ }
+ args_info->first_given++;
+ if (args_info->first_given <= 1)
+ args_info->first_flag = !(args_info->first_flag);
+ }
+
+ /* Project upper side. */
+ else if (strcmp(olong, "second") == 0) {
+ if (args_info->second_given) {
+ fprintf(stderr, "%s: `--second' (`-2') option given more than once\n", PROGRAM);
+ }
+ args_info->second_given++;
+ if (args_info->second_given <= 1)
+ args_info->second_flag = !(args_info->second_flag);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmproject_cmdparser.h b/gfsm/gfsm/src/programs/gfsmproject_cmdparser.h
new file mode 100644
index 0000000..e7fbb80
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproject_cmdparser.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmproject_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmproject_cmdparser_h
+#define gfsmproject_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int first_flag; /* Project lower side [default]. (default=0). */
+ int i_flag; /* Project input tape (alias for -1) (default=0). */
+ int second_flag; /* Project upper side. (default=0). */
+ int o_flag; /* Project output side (alias for -2) (default=0). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int first_given; /* Whether first was given */
+ int i_given; /* Whether - was given */
+ int second_given; /* Whether second was given */
+ int o_given; /* Whether - was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmproject_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmproject_main.c b/gfsm/gfsm/src/programs/gfsmproject_main.c
new file mode 100644
index 0000000..528b456
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmproject_main.c
@@ -0,0 +1,100 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmproject_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmproject";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs & vars
+gfsmAutomaton *fsm;
+gfsmLabelSide which = gfsmLSLower;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- which?
+ if (args.second_given || args.o_given) which = gfsmLSUpper;
+ else which = gfsmLSLower;
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- invert
+ gfsm_automaton_project(fsm,which);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmrenumber.gog b/gfsm/gfsm/src/programs/gfsmrenumber.gog
new file mode 100644
index 0000000..df2d0b6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrenumber.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmrenumber"
+#program_version "0.01"
+
+purpose "Renumber states in finite state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.c b/gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.c
new file mode 100644
index 0000000..a058eb2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmrenumber_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmrenumber_cmdparser gfsmrenumber.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmrenumber"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmrenumber_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmrenumber (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Renumber states in finite state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmrenumber");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.h b/gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.h
new file mode 100644
index 0000000..08db747
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmrenumber_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmrenumber_cmdparser_h
+#define gfsmrenumber_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmrenumber_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmrenumber_main.c b/gfsm/gfsm/src/programs/gfsmrenumber_main.c
new file mode 100644
index 0000000..7bf7a59
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrenumber_main.c
@@ -0,0 +1,95 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmrenumber_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmrenumber";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- renumber
+ gfsm_automaton_renumber_states(fsm);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmreplace.gog b/gfsm/gfsm/src/programs/gfsmreplace.gog
new file mode 100644
index 0000000..466526d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreplace.gog
@@ -0,0 +1,79 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmreplace"
+#program_version "0.01"
+
+purpose "Replace some automaton arcs with a whole automaton"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+string "replacement" r "Replacement automaton (binary gfsm file)" \
+ arg="FSMFILE" \
+ default="-" \
+ details="
+If unspecified, standard input will be read.
+"
+
+int "lower" l "Lower label to replace (default=any)" \
+ arg="LABEL"
+
+int "upper" u "Upper label to replace (default=any)" \
+ arg="LABEL"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmreplace_cmdparser.c b/gfsm/gfsm/src/programs/gfsmreplace_cmdparser.c
new file mode 100644
index 0000000..652c7a7
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreplace_cmdparser.c
@@ -0,0 +1,514 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmreplace_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmreplace_cmdparser gfsmreplace.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmreplace"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmreplace_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmreplace (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Replace some automaton arcs with a whole automaton\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... [FILES]...\n", "gfsmreplace");
+
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -rFSMFILE --replacement=FSMFILE Replacement automaton (binary gfsm file)\n");
+ printf(" -lLABEL --lower=LABEL Lower label to replace (default=any)\n");
+ printf(" -uLABEL --upper=LABEL Upper label to replace (default=any)\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->replacement_arg = strdup("-");
+ args_info->lower_arg = 0;
+ args_info->upper_arg = 0;
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->replacement_given = 0;
+ args_info->lower_given = 0;
+ args_info->upper_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "replacement", 1, NULL, 'r' },
+ { "lower", 1, NULL, 'l' },
+ { "upper", 1, NULL, 'u' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'r', ':',
+ 'l', ':',
+ 'u', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'r': /* Replacement automaton (binary gfsm file) */
+ if (args_info->replacement_given) {
+ fprintf(stderr, "%s: `--replacement' (`-r') option given more than once\n", PROGRAM);
+ }
+ args_info->replacement_given++;
+ if (args_info->replacement_arg) free(args_info->replacement_arg);
+ args_info->replacement_arg = strdup(val);
+ break;
+
+ case 'l': /* Lower label to replace (default=any) */
+ if (args_info->lower_given) {
+ fprintf(stderr, "%s: `--lower' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->lower_given++;
+ args_info->lower_arg = (int)atoi(val);
+ break;
+
+ case 'u': /* Upper label to replace (default=any) */
+ if (args_info->upper_given) {
+ fprintf(stderr, "%s: `--upper' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->upper_given++;
+ args_info->upper_arg = (int)atoi(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Replacement automaton (binary gfsm file) */
+ else if (strcmp(olong, "replacement") == 0) {
+ if (args_info->replacement_given) {
+ fprintf(stderr, "%s: `--replacement' (`-r') option given more than once\n", PROGRAM);
+ }
+ args_info->replacement_given++;
+ if (args_info->replacement_arg) free(args_info->replacement_arg);
+ args_info->replacement_arg = strdup(val);
+ }
+
+ /* Lower label to replace (default=any) */
+ else if (strcmp(olong, "lower") == 0) {
+ if (args_info->lower_given) {
+ fprintf(stderr, "%s: `--lower' (`-l') option given more than once\n", PROGRAM);
+ }
+ args_info->lower_given++;
+ args_info->lower_arg = (int)atoi(val);
+ }
+
+ /* Upper label to replace (default=any) */
+ else if (strcmp(olong, "upper") == 0) {
+ if (args_info->upper_given) {
+ fprintf(stderr, "%s: `--upper' (`-u') option given more than once\n", PROGRAM);
+ }
+ args_info->upper_given++;
+ args_info->upper_arg = (int)atoi(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmreplace_cmdparser.h b/gfsm/gfsm/src/programs/gfsmreplace_cmdparser.h
new file mode 100644
index 0000000..f7c704d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreplace_cmdparser.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmreplace_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmreplace_cmdparser_h
+#define gfsmreplace_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * replacement_arg; /* Replacement automaton (binary gfsm file) (default=-). */
+ int lower_arg; /* Lower label to replace (default=any) (default=0). */
+ int upper_arg; /* Upper label to replace (default=any) (default=0). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int replacement_given; /* Whether replacement was given */
+ int lower_given; /* Whether lower was given */
+ int upper_given; /* Whether upper was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmreplace_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmreplace_main.c b/gfsm/gfsm/src/programs/gfsmreplace_main.c
new file mode 100644
index 0000000..c2b1107
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreplace_main.c
@@ -0,0 +1,108 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <gfsm.h>
+
+#include "gfsmreplace_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmreplace";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *replfilename = "-";
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *repl = NULL, *fsm=NULL;
+gfsmError *err = NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.replacement_given) replfilename = args.replacement_arg;
+ outfilename = args.output_arg;
+
+ //-- load replacement automaton
+ repl = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(repl, replfilename, &err)) {
+ g_printerr("%s: load failed for FST file '%s': %s\n", progname, replfilename, err->message);
+ exit(255);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- load input automaton
+ fsm = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- perform replacement
+ gfsm_automaton_replace(fsm,
+ (args.lower_given ? args.lower_arg : gfsmNoLabel),
+ (args.upper_given ? args.upper_arg : gfsmNoLabel),
+ repl);
+
+ //-- save output
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (repl) gfsm_automaton_free(repl);
+ if (fsm) gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmreverse.gog b/gfsm/gfsm/src/programs/gfsmreverse.gog
new file mode 100644
index 0000000..f67c417
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreverse.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmreverse"
+#program_version "0.01"
+
+purpose "Reverse a finite state machine"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read.
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmreverse_cmdparser.c b/gfsm/gfsm/src/programs/gfsmreverse_cmdparser.c
new file mode 100644
index 0000000..f992776
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreverse_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmreverse_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmreverse_cmdparser gfsmreverse.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmreverse"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmreverse_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmreverse (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Reverse a finite state machine\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmreverse");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmreverse_cmdparser.h b/gfsm/gfsm/src/programs/gfsmreverse_cmdparser.h
new file mode 100644
index 0000000..81ed264
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreverse_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmreverse_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmreverse_cmdparser_h
+#define gfsmreverse_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmreverse_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmreverse_main.c b/gfsm/gfsm/src/programs/gfsmreverse_main.c
new file mode 100644
index 0000000..e2b24f1
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmreverse_main.c
@@ -0,0 +1,101 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmreverse_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmreverse";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs & vars
+gfsmAutomaton *fsm;
+int which = 1;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- invert
+ gfsm_automaton_reverse(fsm);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmrmepsilon.gog b/gfsm/gfsm/src/programs/gfsmrmepsilon.gog
new file mode 100644
index 0000000..e1b78d6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrmepsilon.gog
@@ -0,0 +1,80 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmrmepsilon"
+#program_version "0.01"
+
+purpose "Remove epsilon arcs from finite state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+=over 4
+
+=item
+
+No negative-cost epsilon cycles are allowed in the input automaton.
+
+=item
+
+Probably many more.
+
+=back
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.c b/gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.c
new file mode 100644
index 0000000..1f4351f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmrmepsilon_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmrmepsilon_cmdparser gfsmrmepsilon.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmrmepsilon"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmrmepsilon_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmrmepsilon (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Remove epsilon arcs from finite state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmrmepsilon");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.h b/gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.h
new file mode 100644
index 0000000..e9deda5
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmrmepsilon_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmrmepsilon_cmdparser_h
+#define gfsmrmepsilon_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmrmepsilon_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmrmepsilon_main.c b/gfsm/gfsm/src/programs/gfsmrmepsilon_main.c
new file mode 100644
index 0000000..ec3e899
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmrmepsilon_main.c
@@ -0,0 +1,95 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmrmepsilon_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmrmepsilon";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fsm;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) infilename = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsm = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmError *err = NULL;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- rmepsilon
+ gfsm_automaton_rmepsilon(fsm);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsm,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsm) gfsm_automaton_free(fsm);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmsigma.gog b/gfsm/gfsm/src/programs/gfsmsigma.gog
new file mode 100644
index 0000000..68b7243
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmsigma.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmsigma"
+#program_version "0.01"
+
+purpose "Create a single-state alphabet acceptor"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "LABFILE" "Alphabet file" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmsigma_cmdparser.c b/gfsm/gfsm/src/programs/gfsmsigma_cmdparser.c
new file mode 100644
index 0000000..7cf017f
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmsigma_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmsigma_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmsigma_cmdparser gfsmsigma.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmsigma"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmsigma_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmsigma (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Create a single-state alphabet acceptor\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... LABFILE\n", "gfsmsigma");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" LABFILE Alphabet file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmsigma_cmdparser.h b/gfsm/gfsm/src/programs/gfsmsigma_cmdparser.h
new file mode 100644
index 0000000..4a7832c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmsigma_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmsigma_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmsigma_cmdparser_h
+#define gfsmsigma_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmsigma_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmsigma_main.c b/gfsm/gfsm/src/programs/gfsmsigma_main.c
new file mode 100644
index 0000000..ce5c59d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmsigma_main.c
@@ -0,0 +1,100 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmsigma_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmsigma";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *abetname = "-";
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsmOut=NULL;
+gfsmAlphabet *abet=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- output
+ if (args.inputs_num) abetname = args.inputs[0];
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- initialize automaton
+ fsmOut = gfsm_automaton_new();
+}
+
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ //-- load alphabet
+ abet = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(abet, abetname, &err)) {
+ g_printerr("%s: load failed for alphabet file '%s': %s\n",
+ progname, abetname, err->message);
+ exit(2);
+ }
+
+ //-- compute operation
+ gfsm_automaton_sigma(fsmOut,abet);
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsmOut,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (abet) gfsm_alphabet_free(abet);
+ if (fsmOut) gfsm_automaton_free(fsmOut);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmstrings.gog b/gfsm/gfsm/src/programs/gfsmstrings.gog
new file mode 100644
index 0000000..5672f36
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmstrings.gog
@@ -0,0 +1,76 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmstrings"
+#program_version "0.01"
+
+purpose "Serialize binary acyclic gfsm files to lists of strings"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+#details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/gfsmrc"
+#rcfile "~/.gfsmrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE" "Stored binary gfsm file" \
+ details="
+If unspecified, standard input will be read.
+"
+
+#-----------------------------------------------------------------------------
+# Common Options
+#-----------------------------------------------------------------------------
+group "Common Options"
+
+string "ilabels" i "Specify input (lower) labels file." \
+ arg="LABELS"
+
+string "olabels" o "Specify output (upper) labels file." \
+ arg="LABELS"
+
+flag "att" a "Output in AT&T regex format." \
+ default=0
+
+flag "viterbi" v "Treat input automaton as a Viterbi trellis." \
+ default=0
+
+string "output" F "Output file." \
+ arg="TXTFILE" \
+ details="
+Default behavior is to write to stdout.
+"
+
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>,
+"
diff --git a/gfsm/gfsm/src/programs/gfsmstrings_cmdparser.c b/gfsm/gfsm/src/programs/gfsmstrings_cmdparser.c
new file mode 100644
index 0000000..6f2c30b
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmstrings_cmdparser.c
@@ -0,0 +1,525 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmstrings_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmstrings_cmdparser gfsmstrings.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmstrings"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmstrings_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmstrings (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Serialize binary acyclic gfsm files to lists of strings\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE\n", "gfsmstrings");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE Stored binary gfsm file\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf("\n");
+ printf(" Common Options:\n");
+ printf(" -iLABELS --ilabels=LABELS Specify input (lower) labels file.\n");
+ printf(" -oLABELS --olabels=LABELS Specify output (upper) labels file.\n");
+ printf(" -a --att Output in AT&T regex format.\n");
+ printf(" -v --viterbi Treat input automaton as a Viterbi trellis.\n");
+ printf(" -FTXTFILE --output=TXTFILE Output file.\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->ilabels_arg = NULL;
+ args_info->olabels_arg = NULL;
+ args_info->att_flag = 0;
+ args_info->viterbi_flag = 0;
+ args_info->output_arg = NULL;
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->ilabels_given = 0;
+ args_info->olabels_given = 0;
+ args_info->att_given = 0;
+ args_info->viterbi_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "ilabels", 1, NULL, 'i' },
+ { "olabels", 1, NULL, 'o' },
+ { "att", 0, NULL, 'a' },
+ { "viterbi", 0, NULL, 'v' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'i', ':',
+ 'o', ':',
+ 'a',
+ 'v',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'i': /* Specify input (lower) labels file. */
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ break;
+
+ case 'o': /* Specify output (upper) labels file. */
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ break;
+
+ case 'a': /* Output in AT&T regex format. */
+ if (args_info->att_given) {
+ fprintf(stderr, "%s: `--att' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->att_given++;
+ if (args_info->att_given <= 1)
+ args_info->att_flag = !(args_info->att_flag);
+ break;
+
+ case 'v': /* Treat input automaton as a Viterbi trellis. */
+ if (args_info->viterbi_given) {
+ fprintf(stderr, "%s: `--viterbi' (`-v') option given more than once\n", PROGRAM);
+ }
+ args_info->viterbi_given++;
+ if (args_info->viterbi_given <= 1)
+ args_info->viterbi_flag = !(args_info->viterbi_flag);
+ break;
+
+ case 'F': /* Output file. */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify input (lower) labels file. */
+ else if (strcmp(olong, "ilabels") == 0) {
+ if (args_info->ilabels_given) {
+ fprintf(stderr, "%s: `--ilabels' (`-i') option given more than once\n", PROGRAM);
+ }
+ args_info->ilabels_given++;
+ if (args_info->ilabels_arg) free(args_info->ilabels_arg);
+ args_info->ilabels_arg = strdup(val);
+ }
+
+ /* Specify output (upper) labels file. */
+ else if (strcmp(olong, "olabels") == 0) {
+ if (args_info->olabels_given) {
+ fprintf(stderr, "%s: `--olabels' (`-o') option given more than once\n", PROGRAM);
+ }
+ args_info->olabels_given++;
+ if (args_info->olabels_arg) free(args_info->olabels_arg);
+ args_info->olabels_arg = strdup(val);
+ }
+
+ /* Output in AT&T regex format. */
+ else if (strcmp(olong, "att") == 0) {
+ if (args_info->att_given) {
+ fprintf(stderr, "%s: `--att' (`-a') option given more than once\n", PROGRAM);
+ }
+ args_info->att_given++;
+ if (args_info->att_given <= 1)
+ args_info->att_flag = !(args_info->att_flag);
+ }
+
+ /* Treat input automaton as a Viterbi trellis. */
+ else if (strcmp(olong, "viterbi") == 0) {
+ if (args_info->viterbi_given) {
+ fprintf(stderr, "%s: `--viterbi' (`-v') option given more than once\n", PROGRAM);
+ }
+ args_info->viterbi_given++;
+ if (args_info->viterbi_given <= 1)
+ args_info->viterbi_flag = !(args_info->viterbi_flag);
+ }
+
+ /* Output file. */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmstrings_cmdparser.h b/gfsm/gfsm/src/programs/gfsmstrings_cmdparser.h
new file mode 100644
index 0000000..51e085e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmstrings_cmdparser.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmstrings_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmstrings_cmdparser_h
+#define gfsmstrings_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * ilabels_arg; /* Specify input (lower) labels file. (default=NULL). */
+ char * olabels_arg; /* Specify output (upper) labels file. (default=NULL). */
+ int att_flag; /* Output in AT&T regex format. (default=0). */
+ int viterbi_flag; /* Treat input automaton as a Viterbi trellis. (default=0). */
+ char * output_arg; /* Output file. (default=NULL). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int ilabels_given; /* Whether ilabels was given */
+ int olabels_given; /* Whether olabels was given */
+ int att_given; /* Whether att was given */
+ int viterbi_given; /* Whether viterbi was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmstrings_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmstrings_main.c b/gfsm/gfsm/src/programs/gfsmstrings_main.c
new file mode 100644
index 0000000..4b561e6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmstrings_main.c
@@ -0,0 +1,153 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmstrings_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmstrings";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename = "-";
+const char *outfilename = "-";
+FILE *outfile = NULL;
+
+//-- global structs
+gfsmAutomaton *fsm;
+gfsmAlphabet *ilabels=NULL, *olabels=NULL;
+gfsmError *err = NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.inputs_num > 0) infilename = args.inputs[0];
+ if (args.output_given) outfilename = args.output_arg;
+
+ //-- labels: input
+ if (args.ilabels_given) {
+ ilabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(ilabels,args.ilabels_arg,&err)) {
+ g_printerr("%s: load failed for input-labels file '%s': %s\n",
+ progname, args.ilabels_arg, (err ? err->message : "?"));
+ exit(2);
+ }
+ }
+ //-- labels: output
+ if (args.olabels_given) {
+ olabels = gfsm_string_alphabet_new();
+ if (!gfsm_alphabet_load_filename(olabels,args.olabels_arg,&err)) {
+ g_printerr("%s: load failed for output-labels file '%s': %s\n",
+ progname, args.olabels_arg, (err ? err->message : "?"));
+ exit(2);
+ }
+ }
+
+ //-- initialize fsm
+ fsm = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmSet *paths = NULL;
+ GSList *strings = NULL;
+ get_my_options(argc,argv);
+
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsm,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, (err ? err->message : "?"));
+ exit(3);
+ }
+
+ //-- sanity check
+ if (gfsm_automaton_is_cyclic(fsm)) {
+ g_printerr("%s: input automaton must be acyclic!\n", progname);
+ exit(255);
+ }
+
+ //-- open output file
+ outfile = gfsm_open_filename(outfilename, "w", &err);
+ if (!outfile) {
+ g_printerr("%s: %s\n", progname, (err ? err->message : "?"));
+ exit(4);
+ }
+
+
+ //-- get & stringify full paths
+ if (args.viterbi_flag) {
+ //-- serialize Viterbi trellis automaton
+ paths = gfsm_viterbi_trellis_paths_full(fsm, NULL, gfsmLSBoth);
+ }
+ else {
+ //-- serialize "normal" automaton
+ paths = gfsm_automaton_paths_full(fsm, NULL, gfsmLSBoth);
+ }
+ strings = gfsm_paths_to_strings(paths,
+ ilabels,
+ olabels,
+ fsm->sr,
+ TRUE,
+ args.att_given,
+ NULL);
+ while (strings) {
+ //-- pop first datum
+ char *s = (char *)strings->data;
+ strings = g_slist_delete_link(strings,strings);
+
+ //-- print string
+ fputs(s, outfile);
+ fputc('\n', outfile);
+
+ g_free(s);
+ }
+
+ //-- cleanup
+ if (paths) gfsm_set_free(paths);
+ if (ilabels) gfsm_alphabet_free(ilabels);
+ if (olabels) gfsm_alphabet_free(olabels);
+ if (fsm) gfsm_automaton_free(fsm);
+
+ if (outfile != stdout) fclose(outfile);
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmunion.gog b/gfsm/gfsm/src/programs/gfsmunion.gog
new file mode 100644
index 0000000..96d84e2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmunion.gog
@@ -0,0 +1,70 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmunion"
+#program_version "0.01"
+
+purpose "Compute union of finite state machines"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "BINFILE(s)" "Stored binary gfsm file(s)" \
+ details="
+If unspecified, standard input will be read
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+None known.
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmunion_cmdparser.c b/gfsm/gfsm/src/programs/gfsmunion_cmdparser.c
new file mode 100644
index 0000000..31aafa8
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmunion_cmdparser.c
@@ -0,0 +1,449 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmunion_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmunion_cmdparser gfsmunion.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmunion"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmunion_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmunion (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" Compute union of finite state machines\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... BINFILE(s)\n", "gfsmunion");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" BINFILE(s) Stored binary gfsm file(s)\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmunion_cmdparser.h b/gfsm/gfsm/src/programs/gfsmunion_cmdparser.h
new file mode 100644
index 0000000..6086492
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmunion_cmdparser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmunion_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmunion_cmdparser_h
+#define gfsmunion_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmunion_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmunion_main.c b/gfsm/gfsm/src/programs/gfsmunion_main.c
new file mode 100644
index 0000000..dd7998d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmunion_main.c
@@ -0,0 +1,123 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2004 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gfsm.h>
+
+#include "gfsmunion_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmunion";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *infilename;
+const char *outfilename = "-";
+
+//-- global structs etc.
+gfsmError *err = NULL;
+gfsmAutomaton *fsmUnion=NULL, *fsmIn=NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- require at least one file argument
+ if (args.inputs_num < 1) {
+ cmdline_parser_print_help();
+ exit(2);
+ }
+
+ //-- output
+ if (args.output_arg) outfilename = args.output_arg;
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- initialize automaton
+ fsmIn = gfsm_automaton_new();
+}
+
+/*--------------------------------------------------------------------------
+ * compute_union()
+ * + utility routine
+ */
+void compute_union(const char *infilename)
+{
+ //-- load automaton
+ if (!gfsm_automaton_load_bin_filename(fsmIn,infilename,&err)) {
+ g_printerr("%s: load failed for '%s': %s\n", progname, infilename, err->message);
+ exit(255);
+ }
+
+ //-- compute union
+ if (fsmUnion == NULL) {
+ fsmUnion = fsmIn;
+ fsmIn = gfsm_automaton_new();
+ } else {
+ gfsm_automaton_union(fsmUnion,fsmIn);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ int i;
+
+ GFSM_INIT
+
+ get_my_options(argc,argv);
+
+ for (i = 0; i < args.inputs_num; i++) {
+ compute_union(args.inputs[i]);
+ }
+ if (args.inputs_num == 1) compute_union("-");
+
+ //-- spew automaton
+ if (!gfsm_automaton_save_bin_filename(fsmUnion,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fsmIn) gfsm_automaton_free(fsmIn);
+ if (fsmUnion) gfsm_automaton_free(fsmUnion);
+
+ GFSM_FINISH
+
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmview.sh b/gfsm/gfsm/src/programs/gfsmview.sh
new file mode 100755
index 0000000..d8df9c2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmview.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+GFSMDRAW=./gfsmdraw
+DOTGV=dotgv.sh
+
+exec $GFSMDRAW "$@" | $DOTGV
diff --git a/gfsm/gfsm/src/programs/gfsmviterbi.gog b/gfsm/gfsm/src/programs/gfsmviterbi.gog
new file mode 100644
index 0000000..827d26e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmviterbi.gog
@@ -0,0 +1,88 @@
+# -*- Mode: Shell-Script -*-
+#
+# Getopt::Gen specification
+#-----------------------------------------------------------------------------
+program "gfsmviterbi"
+#program_version "0.01"
+
+purpose "EXPERIMENTAL: Compute Viterbi trellis for a linear label sequence in a transducer"
+author "Bryan Jurish <moocow@ling.uni-potsdam.de>"
+on_reparse "warn"
+
+#-----------------------------------------------------------------------------
+# Details
+#-----------------------------------------------------------------------------
+details ""
+
+#-----------------------------------------------------------------------------
+# Files
+#-----------------------------------------------------------------------------
+#rcfile "/etc/mootrc"
+#rcfile "~/.mootrc"
+
+#-----------------------------------------------------------------------------
+# Arguments
+#-----------------------------------------------------------------------------
+argument "LABELID..." "Input label IDs" \
+ details="
+In ASCII decimal notation.
+"
+
+#-----------------------------------------------------------------------------
+# Options
+#-----------------------------------------------------------------------------
+#group "Basic Options"
+
+string "fst" f "Weighted transducer to apply (default=stdin)." \
+ arg="FSTFILE" \
+ default="-" \
+ details="
+If unspecified, standard input will be read.
+"
+
+int "compress" z "Specify compression level of output file." \
+ arg="LEVEL" \
+ default="-1" \
+ details="
+Specify zlib compression level of output file. -1 (default) indicates
+the default compression level, 0 (zero) indicates no zlib compression at all,
+and 9 indicates the best possible compression.
+"
+
+string "output" F "Specifiy output file (default=stdout)." \
+ arg="FILE" \
+ default="-"
+
+#-----------------------------------------------------------------------------
+# Addenda
+#-----------------------------------------------------------------------------
+#addenda ""
+
+#-----------------------------------------------------------------------------
+# Bugs
+#-----------------------------------------------------------------------------
+bugs "
+
+=over 4
+
+=item
+
+No negative-cost epsilon cycles are allowed in the transducer.
+
+=item
+
+The Viterbi API, the existence of the gfsmviterbi command-line program,
+its arguments & optiosn, etc. are HIGHLY UNSTABLE.
+
+=back
+
+"
+
+#-----------------------------------------------------------------------------
+# Footer
+#-----------------------------------------------------------------------------
+#acknowledge `cat acknowledge.pod`
+
+seealso "
+L<gfsmutils>
+"
diff --git a/gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.c b/gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.c
new file mode 100644
index 0000000..f4de7a9
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.c
@@ -0,0 +1,473 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmviterbi_cmdparser.c
+ * Description: Code for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05
+ * generated with the following command:
+ * /usr/local/bin/optgen.perl -u -l --no-handle-rcfile --nopod -F gfsmviterbi_cmdparser gfsmviterbi.gog
+ *
+ * The developers of optgen.perl consider the fixed text that goes in all
+ * optgen.perl output files to be in the public domain:
+ * we make no copyright claims on it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* If we use autoconf/autoheader. */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+/* Allow user-overrides for PACKAGE and VERSION */
+#ifndef PACKAGE
+# define PACKAGE "PACKAGE"
+#endif
+
+#ifndef VERSION
+# define VERSION "VERSION"
+#endif
+
+
+#ifndef PROGRAM
+# define PROGRAM "gfsmviterbi"
+#endif
+
+/* #define cmdline_parser_DEBUG */
+
+/* Check for "configure's" getopt check result. */
+#ifndef HAVE_GETOPT_LONG
+# include "getopt.h"
+#else
+# include <getopt.h>
+#endif
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+# define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "gfsmviterbi_cmdparser.h"
+
+
+/* user code section */
+
+/* end user code section */
+
+
+void
+cmdline_parser_print_version (void)
+{
+ printf("gfsmviterbi (%s %s) by Bryan Jurish <moocow@ling.uni-potsdam.de>\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ cmdline_parser_print_version ();
+ printf("\n");
+ printf("Purpose:\n");
+ printf(" EXPERIMENTAL: Compute Viterbi trellis for a linear label sequence in a transducer\n");
+ printf("\n");
+
+ printf("Usage: %s [OPTIONS]... LABELID...\n", "gfsmviterbi");
+
+ printf("\n");
+ printf(" Arguments:\n");
+ printf(" LABELID... Input label IDs\n");
+
+ printf("\n");
+ printf(" Options:\n");
+ printf(" -h --help Print help and exit.\n");
+ printf(" -V --version Print version and exit.\n");
+ printf(" -fFSTFILE --fst=FSTFILE Weighted transducer to apply (default=stdin).\n");
+ printf(" -zLEVEL --compress=LEVEL Specify compression level of output file.\n");
+ printf(" -FFILE --output=FILE Specifiy output file (default=stdout).\n");
+}
+
+#if !defined(HAVE_STRDUP) && !defined(strdup)
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+#endif /* HAVE_STRDUP */
+
+/* clear_args(args_info): clears all args & resets to defaults */
+static void
+clear_args(struct gengetopt_args_info *args_info)
+{
+ args_info->fst_arg = strdup("-");
+ args_info->compress_arg = -1;
+ args_info->output_arg = strdup("-");
+}
+
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+ int c; /* Character of the parsed option. */
+ int missing_required_options = 0;
+
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->fst_given = 0;
+ args_info->compress_given = 0;
+ args_info->output_given = 0;
+
+ clear_args(args_info);
+
+ /* rcfile handling */
+
+ /* end rcfile handling */
+
+ optarg = 0;
+ optind = 1;
+ opterr = 1;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "fst", 1, NULL, 'f' },
+ { "compress", 1, NULL, 'z' },
+ { "output", 1, NULL, 'F' },
+ { NULL, 0, NULL, 0 }
+ };
+ static char short_options[] = {
+ 'h',
+ 'V',
+ 'f', ':',
+ 'z', ':',
+ 'F', ':',
+ '\0'
+ };
+
+ c = getopt_long (argc, argv, short_options, long_options, &option_index);
+
+ if (c == -1) break; /* Exit from 'while (1)' loop. */
+
+ if (cmdline_parser_parse_option(c, long_options[option_index].name, optarg, args_info) != 0) {
+ exit (EXIT_FAILURE);
+ }
+ } /* while */
+
+
+
+ if ( missing_required_options )
+ exit (EXIT_FAILURE);
+
+
+ if (optind < argc) {
+ int i = 0 ;
+ args_info->inputs_num = argc - optind ;
+ args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
+ while (optind < argc)
+ args_info->inputs[ i++ ] = strdup (argv[optind++]) ;
+ }
+
+ return 0;
+}
+
+
+/* Parse a single option */
+int
+cmdline_parser_parse_option(char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info)
+{
+ if (!oshort && !(olong && *olong)) return 1; /* ignore null options */
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "parse_option(): oshort='%c', olong='%s', val='%s'\n", oshort, olong, val);*/
+#endif
+
+ switch (oshort)
+ {
+ case 'h': /* Print help and exit. */
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'V': /* Print version and exit. */
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ break;
+
+ case 'f': /* Weighted transducer to apply (default=stdin). */
+ if (args_info->fst_given) {
+ fprintf(stderr, "%s: `--fst' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->fst_given++;
+ if (args_info->fst_arg) free(args_info->fst_arg);
+ args_info->fst_arg = strdup(val);
+ break;
+
+ case 'z': /* Specify compression level of output file. */
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ break;
+
+ case 'F': /* Specifiy output file (default=stdout). */
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ break;
+
+ case 0: /* Long option(s) with no short form */
+ /* Print help and exit. */
+ if (strcmp(olong, "help") == 0) {
+ if (args_info->help_given) {
+ fprintf(stderr, "%s: `--help' (`-h') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_help();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Print version and exit. */
+ else if (strcmp(olong, "version") == 0) {
+ if (args_info->version_given) {
+ fprintf(stderr, "%s: `--version' (`-V') option given more than once\n", PROGRAM);
+ }
+ clear_args(args_info);
+ cmdline_parser_print_version();
+ exit(EXIT_SUCCESS);
+
+ }
+
+ /* Weighted transducer to apply (default=stdin). */
+ else if (strcmp(olong, "fst") == 0) {
+ if (args_info->fst_given) {
+ fprintf(stderr, "%s: `--fst' (`-f') option given more than once\n", PROGRAM);
+ }
+ args_info->fst_given++;
+ if (args_info->fst_arg) free(args_info->fst_arg);
+ args_info->fst_arg = strdup(val);
+ }
+
+ /* Specify compression level of output file. */
+ else if (strcmp(olong, "compress") == 0) {
+ if (args_info->compress_given) {
+ fprintf(stderr, "%s: `--compress' (`-z') option given more than once\n", PROGRAM);
+ }
+ args_info->compress_given++;
+ args_info->compress_arg = (int)atoi(val);
+ }
+
+ /* Specifiy output file (default=stdout). */
+ else if (strcmp(olong, "output") == 0) {
+ if (args_info->output_given) {
+ fprintf(stderr, "%s: `--output' (`-F') option given more than once\n", PROGRAM);
+ }
+ args_info->output_given++;
+ if (args_info->output_arg) free(args_info->output_arg);
+ args_info->output_arg = strdup(val);
+ }
+
+ else {
+ fprintf(stderr, "%s: unknown long option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+ }
+ break;
+
+ case '?': /* Invalid Option */
+ fprintf(stderr, "%s: unknown option '%s'.\n", PROGRAM, olong);
+ return (EXIT_FAILURE);
+
+
+ default: /* bug: options not considered. */
+ fprintf (stderr, "%s: option unknown: %c\n", PROGRAM, oshort);
+ abort ();
+ } /* switch */
+ return 0;
+}
+
+
+/* Initialize options not yet given from environmental defaults */
+void
+cmdline_parser_envdefaults(struct gengetopt_args_info *args_info)
+{
+
+
+ return;
+}
+
+
+/* Load option values from an .rc file */
+void
+cmdline_parser_read_rcfile(const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified)
+{
+ char *fullname;
+ FILE *rcfile;
+
+ if (!filename) return; /* ignore NULL filenames */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
+ if (*filename == '~') {
+ /* tilde-expansion hack */
+ struct passwd *pwent = getpwuid(getuid());
+ if (!pwent) {
+ fprintf(stderr, "%s: user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ if (!pwent->pw_dir) {
+ fprintf(stderr, "%s: home directory for user-id %d not found!\n", PROGRAM, getuid());
+ return;
+ }
+ fullname = (char *)malloc(strlen(pwent->pw_dir)+strlen(filename));
+ strcpy(fullname, pwent->pw_dir);
+ strcat(fullname, filename+1);
+ } else {
+ fullname = strdup(filename);
+ }
+#else /* !(defined(HAVE_GETUID) && defined(HAVE_GETPWUID)) */
+ fullname = strdup(filename);
+#endif /* defined(HAVE_GETUID) && defined(HAVE_GETPWUID) */
+
+ /* try to open */
+ rcfile = fopen(fullname,"r");
+ if (!rcfile) {
+ if (user_specified) {
+ fprintf(stderr, "%s: warning: open failed for rc-file '%s': %s\n",
+ PROGRAM, fullname, strerror(errno));
+ }
+ }
+ else {
+ cmdline_parser_read_rc_stream(rcfile, fullname, args_info);
+ }
+
+ /* cleanup */
+ if (fullname != filename) free(fullname);
+ if (rcfile) fclose(rcfile);
+
+ return;
+}
+
+
+/* Parse option values from an .rc file : guts */
+#define OPTPARSE_GET 32
+void
+cmdline_parser_read_rc_stream(FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info)
+{
+ char *optname = (char *)malloc(OPTPARSE_GET);
+ char *optval = (char *)malloc(OPTPARSE_GET);
+ size_t onsize = OPTPARSE_GET;
+ size_t ovsize = OPTPARSE_GET;
+ size_t onlen = 0;
+ size_t ovlen = 0;
+ int lineno = 0;
+ char c;
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'):\n", filename);
+#endif
+
+ while ((c = fgetc(rcfile)) != EOF) {
+ onlen = 0;
+ ovlen = 0;
+ lineno++;
+
+ /* -- get next option-name */
+ /* skip leading space and comments */
+ if (isspace(c)) continue;
+ if (c == '#') {
+ while ((c = fgetc(rcfile)) != EOF) {
+ if (c == '\n') break;
+ }
+ continue;
+ }
+
+ /* parse option-name */
+ while (c != EOF && c != '=' && !isspace(c)) {
+ /* re-allocate if necessary */
+ if (onlen >= onsize-1) {
+ char *tmp = (char *)malloc(onsize+OPTPARSE_GET);
+ strcpy(tmp,optname);
+ free(optname);
+
+ onsize += OPTPARSE_GET;
+ optname = tmp;
+ }
+ optname[onlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optname[onlen++] = '\0';
+
+#ifdef cmdline_parser_DEBUG
+ fprintf(stderr, "cmdline_parser_read_rc_stream('%s'): line %d: optname='%s'\n",
+ filename, lineno, optname);
+#endif
+
+ /* -- get next option-value */
+ /* skip leading space */
+ while ((c = fgetc(rcfile)) != EOF && isspace(c)) {
+ ;
+ }
+
+ /* parse option-value */
+ while (c != EOF && c != '\n') {
+ /* re-allocate if necessary */
+ if (ovlen >= ovsize-1) {
+ char *tmp = (char *)malloc(ovsize+OPTPARSE_GET);
+ strcpy(tmp,optval);
+ free(optval);
+ ovsize += OPTPARSE_GET;
+ optval = tmp;
+ }
+ optval[ovlen++] = c;
+ c = fgetc(rcfile);
+ }
+ optval[ovlen++] = '\0';
+
+ /* now do the action for the option */
+ if (cmdline_parser_parse_option('\0',optname,optval,args_info) != 0) {
+ fprintf(stderr, "%s: error in file '%s' at line %d.\n", PROGRAM, filename, lineno);
+
+ }
+ }
+
+ /* cleanup */
+ free(optname);
+ free(optval);
+
+ return;
+}
diff --git a/gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.h b/gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.h
new file mode 100644
index 0000000..d38087d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C -*-
+ *
+ * File: gfsmviterbi_cmdparser.h
+ * Description: Headers for command-line parser struct gengetopt_args_info.
+ *
+ * File autogenerated by optgen.perl version 0.05.
+ *
+ */
+
+#ifndef gfsmviterbi_cmdparser_h
+#define gfsmviterbi_cmdparser_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * moocow: Never set PACKAGE and VERSION here.
+ */
+
+struct gengetopt_args_info {
+ char * fst_arg; /* Weighted transducer to apply (default=stdin). (default=-). */
+ int compress_arg; /* Specify compression level of output file. (default=-1). */
+ char * output_arg; /* Specifiy output file (default=stdout). (default=-). */
+
+ int help_given; /* Whether help was given */
+ int version_given; /* Whether version was given */
+ int fst_given; /* Whether fst was given */
+ int compress_given; /* Whether compress was given */
+ int output_given; /* Whether output was given */
+
+ char **inputs; /* unnamed arguments */
+ unsigned inputs_num; /* number of unnamed arguments */
+};
+
+/* read rc files (if any) and parse all command-line options in one swell foop */
+int cmdline_parser (int argc, char *const *argv, struct gengetopt_args_info *args_info);
+
+/* instantiate defaults from environment variables: you must call this yourself! */
+void cmdline_parser_envdefaults (struct gengetopt_args_info *args_info);
+
+/* read a single rc-file */
+void cmdline_parser_read_rcfile (const char *filename,
+ struct gengetopt_args_info *args_info,
+ int user_specified);
+
+/* read a single rc-file (stream) */
+void cmdline_parser_read_rc_stream (FILE *rcfile,
+ const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/* parse a single option */
+int cmdline_parser_parse_option (char oshort, const char *olong, const char *val,
+ struct gengetopt_args_info *args_info);
+
+/* print help message */
+void cmdline_parser_print_help(void);
+
+/* print version */
+void cmdline_parser_print_version(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* gfsmviterbi_cmdparser_h */
diff --git a/gfsm/gfsm/src/programs/gfsmviterbi_main.c b/gfsm/gfsm/src/programs/gfsmviterbi_main.c
new file mode 100644
index 0000000..33bb01a
--- /dev/null
+++ b/gfsm/gfsm/src/programs/gfsmviterbi_main.c
@@ -0,0 +1,125 @@
+/*
+ gfsm-utils : finite state automaton utilities
+ Copyright (C) 2005 by Bryan Jurish <moocow@ling.uni-potsdam.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <gfsm.h>
+
+#include "gfsmviterbi_cmdparser.h"
+
+/*--------------------------------------------------------------------------
+ * Globals
+ *--------------------------------------------------------------------------*/
+char *progname = "gfsmviterbi";
+
+//-- options
+struct gengetopt_args_info args;
+
+//-- files
+const char *fstfilename = "-";
+const char *outfilename = "-";
+
+//-- global structs
+gfsmAutomaton *fst = NULL;
+gfsmError *err = NULL;
+
+/*--------------------------------------------------------------------------
+ * Option Processing
+ *--------------------------------------------------------------------------*/
+void get_my_options(int argc, char **argv)
+{
+ if (cmdline_parser(argc, argv, &args) != 0)
+ exit(1);
+
+ //-- load environmental defaults
+ //cmdline_parser_envdefaults(&args);
+
+ //-- filenames
+ if (args.fst_given) fstfilename = args.fst_arg;
+ outfilename = args.output_arg;
+
+ //-- load FST
+ fst = gfsm_automaton_new();
+ if (!gfsm_automaton_load_bin_filename(fst, fstfilename, &err)) {
+ g_printerr("%s: load failed for FST file '%s': %s\n", progname, fstfilename, err->message);
+ exit(255);
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * viterbi_labels()
+ */
+gfsmAutomaton *viterbi_labels(gfsmAutomaton *fst, int argc, char **argv)
+{
+ gfsmLabelVector *vec = g_ptr_array_sized_new(argc);
+ char *s=NULL, *tail=NULL;
+ gfsmLabelVal lab;
+ gfsmAutomaton *trellis = NULL;
+ int i;
+
+ //-- fill input vector
+ for (i=0; i < argc; i++) {
+ for (s=argv[i], lab=strtol(s,&tail,0); s != tail; s=tail, lab=strtol(s,&tail,0)) {
+ g_ptr_array_add(vec, (gpointer)lab);
+ }
+ }
+
+ //-- actual viterbi lookup
+ trellis = gfsm_automaton_lookup_viterbi(fst, vec, trellis);
+
+ //-- cleanup
+ g_ptr_array_free(vec,TRUE);
+
+ return trellis;
+}
+
+/*--------------------------------------------------------------------------
+ * MAIN
+ *--------------------------------------------------------------------------*/
+int main (int argc, char **argv)
+{
+ gfsmAutomaton *trellis;
+
+ GFSM_INIT
+ get_my_options(argc,argv);
+
+ //-- process input
+ trellis = viterbi_labels(fst, args.inputs_num, args.inputs);
+
+ //-- save output
+ if (!gfsm_automaton_save_bin_filename(trellis,outfilename,args.compress_arg,&err)) {
+ g_printerr("%s: store failed to '%s': %s\n", progname, outfilename, err->message);
+ exit(4);
+ }
+
+ //-- cleanup
+ if (fst) gfsm_automaton_free(fst);
+ if (trellis) gfsm_automaton_free(trellis);
+
+ GFSM_FINISH
+ return 0;
+}
diff --git a/gfsm/gfsm/src/programs/isect1.tfst b/gfsm/gfsm/src/programs/isect1.tfst
new file mode 100644
index 0000000..5781fec
--- /dev/null
+++ b/gfsm/gfsm/src/programs/isect1.tfst
@@ -0,0 +1,4 @@
+0 1 0 0
+1
+1 2 1 1
+2
diff --git a/gfsm/gfsm/src/programs/isect2.tfst b/gfsm/gfsm/src/programs/isect2.tfst
new file mode 100644
index 0000000..d64b6cb
--- /dev/null
+++ b/gfsm/gfsm/src/programs/isect2.tfst
@@ -0,0 +1,5 @@
+0 0 1 1
+0 1 0 0
+0
+1 1 2 2
+1
diff --git a/gfsm/gfsm/src/programs/lkptest.tfst b/gfsm/gfsm/src/programs/lkptest.tfst
new file mode 100644
index 0000000..40c6d7a
--- /dev/null
+++ b/gfsm/gfsm/src/programs/lkptest.tfst
@@ -0,0 +1,13 @@
+0 0 1 2 1
+0 0 2 3 1
+0 0 3 1 1
+0 0
+
+0 1 2 2 1
+1 2 2 2 1
+2 3 3 3 1
+3 0
+
+0 4 1 0 1
+4 5 0 3 1
+5 0
diff --git a/gfsm/gfsm/src/programs/p1.tfst b/gfsm/gfsm/src/programs/p1.tfst
new file mode 100644
index 0000000..671e9e0
--- /dev/null
+++ b/gfsm/gfsm/src/programs/p1.tfst
@@ -0,0 +1,5 @@
+0 1 1 1
+0 1 2 2
+1
+1 2 3 3
+2
diff --git a/gfsm/gfsm/src/programs/p2.tfst b/gfsm/gfsm/src/programs/p2.tfst
new file mode 100644
index 0000000..f8fd663
--- /dev/null
+++ b/gfsm/gfsm/src/programs/p2.tfst
@@ -0,0 +1,3 @@
+0 1 4 4
+0 1 5 5
+1
diff --git a/gfsm/gfsm/src/programs/prunetest.tfst b/gfsm/gfsm/src/programs/prunetest.tfst
new file mode 100644
index 0000000..0dc8950
--- /dev/null
+++ b/gfsm/gfsm/src/programs/prunetest.tfst
@@ -0,0 +1,6 @@
+0 1 1 1 0
+1 2 2 2 0
+0 3 3 3 0
+1 0
+4 5 4 4 0
+5 0
diff --git a/gfsm/gfsm/src/programs/r1.tfst b/gfsm/gfsm/src/programs/r1.tfst
new file mode 100644
index 0000000..f9608f2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/r1.tfst
@@ -0,0 +1,9 @@
+0 1 1 1
+0 2 0 1
+0 3 1 0
+1 4 4 4
+2 5 5 5
+3 6 6 6
+4
+5
+6
diff --git a/gfsm/gfsm/src/programs/r2.tfst b/gfsm/gfsm/src/programs/r2.tfst
new file mode 100644
index 0000000..a61738d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/r2.tfst
@@ -0,0 +1,4 @@
+0 1 24 7
+0 2 7 24
+1 10
+2 20
diff --git a/gfsm/gfsm/src/programs/renumber.tfst b/gfsm/gfsm/src/programs/renumber.tfst
new file mode 100644
index 0000000..b4697b0
--- /dev/null
+++ b/gfsm/gfsm/src/programs/renumber.tfst
@@ -0,0 +1,5 @@
+5 4 43 0 0
+5 1 42 0 0
+7 0
+1 7 1 1 0
+4 7 1 1 0
diff --git a/gfsm/gfsm/src/programs/renumber2.tfst b/gfsm/gfsm/src/programs/renumber2.tfst
new file mode 100644
index 0000000..1c71c3d
--- /dev/null
+++ b/gfsm/gfsm/src/programs/renumber2.tfst
@@ -0,0 +1,8 @@
+5 1 42 0 0
+5 4 43 0 0
+6 7 1 1 0
+7 0
+0 1 42 0 0
+1 7 1 1 0
+3 4 43 0 0
+4 7 1 1 0
diff --git a/gfsm/gfsm/src/programs/rev1.tfst b/gfsm/gfsm/src/programs/rev1.tfst
new file mode 100644
index 0000000..5a428b4
--- /dev/null
+++ b/gfsm/gfsm/src/programs/rev1.tfst
@@ -0,0 +1,7 @@
+0 1 0 1 1
+1 2 1 2 12
+2 2 2 2 22
+2 20
+1 3 1 3 13
+3 4 3 4 34
+4 40 \ No newline at end of file
diff --git a/gfsm/gfsm/src/programs/rme.tfst b/gfsm/gfsm/src/programs/rme.tfst
new file mode 100644
index 0000000..06922fa
--- /dev/null
+++ b/gfsm/gfsm/src/programs/rme.tfst
@@ -0,0 +1,6 @@
+0 0 0 0 0
+0 1 0 0 1
+1 2 0 0 2
+0 2 0 0 10
+2 3 1 1 3
+3
diff --git a/gfsm/gfsm/src/programs/rme2.tfst b/gfsm/gfsm/src/programs/rme2.tfst
new file mode 100644
index 0000000..b30d66e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/rme2.tfst
@@ -0,0 +1,8 @@
+5 0 0 0 0
+5 3 0 0 0
+6 7 0 0 0
+7 0
+0 1 42 0 0
+1 6 0 0 0
+3 4 43 0 0
+4 6 0 0 0
diff --git a/gfsm/gfsm/src/programs/rme2b.tfst b/gfsm/gfsm/src/programs/rme2b.tfst
new file mode 100644
index 0000000..da2ffd2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/rme2b.tfst
@@ -0,0 +1,8 @@
+5 0 0 0 0
+5 3 0 0 0
+6 7 1 1 0
+7 0
+0 1 42 0 0
+1 6 0 0 0
+3 4 43 0 0
+4 6 0 0 0
diff --git a/gfsm/gfsm/src/programs/rme3.tfst b/gfsm/gfsm/src/programs/rme3.tfst
new file mode 100644
index 0000000..8235e2b
--- /dev/null
+++ b/gfsm/gfsm/src/programs/rme3.tfst
@@ -0,0 +1,5 @@
+0 1 42 0
+0 2 43 0
+1 3 0 0 0
+2 3 0 0 0
+3 0
diff --git a/gfsm/gfsm/src/programs/sort.tfst b/gfsm/gfsm/src/programs/sort.tfst
new file mode 100644
index 0000000..a5bb1c7
--- /dev/null
+++ b/gfsm/gfsm/src/programs/sort.tfst
@@ -0,0 +1,7 @@
+0 1 1 2 1
+0 1 2 1 2
+0 1 2 2 3
+0 1 1 2 3
+0 1 2 1 2
+0 1 2 2 1
+1
diff --git a/gfsm/gfsm/src/programs/sortme.tfst b/gfsm/gfsm/src/programs/sortme.tfst
new file mode 100644
index 0000000..d48ea71
--- /dev/null
+++ b/gfsm/gfsm/src/programs/sortme.tfst
@@ -0,0 +1,15 @@
+0 1 1 10 10.0
+0 1 2 10 10.0
+0 1 1 20 10.0
+0 1 2 20 10.0
+0 1 3 10 10.0
+0 1 3 20 10.0
+0 1 3 30 10.0
+0 1 4 40 1.0
+0 1 4 40 2.0
+0 1 4 40 3.0
+0 0 5 50 10.0
+0 0 5 50 10.0
+0 0 5 50 10.0
+0 0.0
+1 0.0
diff --git a/gfsm/gfsm/src/programs/symtest.lab b/gfsm/gfsm/src/programs/symtest.lab
new file mode 100644
index 0000000..4d677d5
--- /dev/null
+++ b/gfsm/gfsm/src/programs/symtest.lab
@@ -0,0 +1,15 @@
+<epsilon> 0
+a 1
+b 2
+c 3
+A 4
+B 5
+C 6
+acc 7
+dat 8
+sg 9
+pl 10
+_NOUN 11
+_Case 12
+_Number 13
+_VERB 14
diff --git a/gfsm/gfsm/src/programs/symtest.sym b/gfsm/gfsm/src/programs/symtest.sym
new file mode 100644
index 0000000..f151932
--- /dev/null
+++ b/gfsm/gfsm/src/programs/symtest.sym
@@ -0,0 +1,8 @@
+Lower a b c
+Upper A B C
+
+Case acc dat
+Number sg pl
+
+Category: NOUN Case Number
+Category: VERB Number
diff --git a/gfsm/gfsm/src/programs/test+lab.tfst b/gfsm/gfsm/src/programs/test+lab.tfst
new file mode 100644
index 0000000..252d6a6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test+lab.tfst
@@ -0,0 +1,3 @@
+0 1 a b 0
+1 2 c d 0
+2 0
diff --git a/gfsm/gfsm/src/programs/test-rn.tfst b/gfsm/gfsm/src/programs/test-rn.tfst
new file mode 100644
index 0000000..694ddcd
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test-rn.tfst
@@ -0,0 +1,8 @@
+0 1 1 1 0
+0 0
+1 0
+2 0
+3 0
+4
+5
+6
diff --git a/gfsm/gfsm/src/programs/test.lab b/gfsm/gfsm/src/programs/test.lab
new file mode 100644
index 0000000..b7c05ae
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test.lab
@@ -0,0 +1,15 @@
+<eps> 0
+a 1
+b 2
+c 3
+d 4
+e 5
+f 6
+fourtwenty 420
+twentyfour 24
+seven 7
+( 10
+) 11
+FOO 12
+BAR 13
+BAZ 14
diff --git a/gfsm/gfsm/src/programs/test.tfst b/gfsm/gfsm/src/programs/test.tfst
new file mode 100644
index 0000000..02acee3
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test.tfst
@@ -0,0 +1,3 @@
+0 1 420 24 0.7
+1 2 0 0 99
+2
diff --git a/gfsm/gfsm/src/programs/test2.tfst b/gfsm/gfsm/src/programs/test2.tfst
new file mode 100644
index 0000000..37fe96a
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test2.tfst
@@ -0,0 +1,7 @@
+0 1 1 3 .042
+0 2 2 2 .24
+0 3 3 1 .07
+1
+2
+3
+
diff --git a/gfsm/gfsm/src/programs/test3.tfst b/gfsm/gfsm/src/programs/test3.tfst
new file mode 100644
index 0000000..669bfc9
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test3.tfst
@@ -0,0 +1,6 @@
+0 1 1 1 100
+0 4 4 4 400
+1 2 2 2 200
+2 3 3 3 300
+3 0
+4 0
diff --git a/gfsm/gfsm/src/programs/test4.tfst b/gfsm/gfsm/src/programs/test4.tfst
new file mode 100644
index 0000000..44d5c9e
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test4.tfst
@@ -0,0 +1,9 @@
+0 1 0 0 0
+0 1 0 0 1
+0 1 0 1 0
+0 1 0 1 1
+0 1 1 0 0
+0 1 1 0 1
+0 1 1 1 0
+0 1 1 1 1
+1
diff --git a/gfsm/gfsm/src/programs/test4b.tfst b/gfsm/gfsm/src/programs/test4b.tfst
new file mode 100644
index 0000000..8890ba6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test4b.tfst
@@ -0,0 +1,9 @@
+0 1 1 1 1
+0 1 1 1 0
+0 1 1 0 1
+0 1 1 0 0
+0 1 0 1 1
+0 1 0 1 0
+0 1 0 0 1
+0 1 0 0 0
+1 \ No newline at end of file
diff --git a/gfsm/gfsm/src/programs/test5.tfst b/gfsm/gfsm/src/programs/test5.tfst
new file mode 100644
index 0000000..ac8c248
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test5.tfst
@@ -0,0 +1,3 @@
+0 1 1 1 0
+1 2 2 2 0
+2 0
diff --git a/gfsm/gfsm/src/programs/test6.tfst b/gfsm/gfsm/src/programs/test6.tfst
new file mode 100644
index 0000000..4c306da
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test6.tfst
@@ -0,0 +1,12 @@
+0 1 0 0 0
+0 2 0 0 0
+0 3 0 0 0
+3 4 0 0 0
+1 10 1 1 0
+2 20 2 2 0
+4 5 4 4 0
+4 1 4 4 1
+10
+20
+5
+
diff --git a/gfsm/gfsm/src/programs/test7.lab b/gfsm/gfsm/src/programs/test7.lab
new file mode 100644
index 0000000..0cedd17
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test7.lab
@@ -0,0 +1,4 @@
+<eps> 0
+a 1
+b 2
+c 3
diff --git a/gfsm/gfsm/src/programs/test7.tfst b/gfsm/gfsm/src/programs/test7.tfst
new file mode 100644
index 0000000..c96f7e6
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test7.tfst
@@ -0,0 +1,2 @@
+0 1 1 1 0
+1 0
diff --git a/gfsm/gfsm/src/programs/test8.tfst b/gfsm/gfsm/src/programs/test8.tfst
new file mode 100644
index 0000000..9009985
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test8.tfst
@@ -0,0 +1,4 @@
+0 1 1 1 0
+0 2 2 2 0
+1 0
+2 0
diff --git a/gfsm/gfsm/src/programs/test9.tfst b/gfsm/gfsm/src/programs/test9.tfst
new file mode 100644
index 0000000..47867d2
--- /dev/null
+++ b/gfsm/gfsm/src/programs/test9.tfst
@@ -0,0 +1,4 @@
+0 0
+1 0
+2 0
+3 0
diff --git a/gfsm/gfsm/src/programs/testa.tfsa b/gfsm/gfsm/src/programs/testa.tfsa
new file mode 100644
index 0000000..f2926c5
--- /dev/null
+++ b/gfsm/gfsm/src/programs/testa.tfsa
@@ -0,0 +1,6 @@
+0 0 0
+0 1 1 10
+0
+1 2 2 20
+1 100
+2 200
diff --git a/gfsm/gfsm/src/programs/testa.tfst b/gfsm/gfsm/src/programs/testa.tfst
new file mode 100644
index 0000000..1078be4
--- /dev/null
+++ b/gfsm/gfsm/src/programs/testa.tfst
@@ -0,0 +1,6 @@
+0 0 0
+0 1 1 1
+0
+1 2 2 2 20
+1 100
+2 200
diff --git a/gfsm/gfsm/src/programs/testrn.tfst b/gfsm/gfsm/src/programs/testrn.tfst
new file mode 100644
index 0000000..0bcf201
--- /dev/null
+++ b/gfsm/gfsm/src/programs/testrn.tfst
@@ -0,0 +1,3 @@
+300 100 1 1
+100 200 2 2
+200 0
diff --git a/gfsm/gfsm/src/programs/vit-in.lab b/gfsm/gfsm/src/programs/vit-in.lab
new file mode 100644
index 0000000..5c74e25
--- /dev/null
+++ b/gfsm/gfsm/src/programs/vit-in.lab
@@ -0,0 +1,3 @@
+<eps> 0
+a 1
+b 2
diff --git a/gfsm/gfsm/src/programs/vit-out.lab b/gfsm/gfsm/src/programs/vit-out.lab
new file mode 100644
index 0000000..bd1493c
--- /dev/null
+++ b/gfsm/gfsm/src/programs/vit-out.lab
@@ -0,0 +1,7 @@
+<eps> 0
+a_A 1
+a_B 2
+b_A 3
+b_B 4
+<eps>_A 5
+<eps>_B 6
diff --git a/gfsm/gfsm/src/programs/vit-q.lab b/gfsm/gfsm/src/programs/vit-q.lab
new file mode 100644
index 0000000..0fbd83b
--- /dev/null
+++ b/gfsm/gfsm/src/programs/vit-q.lab
@@ -0,0 +1,3 @@
+<BOS> 0
+A 1
+B 2
diff --git a/gfsm/gfsm/src/programs/vit.tfst b/gfsm/gfsm/src/programs/vit.tfst
new file mode 100644
index 0000000..e92ec55
--- /dev/null
+++ b/gfsm/gfsm/src/programs/vit.tfst
@@ -0,0 +1,17 @@
+<BOS> A a a_A 1
+<BOS> A b b_A 1
+<BOS> B a a_B 1
+<BOS> B b b_B 1
+<BOS> 1
+
+A A a a_A .4
+A A b b_A .3
+A B a a_B .2
+A B b b_B .1
+A 1
+
+B B b b_B .4
+B A a a_A .3
+B A b b_A .2
+B B a a_B .1
+B 1
diff --git a/gfsm/gfsm/src/programs/vit2.tfst b/gfsm/gfsm/src/programs/vit2.tfst
new file mode 100644
index 0000000..879b3a1
--- /dev/null
+++ b/gfsm/gfsm/src/programs/vit2.tfst
@@ -0,0 +1,15 @@
+<BOS> A <eps> <eps>_A .4
+<BOS> A a a_A .3
+<BOS> B <eps> <eps>_B .2
+<BOS> B b b_B .1
+<BOS> 1
+
+A A a a_A .7
+A B <eps> <eps>_B .2
+A B b b_B .1
+A 1
+
+B B b b_B .7
+B A a a_A .2
+B A <eps> <eps>_A .1
+B 1
diff --git a/gfsm/gfsm/tests/.cvsignore b/gfsm/gfsm/tests/.cvsignore
new file mode 100644
index 0000000..a90c334
--- /dev/null
+++ b/gfsm/gfsm/tests/.cvsignore
@@ -0,0 +1,11 @@
+*~
+.*~
+
+perl-t
+atconfig
+atlocal
+Makefile
+Makefile.in
+testsuite
+testsuite.dir
+testsuite.log \ No newline at end of file
diff --git a/gfsm/gfsm/tests/01_basic.at b/gfsm/gfsm/tests/01_basic.at
new file mode 100644
index 0000000..9f9d587
--- /dev/null
+++ b/gfsm/gfsm/tests/01_basic.at
@@ -0,0 +1,54 @@
+## -*- Mode: Autotest -*-
+##
+## File: basic.at
+## Package: gfsm
+## Description: autotest test-suite script: basic tests
+##
+
+AT_BANNER([basic automaton manipulation])
+
+##--------------------------------------------------------------
+## Test: compile+print: null
+AT_SETUP([compile+print.null])
+AT_KEYWORDS([basic compile print info])
+
+##-- compile: null
+AT_CHECK([[$progdir/gfsmcompile $tdata/null.tfst -F null.gfst]],0,[],[])
+
+##-- print: null
+AT_CHECK([[$progdir/gfsmprint null.gfst]],0,[],[ignore])
+
+##-- info: null
+rm -f expout; ln $tdata/null.inf expout
+AT_CHECK([[$progdir/gfsminfo < null.gfst]],0,expout)
+
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: compile+print: simple
+AT_SETUP([compile+print.simple])
+AT_KEYWORDS([basic compile print info])
+
+AT_CHECK([[$progdir/gfsmcompile $tdata/basic1.tfst -F basic1.gfst]],0)
+
+rm -f expout; ln $tdata/basic1.tfst expout
+AT_CHECK([[$progdir/gfsmprint basic1.gfst]],0,expout,[])
+
+rm -f expout; ln $tdata/basic1.inf expout
+AT_CHECK([[$progdir/gfsminfo < basic1.gfst]],0,expout,[])
+
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: compile+print: with labels
+AT_SETUP([compile+print.labels])
+AT_KEYWORDS([basic compile print info alphabet])
+AT_CHECK([[$progdir/gfsmcompile -i $tdata/test.lab -o $tdata/test.lab $tdata/basic2.labs.tfst -F basic2.gfst]],0)
+
+rm -f expout; ln $tdata/basic2.labs.tfst expout
+AT_CHECK([[$progdir/gfsmprint -i $tdata/test.lab -o $tdata/test.lab basic2.gfst]],0,expout,[])
+
+rm -f expout; ln $tdata/basic2.labs.inf expout
+AT_CHECK([[$progdir/gfsminfo < basic2.gfst]],0,expout,[])
+
+AT_CLEANUP
diff --git a/gfsm/gfsm/tests/02_arith.at b/gfsm/gfsm/tests/02_arith.at
new file mode 100644
index 0000000..856ab05
--- /dev/null
+++ b/gfsm/gfsm/tests/02_arith.at
@@ -0,0 +1,107 @@
+## -*- Mode: Autotest -*-
+##
+## File: arith.at
+## Package: gfsm
+## Description: autotest test-suite script: semiring
+##
+
+AT_BANNER([(semiring-)arithmetic])
+
+##--------------------------------------------------------------
+## gfsmarith (real: vanilla)
+AT_SETUP([arith.real])
+AT_KEYWORDS([arith semiring])
+
+##-- real ops: add, multiply
+AT_CHECK([[echo "0 0" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -a 1 | $progdir/gfsmprint]],0,
+[0 1
+],[])
+AT_CHECK([[echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -m 42 | $progdir/gfsmprint]],0,
+[0 42
+],[])
+
+##-- real ops: log, exp
+AT_CHECK([[echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --log | $progdir/gfsmprint]],0,
+[0 0
+],[])
+AT_CHECK([[echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --exp | $progdir/gfsmprint]],0,
+[0 2.71828
+],[])
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## semiring: boolean
+AT_SETUP([arith.sr.boolean])
+AT_KEYWORDS([arith semiring])
+AT_CHECK(
+[[echo "0 0" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --plus=1 | $progdir/gfsmprint]],0,
+[0 1
+])
+AT_CHECK(
+[[echo "0 0" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --times=1 | $progdir/gfsmprint]],0,
+[0 0
+])
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## semiring: log
+AT_SETUP([arith.sr.log])
+AT_KEYWORDS([arith semiring])
+# -log(.125)= 2.07944
+# -log(.25) = 1.38629
+# -log(.5) = .693147
+# -log(.75) = 0.287682
+AT_CHECK(
+[[echo "0 .693147" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --plus=1.38629 | $progdir/gfsmprint]],0,
+[0 0.28768
+])
+AT_CHECK(
+[[echo "0 .5" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --times=0.25 | $progdir/gfsmprint]],0,
+[0 0.75
+])
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## semiring: positive log
+AT_SETUP([arith.sr.plog])
+AT_KEYWORDS([arith semiring])
+# log(.125)= -2.07944
+# log(.25) = -1.38629
+# log(.5) = -0.693147
+# log(.75) = -0.287682
+AT_CHECK(
+[[echo "0 -0.693147" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --plus=-1.38629 | $progdir/gfsmprint]],0,
+[0 -0.28768
+])
+AT_CHECK(
+[[echo "0 -0.5" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --times=-0.25 | $progdir/gfsmprint]],0,
+[0 -0.75
+])
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## semiring: real
+AT_SETUP([arith.sr.real])
+AT_CHECK(
+[[echo "0 3" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint]],0,
+[0 7
+])
+AT_CHECK(
+[[echo "0 3" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint]],0,
+[0 12
+])
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## semiring: tropical
+AT_SETUP([arith.sr.tropical])
+AT_KEYWORDS([arith semiring])
+AT_CHECK(
+[[echo "0 3" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint]],0,
+[0 3
+])
+AT_CHECK(
+[[echo "0 3" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint]],0,
+[0 7
+])
+AT_CLEANUP
diff --git a/gfsm/gfsm/tests/03_algebra.at b/gfsm/gfsm/tests/03_algebra.at
new file mode 100644
index 0000000..0692f10
--- /dev/null
+++ b/gfsm/gfsm/tests/03_algebra.at
@@ -0,0 +1,223 @@
+## -*- Mode: Autotest -*-
+##
+## File: algebra.at
+## Package: gfsm
+## Description: autotest test-suite script: basic tests
+##
+
+AT_BANNER([algebraic operations])
+
+##--------------------------------------------------------------
+## Test: unary: closure.plus
+AT_SETUP([closure.plus])
+AT_KEYWORDS([algebra closure])
+opname="closure-plus"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmclosure --plus ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: closure.star
+AT_SETUP([closure.star])
+AT_KEYWORDS([algebra closure])
+opname="closure-star"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmclosure ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: complement
+AT_SETUP([complement])
+AT_KEYWORDS([algebra complement])
+opname="complement"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmcomplement ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+##
+##-- complement(b): given alphabet
+opname="complement-b"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmcomplement -i $tdata/test.lab ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: binary: compose
+AT_SETUP([compose])
+AT_KEYWORDS([algebra compose])
+opname="compose"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst]])
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst]])
+AT_CHECK([[$progdir/gfsmcompose ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: binary: concat
+AT_SETUP([concat])
+AT_KEYWORDS([algebra concat])
+opname="concat"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst]])
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst]])
+AT_CHECK([[$progdir/gfsmconcat ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: connect
+AT_SETUP([connect])
+AT_KEYWORDS([algebra connect])
+opname="connect"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmconnect ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: determinize
+AT_SETUP([determinize])
+AT_KEYWORDS([algebra determinize])
+opname="determinize"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmdeterminize ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: binary: difference
+## + found bug: clone() wasn't setting root_id (assumed to have been done in copy_shallow())
+AT_SETUP([difference])
+AT_KEYWORDS([algebra difference])
+opname="difference"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst]])
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst]])
+AT_CHECK([[$progdir/gfsmdifference ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: binary: intersect
+AT_SETUP([intersect])
+AT_KEYWORDS([algebra intersect])
+opname="intersect"
+opfile="$opname"
+
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst]])
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst]])
+AT_CHECK([[$progdir/gfsmintersect ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+
+opfile="intersect2" ##-- intersection as called by gfsm_automaton_difference()
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst]])
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst]])
+AT_CHECK([[$progdir/gfsmintersect ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: invert
+AT_SETUP([invert])
+AT_KEYWORDS([algebra invert])
+opname="invert"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsminvert ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: optional
+AT_SETUP([optional])
+AT_KEYWORDS([algebra optional])
+opname="optional"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmoptional ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: project.lo
+AT_SETUP([project.lo])
+AT_KEYWORDS([algebra project])
+opname="project-lo"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmproject -1 ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: project.hi
+AT_SETUP([project.hi])
+AT_KEYWORDS([algebra project])
+opname="project-hi"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmproject -2 ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: renumber
+AT_SETUP([renumber])
+AT_KEYWORDS([algebra renumber])
+opname="renumber"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmrenumber ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: unary: rmepsilon
+AT_SETUP([rmepsilon])
+AT_KEYWORDS([algebra rmepsilon])
+opname="rmepsilon"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst]])
+AT_CHECK([[$progdir/gfsmrmepsilon ${opfile}-in.gfst -F ${opfile}-got.gfst]]) ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
+
+##--------------------------------------------------------------
+## Test: binary: union
+AT_SETUP([union])
+AT_KEYWORDS([algebra union])
+opname="union"
+opfile="$opname"
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst]])
+AT_CHECK([[$progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst]])
+AT_CHECK([[$progdir/gfsmunion ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst]]) ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+AT_CHECK([[$progdir/gfsmprint ${opfile}-got.gfst]],0,expout)
+AT_CLEANUP
diff --git a/gfsm/gfsm/tests/Makefile.am b/gfsm/gfsm/tests/Makefile.am
new file mode 100644
index 0000000..63e83ae
--- /dev/null
+++ b/gfsm/gfsm/tests/Makefile.am
@@ -0,0 +1,159 @@
+# File: ./tests/Makefile.am
+# Package: gfsm
+# Description:
+# + test-level automake file
+#
+# Process this file with Automake to create Makefile.in.
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# Options & Subdirectories
+#-----------------------------------------------------------------------
+
+## --- recursion subdirectories
+#SUBDIRS =
+
+#-----------------------------------------------------------------------
+# Rules: test (check)
+#-----------------------------------------------------------------------
+
+$(srcdir)/package.m4: $(top_srcdir)/configure.in
+ { \
+ echo '# Signature of the current package.'; \
+ echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \
+ echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \
+ echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \
+ echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \
+ echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \
+ } >$(srcdir)/package.m4
+
+TESTSUITE = $(srcdir)/testsuite
+check-local: atconfig atlocal $(TESTSUITE)
+ sh $(TESTSUITE)
+
+AUTOTEST = autom4te --language=autotest
+$(TESTSUITE): $(srcdir)/testsuite.at \
+ $(srcdir)/01_basic.at \
+ $(srcdir)/02_arith.at \
+ $(srcdir)/03_algebra.at
+ $(AUTOTEST) -I $(srcdir) $^ -o $@.tmp
+ mv $@.tmp $@
+
+#-----------------------------------------------------------------------
+# Variables: cleanup
+#-----------------------------------------------------------------------
+
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+#CLEANFILES =
+
+## --- distclean: built by 'configure'
+DISTCLEANFILES = \
+ autom4te.cache \
+ config.log \
+ config.status \
+ config.cache \
+ atconfig \
+ testsuite.log
+
+distclean-local:
+ rm -rf testsuite.dir
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = *~ \
+ Makefile Makefile.in \
+ aclocal.m4 \
+ configure
+
+#-----------------------------------------------------------------------
+# Variables: distribution
+#-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ atconfig \
+ atlocal.in \
+ package.m4 \
+ 01_basic.at \
+ 02_arith.at \
+ testsuite.at \
+ testsuite
+
+## --- recursion subdirectories for 'make dist'
+DIST_SUBDIRS = $(SUBDIRS)
+
+## --- dist-hook: when another 'Makefile.am' is overkill
+DISTHOOK_DIRS = data
+DISTHOOK_FILES = \
+ data/basic1.inf \
+ data/basic1.tfst \
+ data/basic2.labs.inf \
+ data/basic2.labs.tfst \
+ data/closure-plus-in.tfst \
+ data/closure-plus-want.tfst \
+ data/closure-star-in.tfst \
+ data/closure-star-want.tfst \
+ data/complement-b-in.tfst \
+ data/complement-b-want.tfst \
+ data/complement-in.tfst \
+ data/complement-want.tfst \
+ data/compose-in-1.tfst \
+ data/compose-in-2.tfst \
+ data/compose-want.tfst \
+ data/concat-in-1.tfst \
+ data/concat-in-2.tfst \
+ data/concat-want.tfst \
+ data/connect-in.tfst \
+ data/connect-want.tfst \
+ data/determinize-in.tfst \
+ data/determinize-want.tfst \
+ data/difference-in-1.tfst \
+ data/difference-in-2.tfst \
+ data/difference-want.tfst \
+ data/intersect-in-1.tfst \
+ data/intersect-in-2.tfst \
+ data/intersect-want.tfst \
+ data/intersect2-in-1.tfst \
+ data/intersect2-in-2.tfst \
+ data/intersect2-want.tfst \
+ data/invert-in.tfst \
+ data/invert-want.tfst \
+ data/lookup-123-want.tfst \
+ data/lookup-223-want.tfst \
+ data/lookup.tfst \
+ data/n_closure-in.tfst \
+ data/n_closure-want.tfst \
+ data/null.inf \
+ data/null.tfst \
+ data/optional-in.tfst \
+ data/optional-want.tfst \
+ data/project-hi-in.tfst \
+ data/project-hi-want.tfst \
+ data/project-lo-in.tfst \
+ data/project-lo-want.tfst \
+ data/renumber-in.tfst \
+ data/renumber-want.tfst \
+ data/rmepsilon-in.tfst \
+ data/rmepsilon-want.tfst \
+ data/test.lab \
+ data/union-in-1.tfst \
+ data/union-in-2.tfst \
+ data/union-want.tfst
+
+dist-hook:
+ for d in $(DISTHOOK_DIRS); do\
+ mkdir -p $(distdir)/$$d ;\
+ done
+ for f in $(DISTHOOK_FILES); do\
+ cp -p $(srcdir)/$$f $(distdir)/$$f ;\
+ done
+
+#-----------------------------------------------------------------------
+# Rules: cleanup
+#-----------------------------------------------------------------------
+.PHONY: cvsclean cvsclean-hook
+
+cvsclean: maintainer-clean ;
+
diff --git a/gfsm/gfsm/tests/atlocal.in b/gfsm/gfsm/tests/atlocal.in
new file mode 100644
index 0000000..8813525
--- /dev/null
+++ b/gfsm/gfsm/tests/atlocal.in
@@ -0,0 +1,37 @@
+# -*- Mode: Shell-Script -*-
+# @configure_input@
+#
+# File: atlocal.in
+# Copied verbatim from autoconf's atlocal.in
+# - Configurable variable values for Autoconf test suite.
+
+# Copyright (C) 2000, 2001, 2005 Free Software Foundation, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+PERL='@PERL@'
+GREP='@GREP@'
+EGREP='@EGREP@'
+SED='@SED@'
+
+# We need to know if sh -n is ok.
+ac_cv_sh_n_works='@ac_cv_sh_n_works@'
+
+##-- we need this for gfsmutils program locations;
+## use 'pwd' to get at the raw location
+buildroot=`(cd "@top_builddir@"; pwd)`
+progdir="${buildroot}/src/programs"
+
+srcroot=`(cd "@top_srcdir@"; pwd)`
+tdata="${srcroot}/tests/data"
diff --git a/gfsm/gfsm/tests/data/.cvsignore b/gfsm/gfsm/tests/data/.cvsignore
new file mode 100644
index 0000000..8a66113
--- /dev/null
+++ b/gfsm/gfsm/tests/data/.cvsignore
@@ -0,0 +1,4 @@
+*~
+.*~
+
+*.gfst
diff --git a/gfsm/gfsm/tests/data/basic1.inf b/gfsm/gfsm/tests/data/basic1.inf
new file mode 100644
index 0000000..7174fe2
--- /dev/null
+++ b/gfsm/gfsm/tests/data/basic1.inf
@@ -0,0 +1,14 @@
+Filename : -
+Semiring : tropical
+Transducer? : y
+Weighted? : y
+Deterministic? : n
+Sort Mode : none, none, none, none, none, none
+Initial state : 0
+# of states : 2
+# of final states : 1
+# of arcs : 1
+# of i/o epsilon arcs : 0
+# of input epsilon arcs : 0
+# of output epsilon arcs: 0
+cyclic? : n
diff --git a/gfsm/gfsm/tests/data/basic1.tfst b/gfsm/gfsm/tests/data/basic1.tfst
new file mode 100644
index 0000000..429ad08
--- /dev/null
+++ b/gfsm/gfsm/tests/data/basic1.tfst
@@ -0,0 +1,2 @@
+0 1 2 3 4.5
+1 6.7
diff --git a/gfsm/gfsm/tests/data/basic2.labs.inf b/gfsm/gfsm/tests/data/basic2.labs.inf
new file mode 100644
index 0000000..b61e0f1
--- /dev/null
+++ b/gfsm/gfsm/tests/data/basic2.labs.inf
@@ -0,0 +1,14 @@
+Filename : -
+Semiring : tropical
+Transducer? : y
+Weighted? : y
+Deterministic? : n
+Sort Mode : none, none, none, none, none, none
+Initial state : 0
+# of states : 4
+# of final states : 1
+# of arcs : 3
+# of i/o epsilon arcs : 0
+# of input epsilon arcs : 1
+# of output epsilon arcs: 1
+cyclic? : n
diff --git a/gfsm/gfsm/tests/data/basic2.labs.tfst b/gfsm/gfsm/tests/data/basic2.labs.tfst
new file mode 100644
index 0000000..ce63bf6
--- /dev/null
+++ b/gfsm/gfsm/tests/data/basic2.labs.tfst
@@ -0,0 +1,4 @@
+0 1 a b 4.5
+1 2 <eps> c 6.7
+2 3 foo <eps> 8.9
+3 0
diff --git a/gfsm/gfsm/tests/data/closure-plus-in.tfst b/gfsm/gfsm/tests/data/closure-plus-in.tfst
new file mode 100644
index 0000000..9009985
--- /dev/null
+++ b/gfsm/gfsm/tests/data/closure-plus-in.tfst
@@ -0,0 +1,4 @@
+0 1 1 1 0
+0 2 2 2 0
+1 0
+2 0
diff --git a/gfsm/gfsm/tests/data/closure-plus-want.tfst b/gfsm/gfsm/tests/data/closure-plus-want.tfst
new file mode 100644
index 0000000..c0fe0f6
--- /dev/null
+++ b/gfsm/gfsm/tests/data/closure-plus-want.tfst
@@ -0,0 +1,6 @@
+0 2 2 2 0
+0 1 1 1 0
+1 0 0 0 0
+1 0
+2 0 0 0 0
+2 0
diff --git a/gfsm/gfsm/tests/data/closure-star-in.tfst b/gfsm/gfsm/tests/data/closure-star-in.tfst
new file mode 100644
index 0000000..9009985
--- /dev/null
+++ b/gfsm/gfsm/tests/data/closure-star-in.tfst
@@ -0,0 +1,4 @@
+0 1 1 1 0
+0 2 2 2 0
+1 0
+2 0
diff --git a/gfsm/gfsm/tests/data/closure-star-want.tfst b/gfsm/gfsm/tests/data/closure-star-want.tfst
new file mode 100644
index 0000000..e22651e
--- /dev/null
+++ b/gfsm/gfsm/tests/data/closure-star-want.tfst
@@ -0,0 +1,7 @@
+0 2 2 2 0
+0 1 1 1 0
+0 0
+1 0 0 0 0
+1 0
+2 0 0 0 0
+2 0
diff --git a/gfsm/gfsm/tests/data/complement-b-in.tfst b/gfsm/gfsm/tests/data/complement-b-in.tfst
new file mode 100644
index 0000000..45e1e1b
--- /dev/null
+++ b/gfsm/gfsm/tests/data/complement-b-in.tfst
@@ -0,0 +1,4 @@
+0 1 1 1
+1 2 2 2
+2 2 2 2
+2 0
diff --git a/gfsm/gfsm/tests/data/complement-b-want.tfst b/gfsm/gfsm/tests/data/complement-b-want.tfst
new file mode 100644
index 0000000..dfb5346
--- /dev/null
+++ b/gfsm/gfsm/tests/data/complement-b-want.tfst
@@ -0,0 +1,43 @@
+0 1 1 1 0
+0 3 2 2 0
+0 3 3 3 0
+0 3 4 4 0
+0 3 5 5 0
+0 3 6 6 0
+0 3 7 7 0
+0 3 8 8 0
+0 3 9 9 0
+0 3 10 10 0
+0 0
+1 2 2 2 0
+1 3 1 1 0
+1 3 3 3 0
+1 3 4 4 0
+1 3 5 5 0
+1 3 6 6 0
+1 3 7 7 0
+1 3 8 8 0
+1 3 9 9 0
+1 3 10 10 0
+1 0
+2 2 2 2 0
+2 3 1 1 0
+2 3 3 3 0
+2 3 4 4 0
+2 3 5 5 0
+2 3 6 6 0
+2 3 7 7 0
+2 3 8 8 0
+2 3 9 9 0
+2 3 10 10 0
+3 3 1 1 0
+3 3 2 2 0
+3 3 3 3 0
+3 3 4 4 0
+3 3 5 5 0
+3 3 6 6 0
+3 3 7 7 0
+3 3 8 8 0
+3 3 9 9 0
+3 3 10 10 0
+3 0
diff --git a/gfsm/gfsm/tests/data/complement-in.tfst b/gfsm/gfsm/tests/data/complement-in.tfst
new file mode 100644
index 0000000..45e1e1b
--- /dev/null
+++ b/gfsm/gfsm/tests/data/complement-in.tfst
@@ -0,0 +1,4 @@
+0 1 1 1
+1 2 2 2
+2 2 2 2
+2 0
diff --git a/gfsm/gfsm/tests/data/complement-want.tfst b/gfsm/gfsm/tests/data/complement-want.tfst
new file mode 100644
index 0000000..d18d1ed
--- /dev/null
+++ b/gfsm/gfsm/tests/data/complement-want.tfst
@@ -0,0 +1,11 @@
+0 1 1 1 0
+0 3 2 2 0
+0 0
+1 2 2 2 0
+1 3 1 1 0
+1 0
+2 2 2 2 0
+2 3 1 1 0
+3 3 1 1 0
+3 3 2 2 0
+3 0
diff --git a/gfsm/gfsm/tests/data/compose-in-1.tfst b/gfsm/gfsm/tests/data/compose-in-1.tfst
new file mode 100644
index 0000000..c98130b
--- /dev/null
+++ b/gfsm/gfsm/tests/data/compose-in-1.tfst
@@ -0,0 +1,4 @@
+0 1 1 0 0
+1 2 0 0 0
+2 3 0 2 0
+3 0
diff --git a/gfsm/gfsm/tests/data/compose-in-2.tfst b/gfsm/gfsm/tests/data/compose-in-2.tfst
new file mode 100644
index 0000000..7818495
--- /dev/null
+++ b/gfsm/gfsm/tests/data/compose-in-2.tfst
@@ -0,0 +1,4 @@
+0 1 2 0 0
+1 2 0 0 0
+2 3 0 3 0
+3 0
diff --git a/gfsm/gfsm/tests/data/compose-want.tfst b/gfsm/gfsm/tests/data/compose-want.tfst
new file mode 100644
index 0000000..5eb2b86
--- /dev/null
+++ b/gfsm/gfsm/tests/data/compose-want.tfst
@@ -0,0 +1,6 @@
+0 1 1 0 0
+1 2 0 0 0
+2 3 0 0 0
+3 4 0 0 0
+4 5 0 3 0
+5 0
diff --git a/gfsm/gfsm/tests/data/concat-in-1.tfst b/gfsm/gfsm/tests/data/concat-in-1.tfst
new file mode 100644
index 0000000..6ff2ca6
--- /dev/null
+++ b/gfsm/gfsm/tests/data/concat-in-1.tfst
@@ -0,0 +1,4 @@
+0 1 1 1
+1 0 2 2
+0
+1
diff --git a/gfsm/gfsm/tests/data/concat-in-2.tfst b/gfsm/gfsm/tests/data/concat-in-2.tfst
new file mode 100644
index 0000000..0b17350
--- /dev/null
+++ b/gfsm/gfsm/tests/data/concat-in-2.tfst
@@ -0,0 +1,4 @@
+0 1 3 3
+0 2 4 4
+1
+2
diff --git a/gfsm/gfsm/tests/data/concat-want.tfst b/gfsm/gfsm/tests/data/concat-want.tfst
new file mode 100644
index 0000000..b7a3015
--- /dev/null
+++ b/gfsm/gfsm/tests/data/concat-want.tfst
@@ -0,0 +1,8 @@
+0 1 1 1 0
+0 2 0 0 0
+1 0 2 2 0
+1 2 0 0 0
+2 4 4 4 0
+2 3 3 3 0
+3 0
+4 0
diff --git a/gfsm/gfsm/tests/data/connect-in.tfst b/gfsm/gfsm/tests/data/connect-in.tfst
new file mode 100644
index 0000000..f160c6c
--- /dev/null
+++ b/gfsm/gfsm/tests/data/connect-in.tfst
@@ -0,0 +1,7 @@
+0 1 0 1
+0 2 0 2
+1 3 1 3
+1 4 1 4
+2 4 2 4
+2 3 2 3
+3
diff --git a/gfsm/gfsm/tests/data/connect-want.tfst b/gfsm/gfsm/tests/data/connect-want.tfst
new file mode 100644
index 0000000..a2baa2f
--- /dev/null
+++ b/gfsm/gfsm/tests/data/connect-want.tfst
@@ -0,0 +1,5 @@
+0 2 0 2 0
+0 1 0 1 0
+1 3 1 3 0
+2 3 2 3 0
+3 0
diff --git a/gfsm/gfsm/tests/data/determinize-in.tfst b/gfsm/gfsm/tests/data/determinize-in.tfst
new file mode 100644
index 0000000..8a6d556
--- /dev/null
+++ b/gfsm/gfsm/tests/data/determinize-in.tfst
@@ -0,0 +1,7 @@
+0 1 1 1
+0 2 2 2
+0 2 1 1
+2 1 1 1
+2 3 3 3
+1 10
+3 30
diff --git a/gfsm/gfsm/tests/data/determinize-want.tfst b/gfsm/gfsm/tests/data/determinize-want.tfst
new file mode 100644
index 0000000..705ac7d
--- /dev/null
+++ b/gfsm/gfsm/tests/data/determinize-want.tfst
@@ -0,0 +1,9 @@
+0 1 1 1 0
+0 4 2 2 0
+1 2 1 1 0
+1 3 3 3 0
+1 0
+2 0
+3 0
+4 2 1 1 0
+4 3 3 3 0
diff --git a/gfsm/gfsm/tests/data/difference-in-1.tfst b/gfsm/gfsm/tests/data/difference-in-1.tfst
new file mode 100644
index 0000000..db980d5
--- /dev/null
+++ b/gfsm/gfsm/tests/data/difference-in-1.tfst
@@ -0,0 +1,6 @@
+0 0 1 1
+0 0 2 2
+0 0 3 3
+0 1 4 4
+1 0
+
diff --git a/gfsm/gfsm/tests/data/difference-in-2.tfst b/gfsm/gfsm/tests/data/difference-in-2.tfst
new file mode 100644
index 0000000..39bc8c9
--- /dev/null
+++ b/gfsm/gfsm/tests/data/difference-in-2.tfst
@@ -0,0 +1,5 @@
+4 3 1 0
+0 1 4 0
+1 0
+2 0 3 0
+3 2 2 0
diff --git a/gfsm/gfsm/tests/data/difference-want.tfst b/gfsm/gfsm/tests/data/difference-want.tfst
new file mode 100644
index 0000000..a98129f
--- /dev/null
+++ b/gfsm/gfsm/tests/data/difference-want.tfst
@@ -0,0 +1,21 @@
+0 1 1 0
+0 2 2 0
+0 2 3 0
+0 3 4 0
+1 2 1 0
+1 4 2 0
+1 2 3 0
+1 3 4 0
+2 2 1 0
+2 2 2 0
+2 2 3 0
+2 3 4 0
+3 0
+4 2 1 0
+4 2 2 0
+4 5 3 0
+4 3 4 0
+5 2 1 0
+5 2 2 0
+5 2 3 0
+5 6 4 0
diff --git a/gfsm/gfsm/tests/data/intersect-in-1.tfst b/gfsm/gfsm/tests/data/intersect-in-1.tfst
new file mode 100644
index 0000000..5781fec
--- /dev/null
+++ b/gfsm/gfsm/tests/data/intersect-in-1.tfst
@@ -0,0 +1,4 @@
+0 1 0 0
+1
+1 2 1 1
+2
diff --git a/gfsm/gfsm/tests/data/intersect-in-2.tfst b/gfsm/gfsm/tests/data/intersect-in-2.tfst
new file mode 100644
index 0000000..d64b6cb
--- /dev/null
+++ b/gfsm/gfsm/tests/data/intersect-in-2.tfst
@@ -0,0 +1,5 @@
+0 0 1 1
+0 1 0 0
+0
+1 1 2 2
+1
diff --git a/gfsm/gfsm/tests/data/intersect-want.tfst b/gfsm/gfsm/tests/data/intersect-want.tfst
new file mode 100644
index 0000000..57ed75d
--- /dev/null
+++ b/gfsm/gfsm/tests/data/intersect-want.tfst
@@ -0,0 +1,11 @@
+0 1 0 0
+0 4 0 0
+0 5 0 0
+1 2 1 0
+1 4 0 0
+1 0
+2 3 0 0
+2 0
+3 0
+4 0
+5 4 0 0
diff --git a/gfsm/gfsm/tests/data/intersect2-in-1.tfst b/gfsm/gfsm/tests/data/intersect2-in-1.tfst
new file mode 100644
index 0000000..db980d5
--- /dev/null
+++ b/gfsm/gfsm/tests/data/intersect2-in-1.tfst
@@ -0,0 +1,6 @@
+0 0 1 1
+0 0 2 2
+0 0 3 3
+0 1 4 4
+1 0
+
diff --git a/gfsm/gfsm/tests/data/intersect2-in-2.tfst b/gfsm/gfsm/tests/data/intersect2-in-2.tfst
new file mode 100644
index 0000000..cb7225c
--- /dev/null
+++ b/gfsm/gfsm/tests/data/intersect2-in-2.tfst
@@ -0,0 +1,29 @@
+0 1 1 0 0
+0 5 2 2 0
+0 5 3 3 0
+0 5 4 4 0
+0 0
+1 2 2 0 0
+1 5 1 1 0
+1 5 3 3 0
+1 5 4 4 0
+1 0
+2 3 3 0 0
+2 5 1 1 0
+2 5 2 2 0
+2 5 4 4 0
+2 0
+3 4 4 0 0
+3 5 1 1 0
+3 5 2 2 0
+3 5 3 3 0
+3 0
+4 5 1 1 0
+4 5 2 2 0
+4 5 3 3 0
+4 5 4 4 0
+5 5 1 1 0
+5 5 2 2 0
+5 5 3 3 0
+5 5 4 4 0
+5 0
diff --git a/gfsm/gfsm/tests/data/intersect2-want.tfst b/gfsm/gfsm/tests/data/intersect2-want.tfst
new file mode 100644
index 0000000..a98129f
--- /dev/null
+++ b/gfsm/gfsm/tests/data/intersect2-want.tfst
@@ -0,0 +1,21 @@
+0 1 1 0
+0 2 2 0
+0 2 3 0
+0 3 4 0
+1 2 1 0
+1 4 2 0
+1 2 3 0
+1 3 4 0
+2 2 1 0
+2 2 2 0
+2 2 3 0
+2 3 4 0
+3 0
+4 2 1 0
+4 2 2 0
+4 5 3 0
+4 3 4 0
+5 2 1 0
+5 2 2 0
+5 2 3 0
+5 6 4 0
diff --git a/gfsm/gfsm/tests/data/invert-in.tfst b/gfsm/gfsm/tests/data/invert-in.tfst
new file mode 100644
index 0000000..14649fb
--- /dev/null
+++ b/gfsm/gfsm/tests/data/invert-in.tfst
@@ -0,0 +1,5 @@
+0 1 0 1 10
+1 2 1 2 20
+1 3 1 3 30
+2 200
+3 300
diff --git a/gfsm/gfsm/tests/data/invert-want.tfst b/gfsm/gfsm/tests/data/invert-want.tfst
new file mode 100644
index 0000000..9a38c70
--- /dev/null
+++ b/gfsm/gfsm/tests/data/invert-want.tfst
@@ -0,0 +1,5 @@
+0 1 1 0 10
+1 3 3 1 30
+1 2 2 1 20
+2 200
+3 300
diff --git a/gfsm/gfsm/tests/data/lookup-123-want.tfst b/gfsm/gfsm/tests/data/lookup-123-want.tfst
new file mode 100644
index 0000000..e9d87c3
--- /dev/null
+++ b/gfsm/gfsm/tests/data/lookup-123-want.tfst
@@ -0,0 +1,7 @@
+0 2 1 2 1
+0 1 1 0 1
+1 6 0 3 1
+2 4 2 3 1
+2 3 2 2 0
+4 5 3 1 1
+5 0
diff --git a/gfsm/gfsm/tests/data/lookup-223-want.tfst b/gfsm/gfsm/tests/data/lookup-223-want.tfst
new file mode 100644
index 0000000..caa4069
--- /dev/null
+++ b/gfsm/gfsm/tests/data/lookup-223-want.tfst
@@ -0,0 +1,9 @@
+0 2 2 3 1
+0 1 2 2 0
+1 6 2 2 0
+2 4 2 3 1
+2 3 2 2 0
+4 5 3 1 1
+5 0
+6 7 3 3 0
+7 0
diff --git a/gfsm/gfsm/tests/data/lookup.tfst b/gfsm/gfsm/tests/data/lookup.tfst
new file mode 100644
index 0000000..0ecac5e
--- /dev/null
+++ b/gfsm/gfsm/tests/data/lookup.tfst
@@ -0,0 +1,13 @@
+0 0 1 2 1
+0 0 2 3 1
+0 0 3 1 1
+0 0
+
+0 1 2 2 0
+1 2 2 2 0
+2 3 3 3 0
+3 0
+
+0 4 1 0 1
+4 5 0 3 1
+5 0
diff --git a/gfsm/gfsm/tests/data/n_closure-in.tfst b/gfsm/gfsm/tests/data/n_closure-in.tfst
new file mode 100644
index 0000000..9009985
--- /dev/null
+++ b/gfsm/gfsm/tests/data/n_closure-in.tfst
@@ -0,0 +1,4 @@
+0 1 1 1 0
+0 2 2 2 0
+1 0
+2 0
diff --git a/gfsm/gfsm/tests/data/n_closure-want.tfst b/gfsm/gfsm/tests/data/n_closure-want.tfst
new file mode 100644
index 0000000..c993890
--- /dev/null
+++ b/gfsm/gfsm/tests/data/n_closure-want.tfst
@@ -0,0 +1,14 @@
+0 2 2 2 0
+0 1 1 1 0
+1 3 0 0 0
+2 3 0 0 0
+3 5 2 2 0
+3 4 1 1 0
+4 6 0 0 0
+5 6 0 0 0
+6 8 2 2 0
+6 7 1 1 0
+7 0 0 0 0
+7 0
+8 0 0 0 0
+8 0
diff --git a/gfsm/gfsm/tests/data/null.inf b/gfsm/gfsm/tests/data/null.inf
new file mode 100644
index 0000000..e788b4e
--- /dev/null
+++ b/gfsm/gfsm/tests/data/null.inf
@@ -0,0 +1,14 @@
+Filename : -
+Semiring : tropical
+Transducer? : y
+Weighted? : y
+Deterministic? : n
+Sort Mode : none, none, none, none, none, none
+Initial state : none
+# of states : 0
+# of final states : 0
+# of arcs : 0
+# of i/o epsilon arcs : 0
+# of input epsilon arcs : 0
+# of output epsilon arcs: 0
+cyclic? : n
diff --git a/gfsm/gfsm/tests/data/null.tfst b/gfsm/gfsm/tests/data/null.tfst
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gfsm/gfsm/tests/data/null.tfst
diff --git a/gfsm/gfsm/tests/data/optional-in.tfst b/gfsm/gfsm/tests/data/optional-in.tfst
new file mode 100644
index 0000000..c96f7e6
--- /dev/null
+++ b/gfsm/gfsm/tests/data/optional-in.tfst
@@ -0,0 +1,2 @@
+0 1 1 1 0
+1 0
diff --git a/gfsm/gfsm/tests/data/optional-want.tfst b/gfsm/gfsm/tests/data/optional-want.tfst
new file mode 100644
index 0000000..fe716fc
--- /dev/null
+++ b/gfsm/gfsm/tests/data/optional-want.tfst
@@ -0,0 +1,3 @@
+0 1 1 1 0
+0 0
+1 0
diff --git a/gfsm/gfsm/tests/data/project-hi-in.tfst b/gfsm/gfsm/tests/data/project-hi-in.tfst
new file mode 100644
index 0000000..d907516
--- /dev/null
+++ b/gfsm/gfsm/tests/data/project-hi-in.tfst
@@ -0,0 +1,6 @@
+0 1 1 1 1.5
+1 2 1 2 2.5
+2 3 0 0 0
+3 4 0 3 0
+4 5 4 0 0
+5 1.1
diff --git a/gfsm/gfsm/tests/data/project-hi-want.tfst b/gfsm/gfsm/tests/data/project-hi-want.tfst
new file mode 100644
index 0000000..9f01daf
--- /dev/null
+++ b/gfsm/gfsm/tests/data/project-hi-want.tfst
@@ -0,0 +1,6 @@
+0 1 1 1.5
+1 2 2 2.5
+2 3 0 0
+3 4 3 0
+4 5 0 0
+5 1.1
diff --git a/gfsm/gfsm/tests/data/project-lo-in.tfst b/gfsm/gfsm/tests/data/project-lo-in.tfst
new file mode 100644
index 0000000..d907516
--- /dev/null
+++ b/gfsm/gfsm/tests/data/project-lo-in.tfst
@@ -0,0 +1,6 @@
+0 1 1 1 1.5
+1 2 1 2 2.5
+2 3 0 0 0
+3 4 0 3 0
+4 5 4 0 0
+5 1.1
diff --git a/gfsm/gfsm/tests/data/project-lo-want.tfst b/gfsm/gfsm/tests/data/project-lo-want.tfst
new file mode 100644
index 0000000..c6bef07
--- /dev/null
+++ b/gfsm/gfsm/tests/data/project-lo-want.tfst
@@ -0,0 +1,6 @@
+0 1 1 1.5
+1 2 1 2.5
+2 3 0 0
+3 4 0 0
+4 5 4 0
+5 1.1
diff --git a/gfsm/gfsm/tests/data/renumber-in.tfst b/gfsm/gfsm/tests/data/renumber-in.tfst
new file mode 100644
index 0000000..07fe277
--- /dev/null
+++ b/gfsm/gfsm/tests/data/renumber-in.tfst
@@ -0,0 +1,8 @@
+5 0 0 0 0
+5 3 0 0 0
+6 7 1 1 0
+7 0
+0 1 2 0 0
+1 6 0 0 0
+3 4 3 0 0
+4 6 0 0 0
diff --git a/gfsm/gfsm/tests/data/renumber-want.tfst b/gfsm/gfsm/tests/data/renumber-want.tfst
new file mode 100644
index 0000000..ed8fc73
--- /dev/null
+++ b/gfsm/gfsm/tests/data/renumber-want.tfst
@@ -0,0 +1,8 @@
+0 3 0 0 0
+0 1 0 0 0
+1 2 2 0 0
+2 5 0 0 0
+3 4 3 0 0
+4 5 0 0 0
+5 6 1 1 0
+6 0
diff --git a/gfsm/gfsm/tests/data/rmepsilon-in.tfst b/gfsm/gfsm/tests/data/rmepsilon-in.tfst
new file mode 100644
index 0000000..07fe277
--- /dev/null
+++ b/gfsm/gfsm/tests/data/rmepsilon-in.tfst
@@ -0,0 +1,8 @@
+5 0 0 0 0
+5 3 0 0 0
+6 7 1 1 0
+7 0
+0 1 2 0 0
+1 6 0 0 0
+3 4 3 0 0
+4 6 0 0 0
diff --git a/gfsm/gfsm/tests/data/rmepsilon-want.tfst b/gfsm/gfsm/tests/data/rmepsilon-want.tfst
new file mode 100644
index 0000000..dbf6232
--- /dev/null
+++ b/gfsm/gfsm/tests/data/rmepsilon-want.tfst
@@ -0,0 +1,8 @@
+5 1 2 0 0
+5 4 3 0 0
+6 7 1 1 0
+7 0
+0 1 2 0 0
+1 7 1 1 0
+3 4 3 0 0
+4 7 1 1 0
diff --git a/gfsm/gfsm/tests/data/t1.linf b/gfsm/gfsm/tests/data/t1.linf
new file mode 100644
index 0000000..04e4f00
--- /dev/null
+++ b/gfsm/gfsm/tests/data/t1.linf
@@ -0,0 +1,14 @@
+Filename : -
+Semiring : tropical
+Transducer? : y
+Weighted? : y
+Deterministic? : n
+Sort Mode : none
+Initial state : 0
+# of states : 4
+# of final states : 1
+# of arcs : 3
+# of i/o epsilon arcs : 0
+# of input epsilon arcs : 1
+# of output epsilon arcs: 1
+cyclic? : n
diff --git a/gfsm/gfsm/tests/data/test.lab b/gfsm/gfsm/tests/data/test.lab
new file mode 100644
index 0000000..701436d
--- /dev/null
+++ b/gfsm/gfsm/tests/data/test.lab
@@ -0,0 +1,11 @@
+<eps> 0
+a 1
+b 2
+c 3
+d 4
+e 5
+f 6
+foo 7
+bar 8
+baz 9
+bonk 10
diff --git a/gfsm/gfsm/tests/data/union-in-1.tfst b/gfsm/gfsm/tests/data/union-in-1.tfst
new file mode 100644
index 0000000..6ff2ca6
--- /dev/null
+++ b/gfsm/gfsm/tests/data/union-in-1.tfst
@@ -0,0 +1,4 @@
+0 1 1 1
+1 0 2 2
+0
+1
diff --git a/gfsm/gfsm/tests/data/union-in-2.tfst b/gfsm/gfsm/tests/data/union-in-2.tfst
new file mode 100644
index 0000000..cbb2134
--- /dev/null
+++ b/gfsm/gfsm/tests/data/union-in-2.tfst
@@ -0,0 +1,4 @@
+0 0 3 3
+0 0 4 4
+0 1 5 5
+1
diff --git a/gfsm/gfsm/tests/data/union-want.tfst b/gfsm/gfsm/tests/data/union-want.tfst
new file mode 100644
index 0000000..0ee9068
--- /dev/null
+++ b/gfsm/gfsm/tests/data/union-want.tfst
@@ -0,0 +1,10 @@
+5 0 0 0 0
+5 3 0 0 0
+0 1 1 1 0
+0 0
+1 0 2 2 0
+1 0
+3 4 5 5 0
+3 3 4 4 0
+3 3 3 3 0
+4 0
diff --git a/gfsm/gfsm/tests/data/zzz-compile-all.sh b/gfsm/gfsm/tests/data/zzz-compile-all.sh
new file mode 100755
index 0000000..8a0d92b
--- /dev/null
+++ b/gfsm/gfsm/tests/data/zzz-compile-all.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+dir=`pwd -P`
+progdir="$dir/../../src/programs"
+
+for f in *.tfst ; do
+ b=`basename $f .tfst`
+ echo "$f -> $b.gfst"
+ ${progdir}/gfsmcompile "$f" -F "$b.gfst"
+done
+
+ \ No newline at end of file
diff --git a/gfsm/gfsm/tests/package.m4 b/gfsm/gfsm/tests/package.m4
new file mode 100644
index 0000000..00542a7
--- /dev/null
+++ b/gfsm/gfsm/tests/package.m4
@@ -0,0 +1,6 @@
+# Signature of the current package.
+m4_define([AT_PACKAGE_NAME], [gfsm])
+m4_define([AT_PACKAGE_TARNAME], [gfsm])
+m4_define([AT_PACKAGE_VERSION], [0.0.10-pre5])
+m4_define([AT_PACKAGE_STRING], [gfsm 0.0.10-pre5])
+m4_define([AT_PACKAGE_BUGREPORT], [moocow@ling.uni-potsdam.de])
diff --git a/gfsm/gfsm/tests/testsuite b/gfsm/gfsm/tests/testsuite
new file mode 100755
index 0000000..a78bcd2
--- /dev/null
+++ b/gfsm/gfsm/tests/testsuite
@@ -0,0 +1,5251 @@
+#! /bin/sh
+#
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+# Foundation, Inc.
+# This test suite is free software; the Free Software Foundation gives
+# unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# How were we run?
+at_cli_args="$@"
+
+# Load the config file.
+for at_file in atconfig atlocal
+do
+ test -r $at_file || continue
+ . ./$at_file || { echo "$as_me: error: invalid content: $at_file" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# Autoconf <=2.59b set at_top_builddir instead of at_top_build_prefix:
+: ${at_top_build_prefix=$at_top_builddir}
+
+# atconfig delivers names relative to the directory the test suite is
+# in, but the groups themselves are run in testsuite-dir/group-dir.
+if test -n "$at_top_srcdir"; then
+ builddir=../..
+ for at_dir in srcdir top_srcdir top_build_prefix
+ do
+ at_val=`eval echo '${'at_$at_dir'}'`
+ eval "$at_dir=\$at_val/../.."
+ done
+fi
+
+# Not all shells have the 'times' builtin; the subshell is needed to make
+# sure we discard the 'times: not found' message from the shell.
+at_times_p=false
+(times) >/dev/null 2>&1 && at_times_p=:
+
+# CLI Arguments to pass to the debugging scripts.
+at_debug_args=
+# -e sets to true
+at_errexit_p=false
+# Shall we be verbose?
+at_verbose=:
+at_quiet=echo
+
+# Shall we keep the debug scripts? Must be `:' when the suite is
+# run by a debug script, so that the script doesn't remove itself.
+at_debug_p=false
+# Display help message?
+at_help_p=false
+# Display the version message?
+at_version_p=false
+# List test groups?
+at_list_p=false
+# Test groups to run
+at_groups=
+
+# The directory we are in.
+at_dir=`pwd`
+# The directory the whole suite works in.
+# Should be absolutely to let the user `cd' at will.
+at_suite_dir=$at_dir/$as_me.dir
+# The file containing the suite.
+at_suite_log=$at_dir/$as_me.log
+# The file containing the location of the last AT_CHECK.
+at_check_line_file=$at_suite_dir/at-check-line
+# The file containing the exit status of the last command.
+at_status_file=$at_suite_dir/at-status
+# The files containing the output of the tested commands.
+at_stdout=$at_suite_dir/at-stdout
+at_stder1=$at_suite_dir/at-stder1
+at_stderr=$at_suite_dir/at-stderr
+# The file containing dates.
+at_times_file=$at_suite_dir/at-times
+
+# List of the tested programs.
+at_tested=''
+# List of the all the test groups.
+at_groups_all=' banner-1 1 2 3 banner-2 4 5 6 7 8 9 banner-3 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25'
+# As many question marks as there are digits in the last test group number.
+# Used to normalize the test group numbers so that `ls' lists them in
+# numerical order.
+at_format='??'
+# Description of all the test groups.
+at_help_all="1;01_basic.at:12;compile+print.null;basic compile print info;
+2;01_basic.at:29;compile+print.simple;basic compile print info;
+3;01_basic.at:44;compile+print.labels;basic compile print info alphabet;
+4;02_arith.at:12;arith.real;arith semiring;
+5;02_arith.at:34;arith.sr.boolean;arith semiring;
+6;02_arith.at:48;arith.sr.log;arith semiring;
+7;02_arith.at:66;arith.sr.plog;arith semiring;
+8;02_arith.at:84;arith.sr.real;;
+9;02_arith.at:97;arith.sr.tropical;arith semiring;
+10;03_algebra.at:12;closure.plus;algebra closure;
+11;03_algebra.at:24;closure.star;algebra closure;
+12;03_algebra.at:36;complement;algebra complement;
+13;03_algebra.at:56;compose;algebra compose;
+14;03_algebra.at:69;concat;algebra concat;
+15;03_algebra.at:82;connect;algebra connect;
+16;03_algebra.at:94;determinize;algebra determinize;
+17;03_algebra.at:107;difference;algebra difference;
+18;03_algebra.at:120;intersect;algebra intersect;
+19;03_algebra.at:142;invert;algebra invert;
+20;03_algebra.at:154;optional;algebra optional;
+21;03_algebra.at:166;project.lo;algebra project;
+22;03_algebra.at:178;project.hi;algebra project;
+23;03_algebra.at:190;renumber;algebra renumber;
+24;03_algebra.at:202;rmepsilon;algebra rmepsilon;
+25;03_algebra.at:214;union;algebra union;
+"
+
+at_prev=
+for at_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$at_prev"; then
+ at_option=$at_prev=$at_option
+ at_prev=
+ fi
+
+ case $at_option in
+ *=*) at_optarg=`expr "x$at_option" : 'x[^=]*=\(.*\)'` ;;
+ *) at_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $at_option in
+ --help | -h )
+ at_help_p=:
+ ;;
+
+ --list | -l )
+ at_list_p=:
+ ;;
+
+ --version | -V )
+ at_version_p=:
+ ;;
+
+ --clean | -c )
+ test -d "$at_suite_dir" &&
+ find "$at_suite_dir" -type d ! -perm -700 -exec chmod u+rwx \{\} \;
+ rm -f -r "$at_suite_dir" "$at_suite_log"
+ exit 0
+ ;;
+
+ --debug | -d )
+ at_debug_p=:
+ ;;
+
+ --errexit | -e )
+ at_debug_p=:
+ at_errexit_p=:
+ ;;
+
+ --verbose | -v )
+ at_verbose=echo; at_quiet=:
+ ;;
+
+ --trace | -x )
+ at_traceon='set -x'; at_traceoff='set +x'
+ ;;
+
+ [0-9] | [0-9][0-9] | [0-9][0-9][0-9] | [0-9][0-9][0-9][0-9])
+ at_groups="$at_groups$at_option "
+ ;;
+
+ # Ranges
+ [0-9]- | [0-9][0-9]- | [0-9][0-9][0-9]- | [0-9][0-9][0-9][0-9]-)
+ at_range_start=`echo $at_option |tr -d X-`
+ at_range=`echo " $at_groups_all " | \
+ sed -e 's/^.* \('$at_range_start' \)/\1/'`
+ at_groups="$at_groups$at_range "
+ ;;
+
+ -[0-9] | -[0-9][0-9] | -[0-9][0-9][0-9] | -[0-9][0-9][0-9][0-9])
+ at_range_end=`echo $at_option |tr -d X-`
+ at_range=`echo " $at_groups_all " | \
+ sed -e 's/\( '$at_range_end'\) .*$/\1/'`
+ at_groups="$at_groups$at_range "
+ ;;
+
+ [0-9]-[0-9] | [0-9]-[0-9][0-9] | [0-9]-[0-9][0-9][0-9] | \
+ [0-9]-[0-9][0-9][0-9][0-9] | [0-9][0-9]-[0-9][0-9] | \
+ [0-9][0-9]-[0-9][0-9][0-9] | [0-9][0-9]-[0-9][0-9][0-9][0-9] | \
+ [0-9][0-9][0-9]-[0-9][0-9][0-9] | \
+ [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9] | \
+ [0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9] )
+ at_range_start=`expr $at_option : '\(.*\)-'`
+ at_range_end=`expr $at_option : '.*-\(.*\)'`
+ if test $at_range_start -gt $at_range_end; then
+ at_tmp=$at_range_end
+ at_range_end=$at_range_start
+ at_range_start=$at_tmp
+ fi
+ at_range=`echo " $at_groups_all " | \
+ sed -e 's/^.*\( '$at_range_start' \)/\1/' \
+ -e 's/\( '$at_range_end'\) .*$/\1/'`
+ at_groups="$at_groups$at_range "
+ ;;
+
+ # Keywords.
+ --keywords | -k )
+ at_prev=--keywords
+ ;;
+ --keywords=* )
+ at_groups_selected=$at_help_all
+ at_save_IFS=$IFS
+ IFS=,
+ set X $at_optarg
+ shift
+ IFS=$at_save_IFS
+ for at_keyword
+ do
+ at_invert=
+ case $at_keyword in
+ '!'*)
+ at_invert="-v"
+ at_keyword=`expr "X$at_keyword" : 'X!\(.*\)'`
+ ;;
+ esac
+ # It is on purpose that we match the test group titles too.
+ at_groups_selected=`echo "$at_groups_selected" |
+ grep -i $at_invert "^[1-9][^;]*;.*[; ]$at_keyword[ ;]"`
+ done
+ at_groups_selected=`echo "$at_groups_selected" | sed 's/;.*//'`
+ # Smash the newlines.
+ at_groups="$at_groups`echo $at_groups_selected` "
+ ;;
+
+ *=*)
+ at_envvar=`expr "x$at_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$at_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $at_envvar" >&2
+ { (exit 1); exit 1; }; }
+ at_value=`echo "$at_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$at_envvar='$at_value'"
+ export $at_envvar
+ # Propagate to debug scripts.
+ at_debug_args="$at_debug_args $at_envvar='$at_value'"
+ ;;
+
+ *) echo "$as_me: invalid option: $at_option" >&2
+ echo "Try \`$0 --help' for more information." >&2
+ exit 1
+ ;;
+ esac
+done
+
+# Selected test groups.
+if test -z "$at_groups"; then
+ at_groups=$at_groups_all
+else
+ # Sort the tests, removing duplicates:
+ at_groups=`echo $at_groups | tr ' ' "$as_nl" | sort -nu`
+ # and add banners. (Passing at_groups_all is tricky--see the comment
+ # starting with "Passing at_groups is tricky.")
+ at_groups=`echo "$at_groups$as_nl $at_groups_all" |
+ awk 'BEGIN { FS = "@" } # Effectively switch off field splitting.
+ /^$/ { next } # Ignore the empty line.
+ !/ / { groups++; selected[$ 0] = 1; next }
+ # The last line, containing at_groups_all.
+ {
+ n = split($ 0, a, " ")
+ # If there are several tests, select their banners:
+ if (groups > 1) {
+ for (i = 1; i <= n; i++) {
+ if (a[i] ~ /^banner-/)
+ banner = a[i]
+ else if (banner != "" && selected[a[i]] == 1)
+ selected[banner] = 1
+ }
+ }
+ for (i = 1; i <= n; i++)
+ if (selected[a[i]] == 1)
+ list = list " " a[i]
+ print list
+ }'`
+fi
+
+# Help message.
+if $at_help_p; then
+ cat <<_ATEOF
+Usage: $0 [OPTION]... [VARIABLE=VALUE]... [TESTS]
+
+Run all the tests, or the selected TESTS, given by numeric ranges, and
+save a detailed log file. Upon failure, create debugging scripts.
+
+You should not change environment variables unless explicitly passed
+as command line arguments. Set \`AUTOTEST_PATH' to select the executables
+to exercise. Each relative directory is expanded as build and source
+directories relatively to the top level of this distribution. E.g.,
+
+ $ $0 AUTOTEST_PATH=bin
+
+possibly amounts into
+
+ PATH=/tmp/foo-1.0/bin:/src/foo-1.0/bin:\$PATH
+_ATEOF
+cat <<_ATEOF
+
+Operation modes:
+ -h, --help print the help message, then exit
+ -V, --version print version number, then exit
+ -c, --clean remove all the files this test suite might create and exit
+ -l, --list describes all the tests, or the selected TESTS
+_ATEOF
+cat <<_ATEOF
+
+Execution tuning:
+ -k, --keywords=KEYWORDS
+ select the tests matching all the comma-separated KEYWORDS
+ multiple \`-k' accumulate; prefixed \`!' negates a KEYWORD
+ -e, --errexit abort as soon as a test fails; implies --debug
+ -v, --verbose force more detailed output
+ default for debugging scripts
+ -d, --debug inhibit clean up and top-level logging
+ default for debugging scripts
+ -x, --trace enable tests shell tracing
+_ATEOF
+cat <<_ATEOF
+
+Report bugs to <moocow@ling.uni-potsdam.de>.
+_ATEOF
+ exit 0
+fi
+
+# List of tests.
+if $at_list_p; then
+ cat <<_ATEOF
+gfsm 0.0.10-pre5 test suite: gfsmutils test groups:
+
+ NUM: FILE-NAME:LINE TEST-GROUP-NAME
+ KEYWORDS
+
+_ATEOF
+ # Passing at_groups is tricky. We cannot use it to form a literal string
+ # or regexp because of the limitation of AIX awk. And Solaris' awk
+ # doesn't grok more than 99 fields in a record, so we have to use `split'.
+ echo "$at_groups$as_nl$at_help_all" |
+ awk 'BEGIN { FS = ";" }
+ NR == 1 {
+ for (n = split($ 0, a, " "); n; n--) selected[a[n]] = 1
+ next
+ }
+ {
+ if (selected[$ 1]) {
+ printf " %3d: %-18s %s\n", $ 1, $ 2, $ 3
+ if ($ 4) printf " %s\n", $ 4
+ }
+ }'
+ exit 0
+fi
+if $at_version_p; then
+ echo "$as_me (gfsm 0.0.10-pre5)"
+ cat <<\_ACEOF
+
+Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+Foundation, Inc.
+This test suite is free software; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+
+# Don't take risks: use only absolute directories in PATH.
+#
+# For stand-alone test suites, AUTOTEST_PATH is relative to `.'.
+#
+# For embedded test suites, AUTOTEST_PATH is relative to the top level
+# of the package. Then expand it into build/src parts, since users
+# may create executables in both places.
+AUTOTEST_PATH=`echo $AUTOTEST_PATH | sed "s&:&$PATH_SEPARATOR&g"`
+at_path=
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $AUTOTEST_PATH $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -n "$at_path" && at_path=$at_path$PATH_SEPARATOR
+case $as_dir in
+ [\\/]* | ?:[\\/]* )
+ at_path=$at_path$as_dir
+ ;;
+ * )
+ if test -z "$at_top_build_prefix"; then
+ # Stand-alone test suite.
+ at_path=$at_path$as_dir
+ else
+ # Embedded test suite.
+ at_path=$at_path$at_top_build_prefix$as_dir$PATH_SEPARATOR
+ at_path=$at_path$at_top_srcdir/$as_dir
+ fi
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+# Now build and simplify PATH.
+#
+# There might be directories that don't exist, but don't redirect
+# builtins' (eg., cd) stderr directly: Ultrix's sh hates that.
+PATH=
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $at_path
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_dir=`(cd "$as_dir" && pwd) 2>/dev/null`
+test -d "$as_dir" || continue
+case $PATH in
+ $as_dir | \
+ $as_dir$PATH_SEPARATOR* | \
+ *$PATH_SEPARATOR$as_dir | \
+ *$PATH_SEPARATOR$as_dir$PATH_SEPARATOR* ) ;;
+
+ '') PATH=$as_dir ;;
+ *) PATH=$PATH$PATH_SEPARATOR$as_dir ;;
+esac
+done
+IFS=$as_save_IFS
+
+export PATH
+
+# Setting up the FDs.
+# 5 is the log file. Not to be overwritten if `-d'.
+
+if $at_debug_p; then
+ at_suite_log=/dev/null
+else
+ : >"$at_suite_log"
+fi
+exec 5>>"$at_suite_log"
+
+# Banners and logs.
+cat <<\_ASBOX
+## --------------------------------------- ##
+## gfsm 0.0.10-pre5 test suite: gfsmutils. ##
+## --------------------------------------- ##
+_ASBOX
+{
+ cat <<\_ASBOX
+## --------------------------------------- ##
+## gfsm 0.0.10-pre5 test suite: gfsmutils. ##
+## --------------------------------------- ##
+_ASBOX
+ echo
+
+ echo "$as_me: command line was:"
+ echo " $ $0 $at_cli_args"
+ echo
+
+ # Try to find a few ChangeLogs in case it might help determining the
+ # exact version. Use the relative dir: if the top dir is a symlink,
+ # find will not follow it (and options to follow the links are not
+ # portable), which would result in no output here.
+ if test -n "$at_top_srcdir"; then
+ cat <<\_ASBOX
+## ----------- ##
+## ChangeLogs. ##
+## ----------- ##
+_ASBOX
+ echo
+ for at_file in `find "$at_top_srcdir" -name ChangeLog -print`
+ do
+ echo "$as_me: $at_file:"
+ sed 's/^/| /;10q' $at_file
+ echo
+ done
+
+ {
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+}
+ echo
+ fi
+
+ # Contents of the config files.
+ for at_file in atconfig atlocal
+ do
+ test -r $at_file || continue
+ echo "$as_me: $at_file:"
+ sed 's/^/| /' $at_file
+ echo
+ done
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Tested programs. ##
+## ---------------- ##
+_ASBOX
+ echo
+} >&5
+
+# Report what programs are being tested.
+for at_program in : $at_tested
+do
+ test "$at_program" = : && continue
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -f "$as_dir/$at_program" && break
+done
+IFS=$as_save_IFS
+
+ if test -f "$as_dir/$at_program"; then
+ {
+ echo "$at_srcdir/testsuite.at:8: $as_dir/$at_program --version"
+ "$as_dir/$at_program" --version
+ echo
+ } >&5 2>&1
+ else
+ { { echo "$as_me:$LINENO: error: cannot find $at_program" >&5
+echo "$as_me: error: cannot find $at_program" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+done
+
+{
+ cat <<\_ASBOX
+## ------------------ ##
+## Running the tests. ##
+## ------------------ ##
+_ASBOX
+} >&5
+
+at_start_date=`date`
+at_start_time=`date +%s 2>/dev/null`
+echo "$as_me: starting at: $at_start_date" >&5
+at_xpass_list=
+at_xfail_list=
+at_pass_list=
+at_fail_list=
+at_skip_list=
+at_group_count=0
+
+# Create the master directory if it doesn't already exist.
+test -d "$at_suite_dir" ||
+ mkdir "$at_suite_dir" ||
+ { { echo "$as_me:$LINENO: error: cannot create '$at_suite_dir'" >&5
+echo "$as_me: error: cannot create '$at_suite_dir'" >&2;}
+ { (exit 1); exit 1; }; }
+
+# Can we diff with `/dev/null'? DU 5.0 refuses.
+if diff /dev/null /dev/null >/dev/null 2>&1; then
+ at_devnull=/dev/null
+else
+ at_devnull=$at_suite_dir/devnull
+ >"$at_devnull"
+fi
+
+# Use `diff -u' when possible.
+if at_diff=`diff -u "$at_devnull" "$at_devnull" 2>&1` && test -z "$at_diff"
+then
+ at_diff='diff -u'
+else
+ at_diff=diff
+fi
+
+
+for at_group in $at_groups
+do
+ # Be sure to come back to the top test directory.
+ cd "$at_suite_dir"
+
+ case $at_group in
+ banner-*)
+ at_group_log=$at_suite_log
+ ;;
+
+ *)
+ at_group_normalized=$at_group
+
+ while :; do
+ case $at_group_normalized in #(
+ $at_format*) break;;
+ esac
+ at_group_normalized=0$at_group_normalized
+ done
+
+
+ # Create a fresh directory for the next test group, and enter.
+ at_group_dir=$at_suite_dir/$at_group_normalized
+ at_group_log=$at_group_dir/$as_me.log
+ if test -d "$at_group_dir"; then
+ find "$at_group_dir" -type d ! -perm -700 -exec chmod u+rwx \{\} \;
+ rm -fr "$at_group_dir"
+ fi
+ # Be tolerant if the above `rm' was not able to remove the directory.
+ { as_dir=$at_group_dir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ cd $at_group_dir
+ ;;
+ esac
+
+ echo 0 > "$at_status_file"
+
+ # Clearly separate the test groups when verbose.
+ test $at_group_count != 0 && $at_verbose
+
+ # In verbose mode, append to the log file *and* show on
+ # the standard output; in quiet mode only write to the log
+ if test $at_verbose = echo; then
+ at_tee_pipe='tee -a "$at_group_log"'
+ else
+ at_tee_pipe='cat >> "$at_group_log"'
+ fi
+
+ case $at_group in
+
+ banner-1 ) # Banner 1. 01_basic.at:8
+ cat <<\_ATEOF
+
+basic automaton manipulation
+
+_ATEOF
+ ;;
+
+ 1 ) # 1. 01_basic.at:12: compile+print.null
+ at_setup_line='01_basic.at:12'
+ at_desc="compile+print.null"
+ $at_quiet $ECHO_N " 1: compile+print.null $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "1. 01_basic.at:12: testing ..."
+ $at_traceon
+
+
+
+##-- compile: null
+$at_traceoff
+echo "$at_srcdir/01_basic.at:16: \$progdir/gfsmcompile \$tdata/null.tfst -F null.gfst"
+echo 01_basic.at:16 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsmcompile $tdata/null.tfst -F null.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/null.tfst -F null.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/null.tfst -F null.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:16: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+##-- print: null
+$at_traceoff
+echo "$at_srcdir/01_basic.at:19: \$progdir/gfsmprint null.gfst"
+echo 01_basic.at:19 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsmprint null.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint null.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint null.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+echo stderr:; cat "$at_stderr"
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:19: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+##-- info: null
+rm -f expout; ln $tdata/null.inf expout
+$at_traceoff
+echo "$at_srcdir/01_basic.at:23: \$progdir/gfsminfo < null.gfst"
+echo 01_basic.at:23 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsminfo < null.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsminfo < null.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsminfo < null.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:23: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 2 ) # 2. 01_basic.at:29: compile+print.simple
+ at_setup_line='01_basic.at:29'
+ at_desc="compile+print.simple"
+ $at_quiet $ECHO_N " 2: compile+print.simple $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "2. 01_basic.at:29: testing ..."
+ $at_traceon
+
+
+
+$at_traceoff
+echo "$at_srcdir/01_basic.at:32: \$progdir/gfsmcompile \$tdata/basic1.tfst -F basic1.gfst"
+echo 01_basic.at:32 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsmcompile $tdata/basic1.tfst -F basic1.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/basic1.tfst -F basic1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/basic1.tfst -F basic1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:32: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+rm -f expout; ln $tdata/basic1.tfst expout
+$at_traceoff
+echo "$at_srcdir/01_basic.at:35: \$progdir/gfsmprint basic1.gfst"
+echo 01_basic.at:35 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsmprint basic1.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint basic1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint basic1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:35: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+rm -f expout; ln $tdata/basic1.inf expout
+$at_traceoff
+echo "$at_srcdir/01_basic.at:38: \$progdir/gfsminfo < basic1.gfst"
+echo 01_basic.at:38 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsminfo < basic1.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsminfo < basic1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsminfo < basic1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:38: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 3 ) # 3. 01_basic.at:44: compile+print.labels
+ at_setup_line='01_basic.at:44'
+ at_desc="compile+print.labels"
+ $at_quiet $ECHO_N " 3: compile+print.labels $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "3. 01_basic.at:44: testing ..."
+ $at_traceon
+
+
+$at_traceoff
+echo "$at_srcdir/01_basic.at:46: \$progdir/gfsmcompile -i \$tdata/test.lab -o \$tdata/test.lab \$tdata/basic2.labs.tfst -F basic2.gfst"
+echo 01_basic.at:46 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsmcompile -i $tdata/test.lab -o $tdata/test.lab $tdata/basic2.labs.tfst -F basic2.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile -i $tdata/test.lab -o $tdata/test.lab $tdata/basic2.labs.tfst -F basic2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile -i $tdata/test.lab -o $tdata/test.lab $tdata/basic2.labs.tfst -F basic2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:46: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+rm -f expout; ln $tdata/basic2.labs.tfst expout
+$at_traceoff
+echo "$at_srcdir/01_basic.at:49: \$progdir/gfsmprint -i \$tdata/test.lab -o \$tdata/test.lab basic2.gfst"
+echo 01_basic.at:49 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsmprint -i $tdata/test.lab -o $tdata/test.lab basic2.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint -i $tdata/test.lab -o $tdata/test.lab basic2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint -i $tdata/test.lab -o $tdata/test.lab basic2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:49: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+rm -f expout; ln $tdata/basic2.labs.inf expout
+$at_traceoff
+echo "$at_srcdir/01_basic.at:52: \$progdir/gfsminfo < basic2.gfst"
+echo 01_basic.at:52 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "$progdir/gfsminfo < basic2.gfst" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsminfo < basic2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsminfo < basic2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/01_basic.at:52: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+
+ banner-2 ) # Banner 2. 02_arith.at:8
+ cat <<\_ATEOF
+
+(semiring-)arithmetic
+
+_ATEOF
+ ;;
+
+ 4 ) # 4. 02_arith.at:12: arith.real
+ at_setup_line='02_arith.at:12'
+ at_desc="arith.real"
+ $at_quiet $ECHO_N " 4: arith.real $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "4. 02_arith.at:12: testing ..."
+ $at_traceon
+
+
+
+##-- real ops: add, multiply
+$at_traceoff
+echo "$at_srcdir/02_arith.at:16: echo \"0 0\" | \$progdir/gfsmcompile | \$progdir/gfsmarith -Z -a 1 | \$progdir/gfsmprint"
+echo 02_arith.at:16 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 0\" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -a 1 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 0" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -a 1 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 0" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -a 1 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 1
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:16: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:19: echo \"0 1\" | \$progdir/gfsmcompile | \$progdir/gfsmarith -Z -m 42 | \$progdir/gfsmprint"
+echo 02_arith.at:19 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 1\" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -m 42 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -m 42 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z -m 42 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 42
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:19: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+##-- real ops: log, exp
+$at_traceoff
+echo "$at_srcdir/02_arith.at:24: echo \"0 1\" | \$progdir/gfsmcompile | \$progdir/gfsmarith -Z --log | \$progdir/gfsmprint"
+echo 02_arith.at:24 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 1\" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --log | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --log | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --log | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 0
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:24: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:27: echo \"0 1\" | \$progdir/gfsmcompile | \$progdir/gfsmarith -Z --exp | \$progdir/gfsmprint"
+echo 02_arith.at:27 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 1\" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --exp | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --exp | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 1" | $progdir/gfsmcompile | $progdir/gfsmarith -Z --exp | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 2.71828
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:27: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 5 ) # 5. 02_arith.at:34: arith.sr.boolean
+ at_setup_line='02_arith.at:34'
+ at_desc="arith.sr.boolean"
+ $at_quiet $ECHO_N " 5: arith.sr.boolean $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "5. 02_arith.at:34: testing ..."
+ $at_traceon
+
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:36: echo \"0 0\" | \$progdir/gfsmcompile -s boolean | \$progdir/gfsmarith -Z --plus=1 | \$progdir/gfsmprint"
+echo 02_arith.at:36 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 0\" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --plus=1 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 0" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --plus=1 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 0" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --plus=1 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 1
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:36: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:40: echo \"0 0\" | \$progdir/gfsmcompile -s boolean | \$progdir/gfsmarith -Z --times=1 | \$progdir/gfsmprint"
+echo 02_arith.at:40 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 0\" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --times=1 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 0" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --times=1 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 0" | $progdir/gfsmcompile -s boolean | $progdir/gfsmarith -Z --times=1 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 0
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:40: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 6 ) # 6. 02_arith.at:48: arith.sr.log
+ at_setup_line='02_arith.at:48'
+ at_desc="arith.sr.log"
+ $at_quiet $ECHO_N " 6: arith.sr.log $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "6. 02_arith.at:48: testing ..."
+ $at_traceon
+
+
+# -log(.125)= 2.07944
+# -log(.25) = 1.38629
+# -log(.5) = .693147
+# -log(.75) = 0.287682
+$at_traceoff
+echo "$at_srcdir/02_arith.at:54: echo \"0 .693147\" | \$progdir/gfsmcompile -s log | \$progdir/gfsmarith -Z --plus=1.38629 | \$progdir/gfsmprint"
+echo 02_arith.at:54 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 .693147\" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --plus=1.38629 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 .693147" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --plus=1.38629 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 .693147" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --plus=1.38629 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 0.28768
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:54: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:58: echo \"0 .5\" | \$progdir/gfsmcompile -s log | \$progdir/gfsmarith -Z --times=0.25 | \$progdir/gfsmprint"
+echo 02_arith.at:58 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 .5\" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --times=0.25 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 .5" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --times=0.25 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 .5" | $progdir/gfsmcompile -s log | $progdir/gfsmarith -Z --times=0.25 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 0.75
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:58: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 7 ) # 7. 02_arith.at:66: arith.sr.plog
+ at_setup_line='02_arith.at:66'
+ at_desc="arith.sr.plog"
+ $at_quiet $ECHO_N " 7: arith.sr.plog $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "7. 02_arith.at:66: testing ..."
+ $at_traceon
+
+
+# log(.125)= -2.07944
+# log(.25) = -1.38629
+# log(.5) = -0.693147
+# log(.75) = -0.287682
+$at_traceoff
+echo "$at_srcdir/02_arith.at:72: echo \"0 -0.693147\" | \$progdir/gfsmcompile -s plog | \$progdir/gfsmarith -Z --plus=-1.38629 | \$progdir/gfsmprint"
+echo 02_arith.at:72 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 -0.693147\" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --plus=-1.38629 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 -0.693147" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --plus=-1.38629 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 -0.693147" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --plus=-1.38629 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 -0.28768
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:72: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:76: echo \"0 -0.5\" | \$progdir/gfsmcompile -s plog | \$progdir/gfsmarith -Z --times=-0.25 | \$progdir/gfsmprint"
+echo 02_arith.at:76 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 -0.5\" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --times=-0.25 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 -0.5" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --times=-0.25 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 -0.5" | $progdir/gfsmcompile -s plog | $progdir/gfsmarith -Z --times=-0.25 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 -0.75
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:76: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 8 ) # 8. 02_arith.at:84: arith.sr.real
+ at_setup_line='02_arith.at:84'
+ at_desc="arith.sr.real"
+ $at_quiet $ECHO_N " 8: arith.sr.real $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "8. 02_arith.at:84: testing ..."
+ $at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:85: echo \"0 3\" | \$progdir/gfsmcompile -s real | \$progdir/gfsmarith -Z --plus=4 | \$progdir/gfsmprint"
+echo 02_arith.at:85 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 3\" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 3" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 3" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 7
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:85: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:89: echo \"0 3\" | \$progdir/gfsmcompile -s real | \$progdir/gfsmarith -Z --times=4 | \$progdir/gfsmprint"
+echo 02_arith.at:89 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 3\" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 3" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 3" | $progdir/gfsmcompile -s real | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 12
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:89: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 9 ) # 9. 02_arith.at:97: arith.sr.tropical
+ at_setup_line='02_arith.at:97'
+ at_desc="arith.sr.tropical"
+ $at_quiet $ECHO_N " 9: arith.sr.tropical $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "9. 02_arith.at:97: testing ..."
+ $at_traceon
+
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:99: echo \"0 3\" | \$progdir/gfsmcompile -s tropical | \$progdir/gfsmarith -Z --plus=4 | \$progdir/gfsmprint"
+echo 02_arith.at:99 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 3\" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 3" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 3" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --plus=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 3
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:99: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/02_arith.at:103: echo \"0 3\" | \$progdir/gfsmcompile -s tropical | \$progdir/gfsmarith -Z --times=4 | \$progdir/gfsmprint"
+echo 02_arith.at:103 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ case "echo \"0 3\" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint" in
+ *'
+'*) echo 'Not enabling shell tracing (command contains an embedded newline)' ;;
+ *) at_trace_this=yes ;;
+ esac
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; echo "0 3" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; echo "0 3" | $progdir/gfsmcompile -s tropical | $progdir/gfsmarith -Z --times=4 | $progdir/gfsmprint ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+echo >>"$at_stdout"; echo "0 7
+" | $at_diff - "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/02_arith.at:103: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+
+ banner-3 ) # Banner 3. 03_algebra.at:8
+ cat <<\_ATEOF
+
+algebraic operations
+
+_ATEOF
+ ;;
+
+ 10 ) # 10. 03_algebra.at:12: closure.plus
+ at_setup_line='03_algebra.at:12'
+ at_desc="closure.plus"
+ $at_quiet $ECHO_N " 10: closure.plus $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "10. 03_algebra.at:12: testing ..."
+ $at_traceon
+
+
+opname="closure-plus"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:16: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:16 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:16: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:17: \$progdir/gfsmclosure --plus \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:17 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmclosure --plus ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmclosure --plus ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:17: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:19: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:19 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:19: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 11 ) # 11. 03_algebra.at:24: closure.star
+ at_setup_line='03_algebra.at:24'
+ at_desc="closure.star"
+ $at_quiet $ECHO_N " 11: closure.star $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "11. 03_algebra.at:24: testing ..."
+ $at_traceon
+
+
+opname="closure-star"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:28: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:28 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:28: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:29: \$progdir/gfsmclosure \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:29 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmclosure ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmclosure ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:29: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:31: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:31 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:31: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 12 ) # 12. 03_algebra.at:36: complement
+ at_setup_line='03_algebra.at:36'
+ at_desc="complement"
+ $at_quiet $ECHO_N " 12: complement $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "12. 03_algebra.at:36: testing ..."
+ $at_traceon
+
+
+opname="complement"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:40: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:40 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:40: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:41: \$progdir/gfsmcomplement \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:41 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcomplement ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcomplement ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:41: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:43: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:43 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:43: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+##
+##-- complement(b): given alphabet
+opname="complement-b"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:48: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:48 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:48: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:49: \$progdir/gfsmcomplement -i \$tdata/test.lab \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:49 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcomplement -i $tdata/test.lab ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcomplement -i $tdata/test.lab ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:49: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:51: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:51 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:51: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 13 ) # 13. 03_algebra.at:56: compose
+ at_setup_line='03_algebra.at:56'
+ at_desc="compose"
+ $at_quiet $ECHO_N " 13: compose $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "13. 03_algebra.at:56: testing ..."
+ $at_traceon
+
+
+opname="compose"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:60: \$progdir/gfsmcompile \$tdata/\${opfile}-in-1.tfst -F \${opfile}-in-1.gfst"
+echo 03_algebra.at:60 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:60: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:61: \$progdir/gfsmcompile \$tdata/\${opfile}-in-2.tfst -F \${opfile}-in-2.gfst"
+echo 03_algebra.at:61 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:61: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:62: \$progdir/gfsmcompose \${opfile}-in-1.gfst \${opfile}-in-2.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:62 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompose ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompose ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:62: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:64: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:64 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:64: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 14 ) # 14. 03_algebra.at:69: concat
+ at_setup_line='03_algebra.at:69'
+ at_desc="concat"
+ $at_quiet $ECHO_N " 14: concat $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "14. 03_algebra.at:69: testing ..."
+ $at_traceon
+
+
+opname="concat"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:73: \$progdir/gfsmcompile \$tdata/\${opfile}-in-1.tfst -F \${opfile}-in-1.gfst"
+echo 03_algebra.at:73 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:73: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:74: \$progdir/gfsmcompile \$tdata/\${opfile}-in-2.tfst -F \${opfile}-in-2.gfst"
+echo 03_algebra.at:74 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:74: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:75: \$progdir/gfsmconcat \${opfile}-in-1.gfst \${opfile}-in-2.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:75 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmconcat ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmconcat ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:75: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:77: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:77 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:77: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 15 ) # 15. 03_algebra.at:82: connect
+ at_setup_line='03_algebra.at:82'
+ at_desc="connect"
+ $at_quiet $ECHO_N " 15: connect $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "15. 03_algebra.at:82: testing ..."
+ $at_traceon
+
+
+opname="connect"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:86: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:86 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:86: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:87: \$progdir/gfsmconnect \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:87 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmconnect ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmconnect ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:87: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:89: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:89 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:89: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 16 ) # 16. 03_algebra.at:94: determinize
+ at_setup_line='03_algebra.at:94'
+ at_desc="determinize"
+ $at_quiet $ECHO_N " 16: determinize $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "16. 03_algebra.at:94: testing ..."
+ $at_traceon
+
+
+opname="determinize"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:98: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:98 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:98: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:99: \$progdir/gfsmdeterminize \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:99 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmdeterminize ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmdeterminize ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:99: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:101: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:101 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:101: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 17 ) # 17. 03_algebra.at:107: difference
+ at_setup_line='03_algebra.at:107'
+ at_desc="difference"
+ $at_quiet $ECHO_N " 17: difference $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "17. 03_algebra.at:107: testing ..."
+ $at_traceon
+
+
+opname="difference"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:111: \$progdir/gfsmcompile \$tdata/\${opfile}-in-1.tfst -F \${opfile}-in-1.gfst"
+echo 03_algebra.at:111 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:111: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:112: \$progdir/gfsmcompile \$tdata/\${opfile}-in-2.tfst -F \${opfile}-in-2.gfst"
+echo 03_algebra.at:112 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:112: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:113: \$progdir/gfsmdifference \${opfile}-in-1.gfst \${opfile}-in-2.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:113 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmdifference ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmdifference ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:113: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:115: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:115 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:115: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 18 ) # 18. 03_algebra.at:120: intersect
+ at_setup_line='03_algebra.at:120'
+ at_desc="intersect"
+ $at_quiet $ECHO_N " 18: intersect $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "18. 03_algebra.at:120: testing ..."
+ $at_traceon
+
+
+opname="intersect"
+opfile="$opname"
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:125: \$progdir/gfsmcompile \$tdata/\${opfile}-in-1.tfst -F \${opfile}-in-1.gfst"
+echo 03_algebra.at:125 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:125: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:126: \$progdir/gfsmcompile \$tdata/\${opfile}-in-2.tfst -F \${opfile}-in-2.gfst"
+echo 03_algebra.at:126 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:126: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:127: \$progdir/gfsmintersect \${opfile}-in-1.gfst \${opfile}-in-2.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:127 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmintersect ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmintersect ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:127: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:129: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:129 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:129: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+opfile="intersect2" ##-- intersection as called by gfsm_automaton_difference()
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:132: \$progdir/gfsmcompile \$tdata/\${opfile}-in-1.tfst -F \${opfile}-in-1.gfst"
+echo 03_algebra.at:132 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:132: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:133: \$progdir/gfsmcompile \$tdata/\${opfile}-in-2.tfst -F \${opfile}-in-2.gfst"
+echo 03_algebra.at:133 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:133: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:134: \$progdir/gfsmintersect \${opfile}-in-1.gfst \${opfile}-in-2.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:134 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmintersect ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmintersect ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:134: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:136: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:136 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:136: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 19 ) # 19. 03_algebra.at:142: invert
+ at_setup_line='03_algebra.at:142'
+ at_desc="invert"
+ $at_quiet $ECHO_N " 19: invert $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "19. 03_algebra.at:142: testing ..."
+ $at_traceon
+
+
+opname="invert"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:146: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:146 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:146: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:147: \$progdir/gfsminvert \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:147 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsminvert ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsminvert ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:147: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:149: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:149 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:149: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 20 ) # 20. 03_algebra.at:154: optional
+ at_setup_line='03_algebra.at:154'
+ at_desc="optional"
+ $at_quiet $ECHO_N " 20: optional $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "20. 03_algebra.at:154: testing ..."
+ $at_traceon
+
+
+opname="optional"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:158: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:158 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:158: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:159: \$progdir/gfsmoptional \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:159 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmoptional ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmoptional ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:159: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:161: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:161 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:161: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 21 ) # 21. 03_algebra.at:166: project.lo
+ at_setup_line='03_algebra.at:166'
+ at_desc="project.lo"
+ $at_quiet $ECHO_N " 21: project.lo $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "21. 03_algebra.at:166: testing ..."
+ $at_traceon
+
+
+opname="project-lo"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:170: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:170 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:170: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:171: \$progdir/gfsmproject -1 \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:171 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmproject -1 ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmproject -1 ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:171: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:173: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:173 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:173: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 22 ) # 22. 03_algebra.at:178: project.hi
+ at_setup_line='03_algebra.at:178'
+ at_desc="project.hi"
+ $at_quiet $ECHO_N " 22: project.hi $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "22. 03_algebra.at:178: testing ..."
+ $at_traceon
+
+
+opname="project-hi"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:182: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:182 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:182: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:183: \$progdir/gfsmproject -2 \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:183 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmproject -2 ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmproject -2 ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:183: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:185: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:185 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:185: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 23 ) # 23. 03_algebra.at:190: renumber
+ at_setup_line='03_algebra.at:190'
+ at_desc="renumber"
+ $at_quiet $ECHO_N " 23: renumber $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "23. 03_algebra.at:190: testing ..."
+ $at_traceon
+
+
+opname="renumber"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:194: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:194 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:194: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:195: \$progdir/gfsmrenumber \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:195 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmrenumber ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmrenumber ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:195: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:197: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:197 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:197: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 24 ) # 24. 03_algebra.at:202: rmepsilon
+ at_setup_line='03_algebra.at:202'
+ at_desc="rmepsilon"
+ $at_quiet $ECHO_N " 24: rmepsilon $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "24. 03_algebra.at:202: testing ..."
+ $at_traceon
+
+
+opname="rmepsilon"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:206: \$progdir/gfsmcompile \$tdata/\${opfile}-in.tfst -F \${opfile}-in.gfst"
+echo 03_algebra.at:206 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in.tfst -F ${opfile}-in.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:206: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:207: \$progdir/gfsmrmepsilon \${opfile}-in.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:207 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmrmepsilon ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmrmepsilon ${opfile}-in.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:207: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <---
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:209: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:209 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:209: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+ 25 ) # 25. 03_algebra.at:214: union
+ at_setup_line='03_algebra.at:214'
+ at_desc="union"
+ $at_quiet $ECHO_N " 25: union $ECHO_C"
+ at_xfail=no
+ echo "# -*- compilation -*-" >> "$at_group_log"
+ (
+ echo "25. 03_algebra.at:214: testing ..."
+ $at_traceon
+
+
+opname="union"
+opfile="$opname"
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:218: \$progdir/gfsmcompile \$tdata/\${opfile}-in-1.tfst -F \${opfile}-in-1.gfst"
+echo 03_algebra.at:218 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-1.tfst -F ${opfile}-in-1.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:218: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:219: \$progdir/gfsmcompile \$tdata/\${opfile}-in-2.tfst -F \${opfile}-in-2.gfst"
+echo 03_algebra.at:219 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmcompile $tdata/${opfile}-in-2.tfst -F ${opfile}-in-2.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:219: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:220: \$progdir/gfsmunion \${opfile}-in-1.gfst \${opfile}-in-2.gfst -F \${opfile}-got.gfst"
+echo 03_algebra.at:220 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmunion ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmunion ${opfile}-in-1.gfst ${opfile}-in-2.gfst -F ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff "$at_devnull" "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:220: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+ ## <----
+rm -f expout; ln $tdata/${opfile}-want.tfst expout
+$at_traceoff
+echo "$at_srcdir/03_algebra.at:222: \$progdir/gfsmprint \${opfile}-got.gfst"
+echo 03_algebra.at:222 >"$at_check_line_file"
+
+at_trace_this=
+if test -n "$at_traceon"; then
+ echo 'Not enabling shell tracing (command contains a ${...} parameter expansion)'
+fi
+
+if test -n "$at_trace_this"; then
+ ( $at_traceon; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stder1"
+ at_status=$?
+ grep '^ *+' "$at_stder1" >&2
+ grep -v '^ *+' "$at_stder1" >"$at_stderr"
+else
+ ( :; $progdir/gfsmprint ${opfile}-got.gfst ) >"$at_stdout" 2>"$at_stderr"
+ at_status=$?
+fi
+
+at_failed=false
+$at_diff "$at_devnull" "$at_stderr" || at_failed=:
+$at_diff expout "$at_stdout" || at_failed=:
+case $at_status in
+ 77) echo 77 > "$at_status_file"; exit 77;;
+ 0) ;;
+ *) echo "$at_srcdir/03_algebra.at:222: exit code was $at_status, expected 0"
+ at_failed=:;;
+esac
+if $at_failed; then
+
+
+ echo 1 > "$at_status_file"
+ exit 1
+fi
+
+$at_traceon
+
+ $at_traceoff
+ $at_times_p && times >"$at_times_file"
+ ) 5>&1 2>&1 | eval $at_tee_pipe
+ at_status=`cat "$at_status_file"`
+ ;;
+
+
+ * )
+ echo "$as_me: no such test group: $at_group" >&2
+ continue
+ ;;
+ esac
+
+ # Be sure to come back to the suite directory, in particular
+ # since below we might `rm' the group directory we are in currently.
+ cd "$at_suite_dir"
+
+ case $at_group in
+ banner-*) ;;
+ *)
+ if test ! -f "$at_check_line_file"; then
+ sed "s/^ */$as_me: warning: /" <<_ATEOF
+ A failure happened in a test group before any test could be
+ run. This means that test suite is improperly designed. Please
+ report this failure to <moocow@ling.uni-potsdam.de>.
+_ATEOF
+ echo "$at_setup_line" >"$at_check_line_file"
+ fi
+ at_group_count=`expr 1 + $at_group_count`
+ $at_verbose $ECHO_N "$at_group. $at_setup_line: $ECHO_C"
+ echo $ECHO_N "$at_group. $at_setup_line: $ECHO_C" >> "$at_group_log"
+ case $at_xfail:$at_status in
+ yes:0)
+ at_msg="UNEXPECTED PASS"
+ at_xpass_list="$at_xpass_list $at_group"
+ at_errexit=$at_errexit_p
+ ;;
+ no:0)
+ at_msg="ok"
+ at_pass_list="$at_pass_list $at_group"
+ at_errexit=false
+ ;;
+ *:77)
+ at_msg='skipped ('`cat "$at_check_line_file"`')'
+ at_skip_list="$at_skip_list $at_group"
+ at_errexit=false
+ ;;
+ yes:*)
+ at_msg='expected failure ('`cat "$at_check_line_file"`')'
+ at_xfail_list="$at_xfail_list $at_group"
+ at_errexit=false
+ ;;
+ no:*)
+ at_msg='FAILED ('`cat "$at_check_line_file"`')'
+ at_fail_list="$at_fail_list $at_group"
+ at_errexit=$at_errexit_p
+ ;;
+ esac
+ # Make sure there is a separator even with long titles.
+ echo " $at_msg"
+ at_log_msg="$at_group. $at_desc ($at_setup_line): $at_msg"
+ case $at_status in
+ 0|77)
+ # $at_times_file is only available if the group succeeded.
+ # We're not including the group log, so the success message
+ # is written in the global log separately. But we also
+ # write to the group log in case they're using -d.
+ if test -f "$at_times_file"; then
+ at_log_msg="$at_log_msg ("`sed 1d "$at_times_file"`')'
+ rm -f "$at_times_file"
+ fi
+ echo "$at_log_msg" >> "$at_group_log"
+ echo "$at_log_msg" >&5
+
+ # Cleanup the group directory, unless the user wants the files.
+ if $at_debug_p ; then
+ {
+ echo "#! /bin/sh"
+ echo 'test "${ZSH_VERSION+set}" = set && alias -g '\''${1+"$@"}'\''='\''"$@"'\'''
+ echo "cd '$at_dir'"
+ echo 'exec ${CONFIG_SHELL-'"$SHELL"'}' "$0" \
+ '-v -d' "$at_debug_args" "$at_group" '${1+"$@"}'
+ echo 'exit 1'
+ } >$at_group_dir/run
+ chmod +x $at_group_dir/run
+
+ elif test -d "$at_group_dir"; then
+ find "$at_group_dir" -type d ! -perm -700 -exec chmod u+rwx \{\} \;
+ rm -fr "$at_group_dir"
+ fi
+ ;;
+ *)
+ # Upon failure, include the log into the testsuite's global
+ # log. The failure message is written in the group log. It
+ # is later included in the global log.
+ echo "$at_log_msg" >> "$at_group_log"
+
+ # Upon failure, keep the group directory for autopsy, and
+ # create the debugging script.
+ {
+ echo "#! /bin/sh"
+ echo 'test "${ZSH_VERSION+set}" = set && alias -g '\''${1+"$@"}'\''='\''"$@"'\'''
+ echo "cd '$at_dir'"
+ echo 'exec ${CONFIG_SHELL-'"$SHELL"'}' "$0" \
+ '-v -d' "$at_debug_args" "$at_group" '${1+"$@"}'
+ echo 'exit 1'
+ } >$at_group_dir/run
+ chmod +x $at_group_dir/run
+
+ $at_errexit && break
+ ;;
+ esac
+ ;;
+ esac
+done
+
+# Back to the top directory.
+cd "$at_dir"
+
+# Compute the duration of the suite.
+at_stop_date=`date`
+at_stop_time=`date +%s 2>/dev/null`
+echo "$as_me: ending at: $at_stop_date" >&5
+case $at_start_time,$at_stop_time in
+ [0-9]*,[0-9]*)
+ at_duration_s=`expr $at_stop_time - $at_start_time`
+ at_duration_m=`expr $at_duration_s / 60`
+ at_duration_h=`expr $at_duration_m / 60`
+ at_duration_s=`expr $at_duration_s % 60`
+ at_duration_m=`expr $at_duration_m % 60`
+ at_duration="${at_duration_h}h ${at_duration_m}m ${at_duration_s}s"
+ echo "$as_me: test suite duration: $at_duration" >&5
+ ;;
+esac
+
+# Wrap up the test suite with summary statistics.
+at_skip_count=`set dummy $at_skip_list; shift; echo $#`
+at_fail_count=`set dummy $at_fail_list; shift; echo $#`
+at_xpass_count=`set dummy $at_xpass_list; shift; echo $#`
+at_xfail_count=`set dummy $at_xfail_list; shift; echo $#`
+
+at_run_count=`expr $at_group_count - $at_skip_count`
+at_unexpected_count=`expr $at_xpass_count + $at_fail_count`
+at_total_fail_count=`expr $at_xfail_count + $at_fail_count`
+
+echo
+cat <<\_ASBOX
+## ------------- ##
+## Test results. ##
+## ------------- ##
+_ASBOX
+echo
+{
+ echo
+ cat <<\_ASBOX
+## ------------- ##
+## Test results. ##
+## ------------- ##
+_ASBOX
+ echo
+} >&5
+
+if test $at_run_count = 1; then
+ at_result="1 test"
+ at_were=was
+else
+ at_result="$at_run_count tests"
+ at_were=were
+fi
+if $at_errexit_p && test $at_unexpected_count != 0; then
+ if test $at_xpass_count = 1; then
+ at_result="$at_result $at_were run, one passed"
+ else
+ at_result="$at_result $at_were run, one failed"
+ fi
+ at_result="$at_result unexpectedly and inhibited subsequent tests."
+else
+ # Don't you just love exponential explosion of the number of cases?
+ case $at_xpass_count:$at_fail_count:$at_xfail_count in
+ # So far, so good.
+ 0:0:0) at_result="$at_result $at_were successful." ;;
+ 0:0:*) at_result="$at_result behaved as expected." ;;
+
+ # Some unexpected failures
+ 0:*:0) at_result="$at_result $at_were run,
+$at_fail_count failed unexpectedly." ;;
+
+ # Some failures, both expected and unexpected
+ 0:*:1) at_result="$at_result $at_were run,
+$at_total_fail_count failed ($at_xfail_count expected failure)." ;;
+ 0:*:*) at_result="$at_result $at_were run,
+$at_total_fail_count failed ($at_xfail_count expected failures)." ;;
+
+ # No unexpected failures, but some xpasses
+ *:0:*) at_result="$at_result $at_were run,
+$at_xpass_count passed unexpectedly." ;;
+
+ # No expected failures, but failures and xpasses
+ *:1:0) at_result="$at_result $at_were run,
+$at_unexpected_count did not behave as expected ($at_fail_count unexpected failure)." ;;
+ *:*:0) at_result="$at_result $at_were run,
+$at_unexpected_count did not behave as expected ($at_fail_count unexpected failures)." ;;
+
+ # All of them.
+ *:*:1) at_result="$at_result $at_were run,
+$at_xpass_count passed unexpectedly,
+$at_total_fail_count failed ($at_xfail_count expected failure)." ;;
+ *:*:*) at_result="$at_result $at_were run,
+$at_xpass_count passed unexpectedly,
+$at_total_fail_count failed ($at_xfail_count expected failures)." ;;
+ esac
+
+ if test $at_skip_count = 0 && test $at_run_count -gt 1; then
+ at_result="All $at_result"
+ fi
+fi
+
+# Now put skips in the mix.
+case $at_skip_count in
+ 0) ;;
+ 1) at_result="$at_result
+1 test was skipped." ;;
+ *) at_result="$at_result
+$at_skip_count tests were skipped." ;;
+esac
+
+if test $at_unexpected_count = 0; then
+ echo "$at_result"
+ echo "$at_result" >&5
+else
+ echo "ERROR: $at_result" >&2
+ echo "ERROR: $at_result" >&5
+ {
+ echo
+ cat <<\_ASBOX
+## ------------------------ ##
+## Summary of the failures. ##
+## ------------------------ ##
+_ASBOX
+
+ # Summary of failed and skipped tests.
+ if test $at_fail_count != 0; then
+ echo "Failed tests:"
+ $SHELL "$0" $at_fail_list --list
+ echo
+ fi
+ if test $at_skip_count != 0; then
+ echo "Skipped tests:"
+ $SHELL "$0" $at_skip_list --list
+ echo
+ fi
+ if test $at_xpass_count != 0; then
+ echo "Unexpected passes:"
+ $SHELL "$0" $at_xpass_list --list
+ echo
+ fi
+ if test $at_fail_count != 0; then
+ cat <<\_ASBOX
+## ---------------------- ##
+## Detailed failed tests. ##
+## ---------------------- ##
+_ASBOX
+ echo
+ for at_group in $at_fail_list
+ do
+ at_group_normalized=$at_group
+
+ while :; do
+ case $at_group_normalized in #(
+ $at_format*) break;;
+ esac
+ at_group_normalized=0$at_group_normalized
+ done
+
+ cat "$at_suite_dir/$at_group_normalized/$as_me.log"
+ echo
+ done
+ echo
+ fi
+ if test -n "$at_top_srcdir"; then
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## ${at_top_build_prefix}config.log ##
+_ASBOX
+ sed 's/^/| /' ${at_top_build_prefix}config.log
+ echo
+ fi
+ } >&5
+
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## $as_me.log was created. ##
+_ASBOX
+
+ echo
+ echo "Please send \`${at_testdir+${at_testdir}/}$as_me.log' and all information you think might help:"
+ echo
+ echo " To: <moocow@ling.uni-potsdam.de>"
+ echo " Subject: [gfsm 0.0.10-pre5] $as_me:$at_fail_list${at_fail_list:+ failed${at_xpass_list:+,}}$at_xpass_list${at_xpass_list:+ passed unexpectedly}"
+ echo
+ if test $at_debug_p = false; then
+ echo
+ echo 'You may investigate any problem if you feel able to do so, in which'
+ echo 'case the test suite provides a good starting point. Its output may'
+ echo "be found below \`${at_testdir+${at_testdir}/}$as_me.dir'."
+ echo
+ fi
+ exit 1
+fi
+
+exit 0
+
+
+
diff --git a/gfsm/gfsm/tests/testsuite.at b/gfsm/gfsm/tests/testsuite.at
new file mode 100644
index 0000000..c410379
--- /dev/null
+++ b/gfsm/gfsm/tests/testsuite.at
@@ -0,0 +1,10 @@
+## -*- Mode: Autotest -*-
+##
+## File: testsuite.at
+## Package: gfsm
+## Description: autotest test-suite script
+##
+
+AT_INIT([gfsmutils])
+
+##-- nothing else happens here
diff --git a/gfsm/gfsm/wishlist.txt b/gfsm/gfsm/wishlist.txt
new file mode 100644
index 0000000..e42bf7e
--- /dev/null
+++ b/gfsm/gfsm/wishlist.txt
@@ -0,0 +1,44 @@
++ move gfsmArcList back to a native type, ditching GSList
+ - sorting, splicing, etc. is then tricky, but maybe we can use
+ temporaries for this
+ - would save us sizeof(void*) per arc: all the space lost by adding source state!
+
++ (style): clearer API/internals demarcation
+
++ allow (arbitrary?) automaton indices
+ - esp. (source_state,lower), (source_state,upper)
+ - load & save with automaton
+ - either:
+ (1) maintain indices over destructive operations, or
+ - generic hooks for destructive gfsmAutomaton API?
+ (2) maintain a "dirty" marker to note when index need update, or
+ (3) maintain a "smart list" of changed data and update on demand
+
++ get rid of "GArray fsm->states": it's just wasting space
+ (30 of 64 bits are unused: track these at compile time with -Wpadded)
+ - replace with (gfsmBitVector)s state_is_valid, state_is_final and
+ a dedicated arc-list array (we can still call that "states" for
+ backwards compatibility, esp. the fsm->states->len idiom)
+ * tagh from 148MB to 129MB: -13%
+
++ allow gfsmArcList to be an array
+ - better: allow *all* arcs for an automaton to be a single array
+
++ [DONE] source state tracking in gfsmArc
+ - obsoletes gfsmReverseArcIndex
+ - adds sizeof(gfsmStateId) bytes per arc (tagh from 148MB to 184MB: +24%)
+
++ Basic types
+ - configure option for gfsmLabelId to fit a pointer
+ * tricky to handle without a union or other explicit label API
+ * without source tracking: tagh from 148MB to 184MB: +24%
+ * with source tracking : tagh from 184MB to 220MB: +20%
+ - configure option for 64-bit gfsmStateId (also 64-bit gfsmLabelId?)
+ * breaks binary compatibility: add header flag?
+
++ store alphabet with fsm
+ - tricky with user alphabets: loadable modules?
+
++ loadable modules for user-defined alphabets & semirings
+ - libgmodule ?
+ - look at Micha's tomata2 code for ideas
diff --git a/gfsm/src/gfsm-help.pd b/gfsm/src/gfsm-help.pd
index ca0aa18..5a1edfa 100644
--- a/gfsm/src/gfsm-help.pd
+++ b/gfsm/src/gfsm-help.pd
@@ -1,6 +1,6 @@
#N canvas 0 0 436 289 10;
#X obj 66 7 gfsm;
-#X text 126 241 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 138 257 Bryan Jurish <moocow@ling.uni-potsdam.de>;
#X text 21 43 EXTERNALS:;
#X obj 41 72 gfsm_alphabet;
#X obj 41 98 gfsm_automaton;
@@ -13,3 +13,5 @@
#X text 99 8 : finite state machine external library;
#X obj 40 150 gfsm_markov;
#X text 161 151 trainable Markov chain;
+#X text 38 227 http://www.ling.uni-potsdam.de/~moocow/projects/gfsm
+;
diff --git a/gfsm/src/noconfig.h b/gfsm/src/noconfig.h
index 5fc7800..3a53581 100644
--- a/gfsm/src/noconfig.h
+++ b/gfsm/src/noconfig.h
@@ -1,5 +1,35 @@
/* src/config.h.in. Generated from configure.in by autoheader. */
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
/* Name of package */
#undef PACKAGE
@@ -18,5 +48,17 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
+/* Date this external was configured */
+#undef PD_GFSM_DATE
+
+/* User who configured this external */
+#undef PD_GFSM_USER
+
+/* Which version of gfsm are we using? */
+#undef PD_GFSM_WHICH
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
/* Version number of package */
#undef VERSION
diff --git a/gfsm/src/pd_gfsm.c b/gfsm/src/pd_gfsm.c
index 0659454..e74acec 100644
--- a/gfsm/src/pd_gfsm.c
+++ b/gfsm/src/pd_gfsm.c
@@ -3,7 +3,7 @@
* Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
* Description: finite state automata for Pd
*
- * Copyright (c) 2004-2006 Bryan Jurish.
+ * Copyright (c) 2004-2008 Bryan Jurish.
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
@@ -72,7 +72,8 @@ void gfsm_setup(void)
//-- banner
post("");
post("gfsm: finite state machine externals v%s by Bryan Jurish", PACKAGE_VERSION);
- //post("fsm: based on code by Helmut Schmid");
+ post("gfsm: using " PD_GFSM_WHICH " libgfsm v%s", gfsm_version_string);
+ post("gfsm: compiled by " PD_GFSM_USER " on " PD_GFSM_DATE);
//-- library
pd_gfsm_alphabet_setup();