spot/bin/common_trans.cc
Alexandre Duret-Lutz 63362d535f Upgrade the Copyright strings to point to AUTHORS and drop years
Fixes #539.

* AUTHORS: Update by indicating the status of each contributor.
* Makefile.am, bench/Makefile.am, bench/dtgbasat/Makefile.am,
bench/dtgbasat/gen.py, bench/emptchk/Makefile.am,
bench/emptchk/defs.in, bench/ltl2tgba/Makefile.am,
bench/ltl2tgba/defs.in, bench/ltl2tgba/sum.py,
bench/ltlclasses/Makefile.am, bench/ltlcounter/Makefile.am,
bench/spin13/Makefile.am, bench/stutter/Makefile.am,
bench/stutter/stutter_invariance_formulas.cc,
bench/stutter/stutter_invariance_randomgraph.cc,
bench/wdba/Makefile.am, bin/Makefile.am, bin/autcross.cc,
bin/autfilt.cc, bin/common_aoutput.cc, bin/common_aoutput.hh,
bin/common_color.cc, bin/common_color.hh, bin/common_conv.cc,
bin/common_conv.hh, bin/common_cout.cc, bin/common_cout.hh,
bin/common_file.cc, bin/common_file.hh, bin/common_finput.cc,
bin/common_finput.hh, bin/common_hoaread.cc, bin/common_hoaread.hh,
bin/common_output.cc, bin/common_output.hh, bin/common_post.cc,
bin/common_post.hh, bin/common_r.cc, bin/common_r.hh,
bin/common_range.cc, bin/common_range.hh, bin/common_setup.cc,
bin/common_setup.hh, bin/common_sys.hh, bin/common_trans.cc,
bin/common_trans.hh, bin/dstar2tgba.cc, bin/genaut.cc, bin/genltl.cc,
bin/ltl2tgba.cc, bin/ltl2tgta.cc, bin/ltlcross.cc, bin/ltldo.cc,
bin/ltlfilt.cc, bin/ltlgrind.cc, bin/ltlsynt.cc, bin/man/Makefile.am,
bin/options.py, bin/randaut.cc, bin/randltl.cc, bin/spot-x.cc,
bin/spot.cc, configure.ac, debian/copyright, doc/Makefile.am,
doc/tl/Makefile.am, elisp/Makefile.am, python/Makefile.am,
python/buddy.i, python/spot/__init__.py, python/spot/aux_.py,
python/spot/gen.i, python/spot/impl.i, python/spot/jupyter.py,
python/spot/ltsmin.i, spot/Makefile.am, spot/gen/Makefile.am,
spot/gen/automata.cc, spot/gen/automata.hh, spot/gen/formulas.cc,
spot/gen/formulas.hh, spot/graph/Makefile.am, spot/graph/graph.hh,
spot/graph/ngraph.hh, spot/kripke/Makefile.am,
spot/kripke/fairkripke.cc, spot/kripke/fairkripke.hh,
spot/kripke/fwd.hh, spot/kripke/kripke.cc, spot/kripke/kripke.hh,
spot/kripke/kripkegraph.hh, spot/ltsmin/Makefile.am,
spot/ltsmin/ltsmin.cc, spot/ltsmin/ltsmin.hh,
spot/ltsmin/spins_interface.cc, spot/ltsmin/spins_interface.hh,
spot/ltsmin/spins_kripke.hh, spot/ltsmin/spins_kripke.hxx,
spot/mc/Makefile.am, spot/mc/bloemen.hh, spot/mc/bloemen_ec.hh,
spot/mc/cndfs.hh, spot/mc/deadlock.hh, spot/mc/intersect.hh,
spot/mc/lpar13.hh, spot/mc/mc.hh, spot/mc/mc_instanciator.hh,
spot/mc/unionfind.cc, spot/mc/unionfind.hh, spot/mc/utils.hh,
spot/misc/Makefile.am, spot/misc/bareword.cc, spot/misc/bareword.hh,
spot/misc/bddlt.hh, spot/misc/bitset.cc, spot/misc/bitset.hh,
spot/misc/bitvect.cc, spot/misc/bitvect.hh, spot/misc/casts.hh,
spot/misc/clz.hh, spot/misc/common.hh, spot/misc/escape.cc,
spot/misc/escape.hh, spot/misc/fixpool.hh, spot/misc/formater.cc,
spot/misc/formater.hh, spot/misc/hash.hh, spot/misc/hashfunc.hh,
spot/misc/intvcmp2.cc, spot/misc/intvcmp2.hh, spot/misc/intvcomp.cc,
spot/misc/intvcomp.hh, spot/misc/ltstr.hh, spot/misc/memusage.cc,
spot/misc/memusage.hh, spot/misc/minato.cc, spot/misc/minato.hh,
spot/misc/mspool.hh, spot/misc/optionmap.cc, spot/misc/optionmap.hh,
spot/misc/random.cc, spot/misc/random.hh, spot/misc/satsolver.cc,
spot/misc/satsolver.hh, spot/misc/timer.cc, spot/misc/timer.hh,
spot/misc/tmpfile.cc, spot/misc/tmpfile.hh, spot/misc/trival.hh,
spot/misc/version.cc, spot/misc/version.hh, spot/parseaut/Makefile.am,
spot/parseaut/fmterror.cc, spot/parseaut/parseaut.yy,
spot/parseaut/parsedecl.hh, spot/parseaut/public.hh,
spot/parseaut/scanaut.ll, spot/parsetl/Makefile.am,
spot/parsetl/fmterror.cc, spot/parsetl/parsedecl.hh,
spot/parsetl/parsetl.yy, spot/parsetl/scantl.ll,
spot/priv/Makefile.am, spot/priv/accmap.hh, spot/priv/bddalloc.cc,
spot/priv/bddalloc.hh, spot/priv/freelist.cc, spot/priv/freelist.hh,
spot/priv/partitioned_relabel.cc, spot/priv/partitioned_relabel.hh,
spot/priv/satcommon.cc, spot/priv/satcommon.hh, spot/priv/trim.cc,
spot/priv/trim.hh, spot/priv/weight.cc, spot/priv/weight.hh,
spot/ta/Makefile.am, spot/ta/ta.cc, spot/ta/ta.hh,
spot/ta/taexplicit.cc, spot/ta/taexplicit.hh, spot/ta/taproduct.cc,
spot/ta/taproduct.hh, spot/ta/tgta.hh, spot/ta/tgtaexplicit.cc,
spot/ta/tgtaexplicit.hh, spot/ta/tgtaproduct.cc,
spot/ta/tgtaproduct.hh, spot/taalgos/Makefile.am, spot/taalgos/dot.cc,
spot/taalgos/dot.hh, spot/taalgos/emptinessta.cc,
spot/taalgos/emptinessta.hh, spot/taalgos/minimize.cc,
spot/taalgos/minimize.hh, spot/taalgos/reachiter.cc,
spot/taalgos/reachiter.hh, spot/taalgos/statessetbuilder.cc,
spot/taalgos/statessetbuilder.hh, spot/taalgos/stats.cc,
spot/taalgos/stats.hh, spot/taalgos/tgba2ta.cc,
spot/taalgos/tgba2ta.hh, spot/tl/Makefile.am, spot/tl/apcollect.cc,
spot/tl/apcollect.hh, spot/tl/contain.cc, spot/tl/contain.hh,
spot/tl/declenv.cc, spot/tl/declenv.hh, spot/tl/defaultenv.cc,
spot/tl/defaultenv.hh, spot/tl/dot.cc, spot/tl/dot.hh,
spot/tl/environment.hh, spot/tl/exclusive.cc, spot/tl/exclusive.hh,
spot/tl/formula.cc, spot/tl/formula.hh, spot/tl/hierarchy.cc,
spot/tl/hierarchy.hh, spot/tl/length.cc, spot/tl/length.hh,
spot/tl/ltlf.cc, spot/tl/ltlf.hh, spot/tl/mark.cc, spot/tl/mark.hh,
spot/tl/mutation.cc, spot/tl/mutation.hh, spot/tl/nenoform.cc,
spot/tl/nenoform.hh, spot/tl/parse.hh, spot/tl/print.cc,
spot/tl/print.hh, spot/tl/randomltl.cc, spot/tl/randomltl.hh,
spot/tl/relabel.cc, spot/tl/relabel.hh, spot/tl/remove_x.cc,
spot/tl/remove_x.hh, spot/tl/simplify.cc, spot/tl/simplify.hh,
spot/tl/snf.cc, spot/tl/snf.hh, spot/tl/sonf.cc, spot/tl/sonf.hh,
spot/tl/unabbrev.cc, spot/tl/unabbrev.hh, spot/twa/Makefile.am,
spot/twa/acc.cc, spot/twa/acc.hh, spot/twa/bdddict.cc,
spot/twa/bdddict.hh, spot/twa/bddprint.cc, spot/twa/bddprint.hh,
spot/twa/formula2bdd.cc, spot/twa/formula2bdd.hh, spot/twa/fwd.hh,
spot/twa/taatgba.cc, spot/twa/taatgba.hh, spot/twa/twa.cc,
spot/twa/twa.hh, spot/twa/twagraph.cc, spot/twa/twagraph.hh,
spot/twa/twaproduct.cc, spot/twa/twaproduct.hh,
spot/twaalgos/Makefile.am, spot/twaalgos/aiger.cc,
spot/twaalgos/aiger.hh, spot/twaalgos/alternation.cc,
spot/twaalgos/alternation.hh, spot/twaalgos/are_isomorphic.cc,
spot/twaalgos/are_isomorphic.hh, spot/twaalgos/bfssteps.cc,
spot/twaalgos/bfssteps.hh, spot/twaalgos/canonicalize.cc,
spot/twaalgos/canonicalize.hh, spot/twaalgos/cleanacc.cc,
spot/twaalgos/cleanacc.hh, spot/twaalgos/cobuchi.cc,
spot/twaalgos/cobuchi.hh, spot/twaalgos/complement.cc,
spot/twaalgos/complement.hh, spot/twaalgos/complete.cc,
spot/twaalgos/complete.hh, spot/twaalgos/compsusp.cc,
spot/twaalgos/compsusp.hh, spot/twaalgos/contains.cc,
spot/twaalgos/contains.hh, spot/twaalgos/copy.hh,
spot/twaalgos/couvreurnew.cc, spot/twaalgos/couvreurnew.hh,
spot/twaalgos/cycles.cc, spot/twaalgos/cycles.hh,
spot/twaalgos/dbranch.cc, spot/twaalgos/dbranch.hh,
spot/twaalgos/degen.cc, spot/twaalgos/degen.hh,
spot/twaalgos/determinize.cc, spot/twaalgos/determinize.hh,
spot/twaalgos/dot.cc, spot/twaalgos/dot.hh, spot/twaalgos/dtbasat.cc,
spot/twaalgos/dtbasat.hh, spot/twaalgos/dtwasat.cc,
spot/twaalgos/dtwasat.hh, spot/twaalgos/dualize.cc,
spot/twaalgos/dualize.hh, spot/twaalgos/emptiness.cc,
spot/twaalgos/emptiness.hh, spot/twaalgos/emptiness_stats.hh,
spot/twaalgos/forq_contains.cc, spot/twaalgos/forq_contains.hh,
spot/twaalgos/game.cc, spot/twaalgos/game.hh, spot/twaalgos/genem.cc,
spot/twaalgos/genem.hh, spot/twaalgos/gfguarantee.cc,
spot/twaalgos/gfguarantee.hh, spot/twaalgos/gtec/Makefile.am,
spot/twaalgos/gtec/ce.cc, spot/twaalgos/gtec/ce.hh,
spot/twaalgos/gtec/gtec.cc, spot/twaalgos/gtec/gtec.hh,
spot/twaalgos/gtec/sccstack.cc, spot/twaalgos/gtec/sccstack.hh,
spot/twaalgos/gtec/status.cc, spot/twaalgos/gtec/status.hh,
spot/twaalgos/gv04.cc, spot/twaalgos/gv04.hh, spot/twaalgos/hoa.cc,
spot/twaalgos/hoa.hh, spot/twaalgos/iscolored.cc,
spot/twaalgos/iscolored.hh, spot/twaalgos/isdet.cc,
spot/twaalgos/isdet.hh, spot/twaalgos/isunamb.cc,
spot/twaalgos/isunamb.hh, spot/twaalgos/isweakscc.cc,
spot/twaalgos/isweakscc.hh, spot/twaalgos/langmap.cc,
spot/twaalgos/langmap.hh, spot/twaalgos/lbtt.cc,
spot/twaalgos/lbtt.hh, spot/twaalgos/ltl2taa.cc,
spot/twaalgos/ltl2taa.hh, spot/twaalgos/ltl2tgba_fm.cc,
spot/twaalgos/ltl2tgba_fm.hh, spot/twaalgos/magic.cc,
spot/twaalgos/magic.hh, spot/twaalgos/mask.cc, spot/twaalgos/mask.hh,
spot/twaalgos/mealy_machine.cc, spot/twaalgos/mealy_machine.hh,
spot/twaalgos/minimize.cc, spot/twaalgos/minimize.hh,
spot/twaalgos/ndfs_result.hxx, spot/twaalgos/neverclaim.cc,
spot/twaalgos/neverclaim.hh, spot/twaalgos/parity.cc,
spot/twaalgos/parity.hh, spot/twaalgos/postproc.cc,
spot/twaalgos/postproc.hh, spot/twaalgos/powerset.cc,
spot/twaalgos/powerset.hh, spot/twaalgos/product.cc,
spot/twaalgos/product.hh, spot/twaalgos/randomgraph.cc,
spot/twaalgos/randomgraph.hh, spot/twaalgos/randomize.cc,
spot/twaalgos/randomize.hh, spot/twaalgos/reachiter.cc,
spot/twaalgos/reachiter.hh, spot/twaalgos/relabel.cc,
spot/twaalgos/relabel.hh, spot/twaalgos/remfin.cc,
spot/twaalgos/remfin.hh, spot/twaalgos/remprop.cc,
spot/twaalgos/remprop.hh, spot/twaalgos/sbacc.cc,
spot/twaalgos/sbacc.hh, spot/twaalgos/sccfilter.cc,
spot/twaalgos/sccfilter.hh, spot/twaalgos/sccinfo.cc,
spot/twaalgos/sccinfo.hh, spot/twaalgos/se05.cc,
spot/twaalgos/se05.hh, spot/twaalgos/sepsets.cc,
spot/twaalgos/sepsets.hh, spot/twaalgos/simulation.cc,
spot/twaalgos/simulation.hh, spot/twaalgos/split.cc,
spot/twaalgos/split.hh, spot/twaalgos/stats.cc,
spot/twaalgos/stats.hh, spot/twaalgos/strength.cc,
spot/twaalgos/strength.hh, spot/twaalgos/stripacc.cc,
spot/twaalgos/stripacc.hh, spot/twaalgos/stutter.cc,
spot/twaalgos/stutter.hh, spot/twaalgos/sum.cc, spot/twaalgos/sum.hh,
spot/twaalgos/synthesis.cc, spot/twaalgos/synthesis.hh,
spot/twaalgos/tau03.cc, spot/twaalgos/tau03.hh,
spot/twaalgos/tau03opt.cc, spot/twaalgos/tau03opt.hh,
spot/twaalgos/toparity.cc, spot/twaalgos/toparity.hh,
spot/twaalgos/totgba.cc, spot/twaalgos/totgba.hh,
spot/twaalgos/toweak.cc, spot/twaalgos/toweak.hh,
spot/twaalgos/translate.cc, spot/twaalgos/translate.hh,
spot/twaalgos/word.cc, spot/twaalgos/word.hh,
spot/twaalgos/zlktree.cc, spot/twaalgos/zlktree.hh,
spot/twacube/Makefile.am, spot/twacube/cube.cc, spot/twacube/cube.hh,
spot/twacube/fwd.hh, spot/twacube/twacube.cc, spot/twacube/twacube.hh,
spot/twacube_algos/Makefile.am, spot/twacube_algos/convert.cc,
spot/twacube_algos/convert.hh, tests/Makefile.am, tests/core/385.test,
tests/core/500.test, tests/core/521.test, tests/core/522.test,
tests/core/acc.cc, tests/core/acc.test, tests/core/acc2.test,
tests/core/acc_word.test, tests/core/accsimpl.test,
tests/core/alternating.test, tests/core/autcross.test,
tests/core/autcross2.test, tests/core/autcross3.test,
tests/core/autcross4.test, tests/core/autcross5.test,
tests/core/babiak.test, tests/core/bare.test, tests/core/basimul.test,
tests/core/bdd.test, tests/core/bdddict.cc, tests/core/bdddict.test,
tests/core/bitvect.cc, tests/core/bitvect.test, tests/core/bricks.cc,
tests/core/bricks.test, tests/core/checkpsl.cc, tests/core/checkta.cc,
tests/core/complement.test, tests/core/complementation.test,
tests/core/complete.test, tests/core/consterm.cc,
tests/core/consterm.test, tests/core/cube.cc, tests/core/cube.test,
tests/core/cycles.test, tests/core/dbacomp.test, tests/core/dca.test,
tests/core/dca2.test, tests/core/defs.in, tests/core/degendet.test,
tests/core/degenid.test, tests/core/degenlskip.test,
tests/core/degenscc.test, tests/core/det.test, tests/core/dfs.test,
tests/core/dnfstreett.test, tests/core/dot2tex.test,
tests/core/dra2dba.test, tests/core/dstar.test,
tests/core/dualize.test, tests/core/dupexp.test,
tests/core/emptchk.cc, tests/core/emptchk.test,
tests/core/emptchke.test, tests/core/emptchkr.test,
tests/core/equals.test, tests/core/equalsf.cc,
tests/core/eventuniv.test, tests/core/exclusive-ltl.test,
tests/core/exclusive-tgba.test, tests/core/explpro2.test,
tests/core/explpro3.test, tests/core/explpro4.test,
tests/core/explprod.test, tests/core/explsum.test,
tests/core/format.test, tests/core/full.test, tests/core/gamehoa.test,
tests/core/genaut.test, tests/core/genltl.test,
tests/core/gragsa.test, tests/core/graph.cc, tests/core/graph.test,
tests/core/hierarchy.test, tests/core/highlightstate.test,
tests/core/ikwiad.cc, tests/core/included.test,
tests/core/intvcmp2.cc, tests/core/intvcomp.cc,
tests/core/intvcomp.test, tests/core/isomorph.test,
tests/core/isop.test, tests/core/kind.cc, tests/core/kind.test,
tests/core/kripke.test, tests/core/kripkecat.cc,
tests/core/latex.test, tests/core/lbt.test, tests/core/lbttparse.test,
tests/core/length.cc, tests/core/length.test, tests/core/lenient.test,
tests/core/ltl2dstar.test, tests/core/ltl2dstar2.test,
tests/core/ltl2dstar3.test, tests/core/ltl2dstar4.test,
tests/core/ltl2neverclaim-lbtt.test, tests/core/ltl2neverclaim.test,
tests/core/ltl2ta.test, tests/core/ltl2ta2.test,
tests/core/ltl2tgba.test, tests/core/ltl2tgba2.test,
tests/core/ltl3ba.test, tests/core/ltl3dra.test,
tests/core/ltlcounter.test, tests/core/ltlcross.test,
tests/core/ltlcross2.test, tests/core/ltlcross3.test,
tests/core/ltlcross4.test, tests/core/ltlcross5.test,
tests/core/ltlcross6.test, tests/core/ltlcrossce.test,
tests/core/ltlcrossce2.test, tests/core/ltlcrossgrind.test,
tests/core/ltldo.test, tests/core/ltldo2.test, tests/core/ltlf.test,
tests/core/ltlfilt.test, tests/core/ltlgrind.test,
tests/core/ltlrel.cc, tests/core/ltlrel.test,
tests/core/ltlsynt-pgame.test, tests/core/ltlsynt.test,
tests/core/ltlsynt2.test, tests/core/lunabbrev.test,
tests/core/maskacc.test, tests/core/maskkeep.test,
tests/core/mempool.cc, tests/core/mempool.test, tests/core/minterm.cc,
tests/core/minterm.test, tests/core/minusx.test,
tests/core/monitor.test, tests/core/nenoform.test,
tests/core/neverclaimread.test, tests/core/ngraph.cc,
tests/core/ngraph.test, tests/core/nondet.test,
tests/core/obligation.test, tests/core/optba.test,
tests/core/parity.cc, tests/core/parity.test, tests/core/parity2.test,
tests/core/parse.test, tests/core/parseaut.test,
tests/core/parseerr.test, tests/core/pdegen.test,
tests/core/pgsolver.test, tests/core/prodchain.test,
tests/core/prodor.test, tests/core/rabin2parity.test,
tests/core/rand.test, tests/core/randaut.test,
tests/core/randomize.test, tests/core/randpsl.test,
tests/core/randtgba.cc, tests/core/randtgba.test,
tests/core/readltl.cc, tests/core/readsave.test, tests/core/reduc.cc,
tests/core/reduc.test, tests/core/reduc0.test,
tests/core/reduccmp.test, tests/core/reducpsl.test,
tests/core/remfin.test, tests/core/remove_x.test,
tests/core/remprop.test, tests/core/renault.test, tests/core/safra.cc,
tests/core/safra.test, tests/core/satmin.test,
tests/core/satmin2.test, tests/core/satmin3.test,
tests/core/sbacc.test, tests/core/scc.test, tests/core/sccdot.test,
tests/core/sccif.cc, tests/core/sccif.test, tests/core/sccsimpl.test,
tests/core/semidet.test, tests/core/sepsets.test,
tests/core/serial.test, tests/core/sim2.test, tests/core/sim3.test,
tests/core/sonf.test, tests/core/split.test, tests/core/spotlbtt.test,
tests/core/spotlbtt2.test, tests/core/streett.test,
tests/core/strength.test, tests/core/stutter-ltl.test,
tests/core/stutter-tgba.test, tests/core/sugar.test,
tests/core/syfco.test, tests/core/syntimpl.cc,
tests/core/syntimpl.test, tests/core/taatgba.cc,
tests/core/taatgba.test, tests/core/tgbagraph.test,
tests/core/tostring.cc, tests/core/tostring.test,
tests/core/tripprod.test, tests/core/trival.cc,
tests/core/trival.test, tests/core/tunabbrev.test,
tests/core/tunenoform.test, tests/core/twacube.cc,
tests/core/twacube.test, tests/core/twagraph.cc,
tests/core/unabbrevwm.test, tests/core/unambig.test,
tests/core/unambig2.test, tests/core/uniq.test, tests/core/utf8.test,
tests/core/uwrm.test, tests/core/wdba.test, tests/core/wdba2.test,
tests/ltsmin/check.test, tests/ltsmin/check2.test,
tests/ltsmin/check3.test, tests/ltsmin/finite.test,
tests/ltsmin/finite2.test, tests/ltsmin/finite3.test,
tests/ltsmin/kripke.test, tests/ltsmin/modelcheck.cc,
tests/ltsmin/testconvert.cc, tests/ltsmin/testconvert.test,
tests/python/298.py, tests/python/341.py, tests/python/471.py,
tests/python/acc.py, tests/python/accparse2.py, tests/python/aiger.py,
tests/python/alarm.py, tests/python/aliases.py,
tests/python/alternating.py, tests/python/bdddict.py,
tests/python/bdditer.py, tests/python/bddnqueen.py,
tests/python/bugdet.py, tests/python/complement_semidet.py,
tests/python/dbranch.py, tests/python/declenv.py,
tests/python/decompose_scc.py, tests/python/det.py,
tests/python/dualize.py, tests/python/ecfalse.py,
tests/python/except.py, tests/python/forq_contains.py,
tests/python/game.py, tests/python/gen.py, tests/python/genem.py,
tests/python/implies.py, tests/python/interdep.py,
tests/python/intrun.py, tests/python/kripke.py,
tests/python/langmap.py, tests/python/ltl2tgba.py,
tests/python/ltl2tgba.test, tests/python/ltlf.py,
tests/python/ltlparse.py, tests/python/ltlsimple.py,
tests/python/mealy.py, tests/python/merge.py,
tests/python/mergedge.py, tests/python/minato.py,
tests/python/misc-ec.py, tests/python/optionmap.py,
tests/python/origstate.py, tests/python/otfcrash.py,
tests/python/parity.py, tests/python/parsetgba.py,
tests/python/pdegen.py, tests/python/powerset.py,
tests/python/prodexpt.py, tests/python/randgen.py,
tests/python/relabel.py, tests/python/remfin.py,
tests/python/removeap.py, tests/python/rs_like.py,
tests/python/satmin.py, tests/python/sbacc.py,
tests/python/sccfilter.py, tests/python/sccinfo.py,
tests/python/sccsplit.py, tests/python/semidet.py,
tests/python/setacc.py, tests/python/setxor.py,
tests/python/simplacc.py, tests/python/simstate.py,
tests/python/sonf.py, tests/python/split.py,
tests/python/splitedge.py, tests/python/streett_totgba.py,
tests/python/streett_totgba2.py, tests/python/stutter.py,
tests/python/sum.py, tests/python/synthesis.py,
tests/python/toparity.py, tests/python/toweak.py,
tests/python/tra2tba.py, tests/python/trival.py,
tests/python/twagraph.py, tests/python/zlktree.py, tests/run.in,
tests/sanity/80columns.test, tests/sanity/bin.test,
tests/sanity/getenv.test, tests/sanity/includes.test,
tests/sanity/ipynb.pl, tests/sanity/namedprop.test,
tests/sanity/private.test, tests/sanity/readme.pl,
tests/sanity/style.test, tools/man2html.pl: Update all copyright
headers.
2023-11-18 21:50:32 +01:00

