From d13da71edce4b913736c1e752a211ae20c193292 Mon Sep 17 00:00:00 2001 From: Bryan Jurish Date: Sat, 29 Nov 2008 23:22:39 +0000 Subject: + 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 --- gfsm/Changes | 4 + gfsm/Makefile.am | 3 +- gfsm/README.pod | 10 +- gfsm/README.txt | 10 +- gfsm/autogen.sh | 9 + gfsm/configure.in | 57 +- gfsm/gfsm/AUTHORS | 31 + gfsm/gfsm/COPYING | 510 ++ gfsm/gfsm/Changes | 112 + gfsm/gfsm/INSTALL | 229 + gfsm/gfsm/Makefile.am | 155 + gfsm/gfsm/README.cvs | 19 + gfsm/gfsm/README.html | 220 + gfsm/gfsm/README.pod | 166 + gfsm/gfsm/README.txt | 116 + gfsm/gfsm/autogen.sh | 57 + gfsm/gfsm/config/.cvsignore | 23 + gfsm/gfsm/config/Makefile.am | 67 + gfsm/gfsm/configure.ac | 870 ++++ gfsm/gfsm/configure.gnu | 2 + gfsm/gfsm/doc/.cvsignore | 27 + gfsm/gfsm/doc/Makefile.am | 56 + gfsm/gfsm/doc/libgfsm/.cvsignore | 32 + gfsm/gfsm/doc/libgfsm/Makefile.am | 235 + gfsm/gfsm/doc/libgfsm/doxy-filter.perl | 145 + gfsm/gfsm/doc/libgfsm/libgfsm-header.html | 8 + gfsm/gfsm/doc/libgfsm/libgfsm.css | 216 + gfsm/gfsm/doc/libgfsm/libgfsm.doxy.dev | 227 + gfsm/gfsm/doc/libgfsm/libgfsm.doxy.in | 229 + gfsm/gfsm/doc/libgfsm/mainpage.dox.in | 102 + gfsm/gfsm/doc/programs/.cvsignore | 41 + gfsm/gfsm/doc/programs/Makefile.am | 309 ++ gfsm/gfsm/doc/programs/gfsmprogs.css | 38 + gfsm/gfsm/doc/programs/gfsmutils.skel | 90 + gfsm/gfsm/gfsm.magic | 17 + gfsm/gfsm/gfsm.pc.in | 26 + gfsm/gfsm/m4/.cvsignore | 4 + gfsm/gfsm/m4/alloca.m4 | 42 + gfsm/gfsm/m4/eoverflow.m4 | 64 + gfsm/gfsm/m4/getdelim.m4 | 30 + gfsm/gfsm/m4/gnulib-cache.m4 | 28 + gfsm/gfsm/m4/gnulib-comp.m4 | 70 + gfsm/gfsm/m4/gnulib-tool.m4 | 33 + gfsm/gfsm/m4/intmax_t.m4 | 61 + gfsm/gfsm/m4/inttypes_h.m4 | 26 + gfsm/gfsm/m4/longdouble.m4 | 28 + gfsm/gfsm/m4/longlong.m4 | 23 + gfsm/gfsm/m4/onceonly_2_57.m4 | 86 + gfsm/gfsm/m4/signed.m4 | 17 + gfsm/gfsm/m4/size_max.m4 | 59 + gfsm/gfsm/m4/stdint_h.m4 | 26 + gfsm/gfsm/m4/vasnprintf.m4 | 58 + gfsm/gfsm/m4/vasprintf.m4 | 25 + gfsm/gfsm/m4/wchar_t.m4 | 20 + gfsm/gfsm/m4/wint_t.m4 | 20 + gfsm/gfsm/m4/xsize.m4 | 13 + gfsm/gfsm/src/.cvsignore | 20 + gfsm/gfsm/src/Makefile.am | 69 + gfsm/gfsm/src/libgfsm/.cvsignore | 43 + gfsm/gfsm/src/libgfsm/Makefile.am | 288 ++ gfsm/gfsm/src/libgfsm/config.h | 1 + gfsm/gfsm/src/libgfsm/dummy-bison.sh | 6 + gfsm/gfsm/src/libgfsm/dummy-flex.sh | 3 + gfsm/gfsm/src/libgfsm/gfsm.c | 27 + gfsm/gfsm/src/libgfsm/gfsm.h | 78 + gfsm/gfsm/src/libgfsm/gfsmAlgebra.c | 1715 +++++++ gfsm/gfsm/src/libgfsm/gfsmAlgebra.h | 559 +++ gfsm/gfsm/src/libgfsm/gfsmAlphabet.c | 1026 ++++ gfsm/gfsm/src/libgfsm/gfsmAlphabet.h | 450 ++ gfsm/gfsm/src/libgfsm/gfsmArc.c | 192 + gfsm/gfsm/src/libgfsm/gfsmArc.h | 305 ++ gfsm/gfsm/src/libgfsm/gfsmArc.hi | 262 + gfsm/gfsm/src/libgfsm/gfsmArcIndex.c | 498 ++ gfsm/gfsm/src/libgfsm/gfsmArcIndex.h | 360 ++ gfsm/gfsm/src/libgfsm/gfsmArcIndex.hi | 325 ++ gfsm/gfsm/src/libgfsm/gfsmArcIter.c | 78 + gfsm/gfsm/src/libgfsm/gfsmArcIter.h | 202 + gfsm/gfsm/src/libgfsm/gfsmArcIter.hi | 126 + gfsm/gfsm/src/libgfsm/gfsmArcList.c | 226 + gfsm/gfsm/src/libgfsm/gfsmArcList.h | 207 + gfsm/gfsm/src/libgfsm/gfsmArcList.hi | 124 + gfsm/gfsm/src/libgfsm/gfsmArith.c | 199 + gfsm/gfsm/src/libgfsm/gfsmArith.h | 137 + gfsm/gfsm/src/libgfsm/gfsmAssert.h | 51 + gfsm/gfsm/src/libgfsm/gfsmAutomaton.c | 338 ++ gfsm/gfsm/src/libgfsm/gfsmAutomaton.h | 557 +++ gfsm/gfsm/src/libgfsm/gfsmAutomaton.hi | 530 ++ gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.c | 897 ++++ gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.h | 225 + gfsm/gfsm/src/libgfsm/gfsmBitVector.c | 80 + gfsm/gfsm/src/libgfsm/gfsmBitVector.h | 141 + gfsm/gfsm/src/libgfsm/gfsmBitVector.hi | 133 + gfsm/gfsm/src/libgfsm/gfsmCommon.c | 42 + gfsm/gfsm/src/libgfsm/gfsmCommon.h | 88 + gfsm/gfsm/src/libgfsm/gfsmCompound.c | 154 + gfsm/gfsm/src/libgfsm/gfsmCompound.h | 266 + gfsm/gfsm/src/libgfsm/gfsmCompound.hi | 217 + gfsm/gfsm/src/libgfsm/gfsmConfig.h | 64 + gfsm/gfsm/src/libgfsm/gfsmConfigAuto.h.in | 185 + gfsm/gfsm/src/libgfsm/gfsmDebug.c | 35 + gfsm/gfsm/src/libgfsm/gfsmDebug.h | 46 + gfsm/gfsm/src/libgfsm/gfsmDraw.c | 293 ++ gfsm/gfsm/src/libgfsm/gfsmDraw.h | 113 + gfsm/gfsm/src/libgfsm/gfsmEnum.c | 39 + gfsm/gfsm/src/libgfsm/gfsmEnum.h | 129 + gfsm/gfsm/src/libgfsm/gfsmEnum.hi | 126 + gfsm/gfsm/src/libgfsm/gfsmError.c | 46 + gfsm/gfsm/src/libgfsm/gfsmError.h | 63 + gfsm/gfsm/src/libgfsm/gfsmIO.c | 558 +++ gfsm/gfsm/src/libgfsm/gfsmIO.h | 208 + gfsm/gfsm/src/libgfsm/gfsmIndexed.c | 157 + gfsm/gfsm/src/libgfsm/gfsmIndexed.h | 231 + gfsm/gfsm/src/libgfsm/gfsmIndexed.hi | 294 ++ gfsm/gfsm/src/libgfsm/gfsmIndexedIO.c | 464 ++ gfsm/gfsm/src/libgfsm/gfsmIndexedIO.h | 163 + gfsm/gfsm/src/libgfsm/gfsmLookup.c | 481 ++ gfsm/gfsm/src/libgfsm/gfsmLookup.h | 212 + gfsm/gfsm/src/libgfsm/gfsmMem.c | 36 + gfsm/gfsm/src/libgfsm/gfsmMem.h | 110 + gfsm/gfsm/src/libgfsm/gfsmMem.hi | 135 + gfsm/gfsm/src/libgfsm/gfsmPaths.c | 431 ++ gfsm/gfsm/src/libgfsm/gfsmPaths.h | 240 + gfsm/gfsm/src/libgfsm/gfsmRegex.lex.h | 342 ++ gfsm/gfsm/src/libgfsm/gfsmRegex.lex.l | 201 + gfsm/gfsm/src/libgfsm/gfsmRegex.tab.h | 84 + gfsm/gfsm/src/libgfsm/gfsmRegex.tab.y | 149 + gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.c | 315 ++ gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.h | 223 + gfsm/gfsm/src/libgfsm/gfsmScanner.c | 246 + gfsm/gfsm/src/libgfsm/gfsmScanner.h | 262 + gfsm/gfsm/src/libgfsm/gfsmSemiring.c | 104 + gfsm/gfsm/src/libgfsm/gfsmSemiring.h | 183 + gfsm/gfsm/src/libgfsm/gfsmSemiring.hi | 257 + gfsm/gfsm/src/libgfsm/gfsmSet.c | 143 + gfsm/gfsm/src/libgfsm/gfsmSet.h | 163 + gfsm/gfsm/src/libgfsm/gfsmSet.hi | 136 + gfsm/gfsm/src/libgfsm/gfsmState.c | 30 + gfsm/gfsm/src/libgfsm/gfsmState.h | 109 + gfsm/gfsm/src/libgfsm/gfsmState.hi | 144 + gfsm/gfsm/src/libgfsm/gfsmStateSet.c | 222 + gfsm/gfsm/src/libgfsm/gfsmStateSet.h | 219 + gfsm/gfsm/src/libgfsm/gfsmStateSet.hi | 154 + gfsm/gfsm/src/libgfsm/gfsmTrie.c | 282 ++ gfsm/gfsm/src/libgfsm/gfsmTrie.h | 201 + gfsm/gfsm/src/libgfsm/gfsmUtils.c | 101 + gfsm/gfsm/src/libgfsm/gfsmUtils.h | 72 + gfsm/gfsm/src/libgfsm/gfsmVersion.c | 52 + gfsm/gfsm/src/libgfsm/gfsmVersion.h | 73 + gfsm/gfsm/src/libgfsm/gfsmWeightMap.c | 54 + gfsm/gfsm/src/libgfsm/gfsmWeightMap.h | 222 + gfsm/gfsm/src/libgfsm/gfsmWeightMap.hi | 232 + gfsm/gfsm/src/libgfsm/gnulib/.cvsignore | 13 + gfsm/gfsm/src/libgfsm/gnulib/Makefile.am | 70 + gfsm/gfsm/src/libgfsm/gnulib/Makefile.in | 555 +++ gfsm/gfsm/src/libgfsm/gnulib/alloca_.h | 52 + gfsm/gfsm/src/libgfsm/gnulib/asnprintf.c | 37 + gfsm/gfsm/src/libgfsm/gnulib/asprintf.c | 37 + gfsm/gfsm/src/libgfsm/gnulib/getdelim.c | 128 + gfsm/gfsm/src/libgfsm/gnulib/getdelim.h | 28 + gfsm/gfsm/src/libgfsm/gnulib/printf-args.c | 118 + gfsm/gfsm/src/libgfsm/gnulib/printf-args.h | 136 + gfsm/gfsm/src/libgfsm/gnulib/printf-parse.c | 536 ++ gfsm/gfsm/src/libgfsm/gnulib/printf-parse.h | 74 + gfsm/gfsm/src/libgfsm/gnulib/size_max.h | 27 + gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.c | 901 ++++ gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.h | 77 + gfsm/gfsm/src/libgfsm/gnulib/vasprintf.c | 42 + gfsm/gfsm/src/libgfsm/gnulib/vasprintf.h | 63 + gfsm/gfsm/src/libgfsm/gnulib/xsize.h | 108 + gfsm/gfsm/src/libgfsm/graveyard.c | 631 +++ gfsm/gfsm/src/libgfsm/inc2dot.perl | 48 + gfsm/gfsm/src/libgfsm/tests/.cvsignore | 38 + gfsm/gfsm/src/libgfsm/tests/Makefile | 116 + gfsm/gfsm/src/libgfsm/tests/NOTES.lookup | 26 + gfsm/gfsm/src/libgfsm/tests/alphachurn.c | 11 + gfsm/gfsm/src/libgfsm/tests/arctab-1test.c | 54 + gfsm/gfsm/src/libgfsm/tests/arytest.c | 27 + gfsm/gfsm/src/libgfsm/tests/arytest2.c | 63 + gfsm/gfsm/src/libgfsm/tests/asciigen.perl | 17 + gfsm/gfsm/src/libgfsm/tests/bvtest.c | 30 + gfsm/gfsm/src/libgfsm/tests/calc2test.l | 56 + gfsm/gfsm/src/libgfsm/tests/calc2test.y | 89 + gfsm/gfsm/src/libgfsm/tests/calctest.l | 52 + gfsm/gfsm/src/libgfsm/tests/calctest.y | 118 + gfsm/gfsm/src/libgfsm/tests/commatest.c | 8 + gfsm/gfsm/src/libgfsm/tests/compre2test.c | 41 + gfsm/gfsm/src/libgfsm/tests/comprelex.l | 297 ++ gfsm/gfsm/src/libgfsm/tests/compretest.l | 199 + gfsm/gfsm/src/libgfsm/tests/compretest.y | 185 + gfsm/gfsm/src/libgfsm/tests/ctest.c | 18 + gfsm/gfsm/src/libgfsm/tests/dettest.c | 21 + gfsm/gfsm/src/libgfsm/tests/flex2test.l | 174 + gfsm/gfsm/src/libgfsm/tests/flex3test.l | 232 + gfsm/gfsm/src/libgfsm/tests/flextest.l | 59 + gfsm/gfsm/src/libgfsm/tests/ftest.c | 17 + gfsm/gfsm/src/libgfsm/tests/gbtest.c | 27 + gfsm/gfsm/src/libgfsm/tests/gfsm-chop.perl | 40 + gfsm/gfsm/src/libgfsm/tests/gfsm-out-degrees.perl | 11 + gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.c | 210 + gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.h | 121 + gfsm/gfsm/src/libgfsm/tests/gfsmlabdump.c | 73 + gfsm/gfsm/src/libgfsm/tests/gscantest.c | 51 + gfsm/gfsm/src/libgfsm/tests/intfloat.c | 31 + gfsm/gfsm/src/libgfsm/tests/iotest.c | 180 + gfsm/gfsm/src/libgfsm/tests/lab2ary.c | 62 + gfsm/gfsm/src/libgfsm/tests/labchurn.c | 23 + gfsm/gfsm/src/libgfsm/tests/labcount.perl | 28 + gfsm/gfsm/src/libgfsm/tests/labprobs.h | 71 + gfsm/gfsm/src/libgfsm/tests/lkptest.tfst | 8 + gfsm/gfsm/src/libgfsm/tests/macrotest.i | 11 + gfsm/gfsm/src/libgfsm/tests/memtest-alphabet.c | 26 + gfsm/gfsm/src/libgfsm/tests/memtest-automaton.c | 20 + gfsm/gfsm/src/libgfsm/tests/memtest-general.c | 168 + gfsm/gfsm/src/libgfsm/tests/memtest.c | 26 + gfsm/gfsm/src/libgfsm/tests/module/.cvsignore | 18 + gfsm/gfsm/src/libgfsm/tests/module/Makefile | 39 + gfsm/gfsm/src/libgfsm/tests/module/mod1a.c | 5 + gfsm/gfsm/src/libgfsm/tests/module/mod1b.c | 5 + gfsm/gfsm/src/libgfsm/tests/module/mod1test.c | 52 + gfsm/gfsm/src/libgfsm/tests/nofinal.tfst | 1 + gfsm/gfsm/src/libgfsm/tests/offsettest.c | 101 + gfsm/gfsm/src/libgfsm/tests/ortest.c | 7 + gfsm/gfsm/src/libgfsm/tests/pathtest.c | 289 ++ gfsm/gfsm/src/libgfsm/tests/pathtest.tfst | 9 + gfsm/gfsm/src/libgfsm/tests/priotest.c | 171 + gfsm/gfsm/src/libgfsm/tests/prtest.c | 28 + gfsm/gfsm/src/libgfsm/tests/prtest.tfst | 8 + gfsm/gfsm/src/libgfsm/tests/ptest.c | 25 + gfsm/gfsm/src/libgfsm/tests/rudtest.c | 100 + gfsm/gfsm/src/libgfsm/tests/rudtest.tfst | 3 + gfsm/gfsm/src/libgfsm/tests/rudtest2.tfst | 5 + gfsm/gfsm/src/libgfsm/tests/seek2test.c | 259 + gfsm/gfsm/src/libgfsm/tests/seek3test.c | 611 +++ gfsm/gfsm/src/libgfsm/tests/seektest.c | 365 ++ gfsm/gfsm/src/libgfsm/tests/seektest.dat | 9 + gfsm/gfsm/src/libgfsm/tests/settest.c | 36 + gfsm/gfsm/src/libgfsm/tests/sizes.bc | 70 + gfsm/gfsm/src/libgfsm/tests/sizetest.c | 16 + gfsm/gfsm/src/libgfsm/tests/sltest.c | 25 + gfsm/gfsm/src/libgfsm/tests/statetest.tfst | 8 + gfsm/gfsm/src/libgfsm/tests/structtest.c | 14 + gfsm/gfsm/src/libgfsm/tests/tagh-lo.testus | 8 + gfsm/gfsm/src/libgfsm/tests/test-255.lab | 3 + gfsm/gfsm/src/libgfsm/tests/test-stateset.c | 61 + gfsm/gfsm/src/libgfsm/tests/test.lab | 10 + gfsm/gfsm/src/libgfsm/tests/test.txt | 2 + gfsm/gfsm/src/libgfsm/tests/test2.lab | 2 + gfsm/gfsm/src/libgfsm/tests/test2.txt | 1 + gfsm/gfsm/src/libgfsm/tests/testme.lab | 5 + gfsm/gfsm/src/programs/.cvsignore | 79 + gfsm/gfsm/src/programs/Makefile.am | 613 +++ gfsm/gfsm/src/programs/arith.tfst | 9 + gfsm/gfsm/src/programs/c1.tfst | 5 + gfsm/gfsm/src/programs/c2.lab | 11 + gfsm/gfsm/src/programs/c2.tfst | 4 + gfsm/gfsm/src/programs/c2a.tfst | 10 + gfsm/gfsm/src/programs/c2b.tfst | 22 + gfsm/gfsm/src/programs/c3a.tfst | 8 + gfsm/gfsm/src/programs/c3b.tfst | 26 + gfsm/gfsm/src/programs/c3filt.tfst | 20 + gfsm/gfsm/src/programs/cat1.tfst | 3 + gfsm/gfsm/src/programs/cat2.tfst | 4 + gfsm/gfsm/src/programs/comp1a.tfst | 4 + gfsm/gfsm/src/programs/comp1b.tfst | 4 + gfsm/gfsm/src/programs/comp2.tfst | 6 + gfsm/gfsm/src/programs/comp2a.tfst | 2 + gfsm/gfsm/src/programs/comp2b.tfst | 3 + gfsm/gfsm/src/programs/complement-in.tfst | 4 + gfsm/gfsm/src/programs/compose-mohri-1.tfst | 5 + gfsm/gfsm/src/programs/compose-mohri-2.tfst | 4 + gfsm/gfsm/src/programs/config.h | 13 + gfsm/gfsm/src/programs/connect-in.tfst | 7 + gfsm/gfsm/src/programs/ctest.tfst | 7 + gfsm/gfsm/src/programs/ctest2.tfst | 6 + gfsm/gfsm/src/programs/det.tfst | 5 + gfsm/gfsm/src/programs/determinize-in.tfst | 7 + gfsm/gfsm/src/programs/elookup.tfst | 2 + gfsm/gfsm/src/programs/gfsmarcsort.gog | 107 + gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.c | 595 +++ gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.h | 77 + gfsm/gfsm/src/programs/gfsmarcsort_main.c | 102 + gfsm/gfsm/src/programs/gfsmarith.gog | 132 + gfsm/gfsm/src/programs/gfsmarith_cmdparser.c | 773 +++ gfsm/gfsm/src/programs/gfsmarith_cmdparser.h | 93 + gfsm/gfsm/src/programs/gfsmarith_main.c | 132 + gfsm/gfsm/src/programs/gfsmclosure.gog | 79 + gfsm/gfsm/src/programs/gfsmclosure_cmdparser.c | 495 ++ gfsm/gfsm/src/programs/gfsmclosure_cmdparser.h | 67 + gfsm/gfsm/src/programs/gfsmclosure_main.c | 100 + gfsm/gfsm/src/programs/gfsmcompile.gog | 102 + gfsm/gfsm/src/programs/gfsmcompile_cmdparser.c | 569 +++ gfsm/gfsm/src/programs/gfsmcompile_cmdparser.h | 73 + gfsm/gfsm/src/programs/gfsmcompile_main.c | 132 + gfsm/gfsm/src/programs/gfsmcomplement.gog | 73 + gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.c | 473 ++ gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.h | 65 + gfsm/gfsm/src/programs/gfsmcomplement_main.c | 105 + gfsm/gfsm/src/programs/gfsmcompose.gog | 70 + gfsm/gfsm/src/programs/gfsmcompose_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmcompose_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmcompose_main.c | 123 + gfsm/gfsm/src/programs/gfsmcompre.gog | 94 + gfsm/gfsm/src/programs/gfsmcompre_cmdparser.c | 542 ++ gfsm/gfsm/src/programs/gfsmcompre_cmdparser.h | 71 + gfsm/gfsm/src/programs/gfsmcompre_main.c | 143 + gfsm/gfsm/src/programs/gfsmconcat.gog | 70 + gfsm/gfsm/src/programs/gfsmconcat_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmconcat_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmconcat_main.c | 118 + gfsm/gfsm/src/programs/gfsmconnect.gog | 70 + gfsm/gfsm/src/programs/gfsmconnect_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmconnect_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmconnect_main.c | 99 + gfsm/gfsm/src/programs/gfsmconvert.gog | 89 + gfsm/gfsm/src/programs/gfsmconvert_cmdparser.c | 517 ++ gfsm/gfsm/src/programs/gfsmconvert_cmdparser.h | 69 + gfsm/gfsm/src/programs/gfsmconvert_main.c | 110 + gfsm/gfsm/src/programs/gfsmdeterminize.gog | 70 + gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmdeterminize_main.c | 100 + gfsm/gfsm/src/programs/gfsmdifference.gog | 71 + gfsm/gfsm/src/programs/gfsmdifference_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmdifference_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmdifference_main.c | 123 + gfsm/gfsm/src/programs/gfsmdraw.gog | 138 + gfsm/gfsm/src/programs/gfsmdraw_cmdparser.c | 835 ++++ gfsm/gfsm/src/programs/gfsmdraw_cmdparser.h | 99 + gfsm/gfsm/src/programs/gfsmdraw_main.c | 166 + gfsm/gfsm/src/programs/gfsmheader.gog | 57 + gfsm/gfsm/src/programs/gfsmheader_cmdparser.c | 403 ++ gfsm/gfsm/src/programs/gfsmheader_cmdparser.h | 60 + gfsm/gfsm/src/programs/gfsmheader_main.c | 129 + gfsm/gfsm/src/programs/gfsmindex.gog | 75 + gfsm/gfsm/src/programs/gfsmindex_cmdparser.c | 473 ++ gfsm/gfsm/src/programs/gfsmindex_cmdparser.h | 65 + gfsm/gfsm/src/programs/gfsmindex_main.c | 124 + gfsm/gfsm/src/programs/gfsminfo.gog | 57 + gfsm/gfsm/src/programs/gfsminfo_cmdparser.c | 403 ++ gfsm/gfsm/src/programs/gfsminfo_cmdparser.h | 60 + gfsm/gfsm/src/programs/gfsminfo_main.c | 123 + gfsm/gfsm/src/programs/gfsmintersect.gog | 70 + gfsm/gfsm/src/programs/gfsmintersect_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmintersect_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmintersect_main.c | 123 + gfsm/gfsm/src/programs/gfsminvert.gog | 70 + gfsm/gfsm/src/programs/gfsminvert_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsminvert_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsminvert_main.c | 95 + gfsm/gfsm/src/programs/gfsmlabels.gog | 78 + gfsm/gfsm/src/programs/gfsmlabels_cmdparser.c | 523 ++ gfsm/gfsm/src/programs/gfsmlabels_cmdparser.h | 69 + gfsm/gfsm/src/programs/gfsmlabels_main.c | 208 + gfsm/gfsm/src/programs/gfsmlookup.gog | 77 + gfsm/gfsm/src/programs/gfsmlookup_cmdparser.c | 473 ++ gfsm/gfsm/src/programs/gfsmlookup_cmdparser.h | 65 + gfsm/gfsm/src/programs/gfsmlookup_main.c | 125 + gfsm/gfsm/src/programs/gfsmoptional.gog | 70 + gfsm/gfsm/src/programs/gfsmoptional_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmoptional_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmoptional_main.c | 101 + gfsm/gfsm/src/programs/gfsmprint.gog | 80 + gfsm/gfsm/src/programs/gfsmprint_cmdparser.c | 498 ++ gfsm/gfsm/src/programs/gfsmprint_cmdparser.h | 67 + gfsm/gfsm/src/programs/gfsmprint_main.c | 125 + gfsm/gfsm/src/programs/gfsmproduct.gog | 78 + gfsm/gfsm/src/programs/gfsmproduct_cmdparser.c | 450 ++ gfsm/gfsm/src/programs/gfsmproduct_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmproduct_main.c | 123 + gfsm/gfsm/src/programs/gfsmproject.gog | 76 + gfsm/gfsm/src/programs/gfsmproject_cmdparser.c | 523 ++ gfsm/gfsm/src/programs/gfsmproject_cmdparser.h | 71 + gfsm/gfsm/src/programs/gfsmproject_main.c | 100 + gfsm/gfsm/src/programs/gfsmrenumber.gog | 70 + gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmrenumber_main.c | 95 + gfsm/gfsm/src/programs/gfsmreplace.gog | 79 + gfsm/gfsm/src/programs/gfsmreplace_cmdparser.c | 514 ++ gfsm/gfsm/src/programs/gfsmreplace_cmdparser.h | 69 + gfsm/gfsm/src/programs/gfsmreplace_main.c | 108 + gfsm/gfsm/src/programs/gfsmreverse.gog | 70 + gfsm/gfsm/src/programs/gfsmreverse_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmreverse_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmreverse_main.c | 101 + gfsm/gfsm/src/programs/gfsmrmepsilon.gog | 80 + gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmrmepsilon_main.c | 95 + gfsm/gfsm/src/programs/gfsmsigma.gog | 70 + gfsm/gfsm/src/programs/gfsmsigma_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmsigma_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmsigma_main.c | 100 + gfsm/gfsm/src/programs/gfsmstrings.gog | 76 + gfsm/gfsm/src/programs/gfsmstrings_cmdparser.c | 525 ++ gfsm/gfsm/src/programs/gfsmstrings_cmdparser.h | 69 + gfsm/gfsm/src/programs/gfsmstrings_main.c | 153 + gfsm/gfsm/src/programs/gfsmunion.gog | 70 + gfsm/gfsm/src/programs/gfsmunion_cmdparser.c | 449 ++ gfsm/gfsm/src/programs/gfsmunion_cmdparser.h | 63 + gfsm/gfsm/src/programs/gfsmunion_main.c | 123 + gfsm/gfsm/src/programs/gfsmview.sh | 6 + gfsm/gfsm/src/programs/gfsmviterbi.gog | 88 + gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.c | 473 ++ gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.h | 65 + gfsm/gfsm/src/programs/gfsmviterbi_main.c | 125 + gfsm/gfsm/src/programs/isect1.tfst | 4 + gfsm/gfsm/src/programs/isect2.tfst | 5 + gfsm/gfsm/src/programs/lkptest.tfst | 13 + gfsm/gfsm/src/programs/p1.tfst | 5 + gfsm/gfsm/src/programs/p2.tfst | 3 + gfsm/gfsm/src/programs/prunetest.tfst | 6 + gfsm/gfsm/src/programs/r1.tfst | 9 + gfsm/gfsm/src/programs/r2.tfst | 4 + gfsm/gfsm/src/programs/renumber.tfst | 5 + gfsm/gfsm/src/programs/renumber2.tfst | 8 + gfsm/gfsm/src/programs/rev1.tfst | 7 + gfsm/gfsm/src/programs/rme.tfst | 6 + gfsm/gfsm/src/programs/rme2.tfst | 8 + gfsm/gfsm/src/programs/rme2b.tfst | 8 + gfsm/gfsm/src/programs/rme3.tfst | 5 + gfsm/gfsm/src/programs/sort.tfst | 7 + gfsm/gfsm/src/programs/sortme.tfst | 15 + gfsm/gfsm/src/programs/symtest.lab | 15 + gfsm/gfsm/src/programs/symtest.sym | 8 + gfsm/gfsm/src/programs/test+lab.tfst | 3 + gfsm/gfsm/src/programs/test-rn.tfst | 8 + gfsm/gfsm/src/programs/test.lab | 15 + gfsm/gfsm/src/programs/test.tfst | 3 + gfsm/gfsm/src/programs/test2.tfst | 7 + gfsm/gfsm/src/programs/test3.tfst | 6 + gfsm/gfsm/src/programs/test4.tfst | 9 + gfsm/gfsm/src/programs/test4b.tfst | 9 + gfsm/gfsm/src/programs/test5.tfst | 3 + gfsm/gfsm/src/programs/test6.tfst | 12 + gfsm/gfsm/src/programs/test7.lab | 4 + gfsm/gfsm/src/programs/test7.tfst | 2 + gfsm/gfsm/src/programs/test8.tfst | 4 + gfsm/gfsm/src/programs/test9.tfst | 4 + gfsm/gfsm/src/programs/testa.tfsa | 6 + gfsm/gfsm/src/programs/testa.tfst | 6 + gfsm/gfsm/src/programs/testrn.tfst | 3 + gfsm/gfsm/src/programs/vit-in.lab | 3 + gfsm/gfsm/src/programs/vit-out.lab | 7 + gfsm/gfsm/src/programs/vit-q.lab | 3 + gfsm/gfsm/src/programs/vit.tfst | 17 + gfsm/gfsm/src/programs/vit2.tfst | 15 + gfsm/gfsm/tests/.cvsignore | 11 + gfsm/gfsm/tests/01_basic.at | 54 + gfsm/gfsm/tests/02_arith.at | 107 + gfsm/gfsm/tests/03_algebra.at | 223 + gfsm/gfsm/tests/Makefile.am | 159 + gfsm/gfsm/tests/atlocal.in | 37 + gfsm/gfsm/tests/data/.cvsignore | 4 + gfsm/gfsm/tests/data/basic1.inf | 14 + gfsm/gfsm/tests/data/basic1.tfst | 2 + gfsm/gfsm/tests/data/basic2.labs.inf | 14 + gfsm/gfsm/tests/data/basic2.labs.tfst | 4 + gfsm/gfsm/tests/data/closure-plus-in.tfst | 4 + gfsm/gfsm/tests/data/closure-plus-want.tfst | 6 + gfsm/gfsm/tests/data/closure-star-in.tfst | 4 + gfsm/gfsm/tests/data/closure-star-want.tfst | 7 + gfsm/gfsm/tests/data/complement-b-in.tfst | 4 + gfsm/gfsm/tests/data/complement-b-want.tfst | 43 + gfsm/gfsm/tests/data/complement-in.tfst | 4 + gfsm/gfsm/tests/data/complement-want.tfst | 11 + gfsm/gfsm/tests/data/compose-in-1.tfst | 4 + gfsm/gfsm/tests/data/compose-in-2.tfst | 4 + gfsm/gfsm/tests/data/compose-want.tfst | 6 + gfsm/gfsm/tests/data/concat-in-1.tfst | 4 + gfsm/gfsm/tests/data/concat-in-2.tfst | 4 + gfsm/gfsm/tests/data/concat-want.tfst | 8 + gfsm/gfsm/tests/data/connect-in.tfst | 7 + gfsm/gfsm/tests/data/connect-want.tfst | 5 + gfsm/gfsm/tests/data/determinize-in.tfst | 7 + gfsm/gfsm/tests/data/determinize-want.tfst | 9 + gfsm/gfsm/tests/data/difference-in-1.tfst | 6 + gfsm/gfsm/tests/data/difference-in-2.tfst | 5 + gfsm/gfsm/tests/data/difference-want.tfst | 21 + gfsm/gfsm/tests/data/intersect-in-1.tfst | 4 + gfsm/gfsm/tests/data/intersect-in-2.tfst | 5 + gfsm/gfsm/tests/data/intersect-want.tfst | 11 + gfsm/gfsm/tests/data/intersect2-in-1.tfst | 6 + gfsm/gfsm/tests/data/intersect2-in-2.tfst | 29 + gfsm/gfsm/tests/data/intersect2-want.tfst | 21 + gfsm/gfsm/tests/data/invert-in.tfst | 5 + gfsm/gfsm/tests/data/invert-want.tfst | 5 + gfsm/gfsm/tests/data/lookup-123-want.tfst | 7 + gfsm/gfsm/tests/data/lookup-223-want.tfst | 9 + gfsm/gfsm/tests/data/lookup.tfst | 13 + gfsm/gfsm/tests/data/n_closure-in.tfst | 4 + gfsm/gfsm/tests/data/n_closure-want.tfst | 14 + gfsm/gfsm/tests/data/null.inf | 14 + gfsm/gfsm/tests/data/null.tfst | 0 gfsm/gfsm/tests/data/optional-in.tfst | 2 + gfsm/gfsm/tests/data/optional-want.tfst | 3 + gfsm/gfsm/tests/data/project-hi-in.tfst | 6 + gfsm/gfsm/tests/data/project-hi-want.tfst | 6 + gfsm/gfsm/tests/data/project-lo-in.tfst | 6 + gfsm/gfsm/tests/data/project-lo-want.tfst | 6 + gfsm/gfsm/tests/data/renumber-in.tfst | 8 + gfsm/gfsm/tests/data/renumber-want.tfst | 8 + gfsm/gfsm/tests/data/rmepsilon-in.tfst | 8 + gfsm/gfsm/tests/data/rmepsilon-want.tfst | 8 + gfsm/gfsm/tests/data/t1.linf | 14 + gfsm/gfsm/tests/data/test.lab | 11 + gfsm/gfsm/tests/data/union-in-1.tfst | 4 + gfsm/gfsm/tests/data/union-in-2.tfst | 4 + gfsm/gfsm/tests/data/union-want.tfst | 10 + gfsm/gfsm/tests/data/zzz-compile-all.sh | 12 + gfsm/gfsm/tests/package.m4 | 6 + gfsm/gfsm/tests/testsuite | 5251 ++++++++++++++++++++ gfsm/gfsm/tests/testsuite.at | 10 + gfsm/gfsm/wishlist.txt | 44 + gfsm/src/gfsm-help.pd | 4 +- gfsm/src/noconfig.h | 42 + gfsm/src/pd_gfsm.c | 5 +- 517 files changed, 67496 insertions(+), 22 deletions(-) create mode 100644 gfsm/gfsm/AUTHORS create mode 100644 gfsm/gfsm/COPYING create mode 100644 gfsm/gfsm/Changes create mode 100644 gfsm/gfsm/INSTALL create mode 100644 gfsm/gfsm/Makefile.am create mode 100644 gfsm/gfsm/README.cvs create mode 100644 gfsm/gfsm/README.html create mode 100644 gfsm/gfsm/README.pod create mode 100644 gfsm/gfsm/README.txt create mode 100755 gfsm/gfsm/autogen.sh create mode 100644 gfsm/gfsm/config/.cvsignore create mode 100644 gfsm/gfsm/config/Makefile.am create mode 100644 gfsm/gfsm/configure.ac create mode 100755 gfsm/gfsm/configure.gnu create mode 100644 gfsm/gfsm/doc/.cvsignore create mode 100644 gfsm/gfsm/doc/Makefile.am create mode 100644 gfsm/gfsm/doc/libgfsm/.cvsignore create mode 100644 gfsm/gfsm/doc/libgfsm/Makefile.am create mode 100755 gfsm/gfsm/doc/libgfsm/doxy-filter.perl create mode 100644 gfsm/gfsm/doc/libgfsm/libgfsm-header.html create mode 100644 gfsm/gfsm/doc/libgfsm/libgfsm.css create mode 100644 gfsm/gfsm/doc/libgfsm/libgfsm.doxy.dev create mode 100644 gfsm/gfsm/doc/libgfsm/libgfsm.doxy.in create mode 100644 gfsm/gfsm/doc/libgfsm/mainpage.dox.in create mode 100644 gfsm/gfsm/doc/programs/.cvsignore create mode 100644 gfsm/gfsm/doc/programs/Makefile.am create mode 100644 gfsm/gfsm/doc/programs/gfsmprogs.css create mode 100644 gfsm/gfsm/doc/programs/gfsmutils.skel create mode 100644 gfsm/gfsm/gfsm.magic create mode 100644 gfsm/gfsm/gfsm.pc.in create mode 100644 gfsm/gfsm/m4/.cvsignore create mode 100644 gfsm/gfsm/m4/alloca.m4 create mode 100644 gfsm/gfsm/m4/eoverflow.m4 create mode 100644 gfsm/gfsm/m4/getdelim.m4 create mode 100644 gfsm/gfsm/m4/gnulib-cache.m4 create mode 100644 gfsm/gfsm/m4/gnulib-comp.m4 create mode 100644 gfsm/gfsm/m4/gnulib-tool.m4 create mode 100644 gfsm/gfsm/m4/intmax_t.m4 create mode 100644 gfsm/gfsm/m4/inttypes_h.m4 create mode 100644 gfsm/gfsm/m4/longdouble.m4 create mode 100644 gfsm/gfsm/m4/longlong.m4 create mode 100644 gfsm/gfsm/m4/onceonly_2_57.m4 create mode 100644 gfsm/gfsm/m4/signed.m4 create mode 100644 gfsm/gfsm/m4/size_max.m4 create mode 100644 gfsm/gfsm/m4/stdint_h.m4 create mode 100644 gfsm/gfsm/m4/vasnprintf.m4 create mode 100644 gfsm/gfsm/m4/vasprintf.m4 create mode 100644 gfsm/gfsm/m4/wchar_t.m4 create mode 100644 gfsm/gfsm/m4/wint_t.m4 create mode 100644 gfsm/gfsm/m4/xsize.m4 create mode 100644 gfsm/gfsm/src/.cvsignore create mode 100644 gfsm/gfsm/src/Makefile.am create mode 100644 gfsm/gfsm/src/libgfsm/.cvsignore create mode 100644 gfsm/gfsm/src/libgfsm/Makefile.am create mode 100644 gfsm/gfsm/src/libgfsm/config.h create mode 100755 gfsm/gfsm/src/libgfsm/dummy-bison.sh create mode 100755 gfsm/gfsm/src/libgfsm/dummy-flex.sh create mode 100644 gfsm/gfsm/src/libgfsm/gfsm.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsm.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAlgebra.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAlgebra.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAlphabet.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAlphabet.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArc.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArc.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArc.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcIndex.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcIndex.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcIndex.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcIter.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcIter.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcIter.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcList.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcList.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArcList.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArith.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmArith.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAssert.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAutomaton.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAutomaton.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAutomaton.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmAutomatonIO.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmBitVector.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmBitVector.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmBitVector.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmCommon.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmCommon.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmCompound.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmCompound.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmCompound.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmConfig.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmConfigAuto.h.in create mode 100644 gfsm/gfsm/src/libgfsm/gfsmDebug.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmDebug.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmDraw.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmDraw.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmEnum.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmEnum.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmEnum.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmError.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmError.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmIO.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmIO.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmIndexed.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmIndexed.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmIndexed.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmIndexedIO.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmIndexedIO.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmLookup.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmLookup.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmMem.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmMem.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmMem.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmPaths.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmPaths.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmRegex.lex.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmRegex.lex.l create mode 100644 gfsm/gfsm/src/libgfsm/gfsmRegex.tab.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmRegex.tab.y create mode 100644 gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmRegexCompiler.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmScanner.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmScanner.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmSemiring.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmSemiring.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmSemiring.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmSet.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmSet.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmSet.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmState.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmState.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmState.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmStateSet.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmStateSet.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmStateSet.hi create mode 100644 gfsm/gfsm/src/libgfsm/gfsmTrie.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmTrie.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmUtils.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmUtils.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmVersion.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmVersion.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmWeightMap.c create mode 100644 gfsm/gfsm/src/libgfsm/gfsmWeightMap.h create mode 100644 gfsm/gfsm/src/libgfsm/gfsmWeightMap.hi create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/.cvsignore create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/Makefile.am create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/Makefile.in create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/alloca_.h create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/asnprintf.c create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/asprintf.c create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/getdelim.c create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/getdelim.h create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/printf-args.c create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/printf-args.h create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/printf-parse.c create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/printf-parse.h create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/size_max.h create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.c create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/vasnprintf.h create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/vasprintf.c create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/vasprintf.h create mode 100644 gfsm/gfsm/src/libgfsm/gnulib/xsize.h create mode 100644 gfsm/gfsm/src/libgfsm/graveyard.c create mode 100755 gfsm/gfsm/src/libgfsm/inc2dot.perl create mode 100644 gfsm/gfsm/src/libgfsm/tests/.cvsignore create mode 100644 gfsm/gfsm/src/libgfsm/tests/Makefile create mode 100644 gfsm/gfsm/src/libgfsm/tests/NOTES.lookup create mode 100644 gfsm/gfsm/src/libgfsm/tests/alphachurn.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/arctab-1test.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/arytest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/arytest2.c create mode 100755 gfsm/gfsm/src/libgfsm/tests/asciigen.perl create mode 100644 gfsm/gfsm/src/libgfsm/tests/bvtest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/calc2test.l create mode 100644 gfsm/gfsm/src/libgfsm/tests/calc2test.y create mode 100644 gfsm/gfsm/src/libgfsm/tests/calctest.l create mode 100644 gfsm/gfsm/src/libgfsm/tests/calctest.y create mode 100644 gfsm/gfsm/src/libgfsm/tests/commatest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/compre2test.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/comprelex.l create mode 100644 gfsm/gfsm/src/libgfsm/tests/compretest.l create mode 100644 gfsm/gfsm/src/libgfsm/tests/compretest.y create mode 100644 gfsm/gfsm/src/libgfsm/tests/ctest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/dettest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/flex2test.l create mode 100644 gfsm/gfsm/src/libgfsm/tests/flex3test.l create mode 100644 gfsm/gfsm/src/libgfsm/tests/flextest.l create mode 100644 gfsm/gfsm/src/libgfsm/tests/ftest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/gbtest.c create mode 100755 gfsm/gfsm/src/libgfsm/tests/gfsm-chop.perl create mode 100755 gfsm/gfsm/src/libgfsm/tests/gfsm-out-degrees.perl create mode 100644 gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/gfsmRegexCompiler-v1.h create mode 100644 gfsm/gfsm/src/libgfsm/tests/gfsmlabdump.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/gscantest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/intfloat.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/iotest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/lab2ary.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/labchurn.c create mode 100755 gfsm/gfsm/src/libgfsm/tests/labcount.perl create mode 100644 gfsm/gfsm/src/libgfsm/tests/labprobs.h create mode 100644 gfsm/gfsm/src/libgfsm/tests/lkptest.tfst create mode 100644 gfsm/gfsm/src/libgfsm/tests/macrotest.i create mode 100644 gfsm/gfsm/src/libgfsm/tests/memtest-alphabet.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/memtest-automaton.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/memtest-general.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/memtest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/module/.cvsignore create mode 100644 gfsm/gfsm/src/libgfsm/tests/module/Makefile create mode 100644 gfsm/gfsm/src/libgfsm/tests/module/mod1a.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/module/mod1b.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/module/mod1test.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/nofinal.tfst create mode 100644 gfsm/gfsm/src/libgfsm/tests/offsettest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/ortest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/pathtest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/pathtest.tfst create mode 100644 gfsm/gfsm/src/libgfsm/tests/priotest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/prtest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/prtest.tfst create mode 100644 gfsm/gfsm/src/libgfsm/tests/ptest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/rudtest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/rudtest.tfst create mode 100644 gfsm/gfsm/src/libgfsm/tests/rudtest2.tfst create mode 100644 gfsm/gfsm/src/libgfsm/tests/seek2test.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/seek3test.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/seektest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/seektest.dat create mode 100644 gfsm/gfsm/src/libgfsm/tests/settest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/sizes.bc create mode 100644 gfsm/gfsm/src/libgfsm/tests/sizetest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/sltest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/statetest.tfst create mode 100644 gfsm/gfsm/src/libgfsm/tests/structtest.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/tagh-lo.testus create mode 100644 gfsm/gfsm/src/libgfsm/tests/test-255.lab create mode 100644 gfsm/gfsm/src/libgfsm/tests/test-stateset.c create mode 100644 gfsm/gfsm/src/libgfsm/tests/test.lab create mode 100644 gfsm/gfsm/src/libgfsm/tests/test.txt create mode 100644 gfsm/gfsm/src/libgfsm/tests/test2.lab create mode 100644 gfsm/gfsm/src/libgfsm/tests/test2.txt create mode 100644 gfsm/gfsm/src/libgfsm/tests/testme.lab create mode 100644 gfsm/gfsm/src/programs/.cvsignore create mode 100644 gfsm/gfsm/src/programs/Makefile.am create mode 100644 gfsm/gfsm/src/programs/arith.tfst create mode 100644 gfsm/gfsm/src/programs/c1.tfst create mode 100644 gfsm/gfsm/src/programs/c2.lab create mode 100644 gfsm/gfsm/src/programs/c2.tfst create mode 100644 gfsm/gfsm/src/programs/c2a.tfst create mode 100644 gfsm/gfsm/src/programs/c2b.tfst create mode 100644 gfsm/gfsm/src/programs/c3a.tfst create mode 100644 gfsm/gfsm/src/programs/c3b.tfst create mode 100644 gfsm/gfsm/src/programs/c3filt.tfst create mode 100644 gfsm/gfsm/src/programs/cat1.tfst create mode 100644 gfsm/gfsm/src/programs/cat2.tfst create mode 100644 gfsm/gfsm/src/programs/comp1a.tfst create mode 100644 gfsm/gfsm/src/programs/comp1b.tfst create mode 100644 gfsm/gfsm/src/programs/comp2.tfst create mode 100644 gfsm/gfsm/src/programs/comp2a.tfst create mode 100644 gfsm/gfsm/src/programs/comp2b.tfst create mode 100644 gfsm/gfsm/src/programs/complement-in.tfst create mode 100644 gfsm/gfsm/src/programs/compose-mohri-1.tfst create mode 100644 gfsm/gfsm/src/programs/compose-mohri-2.tfst create mode 100644 gfsm/gfsm/src/programs/config.h create mode 100644 gfsm/gfsm/src/programs/connect-in.tfst create mode 100644 gfsm/gfsm/src/programs/ctest.tfst create mode 100644 gfsm/gfsm/src/programs/ctest2.tfst create mode 100644 gfsm/gfsm/src/programs/det.tfst create mode 100644 gfsm/gfsm/src/programs/determinize-in.tfst create mode 100644 gfsm/gfsm/src/programs/elookup.tfst create mode 100644 gfsm/gfsm/src/programs/gfsmarcsort.gog create mode 100644 gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmarcsort_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmarcsort_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmarith.gog create mode 100644 gfsm/gfsm/src/programs/gfsmarith_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmarith_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmarith_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmclosure.gog create mode 100644 gfsm/gfsm/src/programs/gfsmclosure_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmclosure_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmclosure_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmcompile.gog create mode 100644 gfsm/gfsm/src/programs/gfsmcompile_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmcompile_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmcompile_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmcomplement.gog create mode 100644 gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmcomplement_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmcomplement_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmcompose.gog create mode 100644 gfsm/gfsm/src/programs/gfsmcompose_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmcompose_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmcompose_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmcompre.gog create mode 100644 gfsm/gfsm/src/programs/gfsmcompre_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmcompre_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmcompre_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmconcat.gog create mode 100644 gfsm/gfsm/src/programs/gfsmconcat_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmconcat_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmconcat_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmconnect.gog create mode 100644 gfsm/gfsm/src/programs/gfsmconnect_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmconnect_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmconnect_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmconvert.gog create mode 100644 gfsm/gfsm/src/programs/gfsmconvert_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmconvert_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmconvert_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmdeterminize.gog create mode 100644 gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmdeterminize_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmdeterminize_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmdifference.gog create mode 100644 gfsm/gfsm/src/programs/gfsmdifference_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmdifference_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmdifference_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmdraw.gog create mode 100644 gfsm/gfsm/src/programs/gfsmdraw_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmdraw_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmdraw_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmheader.gog create mode 100644 gfsm/gfsm/src/programs/gfsmheader_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmheader_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmheader_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmindex.gog create mode 100644 gfsm/gfsm/src/programs/gfsmindex_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmindex_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmindex_main.c create mode 100644 gfsm/gfsm/src/programs/gfsminfo.gog create mode 100644 gfsm/gfsm/src/programs/gfsminfo_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsminfo_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsminfo_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmintersect.gog create mode 100644 gfsm/gfsm/src/programs/gfsmintersect_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmintersect_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmintersect_main.c create mode 100644 gfsm/gfsm/src/programs/gfsminvert.gog create mode 100644 gfsm/gfsm/src/programs/gfsminvert_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsminvert_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsminvert_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmlabels.gog create mode 100644 gfsm/gfsm/src/programs/gfsmlabels_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmlabels_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmlabels_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmlookup.gog create mode 100644 gfsm/gfsm/src/programs/gfsmlookup_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmlookup_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmlookup_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmoptional.gog create mode 100644 gfsm/gfsm/src/programs/gfsmoptional_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmoptional_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmoptional_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmprint.gog create mode 100644 gfsm/gfsm/src/programs/gfsmprint_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmprint_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmprint_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmproduct.gog create mode 100644 gfsm/gfsm/src/programs/gfsmproduct_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmproduct_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmproduct_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmproject.gog create mode 100644 gfsm/gfsm/src/programs/gfsmproject_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmproject_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmproject_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmrenumber.gog create mode 100644 gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmrenumber_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmrenumber_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmreplace.gog create mode 100644 gfsm/gfsm/src/programs/gfsmreplace_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmreplace_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmreplace_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmreverse.gog create mode 100644 gfsm/gfsm/src/programs/gfsmreverse_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmreverse_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmreverse_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmrmepsilon.gog create mode 100644 gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmrmepsilon_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmrmepsilon_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmsigma.gog create mode 100644 gfsm/gfsm/src/programs/gfsmsigma_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmsigma_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmsigma_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmstrings.gog create mode 100644 gfsm/gfsm/src/programs/gfsmstrings_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmstrings_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmstrings_main.c create mode 100644 gfsm/gfsm/src/programs/gfsmunion.gog create mode 100644 gfsm/gfsm/src/programs/gfsmunion_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmunion_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmunion_main.c create mode 100755 gfsm/gfsm/src/programs/gfsmview.sh create mode 100644 gfsm/gfsm/src/programs/gfsmviterbi.gog create mode 100644 gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.c create mode 100644 gfsm/gfsm/src/programs/gfsmviterbi_cmdparser.h create mode 100644 gfsm/gfsm/src/programs/gfsmviterbi_main.c create mode 100644 gfsm/gfsm/src/programs/isect1.tfst create mode 100644 gfsm/gfsm/src/programs/isect2.tfst create mode 100644 gfsm/gfsm/src/programs/lkptest.tfst create mode 100644 gfsm/gfsm/src/programs/p1.tfst create mode 100644 gfsm/gfsm/src/programs/p2.tfst create mode 100644 gfsm/gfsm/src/programs/prunetest.tfst create mode 100644 gfsm/gfsm/src/programs/r1.tfst create mode 100644 gfsm/gfsm/src/programs/r2.tfst create mode 100644 gfsm/gfsm/src/programs/renumber.tfst create mode 100644 gfsm/gfsm/src/programs/renumber2.tfst create mode 100644 gfsm/gfsm/src/programs/rev1.tfst create mode 100644 gfsm/gfsm/src/programs/rme.tfst create mode 100644 gfsm/gfsm/src/programs/rme2.tfst create mode 100644 gfsm/gfsm/src/programs/rme2b.tfst create mode 100644 gfsm/gfsm/src/programs/rme3.tfst create mode 100644 gfsm/gfsm/src/programs/sort.tfst create mode 100644 gfsm/gfsm/src/programs/sortme.tfst create mode 100644 gfsm/gfsm/src/programs/symtest.lab create mode 100644 gfsm/gfsm/src/programs/symtest.sym create mode 100644 gfsm/gfsm/src/programs/test+lab.tfst create mode 100644 gfsm/gfsm/src/programs/test-rn.tfst create mode 100644 gfsm/gfsm/src/programs/test.lab create mode 100644 gfsm/gfsm/src/programs/test.tfst create mode 100644 gfsm/gfsm/src/programs/test2.tfst create mode 100644 gfsm/gfsm/src/programs/test3.tfst create mode 100644 gfsm/gfsm/src/programs/test4.tfst create mode 100644 gfsm/gfsm/src/programs/test4b.tfst create mode 100644 gfsm/gfsm/src/programs/test5.tfst create mode 100644 gfsm/gfsm/src/programs/test6.tfst create mode 100644 gfsm/gfsm/src/programs/test7.lab create mode 100644 gfsm/gfsm/src/programs/test7.tfst create mode 100644 gfsm/gfsm/src/programs/test8.tfst create mode 100644 gfsm/gfsm/src/programs/test9.tfst create mode 100644 gfsm/gfsm/src/programs/testa.tfsa create mode 100644 gfsm/gfsm/src/programs/testa.tfst create mode 100644 gfsm/gfsm/src/programs/testrn.tfst create mode 100644 gfsm/gfsm/src/programs/vit-in.lab create mode 100644 gfsm/gfsm/src/programs/vit-out.lab create mode 100644 gfsm/gfsm/src/programs/vit-q.lab create mode 100644 gfsm/gfsm/src/programs/vit.tfst create mode 100644 gfsm/gfsm/src/programs/vit2.tfst create mode 100644 gfsm/gfsm/tests/.cvsignore create mode 100644 gfsm/gfsm/tests/01_basic.at create mode 100644 gfsm/gfsm/tests/02_arith.at create mode 100644 gfsm/gfsm/tests/03_algebra.at create mode 100644 gfsm/gfsm/tests/Makefile.am create mode 100644 gfsm/gfsm/tests/atlocal.in create mode 100644 gfsm/gfsm/tests/data/.cvsignore create mode 100644 gfsm/gfsm/tests/data/basic1.inf create mode 100644 gfsm/gfsm/tests/data/basic1.tfst create mode 100644 gfsm/gfsm/tests/data/basic2.labs.inf create mode 100644 gfsm/gfsm/tests/data/basic2.labs.tfst create mode 100644 gfsm/gfsm/tests/data/closure-plus-in.tfst create mode 100644 gfsm/gfsm/tests/data/closure-plus-want.tfst create mode 100644 gfsm/gfsm/tests/data/closure-star-in.tfst create mode 100644 gfsm/gfsm/tests/data/closure-star-want.tfst create mode 100644 gfsm/gfsm/tests/data/complement-b-in.tfst create mode 100644 gfsm/gfsm/tests/data/complement-b-want.tfst create mode 100644 gfsm/gfsm/tests/data/complement-in.tfst create mode 100644 gfsm/gfsm/tests/data/complement-want.tfst create mode 100644 gfsm/gfsm/tests/data/compose-in-1.tfst create mode 100644 gfsm/gfsm/tests/data/compose-in-2.tfst create mode 100644 gfsm/gfsm/tests/data/compose-want.tfst create mode 100644 gfsm/gfsm/tests/data/concat-in-1.tfst create mode 100644 gfsm/gfsm/tests/data/concat-in-2.tfst create mode 100644 gfsm/gfsm/tests/data/concat-want.tfst create mode 100644 gfsm/gfsm/tests/data/connect-in.tfst create mode 100644 gfsm/gfsm/tests/data/connect-want.tfst create mode 100644 gfsm/gfsm/tests/data/determinize-in.tfst create mode 100644 gfsm/gfsm/tests/data/determinize-want.tfst create mode 100644 gfsm/gfsm/tests/data/difference-in-1.tfst create mode 100644 gfsm/gfsm/tests/data/difference-in-2.tfst create mode 100644 gfsm/gfsm/tests/data/difference-want.tfst create mode 100644 gfsm/gfsm/tests/data/intersect-in-1.tfst create mode 100644 gfsm/gfsm/tests/data/intersect-in-2.tfst create mode 100644 gfsm/gfsm/tests/data/intersect-want.tfst create mode 100644 gfsm/gfsm/tests/data/intersect2-in-1.tfst create mode 100644 gfsm/gfsm/tests/data/intersect2-in-2.tfst create mode 100644 gfsm/gfsm/tests/data/intersect2-want.tfst create mode 100644 gfsm/gfsm/tests/data/invert-in.tfst create mode 100644 gfsm/gfsm/tests/data/invert-want.tfst create mode 100644 gfsm/gfsm/tests/data/lookup-123-want.tfst create mode 100644 gfsm/gfsm/tests/data/lookup-223-want.tfst create mode 100644 gfsm/gfsm/tests/data/lookup.tfst create mode 100644 gfsm/gfsm/tests/data/n_closure-in.tfst create mode 100644 gfsm/gfsm/tests/data/n_closure-want.tfst create mode 100644 gfsm/gfsm/tests/data/null.inf create mode 100644 gfsm/gfsm/tests/data/null.tfst create mode 100644 gfsm/gfsm/tests/data/optional-in.tfst create mode 100644 gfsm/gfsm/tests/data/optional-want.tfst create mode 100644 gfsm/gfsm/tests/data/project-hi-in.tfst create mode 100644 gfsm/gfsm/tests/data/project-hi-want.tfst create mode 100644 gfsm/gfsm/tests/data/project-lo-in.tfst create mode 100644 gfsm/gfsm/tests/data/project-lo-want.tfst create mode 100644 gfsm/gfsm/tests/data/renumber-in.tfst create mode 100644 gfsm/gfsm/tests/data/renumber-want.tfst create mode 100644 gfsm/gfsm/tests/data/rmepsilon-in.tfst create mode 100644 gfsm/gfsm/tests/data/rmepsilon-want.tfst create mode 100644 gfsm/gfsm/tests/data/t1.linf create mode 100644 gfsm/gfsm/tests/data/test.lab create mode 100644 gfsm/gfsm/tests/data/union-in-1.tfst create mode 100644 gfsm/gfsm/tests/data/union-in-2.tfst create mode 100644 gfsm/gfsm/tests/data/union-want.tfst create mode 100755 gfsm/gfsm/tests/data/zzz-compile-all.sh create mode 100644 gfsm/gfsm/tests/package.m4 create mode 100755 gfsm/gfsm/tests/testsuite create mode 100644 gfsm/gfsm/tests/testsuite.at create mode 100644 gfsm/gfsm/wishlist.txt (limited to 'gfsm') 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 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. + + + + Copyright (C) + + 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. + + , 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 @@ + + + + +DESCRIPTION + + + + + + +

+ + + + + +
+

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-hacked.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/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 Emoocow@ling.uni-potsdam.deE 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 + 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 &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 +# 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 = )) { + 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 @@ + + + + $title + + + + 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 + +\version @VERSION@ + +Project URL: 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 glib +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 +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 Emoocow@ling.uni-potsdam.deE + +=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 + +## 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 , + 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 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 , 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 , 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 +#ifdef EOVERFLOW +yes +#endif + ], have_eoverflow=1) + if test -n "$have_eoverflow"; then + dnl EOVERFLOW exists in . Don't need to define EOVERFLOW ourselves. + ac_cv_decl_EOVERFLOW=yes + else + AC_EGREP_CPP(yes,[ +#define _XOPEN_SOURCE_EXTENDED 1 +#include +#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 +/* The following two lines are a workaround against an autoconf-2.52 bug. */ +#include +#include +]) + 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 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 or . + +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 and don't define.]) + else + AC_DEFINE(HAVE_INTMAX_T, 1, + [Define if you have the 'intmax_t' type in or .]) + 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 +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#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 or .]) + 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 and 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 exists, +# doesn't clash with , 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 +#include ], + [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 exists, doesn't clash with , + 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 +#if HAVE_STDINT_H +#include +#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 ], result=?) + _AC_COMPUTE_INT([(size_t)~(size_t)0 % 10], res_lo, + [#include ], result=?) + _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, + [#include ], 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 + 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 exists, +# doesn't clash with , 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 +#include ], + [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 exists, doesn't clash with , + 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 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 + 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 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 + 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 + * 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 + 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 + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +#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 + * 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 +#include +#include +#include +#include +#include +#include +#include + +/*====================================================================== + * 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 +#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 +#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<arcs), &sortdata); + } + else { al1 = q1->arcs; } + + //-- arcs: sort arclists: fsm2 + if (flags&gfsmCFEfsm2NeedsArcSort) { + gfsmArcCompData sortdata = { (gfsmACLower|(gfsmACUpper<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 + * 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 +#include +#include +#include + +/*====================================================================== + * 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 + * 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 +#include +#include +#include + +#include +#include +#include +#include + +/*====================================================================== + * 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 + * 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 +#include +#include + +/*====================================================================== + * 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 + * 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 +#include + +#ifndef GFSM_INLINE_ENABLED +//-- no inline definitions +# include +#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 + * 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 +#include + +/// "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<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 +#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 + * 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 + +/*====================================================================== + * 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 +#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 +#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( + static_cast(gfsm_acmask_nth(m,nth)) + & + ~static_cast(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 + * 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 +#include + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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; qidsource==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 + * 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 +#include + +/*====================================================================== + * 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 +#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 + * 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 + +/*====================================================================== + * 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 + * 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 + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 + +/*====================================================================== + * 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 +#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 + * 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 + * 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 + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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, Deprecated + * \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 + +/// "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: guint gfsm_arclist_length(gfsmArcList *al) +//#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 +#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 + * 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 + +/*====================================================================== + * 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 + * 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 +#include +#include +#include + + +/*====================================================================== + * 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, + ¶ms); + 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 + * 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 + +/** \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 + * 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 + +/** + * \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 + * 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 +#include +#include +#include +#include + +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 +#include +#include +#include + +/*====================================================================== + * 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 r >= q, + * \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 O(n_arcs) + */ +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 (*func)(gpointer final_stateid, gpointer final_weight, gpointer data); + * 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 qid_new=old2new[qid_old]. + * \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 fsm->sr->zero + */ +GFSM_INLINE +void gfsm_automaton_set_final_state_full(gfsmAutomaton *fsm, + gfsmStateId qid, + gboolean is_final, + gfsmWeight final_weight); + +/** Backwards-compatble wrapper for gfsm_automaton_set_final_state_fulll(fsm,qid,is_final,fsm->sr->one) + * \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 +#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 + * 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 +#include +#include + +/*====================================================================== + * 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 + * 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 +#include +#include +//#include + +#include +#include +#include +#include +#include + + + +/*====================================================================== + * 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 +#include + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 + +/*====================================================================== + * 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 +#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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 +#include + +/*====================================================================== + * 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 +#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 + * 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 +#include +#include + + +/*====================================================================== + * 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 + * 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 +#include + +/* + * 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 , a header that + may be supplied by this distribution. */ +#undef HAVE_ALLOCA + +/* Define HAVE_ALLOCA_H for backward compatibility with older code that + includes 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 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 or . */ +#undef HAVE_INTMAX_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if exists, doesn't clash with , 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 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 header file. */ +#undef HAVE_STDINT_H + +/* Define if exists, doesn't clash with , and declares + uintmax_t. */ +#undef HAVE_STDINT_H_WITH_UINTMAX + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define this if you have the strdup() function */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the 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 and 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 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 +#include +#include + +#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 + * 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 + +/* 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 + * 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 +#include +#include +#include +#include +#include + +/*====================================================================== + * 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 + * 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 + +/*====================================================================== + * 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 + * 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 + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 +#include + +/*====================================================================== + * 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 +#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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 + +/*====================================================================== + * 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 + * 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 + +#include +#include +//#include +#include + +#include +#include +#include +#if 0 +#include +#endif +#include + +#ifdef GFSM_ZLIB_ENABLED +# include +# 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 + * 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 +#include + +#include +#include +#include +#include + +#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 + * 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 +#include + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 + +/*====================================================================== + * 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 +#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 + * 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 + * 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 +#include +#include + +#include +#include +#include +#include +#include + + + +/*====================================================================== + * 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 + +#include +#include +#include +#include + +#include + +/*====================================================================== + * 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 *) + 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 + +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 +#include + +/*---------------------------------------------------------------------- + * 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 +#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 + * 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 + +/*---------------------------------------------------------------------- + * 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(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 + * 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 +#include +#include + + +/*====================================================================== + * 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 + * 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 + +/*====================================================================== + * 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 +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . 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 +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 +#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 +#include + +#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; +} + + + +([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? { + yylval->w = strtod(yytext,NULL); + return TOK_WEIGHT; +} + +\> { + BEGIN(INITIAL); + return '>'; +} + + + +{DIGIT}+ { + BEGIN(INITIAL); + yylval->u = strtol(yytext,NULL,0); + return TOK_UINT; +} + + +[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ } + + + + +. { + BEGIN(INITIAL); + yylval->c = yytext[0]; + return TOK_CHAR; +} + + +{UTF8PREFIX}+. { + g_string_append_len(my_gstr,yytext,yyleng); +} +{SPACE}*"]" { + unput(']'); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) { + yylval->gs = gfsm_gstring_dup(my_gstr); + return TOK_STRING; + } +} +{BCHAR}+ { + g_string_append(my_gstr, yytext); +} +({SPACE}*)"="({SPACE}*) { + unput('='); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) { + yylval->gs = gfsm_gstring_dup(my_gstr); + return TOK_STRING; + } +} +{SPACE}+ { + unput(' '); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) { + yylval->gs = gfsm_gstring_dup(my_gstr); + return TOK_STRING; + } +} +\\ { + BEGIN(STATE_BRACKETED_ESCAPE); +} + + +"]" { + BEGIN(INITIAL); + if (my_gstr->len) { + g_string_truncate(my_gstr,0); + return ']'; + } +} +"=" { + BEGIN(STATE_BRACKETED); + g_string_truncate(my_gstr,0); + return '='; +} +" " { + BEGIN(STATE_BRACKETED); + if (my_gstr->len) { + g_string_truncate(my_gstr,0); + return ' '; + } +} + + +. { + 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 +#include +#include + +#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 TOK_UNKNOWN TOK_CHAR +%token TOK_UINT +%token TOK_STRING +%token TOK_WEIGHT + +%type label +%type weight +%type 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 + * 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 +#include +#include + +#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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 +#include +#include + +/*====================================================================== + * 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 + * 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 +#include + +#include + +/*====================================================================== + * 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 + * 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 + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 +#include + +/*====================================================================== + * Semiring: types + */ +/** Builtin semiring types + * \see fsmcost(3) + */ +typedef enum { + gfsmSRTUnknown = 0, ///< unknown semiring (should never happen) + gfsmSRTBoolean = 1, ///< boolean semiring , zero:0, one:1> + gfsmSRTLog = 2, ///< negative log semiring + gfsmSRTReal = 3, ///< real semiring: + gfsmSRTTrivial = 4, ///< trivial semiring + gfsmSRTTropical = 5, ///< tropical semiring: + gfsmSRTPLog = 6, ///< positive log semiring , 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 +#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 + * 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 +#include +#include + +/*====================================================================== + * 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 (xtype = 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 + * 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 + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 + +/*====================================================================== + * 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 + +///\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 +#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 + * 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 + * 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 + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +# include +#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 + * 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 + +/*====================================================================== + * 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 +#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 + * 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 + +/*====================================================================== + * 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 + * 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 +#include + +//-- no-inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 + +/*====================================================================== + * 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 +#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 + * 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 + +/*====================================================================== + * 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 + * 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 +#include +#include +#include +#include + +/*====================================================================== + * 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 + * 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 +#include + +/*====================================================================== + * 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 + * 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 +#include + +#ifdef HAVE_CONFIG_H +#include +#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 + * 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 + +/*====================================================================== + * 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 + * 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 +#include + +//-- (no-)inline definitions +#ifndef GFSM_INLINE_ENABLED +# include +#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 + * 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 +#include + +/*====================================================================== + * 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 +#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 + * 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 + +/*====================================================================== + * 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 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 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 +# define alloca _alloca +#else +# include +# 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 +#endif + +/* Specification. */ +#include "vasnprintf.h" + +#include + +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 +#endif + +/* Specification. */ +#include "vasprintf.h" + +#include + +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 +#endif + +#include "getdelim.h" + +#include +#include +#include + +#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 +# include +# include + +#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 +#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 + +/* Get wchar_t. */ +#ifdef HAVE_WCHAR_T +# include +#endif + +/* Get wint_t. */ +#ifdef HAVE_WINT_T +# include +#endif + +/* Get va_list. */ +#include + + +/* 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 +#endif + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif + +/* Get size_t, NULL. */ +#include + +/* Get intmax_t. */ +#if HAVE_STDINT_H_WITH_UINTMAX +# include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +# include +#endif + +/* malloc(), realloc(), free(). */ +#include + +/* 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 +# if HAVE_STDINT_H +# include +# 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 to provide a prototype for snprintf(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif +#ifndef IN_LIBINTL +# include +#endif + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +#else +# include "vasnprintf.h" +#endif + +#include /* snprintf(), sprintf() */ +#include /* abort(), malloc(), realloc(), free() */ +#include /* memcpy(), strlen() */ +#include /* errno */ +#include /* CHAR_BIT, INT_MAX */ +#include /* 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 + +/* Get size_t. */ +#include + +#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 +#endif + +/* Specification. */ +#include "vasprintf.h" + +#include + +#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 + +#else + +/* Get va_list. */ +#include + +#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 + +/* Get SIZE_MAX. */ +#include +#if HAVE_STDINT_H +# include +#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(" 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 () { + 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 +#include + +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 +#include +#include + +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 +#include + +int main (void) { + GPtrArray *a; + gpointer p; + g_mem_set_vtable(glib_mem_profiler_table); + + printf("--------\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("--------\n"); + //g_mem_chunk_info(); + + //printf("--------\n"); + g_blow_chunks(); + //g_mem_chunk_info(); + + printf("--------\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 +#include +#include + +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 + +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 +#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 +#include +#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 NUMBER PLUS MINUS TIMES DIV LPAREN RPAREN NEWLINE OTHER +%type 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 +#include +#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 NUMBER PLUS MINUS TIMES DIV LPAREN RPAREN NEWLINE OTHER +%type 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 + +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 +#include + + +/*====================================================================== + * 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 +//#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; +} + + + +([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? { + //yylval->w = strtod(yytext,NULL); + return TOK_WEIGHT; +} + +\> { + BEGIN(INITIAL); + return '>'; +} + + + +{DIGIT}+ { + BEGIN(INITIAL); + //yylval->u = strtol(yytext,NULL,0); + return TOK_UINT; +} + + +[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ } + + + + +. { + BEGIN(INITIAL); + return TOK_CHAR; +} + + + +{UTF8PREFIX}+. { + g_string_append_len(my_gstr,yytext,yyleng); +} +{SPACE}*"]" { + unput(']'); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) return TOK_STRING; +} +{BCHAR}+ { + g_string_append(my_gstr, yytext); + //return TOK_STRING; +} +({SPACE}*)"="({SPACE}*) { + unput('='); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) return TOK_STRING; +} +{SPACE}+ { + unput(' '); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) return TOK_STRING; +} +\\ { + BEGIN(STATE_BRACKETED_ESCAPE); +} + + +"]" { + BEGIN(INITIAL); + if (my_gstr->len) { + g_string_truncate(my_gstr,0); + return ']'; + } +} +"=" { + BEGIN(STATE_BRACKETED); + g_string_truncate(my_gstr,0); + return '='; +} +" " { + BEGIN(STATE_BRACKETED); + if (my_gstr->len) { + g_string_truncate(my_gstr,0); + return ' '; + } +} + + + +. { + 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; +} + +<> { 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 +#include +#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; +} + + + +([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? { + yylval->w = strtod(yytext,NULL); + return TOK_WEIGHT; +} + +\> { + BEGIN(INITIAL); + return '>'; +} + + + +{DIGIT}+ { + BEGIN(INITIAL); + yylval->u = strtol(yytext,NULL,0); + return TOK_UINT; +} + + +[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ } + + + + +. { + BEGIN(INITIAL); + yylval->c = yytext[0]; + return TOK_CHAR; +} + + +{UTF8PREFIX}+. { + g_string_append_len(my_gstr,yytext,yyleng); +} +{SPACE}*"]" { + unput(']'); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) { + yylval->gs = gfsm_gstring_dup(my_gstr); + return TOK_STRING; + } +} +{BCHAR}+ { + g_string_append(my_gstr, yytext); +} +({SPACE}*)"="({SPACE}*) { + unput('='); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) { + yylval->gs = gfsm_gstring_dup(my_gstr); + return TOK_STRING; + } +} +{SPACE}+ { + unput(' '); + BEGIN(STATE_BRACKETED_SEP); + if (my_gstr->len) { + yylval->gs = gfsm_gstring_dup(my_gstr); + return TOK_STRING; + } +} +\\ { + BEGIN(STATE_BRACKETED_ESCAPE); +} + + +"]" { + BEGIN(INITIAL); + if (my_gstr->len) { + g_string_truncate(my_gstr,0); + return ']'; + } +} +"=" { + BEGIN(STATE_BRACKETED); + g_string_truncate(my_gstr,0); + return '='; +} +" " { + BEGIN(STATE_BRACKETED); + if (my_gstr->len) { + g_string_truncate(my_gstr,0); + return ' '; + } +} + + +. { + 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 +#include + +#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 TOK_UNKNOWN TOK_CHAR +%token TOK_UINT +%token TOK_STRING +%token TOK_WEIGHT + +%type label +%type weight +%type 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 + +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 +#include + +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 + +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 + */ +%% + +{WCHAR} { return T_CHAR; } + +{SPACE} { /* ignore */ } + +# { BEGIN(COMMENT); } + +\\ { BEGIN(ESCAPE); } + +\[ { BEGIN(STRING); GSTR_BUF->len = 0; } + +\< { BEGIN(WEIGHT); } + + + +[^\>]+ { return WEIGHT; /* hack */ } + +\> { BEGIN(INITIAL); } + + + +[^\n]*\n { BEGIN(INITIAL); } + + + + +. { BEGIN(INITIAL); return T_CHAR; } + + + + +\] { BEGIN(INITIAL); return T_STRING; } + +{SCHAR} { g_string_append_c(GSTR_BUF, yytext[0]); } + +\\ { BEGIN(SESCAPE); } + + + +. { BEGIN(STRING); g_string_append_c(GSTR_BUF, yytext[0]); } + + + +<> { 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 + +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; } + + + +{UTF8PREFIX}+ { g_string_append(GSTR_BUF, yytext); } + +. { BEGIN(INITIAL); g_string_append_c(GSTR_BUF, yytext[0]); return T_UTF8; } + + +([\+\-])?({DIGIT}*\.)?({DIGIT}+)([Ee]([\+\-]?){DIGIT}+)? { return T_WEIGHT; /* hack */ } + +\> { BEGIN(INITIAL); return T_RANGLE; } + + + +{DIGIT}+ { BEGIN(INITIAL); return T_UINT; } + + +[^\n]*\n { BEGIN(INITIAL); /* ignore comments */ } + + + + +. { BEGIN(INITIAL); return T_CHAR; } + + + +{UTF8PREFIX} { BEGIN(BUTF8); g_string_append_c(GSTR_BUF, yytext[0]); } + +\] { BEGIN(INITIAL); return T_RBRACKET; } + +{BCHAR} { g_string_append_c(GSTR_BUF, yytext[0]); } + +{SPACE} { return T_BSPACE; } + +"=" { return T_BEQUAL; } + +\\ { BEGIN(BESCAPE); } + + +{UTF8PREFIX}+ { g_string_append(GSTR_BUF, yytext); } + +. { BEGIN(BRACKETED); g_string_append_c(GSTR_BUF, yytext[0]); } + + +. { BEGIN(BRACKETED); g_string_append_c(GSTR_BUF, yytext[0]); } + + + +<> { 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; } + +<> { 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 +#include + +int main (int argc, char **argv) { + float f, f2; + gpointer p; + int i; + + for (i=1; ip=%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 +#include + +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 +#include +#include + +#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 +#include +#include +#include + +/** 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 +#include +#include +#include + +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 +#include +#include + +#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 + +#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 +#include +#include +#include +#include + +/*--------------------------------------------------- + * 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 +#include + + +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 + +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 + +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 +#include + +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("--------\n"); + //g_mem_chunk_info(); + + + + printf("--------\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 +#include + +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("--------\n"); + //g_mem_chunk_info(); + + printf("--------\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 +#include + +#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--------\n"); + g_blow_chunks(); + g_mem_chunk_info(); +#endif + // +#ifdef VTABLE_PROFILE + printf("\n--------\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 +#include + +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("--------\n"); + //g_mem_chunk_info(); + + + + printf("--------\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 + +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 + +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 +#include +#include + +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 +#include +#include + +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 +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 + + +//#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--------\n"); + g_blow_chunks(); + g_mem_chunk_info(); +#endif + // +#ifdef DO_PROFILE + printf("\n--------\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 +#include +#include + +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<>(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 +#include + +//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 +#include + +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 +#include +#include + +//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 +#include +#include +#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->lowerlower>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 +#include +#include + +/*====================================================================== + * 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.minlower < 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 +#include +#include +#include +#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); aidarcs, 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 +#include + +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 + +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 +#include + +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 +#include + +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 +#include +#include + +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 @@ + 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 @@ + 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 @@ + 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 a +2 3 a {AA|B} +3 2 a +2 4 b {A|B} +4 0 b +0 5 b {A|B} +5 0 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 +0 2 +0 3 +3 4 {A|B} B +3 4 {AA|B} B +4 1 b +2 5 {A|B} A +2 5 {AA|B} AA +5 1 a +3 6 {A|B} B +3 6 {AA|B} B +6 2 b +2 7 {A|B} A +2 7 {AA|B} AA +7 2 a +3 8 {A|B} B +3 8 {AA|B} B +8 3 b +2 9 {A|B} A +2 9 {AA|B} AA +9 3 a +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 A +0 2 b b +2 0 B +0 +0 0 +1 1 +2 2 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 +1 +0 2 +2 4 a A +4 1 A +2 5 a A +5 2 A +2 6 a A +6 3 A +0 3 +3 7 b B +7 1 B +3 8 b B +8 3 B +3 9 b B +9 2 B +0 0 +1 1 +2 2 +3 3 +4 4 +5 5 +6 6 +7 7 +8 8 +9 9 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 +0 0 a a +0 0 b b +0 0 A A +0 0 B B +0 +0 1 +1 1 +1 0 a a +1 0 b b +1 0 A A +1 0 B B +1 +0 2 +2 2 +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 + +/* Define this for verbose memory debugging */ +//#define GFSM_DEBUG_VERBOSE + +#ifdef GFSM_DEBUG_VERBOSE +# include +# 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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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, +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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include +#include + +#include + +/*-- 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; ilen; 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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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, +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include + +#include + +#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 " +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 +" 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 +#include +#include +#include +#include +#include + +/* If we use autoconf/autoheader. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_PWD_H +# include +#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 +#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 \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 + + 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 +#endif + +#include +#include +#include +#include +#include + +#include + +#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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 0 +a_A 1 +a_B 2 +b_A 3 +b_B 4 +_A 5 +_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 @@ + 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 @@ + A a a_A 1 + A b b_A 1 + B a a_B 1 + B b b_B 1 + 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 @@ + A _A .4 + A a a_A .3 + B _B .2 + B b b_B .1 + 1 + +A A a a_A .7 +A B _B .2 +A B b b_B .1 +A 1 + +B B b b_B .7 +B A a a_A .2 +B A _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 . + +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 c 6.7 +2 3 foo 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 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 @@ + 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 . +_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 . +_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: " + 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 ; +#X text 138 257 Bryan Jurish ; #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 header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the 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 * 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(); -- cgit v1.2.1