1091 lines
32 KiB
C++

// -*- coding: utf-8 -*-
// Copyright (C) by the Spot authors, see the AUTHORS file for details.
//
// This file is part of Spot, a model checking library.
//
// Spot 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.
//
// Spot is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "common_trans.hh"
#include "common_setup.hh"
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <iomanip>
#include <fstream>
#if __has_include(<spawn.h>)
#define HAVE_SPAWN_H 1
#include <spawn.h>
#endif
#include <regex>
#include "error.h"
#include <spot/tl/print.hh>
#include <spot/tl/unabbrev.hh>
#include "common_conv.hh"
#include <spot/misc/escape.hh>
#include <spot/twaalgos/hoa.hh>
#include <spot/twaalgos/lbtt.hh>
#include <spot/twaalgos/neverclaim.hh>
// A set of tools for which we know the correct output
struct shorthands_t
{
const char* prefix;
std::regex rprefix;
const char* suffix;
};
#define SHORTHAND(PRE, POST) { PRE, std::regex("^" PRE), POST }
static const shorthands_t shorthands_ltl[] = {
SHORTHAND("delag", " %f>%O"),
SHORTHAND("lbt", " <%L>%O"),
SHORTHAND("ltl2ba", " -f %s>%O"),
SHORTHAND("ltl2(da|dgra|dpa|dra|ldba|na|nba|ngba)", " %f>%O"),
SHORTHAND("ltl2dstar", " --output-format=hoa %[MW]L %O"),
SHORTHAND("ltl2tgba", " -H %f>%O"),
// ltl3tela is the new name of ltl3hoa
SHORTHAND("ltl3(ba|dra|hoa|tela)", " -f %s>%O"),
SHORTHAND("modella", " %[MWei^]L %O"),
SHORTHAND("spin", " -f %s>%O"),
// Starting from Owl 21.0, Owl's tools have been grouped as
// sub-commands of the Owl binary. We still want to support
// use cases where several version of owl are installed with
// different names.
SHORTHAND("owl.* ltl2[bdeglnpr]+a\\b", " -f %f>%O"),
SHORTHAND("owl.* ltl2delta2\\b", " -f %f"),
SHORTHAND("owl.* ltl-utilities\\b", " -f %f"),
};
static const shorthands_t shorthands_autproc[] = {
SHORTHAND("autfilt", " %H>%O"),
SHORTHAND("dra2dpa", " <%H>%O"),
SHORTHAND("dstar2tgba", " %H>%O"),
SHORTHAND("ltl2dstar", " -B %H %O"),
SHORTHAND("nba2l?dpa", " <%H>%O"),
SHORTHAND("seminator", " %H>%O"),
SHORTHAND("owl.* "
"(ngba2ldba|nba(2dpa|2det|sim)|aut2parity|gfg-minimization)\\b",
" <%H>%O"),
};
static void show_shorthands(const shorthands_t* begin, const shorthands_t* end)
{
std::cout
<< ("If a COMMANDFMT does not use any %-sequence, and starts with one of\n"
"the following regexes, then the string on the right is appended.\n\n");
while (begin != end)
{
std::cout << " "
<< std::left << std::setw(40) << begin->prefix
<< begin->suffix << '\n';
++begin;
}
}
tool_spec::tool_spec(const char* spec,
const shorthands_t* begin, const shorthands_t* end,
bool is_ref) noexcept
: spec(spec), cmd(spec), name(spec), reference(is_ref)
{
if (*cmd == '{')
{
// Match the closing '}'
const char* pos = cmd;
unsigned count = 1;
while (*++pos)
{
if (*pos == '{')
++count;
else if (*pos == '}' && --count == 0)
{
name = strndup(cmd + 1, pos - cmd - 1);
cmd = pos + 1;
// skip leading whitespace
while (*cmd == ' ' || *cmd == '\t')
++cmd;
break;
}
}
}
// If there is no % in the string, look for a known
// command from our shorthand list. If we find it,
// add the suffix.
bool allocated = false;
if (!strchr(cmd, '%'))
{
// Skip any leading directory name.
auto basename = cmd;
auto pos = cmd;
while (*pos)
{
if (*pos == '/')
basename = pos + 1;
else if (*pos == ' ')
break;
++pos;
}
// Match a shorthand.
while (begin != end)
{
auto& p = *begin++;
if (std::regex_search(basename, p.rprefix))
{
size_t m = strlen(p.suffix);
size_t q = strlen(cmd);
char* tmp = static_cast<char*>(malloc(q + m + 1));
memcpy(tmp, cmd, q);
memcpy(tmp + q, p.suffix, m + 1);
cmd = tmp;
allocated = true;
break;
}
}
}
if (!allocated)
cmd = strdup(cmd);
}
tool_spec::tool_spec(const tool_spec& other) noexcept
: spec(other.spec), cmd(other.cmd), name(other.name),
reference(other.reference)
{
if (cmd != spec)
cmd = strdup(cmd);
if (name != spec)
name = strdup(name);
}
tool_spec& tool_spec::operator=(const tool_spec& other)
{
spec = other.spec;
cmd = other.cmd;
if (cmd != spec)
cmd = strdup(cmd);
name = other.name;
if (name != spec)
name = strdup(name);
return *this;
}
tool_spec::~tool_spec()
{
if (name != spec)
free(const_cast<char*>(name));
if (cmd != spec)
free(const_cast<char*>(cmd));
}
std::vector<tool_spec> tools;
void tools_push_trans(const char* trans, bool is_ref)
{
tools.emplace_back(trans,
std::begin(shorthands_ltl),
std::end(shorthands_ltl),
is_ref);
}
void tools_push_autproc(const char* proc, bool is_ref)
{
tools.emplace_back(proc,
std::begin(shorthands_autproc),
std::end(shorthands_autproc),
is_ref);
}
void quoted_formula::print(std::ostream& os, const char* pos) const
{
spot::formula f = val_;
if (*pos == '[')
{
++pos;
auto end = strchr(pos, ']');
auto arg = strndup(pos, end - pos);
f = spot::unabbreviate(f, arg);
free(arg);
pos = end + 1;
}
std::ostringstream ss;
std::ostream* out = &ss;
bool quoted = true;
switch (*pos)
{
case 'F':
case 'S':
case 'L':
case 'W':
out = &os;
quoted = false;
}
switch (*pos)
{
case 'f':
case 'F':
print_psl(*out, f, true);
break;
case 's':
case 'S':
print_spin_ltl(*out, f, true);
break;
case 'l':
case 'L':
print_lbt_ltl(*out, f);
break;
case 'w':
case 'W':
print_wring_ltl(*out, f);
break;
}
if (quoted)
{
std::string s = ss.str();
spot::quote_shell_string(os, s.c_str());
}
}
printable_result_filename::printable_result_filename()
{
val_ = nullptr;
}
printable_result_filename::~printable_result_filename()
{
delete val_;
}
void printable_result_filename::reset(unsigned n)
{
translator_num = n;
}
void printable_result_filename::cleanup()
{
delete val_;
val_ = nullptr;
}
void
printable_result_filename::print(std::ostream& os, const char*) const
{
char prefix[30];
snprintf(prefix, sizeof prefix, "lcr-o%u-", translator_num);
const_cast<printable_result_filename*>(this)->val_ =
spot::create_tmpfile(prefix);
spot::quote_shell_string(os, val()->name());
}
static std::string
string_to_tmp(const std::string str, unsigned n)
{
char prefix[30];
snprintf(prefix, sizeof prefix, "lcr-i%u-", n);
spot::open_temporary_file* tmpfile = spot::create_open_tmpfile(prefix);
std::string tmpname = tmpfile->name();
int fd = tmpfile->fd();
ssize_t s = str.size();
if (write(fd, str.c_str(), s) != s
|| write(fd, "\n", 1) != 1)
error(2, errno, "failed to write into %s", tmpname.c_str());
tmpfile->close();
return tmpname;
}
void
filed_formula::print(std::ostream& os, const char* pos) const
{
std::ostringstream ss;
f_.print(ss, pos);
os << '\'' << string_to_tmp(ss.str(), serial_) << '\'';
}
void
filed_automaton::print(std::ostream& os, const char* pos) const
{
std::ostringstream ss;
char* opt = nullptr;
bool filename = true;
if (*pos == '[')
{
++pos;
auto end = strchr(pos, ']');
opt = strndup(pos, end - pos);
pos = end + 1;
}
switch (*pos)
{
case 'H':
spot::print_hoa(ss, aut_, opt);
break;
case 'S':
spot::print_never_claim(ss, aut_, opt);
break;
case 'L':
spot::print_lbtt(ss, aut_, opt);
break;
case 'M':
{
filename = false;
std::string* name = aut_->get_named_prop<std::string>("automaton-name");
spot::quote_shell_string(os,
name ? name->c_str() :
opt ? opt :
"");
}
}
if (opt)
free(opt);
if (filename)
os << '\'' << string_to_tmp(ss.str(), serial_) << '\'';
}
translator_runner::translator_runner(spot::bdd_dict_ptr dict,
bool no_output_allowed)
: dict(dict)
{
declare('f', &ltl_formula);
declare('s', &ltl_formula);
declare('l', &ltl_formula);
declare('w', &ltl_formula);
declare('F', &filename_formula);
declare('S', &filename_formula);
declare('L', &filename_formula);
declare('W', &filename_formula);
declare('D', &output);
declare('H', &output);
declare('N', &output);
declare('T', &output);
declare('O', &output);
size_t s = tools.size();
assert(s);
for (size_t n = 0; n < s; ++n)
{
// Check that each translator uses at least one input and
// one output.
std::vector<bool> has(256);
const tool_spec& t = tools[n];
scan(t.cmd, has);
if (!(has['f'] || has['s'] || has['l'] || has['w']
|| has['F'] || has['S'] || has['L'] || has['W']))
error(2, 0, "no input %%-sequence in '%s'.\n Use "
"one of %%f,%%s,%%l,%%w,%%F,%%S,%%L,%%W to indicate how "
"to pass the formula.", t.spec);
if (!no_output_allowed
&& !(has['O'] ||
// backward-compatibility
has['D'] || has['N'] || has['T'] || has['H']))
error(2, 0, "no output %%-sequence in '%s'.\n Use "
"%%O to indicate where the automaton is output.",
t.spec);
// Remember the %-sequences used by all tools.
prime(t.cmd);
}
}
std::string
translator_runner::formula() const
{
// Pick the most readable format we have...
if (has('f') || has('F'))
return spot::str_psl(ltl_formula, true);
if (has('s') || has('S'))
return spot::str_spin_ltl(ltl_formula, true);
if (has('l') || has('L'))
return spot::str_lbt_ltl(ltl_formula);
if (has('w') || has('W'))
return spot::str_wring_ltl(ltl_formula);
SPOT_UNREACHABLE();
return spot::str_psl(ltl_formula, true);
}
void
translator_runner::round_formula(spot::formula f, unsigned serial)
{
ltl_formula = f;
filename_formula.new_round(serial);
}
autproc_runner::autproc_runner(bool no_output_allowed)
{
declare('H', &filename_automaton);
declare('S', &filename_automaton);
declare('L', &filename_automaton);
declare('M', &filename_automaton);
declare('O', &output);
size_t s = tools.size();
assert(s);
for (size_t n = 0; n < s; ++n)
{
// Check that each translator uses at least one input and
// one output.
std::vector<bool> has(256);
const tool_spec& t = tools[n];
scan(t.cmd, has);
if (!(has['H'] || has['S'] || has['L'] || has['M']))
error(2, 0, "no input %%-sequence in '%s'.\n Use "
"one of %%H,%%S,%%L to indicate the input automaton filename.\n"
" (Or use %%M if you want to work from its name.)\n",
t.spec);
if (!no_output_allowed && !has['O'])
error(2, 0, "no output %%-sequence in '%s'.\n Use "
"%%O to indicate where the automaton is output.",
t.spec);
// Remember the %-sequences used by all tools.
prime(t.cmd);
}
}
void
autproc_runner::round_automaton(spot::const_twa_graph_ptr aut, unsigned serial)
{
filename_automaton.new_round(aut, serial);
}
std::string
read_stdout_of_command(char* const* args)
{
#if HAVE_SPAWN_H
int cout_pipe[2];
if (int err = pipe(cout_pipe))
error(2, err, "pipe() failed");
posix_spawn_file_actions_t actions;
if (int err = posix_spawn_file_actions_init(&actions))
error(2, err, "posix_spawn_file_actions_init() failed");
posix_spawn_file_actions_addclose(&actions, STDIN_FILENO);
posix_spawn_file_actions_addclose(&actions, cout_pipe[0]);
posix_spawn_file_actions_adddup2(&actions, cout_pipe[1], STDOUT_FILENO);
posix_spawn_file_actions_addclose(&actions, cout_pipe[1]);
pid_t pid;
if (int err = posix_spawnp(&pid, args[0], &actions, nullptr, args, environ))
error(2, err, "failed to run '%s'", args[0]);
if (int err = posix_spawn_file_actions_destroy(&actions))
error(2, err, "posix_spawn_file_actions_destroy() failed");
if (close(cout_pipe[1]) < 0)
error(2, errno, "closing write-side of pipe failed");
std::string results;
ssize_t bytes_read;
for (;;)
{
static char buffer[512];
bytes_read = read(cout_pipe[0], buffer, sizeof(buffer));
if (bytes_read > 0)
results.insert(results.end(), buffer, buffer + bytes_read);
else
break;
}
if (bytes_read < 0)
error(2, bytes_read, "failed to read from pipe");
if (cout_pipe[0] < 0)
error(2, errno, "closing read-side of pipe failed");
int exit_code = 0;
if (waitpid(pid, &exit_code, 0) == -1)
error(2, errno, "waitpid() failed");
if (exit_code)
error(2, 0, "'%s' exited with status %d", args[0], exit_code);
return results;
#else
// We could provide a pipe+fork+exec alternative implementation, but
// systems without posix_spawn() might also not have fork and exec.
// For instance MinGW does not. So let's fallback to system+tmpfile
// instead for maximum portability.
char prefix[30];
snprintf(prefix, sizeof prefix, "spot-tmp");
spot::temporary_file* tmpfile = spot::create_tmpfile(prefix);
std::string tmpname = tmpfile->name();
std::ostringstream cmd;
for (auto t = args; *t != nullptr; ++t)
spot::quote_shell_string(cmd, *t) << ' ';
cmd << '>';
spot::quote_shell_string(cmd, tmpfile->name());
std::string cmdstr = cmd.str();
int exit_code = system(cmdstr.c_str());
if (exit_code < 0)
error(2, errno, "failed to execute %s", cmdstr.c_str());
if (exit_code > 0)
error(2, 0, "'%s' exited with status %d", args[0], exit_code);
std::ifstream ifs(tmpname, std::ifstream::in);
if (!ifs)
error(2, 0, "failed to open %s (output of %s)", tmpname.c_str(), args[0]);
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::stringstream buffer;
buffer << ifs.rdbuf();
delete tmpfile;
return buffer.str();
#endif
}
std::atomic<bool> timed_out{false};
unsigned timeout_count = 0;
static unsigned timeout = 0;
#if ENABLE_TIMEOUT
static std::atomic<int> alarm_on{0};
static int child_pid = -1;
static void
sig_handler(int sig)
{
if (child_pid == 0)
error(2, 0, "received signal %d before starting child", sig);
if (sig == SIGALRM && alarm_on)
{
timed_out = true;
if (--alarm_on)
{
// Send SIGTERM to children.
kill(-child_pid, SIGTERM);
// Try again later if it didn't work. (alarm() will be reset
// if it did work and the call to wait() returns)
alarm(2);
}
else
{
// After a few gentle tries, really kill that child.
kill(-child_pid, SIGKILL);
}
}
else
{
// forward signal
kill(-child_pid, sig);
// cleanup files
spot::cleanup_tmpfiles();
// and die verbosely
error(2, 0, "received signal %d", sig);
}
}
void
setup_sig_handler()
{
struct sigaction sa;
sa.sa_handler = sig_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; // So that wait() doesn't get aborted by SIGALRM.
sigaction(SIGALRM, &sa, nullptr);
// Catch termination signals, so we can kill the subprocess.
sigaction(SIGHUP, &sa, nullptr);
sigaction(SIGINT, &sa, nullptr);
sigaction(SIGQUIT, &sa, nullptr);
sigaction(SIGTERM, &sa, nullptr);
}
static char*
get_arg(const char*& cmd)
{
const char* start = cmd;
std::string arg;
while (char c = *cmd)
{
switch (c)
{
// Those characters can have special meaning for the shell.
case '`':
case '~':
case '|':
case ';':
case '!':
case '?':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '$':
case '*':
case '&':
case '#':
case '\\':
case '>':
case '<':
case ' ':
case '\n':
case '\t':
goto end_loop;
case '\'':
{
char d = '\0';
while ((d = *++cmd))
{
if (d == '\'')
break;
arg.push_back(d);
}
if (d == '\0')
return nullptr;
}
break;
case '"':
{
int d = 0;
while ((d = *++cmd))
{
if (d == '\"')
break;
// Backslash can only be used to escape \, $, `, and "
if (d == '\\' && strchr("\\$`\"", *cmd))
d = *++cmd;
else if (strchr("\\$`", d))
return nullptr;
arg.push_back(d);
}
if (d == 0)
return nullptr;
}
break;
default:
arg.push_back(c);
break;
}
++cmd;
}
end_loop:
if (cmd == start) // Not the same as arg.empty()
return nullptr;
return strndup(arg.c_str(), arg.size());
}
static void
skip_ws(const char*& cmd)
{
while (isspace(*cmd))
++cmd;
}
// Commands are run via 'sh -c' so we get all the expressive power of
// the shell. However starting a shell for each translation is slow.
// To mitigate that, if the command to run is simple: we run it
// directly, bypassing the shell. Our definition of simple is:
// - a single command
// - can have single or double-quoted arguments
// - can have >stderr and <stdin redirection
// In particular, variable interpolation is not supported. Complex
// redirections (>& and such) are not support. Chains of commands
// (pipes, semi-colons, etc.) are not supported. Envvar definitions
// before the command are not supported.
struct simple_command
{
std::vector<char*> args;
char* stdin_filename = nullptr;
char* stdout_filename = nullptr;
simple_command(const simple_command& other) = delete;
simple_command& operator=(const simple_command& other) = delete;
simple_command() = default;
simple_command(simple_command&& other) = default;
void clear()
{
for (auto arg: args)
free(arg);
args.clear();
free(stdin_filename);
free(stdout_filename);
stdin_filename = nullptr;
stdout_filename = nullptr;
}
~simple_command()
{
clear();
}
};
static simple_command
parse_simple_command(const char* cmd)
{
simple_command res;
const char* start = cmd;
while (*cmd)
{
skip_ws(cmd);
switch (*cmd)
{
case '<':
{
if (cmd > start && isdigit(cmd[-1]))
goto use_shell;
++cmd;
skip_ws(cmd);
if (res.stdin_filename)
free(res.stdin_filename);
res.stdin_filename = get_arg(cmd);
if (res.stdin_filename == nullptr)
goto use_shell;
break;
}
case '>':
{
if (cmd > start && isdigit(cmd[-1]))
goto use_shell;
++cmd;
skip_ws(cmd);
if (res.stdout_filename)
free(res.stdout_filename);
res.stdout_filename = get_arg(cmd);
if (res.stdout_filename == nullptr)
goto use_shell;
break;
}
default:
{
char* tmp = get_arg(cmd);
if (tmp == nullptr)
goto use_shell;
res.args.push_back(tmp);
break;
}
}
}
// If result is empty, we failed to found the command; let's see if
// the shell is smarter. If the command contains '=', it's unlikely
// to be a command, but probably an environment variable definition
// as in
// FOO=1 command args..
if (res.args.empty() || strchr(res.args[0], '='))
goto use_shell;
res.args.push_back(nullptr);
return res;
use_shell:
res.clear();
return res;
}
#ifndef HAVE_SPAWN_H
static void
exec_command(const char* cmd)
{
simple_command res = parse_simple_command(cmd);
if (!res.args.empty())
{
if (res.stdin_filename)
{
int fd0 = open(res.stdin_filename, O_RDONLY, 0644);
if (fd0 < 0)
error(2, errno, "failed to open '%s'", res.stdin_filename);
if (dup2(fd0, STDIN_FILENO) < 0)
error(2, errno, "dup2() failed");
if (close(fd0) < 0)
error(2, errno, "close() failed");
}
if (res.stdout_filename)
{
int fd1 = creat(res.stdout_filename, 0644);
if (fd1 < 0)
error(2, errno, "failed to open '%s'", res.stdout_filename);
if (dup2(fd1, STDOUT_FILENO) < 0)
error(2, errno, "dup2() failed");
if (close(fd1) < 0)
error(2, errno, "close() failed");
}
execvp(res.args[0], res.args.data());
error(2, errno, "failed to run '%s'", res.args[0]);
SPOT_UNREACHABLE();
return;
}
// Try /bin/sh first, because it is faster to not do any PATH
// lookup.
static bool has_bin_sh = true;
if (has_bin_sh)
execl("/bin/sh", "sh", "-c", cmd, nullptr);
has_bin_sh = false;
execlp("sh", "sh", "-c", cmd, nullptr);
error(2, errno, "failed to run '%s' via 'sh'", cmd);
SPOT_UNREACHABLE();
return;
}
#endif
int
exec_with_timeout(const char* cmd)
{
int status;
timed_out = false;
#ifdef HAVE_SPAWN_H
simple_command res = parse_simple_command(cmd);
// Using posix_spawn should be preferred over fork()/exec(). It can
// be implemented in more systems. Since 2016, posix_spawn()
// should be faster than fork()/exec() on Linux. See also
// https://www.microsoft.com/en-us/research/publication/a-fork-in-the-road/
posix_spawnattr_t attr;
if (int err = posix_spawnattr_init(&attr))
error(2, err, "posix_spawnattr_init() failed");
if (int err = posix_spawnattr_setpgroup(&attr, 0))
error(2, err, "posix_spawnattr_setpgroup() failed");
if (int err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP))
error(2, err, "posix_spawnattr_setflags() failed");
posix_spawn_file_actions_t actions;
if (int err = posix_spawn_file_actions_init(&actions))
error(2, err, "posix_spawn_file_actions_init() failed");
// Close stdin so that children may not read our input. We had this
// nice surprise with Seminator, who greedily consumes its stdin
// (which was also ours) even if it does not use it because it was
// given a file.
if (int err = posix_spawn_file_actions_addclose(&actions, STDIN_FILENO))
error(2, err, "posix_spawn_file_actions_addclose() failed");
if (!res.args.empty())
{
if (res.stdin_filename)
if (int err = posix_spawn_file_actions_addopen(&actions, STDIN_FILENO,
res.stdin_filename,
O_RDONLY, 0644))
error(2, err, "posix_spawn_file_actions_addopen() failed");
if (res.stdout_filename)
if (int err = posix_spawn_file_actions_addopen(&actions, STDOUT_FILENO,
res.stdout_filename,
O_CREAT | O_WRONLY |
O_TRUNC, 0644))
error(2, err, "posix_spawn_file_actions_addopen() failed");
if (int err = posix_spawnp(&child_pid, res.args[0], &actions, &attr,
res.args.data(), environ))
error(2, err, "failed to run '%s'", res.args[0]);
}
else
{
// Try /bin/sh first, because it is faster to not do any PATH
// lookup.
static bool has_bin_sh = true;
if (has_bin_sh)
{
const char* args[] = { "/bin/sh", "-c", cmd, nullptr };
if (posix_spawn(&child_pid, args[0], &actions, &attr,
const_cast<char **>(args), environ))
has_bin_sh = false;
}
if (!has_bin_sh)
{
const char* args[] = { "sh", "-c", cmd, nullptr };
if (int err = posix_spawnp(&child_pid, args[0], &actions, &attr,
const_cast<char **>(args), environ))
error(2, err, "failed to run '%s' via 'sh'", cmd);
}
}
if (int err = posix_spawn_file_actions_destroy(&actions))
error(2, err, "posix_spawn_file_actions_destroy() failed");
if (int err = posix_spawnattr_destroy(&attr))
error(2, err, "posix_spawnattr_destroy() failed");
#else
child_pid = fork();
if (child_pid == -1)
error(2, errno, "failed to fork()");
if (child_pid == 0)
{
setpgid(0, 0);
// Close stdin so that children may not read our input. We had
// this nice surprise with Seminator, who greedily consumes its
// stdin (which was also ours) even if it does not use it
// because it was given a file.
close(STDIN_FILENO);
exec_command(cmd);
// never reached
return -1;
}
#endif
alarm(timeout);
// Upon SIGALRM, the child will receive up to 3
// signals: SIGTERM, SIGTERM, SIGKILL.
alarm_on = 3;
int w = waitpid(child_pid, &status, 0);
alarm_on = 0;
if (w == -1)
error(2, errno, "error during wait()");
alarm(0);
return status;
}
#endif // ENABLE_TIMEOUT
enum {
OPT_LIST = 1,
OPT_RELABEL = 2,
};
static const argp_option options[] =
{
/**************************************************/
{ nullptr, 0, nullptr, 0, "Specifying translators to call:", 2 },
{ "translator", 't', "COMMANDFMT", 0,
"register one translator to call", 0 },
{ "timeout", 'T', "NUMBER", 0, "kill translators after NUMBER seconds", 0 },
{ "list-shorthands", OPT_LIST, nullptr, 0,
"list availabled shorthands to use in COMMANDFMT", 0},
{ "relabel", OPT_RELABEL, nullptr, 0,
"always relabel atomic propositions before calling any translator", 0 },
/**************************************************/
{ nullptr, 0, nullptr, 0,
"COMMANDFMT should specify input and output arguments using the "
"following character sequences:", 3 },
{ "%f,%s,%l,%w", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the formula as a (quoted) string in Spot, Spin, LBT, or Wring's syntax",
0 },
{ "%F,%S,%L,%W", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the formula as a file in Spot, Spin, LBT, or Wring's syntax", 0 },
{ "%O", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the automaton output in HOA, never claim, LBTT, or ltl2dstar's "
"format", 0 },
{ "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, "a single %", 0 },
{ nullptr, 0, nullptr, 0,
"If either %l, %L, or %T are used, any input formula that does "
"not use LBT-style atomic propositions (i.e. p0, p1, ...) will be "
"relabeled automatically. Likewise if %s or %S are used with "
"atomic proposition that compatible with Spin's syntax. You can "
"force this relabeling to always occur with option --relabel.\n"
"The sequences %f,%s,%l,%w,%F,%S,%L,%W can optionally be \"infixed\""
" by a bracketed sequence of operators to unabbreviate before outputing"
" the formula. For instance %[MW]f will rewrite operators M and W"
" before outputing it.\n"
"Furthermore, if COMMANDFMT has the form \"{NAME}CMD\", then only CMD "
"will be passed to the shell, and NAME will be used to name the tool "
"in the output.", 4 },
{ nullptr, 0, nullptr, 0, nullptr, 0 }
};
bool opt_relabel = false;
static int parse_opt_trans(int key, char* arg, struct argp_state*)
{
// Called from C code, so should not raise any exception.
BEGIN_EXCEPTION_PROTECT;
switch (key)
{
case 't':
tools_push_trans(arg);
break;
case 'T':
timeout = to_pos_int(arg, "-T/--timeout");
#if !ENABLE_TIMEOUT
std::cerr << "warning: setting a timeout is not supported "
<< "on your platform" << std::endl;
#endif
break;
case OPT_LIST:
show_shorthands(std::begin(shorthands_ltl), std::end(shorthands_ltl));
std::cout
<< ("\nAny {name} and directory component is skipped for the purpose "
"of\nmatching those prefixes. So for instance\n "
"'{DRA} ~/mytools/ltl2dstar-0.5.2'\n"
"will be changed into\n "
"'{DRA} ~/mytools/ltl2dstar-0.5.2 --output-format=hoa %[MW]L %O'"
"\n");
exit(0);
case OPT_RELABEL:
opt_relabel = true;
break;
default:
return ARGP_ERR_UNKNOWN;
}
END_EXCEPTION_PROTECT;
return 0;
}
const struct argp trans_argp = { options, parse_opt_trans, nullptr, nullptr,
nullptr, nullptr, nullptr };
static const argp_option options_aut[] =
{
/**************************************************/
{ nullptr, 0, nullptr, 0, "Specifying tools to call:", 2 },
{ "tool", 't', "COMMANDFMT", 0,
"register one tool to call", 0 },
{ "timeout", 'T', "NUMBER", 0, "kill tools after NUMBER seconds", 0 },
{ "list-shorthands", OPT_LIST, nullptr, 0,
"list availabled shorthands to use in COMMANDFMT", 0},
/**************************************************/
{ nullptr, 0, nullptr, 0,
"COMMANDFMT should specify input and output arguments using the "
"following character sequences:", 3 },
{ "%H,%S,%L", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"filename for the input automaton in (H) HOA, (S) Spin's neverclaim, "
"or (L) LBTT's format", 0 },
{ "%M, %[val]M", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the name of the input automaton, with an optional default value", 0 },
{ "%O", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"filename for the automaton output in HOA, never claim, LBTT, or "
"ltl2dstar's format", 0 },
{ "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, "a single %", 0 },
{ nullptr, 0, nullptr, 0, nullptr, 0 }
};
static int parse_opt_autproc(int key, char* arg, struct argp_state*)
{
switch (key)
{
case 't':
tools_push_autproc(arg);
break;
case 'T':
timeout = to_pos_int(arg, "-T/--timeout");
#if !ENABLE_TIMEOUT
std::cerr << "warning: setting a timeout is not supported "
<< "on your platform" << std::endl;
#endif
break;
case OPT_LIST:
show_shorthands(std::begin(shorthands_autproc),
std::end(shorthands_autproc));
std::cout
<< ("\nAny {name} and directory component is skipped for the purpose "
"of\nmatching those prefixes. So for instance\n "
"'{AF} ~/mytools/autfilt-2.4 --remove-fin'\n"
"will be changed into\n "
"'{AF} ~/mytools/autfilt-2.4 --remove-fin %H>%O'\n");
exit(0);
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
const struct argp autproc_argp = { options_aut, parse_opt_autproc, nullptr,
nullptr, nullptr, nullptr, nullptr };