aboutsummaryrefslogtreecommitdiff
path: root/gfsm
diff options
context:
space:
mode:
authorBryan Jurish <mukau@users.sourceforge.net>2006-02-02 12:49:19 +0000
committerBryan Jurish <mukau@users.sourceforge.net>2006-02-02 12:49:19 +0000
commit0727bfcaf2bd48bf501a7fa95515c400a1996902 (patch)
tree81a3774a9601ba1242482696344f3de3e08f8f22 /gfsm
parent6a4001a8538862ac02714a03fedd07c3b6f79366 (diff)
initial cvs import
svn path=/trunk/externals/moocow/; revision=4536
Diffstat (limited to 'gfsm')
-rw-r--r--gfsm/COPYING290
-rw-r--r--gfsm/Changes9
-rw-r--r--gfsm/Makefile.am98
-rw-r--r--gfsm/README.cvs13
-rw-r--r--gfsm/README.pod60
-rwxr-xr-xgfsm/autogen.sh48
-rw-r--r--gfsm/config/Makefile.am66
-rw-r--r--gfsm/configure.in233
-rw-r--r--gfsm/src/Makefile.am152
-rw-r--r--gfsm/src/atom_alphabet.c139
-rw-r--r--gfsm/src/atom_alphabet.h80
-rw-r--r--gfsm/src/gfsm-help.pd15
-rw-r--r--gfsm/src/gfsm-help.tfst3
-rw-r--r--gfsm/src/gfsm_alphabet-help.pd64
-rw-r--r--gfsm/src/gfsm_automaton-help.pd288
-rw-r--r--gfsm/src/gfsm_markov-help.pd68
-rw-r--r--gfsm/src/gfsm_markov.pd414
-rw-r--r--gfsm/src/gfsm_state-help.pd55
-rw-r--r--gfsm/src/lkpin.tfst4
-rw-r--r--gfsm/src/lkptest.tfst8
-rw-r--r--gfsm/src/pd_algebra.c299
-rw-r--r--gfsm/src/pd_alphabet.c494
-rw-r--r--gfsm/src/pd_alphabet.h78
-rw-r--r--gfsm/src/pd_automaton.c765
-rw-r--r--gfsm/src/pd_automaton.h85
-rw-r--r--gfsm/src/pd_gfsm.c93
-rw-r--r--gfsm/src/pd_gfsm.h54
-rw-r--r--gfsm/src/pd_io.c75
-rw-r--r--gfsm/src/pd_io.h47
-rw-r--r--gfsm/src/pd_state.c303
-rw-r--r--gfsm/src/pd_state.h58
-rw-r--r--gfsm/src/test-alphabet.pd3
-rw-r--r--gfsm/src/test-alphabet2.pd44
-rw-r--r--gfsm/src/test-automaton.pd260
-rw-r--r--gfsm/src/test-automaton2.pd196
-rw-r--r--gfsm/src/test-fsm.pd2
-rw-r--r--gfsm/src/test-markov.pd211
-rw-r--r--gfsm/src/test-state.pd427
-rw-r--r--gfsm/src/test-state2.pd415
-rw-r--r--gfsm/src/test.lab5
-rw-r--r--gfsm/src/test.tfst3
-rw-r--r--gfsm/src/test2.lab6
-rw-r--r--gfsm/src/test2.tfst4
-rw-r--r--gfsm/src/test3.tfst4
44 files changed, 6038 insertions, 0 deletions
diff --git a/gfsm/COPYING b/gfsm/COPYING
new file mode 100644
index 0000000..fa0bef4
--- /dev/null
+++ b/gfsm/COPYING
@@ -0,0 +1,290 @@
+GNU GENERAL PUBLIC LICENSE
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 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.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom
+to share and change it. By contrast, the GNU General Public License is
+intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This General
+Public License applies to most of the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+(Some other Free Software Foundation software is covered by the
+GNU Library General Public License instead.) You can apply it to your
+programs, too.
+
+When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free
+programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone
+to deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis
+or for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And
+you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on,
+we want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.
+We wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program
+proprietary. To prevent this, we have made it clear that any patent must
+be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+TERMS AND CONDITIONS FOR
+COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a
+notice placed by the copyright holder saying it may be distributed under
+the terms of this General Public License. The "Program", below, refers
+to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it, either
+verbatim or with modifications and/or translated into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of running
+the Program is not restricted, and the output from the Program is
+covered only if its contents constitute a work based on the Program
+(independent of having been made by running the Program). Whether
+that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's
+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 give
+any other recipients of the Program a copy of this License along with the
+Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but does
+ not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program, 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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the
+Program with the Program (or with a work based on the Program) on a
+volume of a storage or distribution medium does not bring the other
+work under the scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) 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; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your cost
+ of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a
+ medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with
+ such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, 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 executable. However, as a special
+exception, the source code 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.
+
+If distribution of executable or 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 counts as distribution of the source
+code, even though third parties are not compelled to copy the source
+along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt otherwise
+to copy, modify, sublicense or distribute the Program 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.
+
+5. 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 Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and all
+its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program 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 to this License.
+
+7. 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 Program at all. For example, if a patent license would not
+permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program 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.
+
+9. The Free Software Foundation may publish revised and/or new
+versions of the 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 Program
+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 Program does not specify a version number
+of this License, you may choose any version ever published by the Free
+Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF
+CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM,
+TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "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 PROGRAM IS WITH YOU. SHOULD
+THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE
+COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE
+WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
+OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
diff --git a/gfsm/Changes b/gfsm/Changes
new file mode 100644
index 0000000..082742a
--- /dev/null
+++ b/gfsm/Changes
@@ -0,0 +1,9 @@
+Change log for PD external 'pd-gfsm'
+
+v0.02 Tue, 21 Sep 2004 01:30:45 +0200
+ + added 'arc_seek' message to gfsm_state
+ + added 'add_weight' message to gfsm_state
+ + began work on 'gfsm_markov.pd'
+
+v0.01 Mon, 13 Sep 2004 11:11:43 +0200
+ + initial version
diff --git a/gfsm/Makefile.am b/gfsm/Makefile.am
new file mode 100644
index 0000000..4983beb
--- /dev/null
+++ b/gfsm/Makefile.am
@@ -0,0 +1,98 @@
+# File: ./Makefile.am
+# Package: pd-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
+
+## --- pseudo-deps for '.SUFFIXES'
+SUFFIXES = .pod .txt
+
+#-----------------------------------------------------------------------
+# 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 = *~ \
+ $(PODS:.pod=.txt) \
+ Makefile Makefile.in \
+ aclocal.m4 \
+ configure \
+ install-sh \
+ stamp-h.in \
+ config.h.in
+
+maintainer-clean-local:
+ rm -rf autom4te.cache
+
+#CVSCLEAN_SUBDIRS = $(SUBDIRS)
+
+#CVSCLEANFILES = Makefile.in Makefile
+
+
+#-----------------------------------------------------------------------
+# Additional Variables & Rules: PODS
+#-----------------------------------------------------------------------
+PODS = README.pod
+
+.pod.txt:
+ pod2text $< $@
+
+all-local: $(PODS:.pod=.txt)
+
+#-----------------------------------------------------------------------
+# Variables: distribution
+#-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ $(PODS:.pod=.txt) autogen.sh configure \
+ README.cvs 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/README.cvs b/gfsm/README.cvs
new file mode 100644
index 0000000..2a0ee0c
--- /dev/null
+++ b/gfsm/README.cvs
@@ -0,0 +1,13 @@
+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.
+
+marmosets,
+ Bryan
diff --git a/gfsm/README.pod b/gfsm/README.pod
new file mode 100644
index 0000000..1155c8c
--- /dev/null
+++ b/gfsm/README.pod
@@ -0,0 +1,60 @@
+=pod
+
+README for pd external package 'gfsm'
+
+Last updated for pd-gfsm v0.04
+
+=head1 DESCRIPTION
+
+pd-gfsm provides Pd bindings for the GFSM finite-state machine library.
+
+=head1 PREREQUISITES
+
+=over 4
+
+=item Pd
+
+Available from http://crca.ucsd.edu/~msp/software.html
+
+=item libgfsm >= v0.0.8-pre6
+
+Available from http://www.ling.uni-potsdam.de/~moocow/projects/gfsm
+
+=back
+
+=head1 INSTALLATION
+
+Issue the following commands to the shell:
+
+ cd DISTNAME-X.YY (or wherever you extracted the distribution)
+ ./configure
+ make
+ make install
+
+=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
+
+=head1 ACKNOWLEDGEMENTS
+
+PD by Miller Puckette and others.
+
+Ideas, black magic, and other nuggets of information drawn
+from code by Guenter Geiger, Larry Troxler, and iohannes m zmoelnig.
+
+=head1 KNOWN BUGS
+
+None known.
+
+=head1 AUTHOR
+
+Bryan Jurish E<lt>moocow@ling.uni-potsdam.deE<gt>
diff --git a/gfsm/autogen.sh b/gfsm/autogen.sh
new file mode 100755
index 0000000..845f276
--- /dev/null
+++ b/gfsm/autogen.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+#-----------------------------------------------------------------------
+# File: autogen.sh
+# Description:
+# + wrapper for m4 black-magic
+#-----------------------------------------------------------------------
+
+MY_ALDIRS="."
+MY_AHDIRS="."
+MY_AMDIRS="."
+MY_ACDIRS="."
+
+test -z "$ACLOCAL" && ACLOCAL=aclocal
+test -z "$AUTOHEADER" && AUTOHEADER=autoheader
+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_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/config/Makefile.am b/gfsm/config/Makefile.am
new file mode 100644
index 0000000..45bdb79
--- /dev/null
+++ b/gfsm/config/Makefile.am
@@ -0,0 +1,66 @@
+## 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 \
+ mkinstalldirs \
+ texinfo.tex \
+ ylwrap
+
+
+##-----------------------------------------------------------------------
+## Variables: distribution
+##-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ Makefile.in \
+ depcomp \
+ install-sh \
+ mkinstalldirs \
+ missing
+
+# 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/configure.in b/gfsm/configure.in
new file mode 100644
index 0000000..ea900a0
--- /dev/null
+++ b/gfsm/configure.in
@@ -0,0 +1,233 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl -- adapted from 'configure.in' in ggee distribution by Guenter Geiger
+AC_PREREQ(2.5)
+
+dnl Some handy macros
+define([THE_PACKAGE_NAME], [pd-gfsm])
+define([THE_PACKAGE_VERSION], [0.04])
+define([THE_PACKAGE_AUTHOR], [moocow@ling.uni-potsdam.de])
+
+AC_INIT(THE_PACKAGE_NAME, THE_PACKAGE_VERSION, THE_PACKAGE_AUTHOR)
+
+dnl
+dnl source & aux
+dnl
+AC_CONFIG_AUX_DIR(config)
+
+dnl
+dnl save user's CFLAGS,CPPFLAGS
+dnl
+UCPPFLAGS="$CPPFLAGS"
+UCFLAGS="$CFLAGS"
+#UCXXFLAGS="$CXXFLAGS"
+
+dnl
+dnl use automake
+dnl
+AM_INIT_AUTOMAKE(THE_PACKAGE_NAME, THE_PACKAGE_VERSION)
+
+dnl
+dnl use autoheader
+dnl
+AM_CONFIG_HEADER([src/config.h])
+
+dnl
+dnl Programs, prefix
+dnl
+AC_PROG_CC
+dnl AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PREFIX_DEFAULT(/usr/local)
+
+dnl
+dnl Substitutions
+dnl
+AC_SUBST(DEFS)
+AC_SUBST(AFLAGS)
+AC_SUBST(DFLAGS)
+AC_SUBST(IFLAGS)
+AC_SUBST(LFLAGS)
+AC_SUBST(OFLAGS)
+AC_SUBST(WFLAGS)
+AC_SUBST(LD)
+AC_SUBST(PDEXT)
+
+dnl version stuff (automatically exported?)
+AC_SUBST(PACKAGE_VERSION)
+AC_SUBST(PACKAGE_NAME)
+AC_SUBST(BUGREPORT)
+
+
+dnl
+dnl pd-directory/ies
+dnl
+AC_ARG_WITH(pd-dir,
+ AC_HELP_STRING([--with-pd-dir=DIR], [PD base directory (default=/usr/local/pd)]),
+ [pddir="$withval"],
+ [pddir="/usr/local/pd"])
+pddocdir="${pddir}/doc/5.reference"
+AC_SUBST(pddir)
+AC_SUBST(pddocdir)
+
+AC_ARG_WITH(pd-include,
+ AC_HELP_STRING([--with-pd-include=DIR], [PD include directory (default=${PD_DIR}/src)]),
+ [pdincludedir="$withval"],
+ [pdincludedir="${PD_DIR}/src"])
+AC_SUBST(pdincludedir)
+
+AC_ARG_WITH(pd-extdir,
+ AC_HELP_STRING([--with-pd-extdir=DIR], [Directory for PD externals (default=PDDIR/externs)]),
+ [pdexternsdir="$withval"],
+ [pdexternsdir="$pddir/externs"])
+AC_SUBST(pdexternsdir)
+
+dnl
+dnl Check for m_pd.h
+dnl
+CPPFLAGS="$CPPFLAGS $IFLAGS"
+AC_CHECK_HEADER(m_pd.h,[],
+ AC_MSG_WARN([-----------------------------------------------------------------])
+ AC_MSG_WARN([could not find PD header file 'm_pd.h' -- things might get ugly.])
+ AC_MSG_WARN([-----------------------------------------------------------------]),
+ [/* nonempty includes: compile only */])
+
+dnl
+dnl debug version?
+dnl
+AC_MSG_CHECKING([whether we are building a 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)
+ DEBUG="yes"
+ DFLAGS="$DFLAGS -DDEBUG"
+else
+ AC_MSG_RESULT(no)
+ DEBUG="no"
+fi
+AC_SUBST(DEBUG)
+
+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
+## gfsm (pkg-config)
+PKG_CHECK_MODULES(GFSM, gfsm >= 0.0.8,
+ [PC_HAVE_GFSM="yes"],
+ [PC_HAVE_GFSM=""])
+
+if test "$PC_HAVE_GFSM" != "yes" ; then
+ AC_MSG_WARN([])
+ AC_MSG_WARN([----------------------------------------------------------------])
+ AC_MSG_WARN([ gfsm library not found!])
+ AC_MSG_WARN([])
+ AC_MSG_WARN([ Is the directory containing gfsm.pc in your])
+ AC_MSG_WARN([ 'PKG_CONFIG_PATH' environment variable?])
+ AC_MSG_WARN([----------------------------------------------------------------])
+ AC_MSG_WARN([])
+ ac_cv_enable_gfsm="no"
+else
+ ac_cv_enable_gfsm="yes"
+fi
+
+if test "$ac_cv_enable_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`"
+fi
+## /gfsm
+##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+dnl --------------------------------------------------------------------
+dnl BEGIN import from pd configure.in
+dnl --------------------------------------------------------------------
+dnl
+dnl machine-dependent variables
+dnl
+LD=ld
+if test `uname -s` = Linux;
+then
+ LFLAGS="-export_dynamic -shared"
+ if test "$DEBUG" == "no"; then
+ #OFLAGS="-O6 -funroll-loops -fomit-frame-pointer -finline-limit-10000000"
+ #OFLAGS="-O6 -funroll-loops -fomit-frame-pointer"
+ OFLAGS="-O3"
+ else
+ OFLAGS="-g"
+ fi
+ PDEXT=pd_linux
+fi
+
+if test `uname -m` = alpha;
+then
+ AFLAGS="-mieee -mcpu=ev56";
+ OFLAGS="$CFLAGS"
+fi
+
+if test `uname -s` = IRIX64;
+then
+ LFLAGS="-n32 -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -shared -rdata_shared"
+ OFLAGS="$CFLAGS"
+ PDEXT=pd_irix6
+fi
+
+if test `uname -s` = IRIX32;
+then
+ LFLAGS="-o32 -DUNIX -DIRIX -O2 -shared -rdata_shared"
+ OFLAGS="$CFLAGS"
+ PDEXT=pd_irix5
+fi
+
+dnl
+dnl Flags for MacOSX, borrowed from pd-0.35-test16
+dnl
+if test `uname -s` = Darwin;
+then
+ LD=cc
+ LFLAGS="-bundle -undefined suppress -flat_namespace"
+ PDEXT=pd_darwin
+ DFLAGS="$DFLAGS -DMACOSX"
+
+ if test "$DEBUG" == "no"; then
+ OFLAGS="-O2"
+ else
+ OFLAGS="-g"
+ fi
+fi
+dnl --------------------------------------------------------------------
+dnl END import from pd configure.in
+dnl --------------------------------------------------------------------
+
+dnl
+dnl restore user's CFLAGS
+dnl
+CFLAGS="$UCFLAGS"
+CPPFLAGS="$UCPPFLAGS"
+#CXXFLAGS="$UCXXFLAGS"
+
+AC_OUTPUT(config/Makefile src/Makefile Makefile)
diff --git a/gfsm/src/Makefile.am b/gfsm/src/Makefile.am
new file mode 100644
index 0000000..05d3eda
--- /dev/null
+++ b/gfsm/src/Makefile.am
@@ -0,0 +1,152 @@
+# File: ./src/Makefile.am
+# Package: pd-gfsm
+# Description:
+# + src-level automake file
+#
+# Process this file with Automake to create Makefile.in.
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# Options & Subdirectories
+#-----------------------------------------------------------------------
+
+## --- recursion subdirectories
+#SUBDIRS =
+
+## --- pseudo-deps for '.SUFFIXES'
+SUFFIXES = .@PDEXT@
+
+#-----------------------------------------------------------------------
+# Flags and variables
+#-----------------------------------------------------------------------
+PDEXT = @PDEXT@
+EXEEXT = .@PDEXT@
+
+#-----------------------------------------------------------------------
+# pd externals (hacked _PROGRAMS target)
+#-----------------------------------------------------------------------
+
+## --- externals
+pdexterns_PROGRAMS = gfsm
+
+## --- patches
+pdexterns_DATA = \
+ gfsm_markov.pd
+
+## --- documentation
+pddoc_DATA = \
+ gfsm-help.pd \
+ gfsm_alphabet-help.pd \
+ gfsm_automaton-help.pd \
+ gfsm_state-help.pd \
+ gfsm_markov-help.pd
+
+#-----------------------------------------------------------------------
+# sources
+#-----------------------------------------------------------------------
+
+gfsm_SOURCES = \
+ config.h \
+ atom_alphabet.h atom_alphabet.c \
+ pd_alphabet.h pd_alphabet.c \
+ \
+ pd_automaton.h pd_automaton.c \
+ pd_algebra.c \
+ \
+ pd_state.h pd_state.c \
+ \
+ pd_io.h pd_io.c \
+ \
+ pd_gfsm.h pd_gfsm.c
+
+
+#----------------------------------------------------------------------
+# external compilation : flags
+#-----------------------------------------------------------------------
+DEFS = @DEFS@
+AFLAGS = @AFLAGS@
+DFLAGS = @DFLAGS@
+IFLAGS = @IFLAGS@
+LFLAGS = @LFLAGS@
+OFLAGS = @OFLAGS@
+WFLAGS = -Wall
+
+AM_CPPFLAGS = $(IFLAGS) $(DFLAGS)
+AM_CFLAGS = $(OFLAGS) $(WFLAGS) $(AFLAGS)
+AM_CXXFLAGS = $(OFLAGS) $(WFLAGS) $(AFLAGS)
+
+gfsm_LDFLAGS = $(LFLAGS)
+#gfsm_LDADD =
+
+#-----------------------------------------------------------------------
+# additional hacks
+#-----------------------------------------------------------------------
+#(none)
+
+#-----------------------------------------------------------------------
+# Variables: cleanup
+#-----------------------------------------------------------------------
+## --- mostlyclean: built by 'make' & commonly rebuilt
+#MOSTLYCLEANFILES =
+
+## --- clean: built by 'make'
+CLEANFILES = *$(EXEEXT)
+
+## --- distclean: built by 'configure'
+DISTCLEANFILES = \
+ config.log \
+ config.cache \
+ config.status
+
+## -- maintainerclean: built by maintainer / by hand
+MAINTAINERCLEANFILES = *~ \
+ $(PODS:.pod=.txt) \
+ Makefile Makefile.in \
+ aclocal.m4 \
+ configure \
+ install-sh \
+ stamp-h.in \
+ config.h.in
+
+maintainer-clean-local:
+ rm -rf autom4te.cache
+
+#CVSCLEAN_SUBDIRS = $(SUBDIRS)
+
+#CVSCLEANFILES = Makefile.in Makefile
+
+
+#-----------------------------------------------------------------------
+# Variables: distribution
+#-----------------------------------------------------------------------
+
+## --- extra distribution files
+EXTRA_DIST = \
+ $(pddoc_DATA) \
+ $(pdexterns_DATA)
+
+
+## --- 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/src/atom_alphabet.c b/gfsm/src/atom_alphabet.c
new file mode 100644
index 0000000..16f4bdd
--- /dev/null
+++ b/gfsm/src/atom_alphabet.c
@@ -0,0 +1,139 @@
+/*=============================================================================*\
+ * File: atom_alphabet.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd: atom alphabet
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#include <atom_alphabet.h>
+#include <string.h>
+
+/*======================================================================
+ * constants
+ */
+gfsmUserAlphabetMethods pd_atom_alphabet_methods =
+ {
+ NULL, //-- key->label lookup function
+ NULL, //-- label->key lookup function
+ NULL, //-- insertion function: receives a newly copied key!
+ NULL, //-- label removal function
+ (gfsmAlphabetKeyReadFunc)gfsm_pd_atom_read, //-- key input function
+ (gfsmAlphabetKeyWriteFunc)gfsm_pd_atom_write //-- key output function
+ };
+
+/*======================================================================
+ * gfsmPdAtomAlphabet: user methods
+ */
+
+
+/*--------------------------------------------------------------
+ * hash()
+ */
+guint gfsm_pd_atom_hash(t_atom *a)
+{
+ if (!a) return 0;
+ switch (a->a_type) {
+ case A_FLOAT: return (guint)(a->a_w.w_float);
+ case A_SYMBOL: return (guint)(a->a_w.w_symbol);
+ case A_SEMI: return (guint)';';
+ case A_COMMA: return (guint)',';
+ default: return 0;
+ }
+ return 0; //-- never reached
+}
+
+/*--------------------------------------------------------------
+ * equal()
+ */
+gboolean gfsm_pd_atom_equal(t_atom *a1, t_atom *a2)
+{
+ if (a1->a_type != a2->a_type) return FALSE;
+ switch (a1->a_type) {
+ case A_FLOAT: return a1->a_w.w_float == a2->a_w.w_float;
+ case A_SYMBOL: return a1->a_w.w_symbol == a2->a_w.w_symbol;
+ default: return memcmp(a1,a2,sizeof(t_atom))==0;
+ }
+}
+
+/*--------------------------------------------------------------
+ * dup()
+ */
+t_atom *gfsm_pd_atom_dup(gfsmPdAtomAlphabet *alph, t_atom *a)
+{
+ //return (a ? copybytes(a, sizeof(t_atom)) : NULL);
+ return (a ? gfsm_mem_dup_n(a,sizeof(t_atom)) : NULL);
+}
+
+/*--------------------------------------------------------------
+ * free()
+ */
+void gfsm_pd_atom_free(t_atom *a)
+{ g_free(a); }
+
+/*--------------------------------------------------------------
+ * read()
+ */
+t_atom *gfsm_pd_atom_read(gfsmPdAtomAlphabet *alph, GString *gstr)
+{
+ binbuf_clear(alph->aa_binbuf);
+ binbuf_text(alph->aa_binbuf, gstr->str, gstr->len);
+ return binbuf_getvec(alph->aa_binbuf);
+}
+
+/*--------------------------------------------------------------
+ * write()
+ */
+void gfsm_pd_atom_write(gfsmPdAtomAlphabet *alph, t_atom *a, GString *gstr)
+{
+ atom_string(a, alph->aa_strbuf, PdGfsmStrBufSize);
+ g_string_assign(gstr, alph->aa_strbuf);
+}
+
+/*======================================================================
+ * gfsmPdAtomAlphabet: shortcuts
+ */
+
+/*--------------------------------------------------------------
+ * new
+ */
+gfsmPdAtomAlphabet *gfsm_pd_atom_alphabet_new(void)
+{
+ gfsmPdAtomAlphabet *alph = g_new0(gfsmPdAtomAlphabet,1);
+ ((gfsmAlphabet*)alph)->type = gfsmATUser;
+ gfsm_user_alphabet_init((gfsmUserAlphabet*)alph,
+ (gfsmAlphabetKeyDupFunc)gfsm_pd_atom_dup,
+ (GHashFunc)gfsm_pd_atom_hash,
+ (GEqualFunc)gfsm_pd_atom_equal,
+ (GDestroyNotify)gfsm_pd_atom_free,
+ NULL,
+ &pd_atom_alphabet_methods);
+ alph->aa_binbuf = binbuf_new();
+ return alph;
+}
+
+//-- destructor
+void gfsm_pd_atom_alphabet_free(gfsmPdAtomAlphabet *alph)
+{
+ if (alph->aa_binbuf) binbuf_free(alph->aa_binbuf);
+ gfsm_alphabet_free((gfsmAlphabet*)alph);
+}
diff --git a/gfsm/src/atom_alphabet.h b/gfsm/src/atom_alphabet.h
new file mode 100644
index 0000000..262ea2c
--- /dev/null
+++ b/gfsm/src/atom_alphabet.h
@@ -0,0 +1,80 @@
+/*=============================================================================*\
+ * File: atom_alphabet.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd: atom alphabet
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifndef _PD_GFSM_ATOM_ALPHABET_H
+#define _PD_GFSM_ATOM_ALPHABET_H
+
+#include <m_pd.h>
+#include <gfsm.h>
+
+/*--------------------------------------------------------------
+ * Constants
+ */
+#define PdGfsmStrBufSize 256
+
+extern gfsmUserAlphabetMethods pd_atom_alphabet_methods;
+
+/*--------------------------------------------------------------
+ * Types: gfsmPdAtomAlphabet
+ */
+typedef struct {
+ gfsmUserAlphabet aa_alph;
+ t_binbuf *aa_binbuf;
+ char aa_strbuf[PdGfsmStrBufSize];
+} gfsmPdAtomAlphabet;
+
+/*--------------------------------------------------------------
+ * gfsmPdAtomAlphabet: user methods
+ */
+//-- hash function for pd atoms
+guint gfsm_pd_atom_hash(t_atom *a);
+
+//-- equality check for pd atoms
+gboolean gfsm_pd_atom_equal(t_atom *a1, t_atom *a2);
+
+//-- dup function for pd atoms
+t_atom *gfsm_pd_atom_dup(gfsmPdAtomAlphabet *alph, t_atom *a);
+
+//-- free function for pd atoms
+void gfsm_pd_atom_free(t_atom *a);
+
+//-- string read function for pd atoms
+t_atom *gfsm_pd_atom_read(gfsmPdAtomAlphabet *alph, GString *gstr);
+
+//-- string write function for pd atoms
+void gfsm_pd_atom_write(gfsmPdAtomAlphabet *alph, t_atom *a, GString *gstr);
+
+/*--------------------------------------------------------------
+ * gfsmPdAtomAlphabet: utilities
+ */
+//-- constructor
+gfsmPdAtomAlphabet *gfsm_pd_atom_alphabet_new(void);
+
+//-- destructor
+void gfsm_pd_atom_alphabet_free(gfsmPdAtomAlphabet *alph);
+
+#endif /* _PD_GFSM_ATOM_ALPHABET_H */
diff --git a/gfsm/src/gfsm-help.pd b/gfsm/src/gfsm-help.pd
new file mode 100644
index 0000000..c91aa46
--- /dev/null
+++ b/gfsm/src/gfsm-help.pd
@@ -0,0 +1,15 @@
+#N canvas 0 0 430 269 10;
+#X obj 66 7 gfsm;
+#X text 126 232 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 21 43 EXTERNALS:;
+#X obj 41 72 gfsm_alphabet;
+#X obj 41 98 gfsm_automaton;
+#X text 159 71 integer <-> atom mapping;
+#X obj 41 124 gfsm_state;
+#X text 161 125 automaton position;
+#X text 160 98 weighted finite state machine;
+#X text 21 184 SEE ALSO:;
+#X text 38 201 gfsmutils(1);
+#X text 99 8 : finite state machine external library;
+#X obj 40 150 gfsm_markov;
+#X text 161 151 trainable Markov chain;
diff --git a/gfsm/src/gfsm-help.tfst b/gfsm/src/gfsm-help.tfst
new file mode 100644
index 0000000..67e2bea
--- /dev/null
+++ b/gfsm/src/gfsm-help.tfst
@@ -0,0 +1,3 @@
+0 2 42 24 0.7
+0 1 2 3 4
+1 0
diff --git a/gfsm/src/gfsm_alphabet-help.pd b/gfsm/src/gfsm_alphabet-help.pd
new file mode 100644
index 0000000..b3d6653
--- /dev/null
+++ b/gfsm/src/gfsm_alphabet-help.pd
@@ -0,0 +1,64 @@
+#N canvas 16 0 646 547 10;
+#X text 289 523 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 9 524 SEE ALSO:;
+#X text 9 69 INLETS:;
+#X text 27 83 1 - control messages;
+#X text 244 68 OUTLETS:;
+#X obj 80 525 gfsm;
+#X text 48 48 NAME - symbolic name of the alphabet;
+#X text 260 81 1 - value outlet;
+#X text 260 96 2 - bang on missing value;
+#X text 14 31 SYNTAX: gfsm_alphabet [NAME];
+#X obj 13 493 print CHAR;
+#X obj 197 492 print ATOM;
+#X msg 29 182 insert x 1;
+#X text 163 185 "insert ATOM CHAR" : map ATOM<->CHAR;
+#X msg 33 203 insert y;
+#X text 198 203 "insert ATOM" : map ATOM to a new character label;
+#X msg 48 232 atom2char x;
+#X text 177 233 "atom2char ATOM" : lookup character label for ATOM
+;
+#X text 170 253 "atom2char! ATOM" : lookup or insert label for ATOM
+;
+#X text 184 284 "char2atom INT" : lookup atom for label INT;
+#X text 177 301 "char2atom! INT" : lookup or insert atom for INT;
+#X msg 63 281 char2atom 1;
+#X msg 65 301 char2atom! 42;
+#X msg 52 252 atom2char! foo;
+#X text 184 129 "alphabet NAME" : sets current alphabet;
+#X msg 19 151 alphabet;
+#X text 219 145 "alphabet" : use private alphabet;
+#X text 309 159 NOTE: alphabets of the same name share data;
+#X msg 75 332 clear;
+#X msg 91 405 print;
+#X text 240 404 "print" : dump alphabet contents to the console;
+#X msg 91 445 save tmp.lab;
+#X text 212 425 "load FILE" : load alphabet contents from a file;
+#X text 212 445 "save FILE" : save alphabet contents to a file;
+#X text 67 4 gfsm_alphabet : integer<->atom map for finite state machines
+;
+#X text 240 333 "clear" : clears entire alphabet;
+#X msg 76 353 rmatom x;
+#X msg 77 374 rmchar 1;
+#X text 205 372 "rmchar INT" : remove mapping for label INT;
+#X text 198 353 "rmatom ATOM" : remove mapping for atom ATOM;
+#X obj 117 525 gfsm_automaton;
+#X obj 13 471 gfsm_alphabet help-alphabet;
+#X msg 13 127 alphabet help-alphabet;
+#X msg 92 425 load tmp.lab;
+#X connect 12 0 41 0;
+#X connect 14 0 41 0;
+#X connect 16 0 41 0;
+#X connect 21 0 41 0;
+#X connect 22 0 41 0;
+#X connect 23 0 41 0;
+#X connect 25 0 41 0;
+#X connect 28 0 41 0;
+#X connect 29 0 41 0;
+#X connect 31 0 41 0;
+#X connect 36 0 41 0;
+#X connect 37 0 41 0;
+#X connect 41 0 10 0;
+#X connect 41 1 11 0;
+#X connect 42 0 41 0;
+#X connect 43 0 41 0;
diff --git a/gfsm/src/gfsm_automaton-help.pd b/gfsm/src/gfsm_automaton-help.pd
new file mode 100644
index 0000000..10f35ba
--- /dev/null
+++ b/gfsm/src/gfsm_automaton-help.pd
@@ -0,0 +1,288 @@
+#N canvas 126 0 473 476 10;
+#X text 89 7 gfsm_automaton : weighted finite state machine;
+#X text 173 441 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 7 379 SEE ALSO:;
+#X obj 22 399 gfsm;
+#X text 12 73 INLETS:;
+#X text 30 87 1 - control messages;
+#X text 244 74 OUTLETS:;
+#X text 260 87 1 - value outlet;
+#X text 48 48 NAME - symbolic name of the machine;
+#X text 14 31 SYNTAX: gfsm_automaton [NAME];
+#X text 7 211 SUBTOPICS:;
+#X text 10 114 DESCRIPTION:;
+#X text 245 211 GUTS:;
+#X text 28 130 gfsm_automaton objects represent weighted finite state
+machines (acceptors or transducers) -- rooted \, acyclic graphs whose
+edges are labelled with triples (LO \, HI \, WEIGHT) \, where LO and
+HI are alphabet labels (see gfsm_alphabet) \, and WEIGHT is a floating
+point number.;
+#X obj 265 272 print fsm-help-out;
+#X obj 137 400 gfsm_alphabet;
+#N canvas 192 14 651 458 help-automaton-flags 0;
+#X text 167 4 gfsm_automaton : flags;
+#X msg 22 36 weighted;
+#X msg 32 171 transducer 1;
+#X msg 33 192 transducer 0;
+#X msg 22 151 transducer;
+#X msg 33 57 weighted 1;
+#X msg 34 78 weighted 0;
+#X msg 24 275 semiring;
+#X msg 37 299 semiring boolean;
+#X msg 37 320 semiring log;
+#X msg 37 361 semiring real;
+#X msg 37 382 semiring trivial;
+#X msg 38 402 semiring tropical;
+#X text 192 35 "weighted" : get value of the boolean "weighted" flag
+;
+#X text 157 57 "weighted BOOL" : set "weighted" flag;
+#X text 214 87 weighted automata may behave differently than unweighted
+automata with respect to certain algebraic operations.;
+#X text 178 148 "transducer" : get value of the boolean "transducer"
+flag;
+#X text 143 170 "transducer BOOL" : set "transducer" flag;
+#X text 216 195 transducers may behave differently than acceptors (which
+have only one label per arc) with respect to certain algebraic operations.
+;
+#X text 157 297 "semiring TYPE" : set semiring to use for weight arithmetic
+;
+#X text 192 272 "semiring" : get semiring type used for weight arithmetic
+;
+#X text 336 434 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 218 328 algebraic operations may be called on to alter arc
+weights \; in this case \, the semiring type associated with the automaton
+will be used to interpret arc weights. work in progress -- if you need
+this for something \, let me know.;
+#X obj 22 101 s fsm-help-in;
+#X obj 22 216 s fsm-help-in;
+#X obj 24 428 s fsm-help-in;
+#X msg 37 341 semiring plog;
+#X connect 1 0 23 0;
+#X connect 2 0 24 0;
+#X connect 3 0 24 0;
+#X connect 4 0 24 0;
+#X connect 5 0 23 0;
+#X connect 6 0 23 0;
+#X connect 7 0 25 0;
+#X connect 8 0 25 0;
+#X connect 9 0 25 0;
+#X connect 10 0 25 0;
+#X connect 11 0 25 0;
+#X connect 12 0 25 0;
+#X connect 26 0 25 0;
+#X restore 19 230 pd help-automaton-flags;
+#N canvas 71 31 651 409 help-automaton-basic 0;
+#X text 345 383 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X obj 21 119 s fsm-help-in;
+#X text 167 4 gfsm_automaton : basic operations;
+#X msg 21 45 automaton;
+#X msg 28 69 automaton fsm-help-2;
+#X msg 29 91 automaton fsm-help;
+#X text 179 38 "automaton" : use an object-local machine;
+#X text 145 51 "automaton NAME" : use a shared machine named NAME;
+#X msg 29 193 clear;
+#X text 124 192 "clear" : clears the automaton;
+#X msg 34 217 info;
+#X text 130 215 "info" : prints summary information to the Pd console
+;
+#X msg 35 241 print;
+#X text 221 74 data is shared between automata of the same name. when
+using multiple shared automata \, take care always to leave at least
+one object "pointing" to each name \, since the underlying data structures
+are freed when all references are lost.;
+#X text 124 236 "print" : prints automaton in at&t text format to stdout
+;
+#X obj 19 269 s fsm-help-in;
+#X text 145 262 WARNING: these methods may hog the cpu for extended
+periods of time when called for large machines.;
+#X msg 22 169 renumber;
+#X text 102 170 "renumber" : renumber automaton states \, closing gaps
+;
+#X connect 3 0 1 0;
+#X connect 4 0 1 0;
+#X connect 5 0 1 0;
+#X connect 8 0 15 0;
+#X connect 10 0 15 0;
+#X connect 12 0 15 0;
+#X connect 17 0 15 0;
+#X restore 19 252 pd help-automaton-basic;
+#N canvas 27 14 658 321 help-automaton-io 0;
+#X text 101 2 gfsm_automaton : input/output;
+#X obj 13 93 s fsm-help-in;
+#X text 211 44 "load FILE" : load an automaton in at&t-style text format
+;
+#X text 212 68 "save FILE" : save automaton in at&t-style text format
+;
+#X obj 10 235 s fsm-help-in;
+#X text 225 160 "load_bin FILE" : load an automaton in GFSM binary
+format;
+#X text 354 292 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X msg 23 48 load gfsm-help.tfst;
+#X msg 17 162 load_bin gfsm-help.gfst;
+#X msg 23 69 save gfsm-help.tfst;
+#X text 243 240 NOTE: gfsm binary format is not portable across different
+architectures.;
+#X text 235 87 NOTE: currently \, all text i/o is done in "weighted
+transducer" format \, regardless of automaton flags or input file content.
+;
+#X text 227 184 "save_bin FILE" : save automaton in GFSM binary format
+;
+#X msg 18 184 save_bin gfsm-help.gfst;
+#X text 228 209 "save_bin FILE ZLEVEL" : save with zlib compression
+;
+#X msg 24 208 save_bin gfsm-help.gfst 9;
+#X connect 7 0 1 0;
+#X connect 8 0 4 0;
+#X connect 9 0 1 0;
+#X connect 13 0 4 0;
+#X connect 15 0 4 0;
+#X restore 21 296 pd help-automaton-io;
+#N canvas 199 1 636 611 help-automaton-algebra 0;
+#X msg 24 33 complement;
+#X msg 24 62 closure 0;
+#X msg 24 79 closure 1;
+#X msg 24 170 determinize;
+#X msg 24 201 difference fsm-help-2;
+#X msg 24 235 intersect fsm-help-2;
+#X msg 24 267 invert;
+#X msg 24 352 product fsm-help-2;
+#X msg 24 413 reverse;
+#X msg 24 444 rmepsilon;
+#X msg 24 479 union fsm-help-2;
+#X text 222 32 "complement" : compute complement of an acceptor;
+#X msg 24 140 concat fsm-help;
+#X text 215 141 "concat FSM2" : concatenate with automaton named FSM2
+;
+#X text 187 197 "difference FSM2" : remove language of automaton named
+FSM2;
+#X text 194 228 "intersect FSM2" : intersect with automaton named FSM2
+;
+#X text 250 266 "invert" : swap upper and lower labels;
+#X msg 24 302 project 0;
+#X msg 24 319 project 1;
+#X text 208 298 "project SIDE" : project one label side;
+#X text 327 311 SIDE=0: project lower labels;
+#X text 328 323 SIDE=1: project upper labels;
+#X text 208 348 "product FSM2" : compute Cartesian product with FSM2
+;
+#X text 243 407 "reverse" : reverse language of an automaton;
+#X text 95 6 gfsm_automaton : algebraic operations;
+#X text 229 439 "rmepsilon" : remove epsilon arcs;
+#X text 222 478 "union FSM2" : compute union with automaton FSM2;
+#X obj 24 505 s fsm-help-in;
+#X text 31 551 WARNING: these methods may block for long periods of
+time for large automata.;
+#X text 329 578 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X msg 24 109 compose fsm-help-2;
+#X text 208 109 "compose FSM2" : compose with transducer FSM2;
+#X text 229 70 "closure N" : compute N-ary closure;
+#X text 215 170 "determinize" : determinize an acceptor;
+#X msg 24 383 connect;
+#X text 244 382 "connect" : remove useless states and arcs;
+#X connect 0 0 27 0;
+#X connect 1 0 27 0;
+#X connect 2 0 27 0;
+#X connect 3 0 27 0;
+#X connect 4 0 27 0;
+#X connect 5 0 27 0;
+#X connect 6 0 27 0;
+#X connect 7 0 27 0;
+#X connect 8 0 27 0;
+#X connect 9 0 27 0;
+#X connect 10 0 27 0;
+#X connect 12 0 27 0;
+#X connect 17 0 27 0;
+#X connect 18 0 27 0;
+#X connect 30 0 27 0;
+#X connect 34 0 27 0;
+#X restore 21 342 pd help-automaton-algebra;
+#X obj 59 400 gfsm_state;
+#X obj 265 230 r fsm-help-in;
+#N canvas 293 117 651 504 help-automaton-access 0;
+#X msg 22 42 size;
+#X floatatom 33 66 5 0 0 0 - - -;
+#X msg 33 82 size \$1;
+#X obj 22 104 s fsm-help-in;
+#X text 118 38 "size" : get number of states in the machine;
+#X text 90 51 "size INT" : grow machine to at least INT states;
+#X text 99 5 gfsm_automaton : automaton access;
+#X floatatom 35 177 5 0 0 0 - - -;
+#X obj 24 215 s fsm-help-in;
+#X msg 24 153 root;
+#X msg 35 193 root \$1;
+#X text 120 149 "root" : get id of machine's initial state or "bang"
+;
+#X text 134 72 note that values reported do not take the VALIDITY of
+states into account -- your mileage may vary.;
+#X text 132 180 in the second form \, the state will be created if
+it does not already exist. states are internally stored in an array
+\, and indexed with positive integer IDs beginning from 0 (zero) --
+i.e. \, a message such as "root 1E+37" is likely to crash Pd.;
+#X text 99 162 "root ID" : set machine's initial state to ID (an integer)
+;
+#X text 139 273 "final ID" : check whether state ID is marked as final
+;
+#X text 104 297 "final ID BOOL" : set final-status of state ID to BOOL
+;
+#X obj 23 344 s fsm-help-in;
+#X text 143 314 same caveats as for "root";
+#X obj 26 436 s fsm-help-in;
+#X msg 23 276 final 1;
+#X msg 30 299 final 1 1;
+#X msg 31 319 final 1 0;
+#X text 207 388 "add_arc FROM TO LO HI WEIGHT" : add an arc;
+#X text 242 403 adds an arc from state FROM to state TO on lower (input)
+label LO and upper (output) label HI with weight WEIGHT. states FROM
+and TO are implicitly created.;
+#X msg 26 390 add_arc 0 1 2 3 4;
+#X msg 38 412 add_arc 0 2 42 24 0.7;
+#X text 349 480 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X connect 0 0 3 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 7 0 10 0;
+#X connect 9 0 8 0;
+#X connect 10 0 8 0;
+#X connect 20 0 17 0;
+#X connect 21 0 17 0;
+#X connect 22 0 17 0;
+#X connect 25 0 19 0;
+#X connect 26 0 19 0;
+#X restore 20 274 pd help-automaton-access;
+#N canvas 15 0 687 348 help-automaton-draw 0;
+#X obj 13 256 s fsm-help-in;
+#X text 246 63 NOTE: interpreting the resulting file requires the 'graphviz'
+package from at&t.;
+#X text 225 39 "draw_dot FILE [OPTIONS]" : save a 'dot' graph specification
+;
+#X text 235 97 OPTIONS:;
+#X text 318 113 title TITLE : graph title;
+#X text 318 168 width WIDTH : graph width (inches);
+#X text 248 127 ilabels ALPHABET_NAME : lower-label alphabet name;
+#X text 248 140 olabels ALPHABET_NAME : upper-label alphabet name;
+#X text 248 154 slabels ALPHABET_NAME : state-label alphabet name;
+#X text 304 180 height HEIGHT : graph height (inches);
+#X text 304 193 fontsize SIZE : font size (points?);
+#X text 304 206 fontname NAME : font name (?);
+#X text 304 219 portrait BOOL : draw in portrait mode? (default=no)
+;
+#X text 304 231 vertical BOOL : draw top-to-bottom? (default=no);
+#X text 297 244 nodesep INCHES : node-separation distance;
+#X text 297 257 ranksep INCHES : rank-separation distance;
+#X text 115 9 gfsm_automaton : draw;
+#X text 370 326 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X msg 13 40 draw_dot fsm-help.dot;
+#X obj 14 311 shell;
+#X msg 14 291 dotty fsm-help.dot;
+#X text 235 291 ... try this if you have the "graphviz" package installed
+;
+#X connect 18 0 0 0;
+#X connect 20 0 19 0;
+#X restore 20 318 pd help-automaton-draw;
+#X text 239 401 gfsmutils(1);
+#X obj 265 344 gfsm_automaton fsm-help-2;
+#X text 248 303 PLACEHOLDERS:;
+#X obj 265 323 gfsm_automaton fsm-help;
+#X obj 265 251 gfsm_automaton fsm-help;
+#X connect 21 0 28 0;
+#X connect 28 0 14 0;
diff --git a/gfsm/src/gfsm_markov-help.pd b/gfsm/src/gfsm_markov-help.pd
new file mode 100644
index 0000000..8d7a3a2
--- /dev/null
+++ b/gfsm/src/gfsm_markov-help.pd
@@ -0,0 +1,68 @@
+#N canvas 39 25 680 536 10;
+#X text 150 -2 gfsm_markov : Markov chain using gfsm;
+#X text 15 41 INLETS:;
+#X text 28 56 1 - control messages;
+#X text 233 41 OUTLETS:;
+#X text 17 21 SYNTAX: gfsm_markov OBJNAME;
+#X text 365 24 REQUIRES:;
+#X obj 433 24 gfsm;
+#X obj 469 24 zexy;
+#X text 246 83 3 - bang when stuck;
+#X text 247 69 2 - upper side atoms on "next";
+#X text 247 55 1 - lower side atoms on "next";
+#X obj 39 494 print lo;
+#X obj 134 494 print hi;
+#X obj 230 494 print stuck;
+#X obj 39 473 gfsm_markov help-gfsm-markov;
+#X msg 48 175 load_bin help-gfsm_markov;
+#X msg 49 192 save-bin help-gfsm_markov;
+#X msg 39 125 load help-gfsm_markov;
+#X msg 40 142 save help-gfsm_markov;
+#X msg 55 250 set foo;
+#X msg 61 267 set;
+#X msg 60 298 add foo bar 0.42;
+#X msg 65 361 addi foo baz 1;
+#X msg 78 408 next \$1;
+#X floatatom 78 392 5 0 0 0 - - -;
+#X msg 78 428 next;
+#X msg 78 450 bang;
+#X msg 53 223 clear;
+#X text 273 126 load BASE : load text files BASE.lab and BASE.tfst
+;
+#X text 274 142 save BASE : save text files BASE.lab \, BASE.tfst;
+#X text 246 175 load_bin BASE : load files BASE.lab \, BASE.gfst;
+#X text 246 192 save_bin BASE : save files BASE.lab \, BASE.gfst;
+#X text 302 224 clear : clear underlying objects;
+#X text 281 250 set ATOM : set current state to ATOM;
+#X text 316 268 set : reset to initial (root) state;
+#X text 227 297 add A1 A2 WEIGHT : add WEIGHT to arc on atom-pair A1:A2
+;
+#X text 276 316 add A1 A2 : like "add A1 A2 1";
+#X msg 62 315 add foo baz;
+#X text 297 332 add A1 : like "add A1 0 1";
+#X text 219 361 addi A1 A2 WEIGHT : add WEIGHT to initial arc on A1:A2
+;
+#X text 273 408 next PROB : follow next arc with PROB hint-probability
+;
+#X text 308 429 next : follow next arc \, random probability;
+#X text 308 450 bang : alias for "next";
+#X text 375 516 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X msg 65 332 add foo;
+#X connect 14 0 11 0;
+#X connect 14 1 12 0;
+#X connect 14 2 13 0;
+#X connect 15 0 14 0;
+#X connect 16 0 14 0;
+#X connect 17 0 14 0;
+#X connect 18 0 14 0;
+#X connect 19 0 14 0;
+#X connect 20 0 14 0;
+#X connect 21 0 14 0;
+#X connect 22 0 14 0;
+#X connect 23 0 14 0;
+#X connect 24 0 23 0;
+#X connect 25 0 14 0;
+#X connect 26 0 14 0;
+#X connect 27 0 14 0;
+#X connect 37 0 14 0;
+#X connect 44 0 14 0;
diff --git a/gfsm/src/gfsm_markov.pd b/gfsm/src/gfsm_markov.pd
new file mode 100644
index 0000000..ab7142d
--- /dev/null
+++ b/gfsm/src/gfsm_markov.pd
@@ -0,0 +1,414 @@
+#N canvas 386 0 450 300 10;
+#X text 85 2 gfsm_markov : Markov chain using gfsm;
+#X text 181 17 for details \, see:;
+#N canvas 266 0 499 471 gfsm_markov_doc 0;
+#X text 85 2 gfsm_markov : Markov chain using gfsm;
+#X text 15 67 INLETS:;
+#X text 28 84 1 - control messages;
+#X text 203 64 OUTLETS:;
+#X text 17 128 MESSAGES:;
+#X text 81 219 set ATOM : set current state to ATOM;
+#X text 116 231 set : reset to initial (root) state;
+#X text 107 441 bang : synonym for "next";
+#X text 16 24 SYNTAX: gfsm_markov OBJNAME;
+#X text 15 44 REQUIRES:;
+#X obj 83 44 gfsm;
+#X text 75 147 load BASE : load text files BASE.lab and BASE.tfst;
+#X text 75 159 save BASE : save text files BASE.lab \, BASE.tfst;
+#X text 47 182 load_bin BASE : load files BASE.lab \, BASE.gfst;
+#X text 47 194 save_bin BASE : save files BASE.lab \, BASE.gfst;
+#X obj 121 45 zexy;
+#X text 156 294 from current state \, and move to;
+#X text 23 281 add A1 A2 WEIGHT : add WEIGHT to arc on atom-pair A1:A2
+;
+#X text 73 411 next PROB : get next arc with PROB as nearest probability
+;
+#X text 107 427 next : get next arc with random probability;
+#X text 216 106 3 - bang when stuck;
+#X text 157 330 + WEIGHT defaults to 1;
+#X text 157 318 + A2 defaults to 0 (epsilon);
+#X text 157 378 + WEIGHT defaults to 1;
+#X text 157 366 + A2 defaults to 0 (epsilon);
+#X text 18 354 addi A1 A2 WEIGHT : add WEIGHT to initial arc on atoms
+A1:A2;
+#X text 156 305 (possibly new) state for atom A1;
+#X text 217 92 2 - upper side atoms on "next";
+#X text 217 78 1 - lower side atoms on "next";
+#X text 102 250 clear : clear underlying objects;
+#X restore 309 19 pd gfsm_markov_doc;
+#X obj 20 60 inlet;
+#X obj 22 261 outlet;
+#X obj 103 260 outlet;
+#N canvas 27 71 720 463 gfsm_markov_control_guts 0;
+#X obj 22 8 inlet;
+#X obj 450 32 print gfsm_markov_bad_message;
+#X obj 183 230 s \$0-load;
+#X obj 215 209 s \$0-save;
+#X obj 247 187 s \$0-load_bin;
+#X obj 280 164 s \$0-save_bin;
+#X obj 86 373 s \$0-set;
+#X obj 312 125 s \$0-clear;
+#X obj 118 337 s \$0-add;
+#X obj 22 409 s \$0-next;
+#X obj 303 99 s \$0-fsm;
+#X obj 335 78 s \$0-alph;
+#X obj 151 295 s \$0-addi;
+#X obj 415 79 s \$0-state-r;
+#X obj 22 28 route next bang set add addi load save load_bin save_bin
+clear fsm alph state add2;
+#X obj 449 122 s \$0-add2;
+#X connect 0 0 14 0;
+#X connect 14 0 9 0;
+#X connect 14 1 9 0;
+#X connect 14 2 6 0;
+#X connect 14 3 8 0;
+#X connect 14 4 12 0;
+#X connect 14 5 2 0;
+#X connect 14 6 3 0;
+#X connect 14 7 4 0;
+#X connect 14 8 5 0;
+#X connect 14 9 7 0;
+#X connect 14 10 10 0;
+#X connect 14 11 11 0;
+#X connect 14 12 13 0;
+#X connect 14 13 15 0;
+#X connect 14 14 1 0;
+#X restore 20 82 pd gfsm_markov_control_guts;
+#N canvas 0 252 310 205 gfsm_markov_fsm_guts 0;
+#X obj 40 121 gfsm_automaton \$1-fsm;
+#X obj 40 53 gfsm_alphabet \$1-alph;
+#X obj 40 100 r \$0-fsm;
+#X obj 40 33 r \$0-alph;
+#X connect 2 0 0 0;
+#X connect 3 0 1 0;
+#X restore 21 113 pd gfsm_markov_fsm_guts;
+#N canvas 114 67 710 486 gfsm_markov_io_guts 0;
+#X obj 21 87 symbol;
+#X msg 209 301 load \$1;
+#X obj 178 86 symbol;
+#X msg 556 308 save \$1;
+#X msg 21 215 load \$1;
+#X obj 367 85 symbol;
+#X obj 526 79 symbol;
+#X obj 21 20 r \$0-load;
+#X obj 367 22 r \$0-save;
+#X obj 526 26 r \$0-save_bin;
+#X obj 178 19 r \$0-load_bin;
+#X obj 21 110 t s s;
+#X obj 178 106 t s s;
+#X obj 367 107 t s s;
+#X obj 526 100 t s s;
+#X msg 179 215 load_bin \$1;
+#X msg 526 216 save_bin \$1;
+#X msg 367 215 save \$1;
+#X obj 21 193 makefilename %s.tfst;
+#X obj 178 192 makefilename %s.gfst;
+#X obj 367 193 makefilename %s.tfst;
+#X obj 526 193 makefilename %s.gfst;
+#X obj 556 286 makefilename %s.lab;
+#X obj 209 280 makefilename %s.lab;
+#X obj 179 434 s \$0-fsm;
+#X obj 367 429 s \$0-alph;
+#X connect 0 0 11 0;
+#X connect 1 0 25 0;
+#X connect 2 0 12 0;
+#X connect 3 0 25 0;
+#X connect 4 0 24 0;
+#X connect 5 0 13 0;
+#X connect 6 0 14 0;
+#X connect 7 0 0 0;
+#X connect 8 0 5 0;
+#X connect 9 0 6 0;
+#X connect 10 0 2 0;
+#X connect 11 0 18 0;
+#X connect 11 1 23 0;
+#X connect 12 0 19 0;
+#X connect 12 1 23 0;
+#X connect 13 0 20 0;
+#X connect 13 1 22 0;
+#X connect 14 0 21 0;
+#X connect 14 1 22 0;
+#X connect 15 0 24 0;
+#X connect 16 0 24 0;
+#X connect 17 0 24 0;
+#X connect 18 0 4 0;
+#X connect 19 0 15 0;
+#X connect 20 0 17 0;
+#X connect 21 0 16 0;
+#X connect 22 0 3 0;
+#X connect 23 0 1 0;
+#X restore 21 138 pd gfsm_markov_io_guts;
+#N canvas 150 351 551 242 gfsm_markov_set_guts 0;
+#X obj 32 18 r \$0-set;
+#X obj 32 40 route bang;
+#X obj 97 133 gfsm_alphabet \$1-alph;
+#X obj 97 61 route float list;
+#X msg 97 110 atom2char! \$1;
+#X obj 204 83 symbol;
+#X msg 97 156 set \$1;
+#X obj 97 178 s \$0-state;
+#X msg 32 83 0;
+#X obj 345 15 r \$0-clear;
+#X obj 389 78 s \$0-alph;
+#X obj 367 126 s \$0-fsm;
+#X msg 367 105 clear \, root 0;
+#X msg 389 57 clear \, atom2char! 0;
+#X obj 345 35 t b b b;
+#X msg 345 150 set 0;
+#X obj 346 170 s \$0-state;
+#X connect 0 0 1 0;
+#X connect 1 0 8 0;
+#X connect 1 1 3 0;
+#X connect 2 0 6 0;
+#X connect 3 0 4 0;
+#X connect 3 1 4 0;
+#X connect 3 2 5 0;
+#X connect 4 0 2 0;
+#X connect 5 0 4 0;
+#X connect 6 0 7 0;
+#X connect 8 0 4 0;
+#X connect 9 0 14 0;
+#X connect 12 0 11 0;
+#X connect 13 0 10 0;
+#X connect 14 0 15 0;
+#X connect 14 1 12 0;
+#X connect 14 2 13 0;
+#X connect 15 0 16 0;
+#X restore 21 162 pd gfsm_markov_set_guts;
+#X obj 261 60 loadbang;
+#N canvas 142 144 416 223 gfsm_markov_init_guts 0;
+#X obj 15 9 inlet;
+#X msg 15 97 char2atom! 0;
+#X obj 15 118 s \$0-alph;
+#X obj 15 66 t b b;
+#X obj 74 10 r \$0-loadbang;
+#X obj 179 124 gfsm_automaton \$1-fsm;
+#X msg 206 97 root;
+#X obj 179 145 route root;
+#X obj 179 168 route bang;
+#X msg 155 98 root 0;
+#X connect 0 0 3 0;
+#X connect 1 0 2 0;
+#X connect 3 0 1 0;
+#X connect 3 1 6 0;
+#X connect 4 0 3 0;
+#X connect 5 0 7 0;
+#X connect 6 0 5 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 5 0;
+#X restore 261 81 pd gfsm_markov_init_guts;
+#N canvas 66 12 666 508 gfsm_markov_add_guts 0;
+#X obj 28 231 gfsm_alphabet \$1-alph;
+#X obj 28 167 route float list;
+#X msg 28 211 atom2char! \$1;
+#X obj 95 190 symbol;
+#X obj 58 426 gfsm_state \$1-fsm;
+#X obj 71 402 r \$0-state;
+#X msg 508 322 set \$1;
+#X obj 508 428 s \$0-state;
+#X obj 28 12 r \$0-add1;
+#X obj 121 12 r \$0-add;
+#X obj 123 320 1;
+#X obj 28 260 t f f;
+#X obj 413 14 r \$0-addi1;
+#X obj 492 14 r \$0-addi;
+#X obj 443 89 gfsm_automaton \$1-fsm;
+#X msg 443 67 root;
+#X obj 413 39 t a b;
+#X obj 443 110 route root;
+#X obj 443 132 route bang;
+#X msg 481 67 root 0;
+#X msg 58 372 add_weight \$1 \$1 \$2 \$3;
+#X obj 28 89 t a b b;
+#X obj 58 347 pack 0 0 0;
+#X obj 90 320 0;
+#X text 139 347 <-- Q=LO HI WEIGHT;
+#X obj 28 112 niagara 1;
+#X obj 231 129 niagara 1;
+#X obj 231 236 gfsm_alphabet \$1-alph;
+#X obj 231 172 route float list;
+#X msg 231 216 atom2char! \$1;
+#X obj 298 195 symbol;
+#X obj 204 12 r \$0-add2;
+#X obj 28 42 t a b;
+#X obj 205 35 t a b;
+#X obj 446 297 spigot;
+#X obj 454 273 0;
+#X obj 479 273 1;
+#X connect 0 0 11 0;
+#X connect 1 0 2 0;
+#X connect 1 1 2 0;
+#X connect 1 2 3 0;
+#X connect 2 0 0 0;
+#X connect 3 0 2 0;
+#X connect 5 0 4 0;
+#X connect 6 0 7 0;
+#X connect 8 0 32 0;
+#X connect 9 0 32 0;
+#X connect 10 0 22 2;
+#X connect 11 0 34 0;
+#X connect 11 1 22 0;
+#X connect 12 0 16 0;
+#X connect 13 0 16 0;
+#X connect 14 0 17 0;
+#X connect 15 0 14 0;
+#X connect 16 0 21 0;
+#X connect 16 1 15 0;
+#X connect 17 0 18 0;
+#X connect 18 0 19 0;
+#X connect 18 1 6 0;
+#X connect 19 0 14 0;
+#X connect 20 0 4 0;
+#X connect 21 0 25 0;
+#X connect 21 1 23 0;
+#X connect 21 2 10 0;
+#X connect 22 0 20 0;
+#X connect 23 0 22 1;
+#X connect 25 0 1 0;
+#X connect 25 1 26 0;
+#X connect 26 0 28 0;
+#X connect 26 1 22 2;
+#X connect 27 0 22 1;
+#X connect 28 0 29 0;
+#X connect 28 1 29 0;
+#X connect 28 2 30 0;
+#X connect 29 0 27 0;
+#X connect 30 0 29 0;
+#X connect 31 0 33 0;
+#X connect 32 0 21 0;
+#X connect 32 1 36 0;
+#X connect 33 0 21 0;
+#X connect 33 1 35 0;
+#X connect 34 0 6 0;
+#X connect 35 0 34 1;
+#X connect 36 0 34 1;
+#X restore 21 186 pd gfsm_markov_add_guts;
+#N canvas 27 0 738 524 gfsm_markov_next_guts 0;
+#X obj 86 25 r \$0-next;
+#X obj 243 464 outlet;
+#X obj 86 47 route bang;
+#X obj 151 158 * -1;
+#X obj 151 136 * 1;
+#X obj 559 376 t b b;
+#N canvas 75 18 312 424 weight_sum 0;
+#X obj 24 9 inlet;
+#X msg 24 114 arc_next;
+#X obj 24 319 f 0;
+#X obj 199 92 0;
+#X obj 89 238 unpack 0 0 0 0;
+#X obj 183 262 + 0;
+#X obj 88 263 t f f;
+#X obj 24 350 outlet;
+#X obj 60 146 r \$0-state;
+#X obj 24 90 until;
+#X obj 24 214 route bang;
+#X obj 24 235 t b b;
+#X obj 24 192 route arc_next;
+#X obj 24 43 t b b b b;
+#X msg 91 114 arc_reset;
+#X obj 24 167 gfsm_state \$1-fsm 0;
+#X connect 0 0 13 0;
+#X connect 1 0 15 0;
+#X connect 2 0 7 0;
+#X connect 3 0 5 1;
+#X connect 4 3 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 5 1;
+#X connect 6 1 2 1;
+#X connect 8 0 15 0;
+#X connect 9 0 1 0;
+#X connect 10 0 11 0;
+#X connect 10 1 4 0;
+#X connect 11 0 2 0;
+#X connect 11 1 9 1;
+#X connect 12 0 10 0;
+#X connect 13 0 9 0;
+#X connect 13 1 3 0;
+#X connect 13 2 14 0;
+#X connect 13 3 9 1;
+#X connect 14 0 15 0;
+#X connect 15 0 12 0;
+#X restore 167 115 pd weight_sum;
+#X obj 25 95 random 131072;
+#X obj 25 116 / 131072;
+#X obj 86 69 t b b b;
+#X obj 151 69 t f b b;
+#X msg 559 227 arc_next;
+#X obj 594 269 r \$0-state;
+#X obj 559 205 until;
+#X obj 559 349 route bang;
+#X obj 559 326 route arc_next;
+#X msg 625 226 arc_reset;
+#X obj 151 180 t b b f;
+#X obj 405 461 outlet;
+#X obj 101 429 gfsm_alphabet \$1-alph;
+#X msg 101 407 char2atom! \$1;
+#X obj 179 296 moses 0;
+#X obj 179 251 + 0;
+#X obj 179 274 t f f;
+#X obj 86 225 unpack 0 0 0 0;
+#X obj 18 386 f 0;
+#X msg 18 411 set \$1;
+#X obj 18 432 s \$0-state;
+#X obj 559 292 gfsm_state \$1-fsm 0;
+#X obj 559 457 outlet;
+#X obj 263 428 gfsm_alphabet \$1-alph;
+#X msg 263 406 char2atom! \$1;
+#X obj 263 384 f 0;
+#X obj 101 385 f 0;
+#X obj 225 316 t b b b b;
+#X connect 0 0 2 0;
+#X connect 2 0 9 0;
+#X connect 2 1 10 0;
+#X connect 3 0 17 0;
+#X connect 4 0 3 0;
+#X connect 5 0 29 0;
+#X connect 5 1 13 1;
+#X connect 6 0 4 1;
+#X connect 7 0 8 0;
+#X connect 8 0 4 0;
+#X connect 9 0 7 0;
+#X connect 9 1 6 0;
+#X connect 9 2 13 1;
+#X connect 10 0 4 0;
+#X connect 10 1 6 0;
+#X connect 10 2 13 1;
+#X connect 11 0 28 0;
+#X connect 12 0 28 0;
+#X connect 13 0 11 0;
+#X connect 14 0 5 0;
+#X connect 14 1 24 0;
+#X connect 15 0 14 0;
+#X connect 16 0 28 0;
+#X connect 17 0 13 0;
+#X connect 17 1 16 0;
+#X connect 17 2 22 1;
+#X connect 19 1 1 0;
+#X connect 20 0 19 0;
+#X connect 21 1 34 0;
+#X connect 22 0 23 0;
+#X connect 23 0 21 0;
+#X connect 23 1 22 1;
+#X connect 24 0 25 1;
+#X connect 24 1 33 1;
+#X connect 24 2 32 1;
+#X connect 24 3 22 0;
+#X connect 25 0 26 0;
+#X connect 26 0 27 0;
+#X connect 28 0 15 0;
+#X connect 30 1 18 0;
+#X connect 31 0 30 0;
+#X connect 32 0 31 0;
+#X connect 33 0 20 0;
+#X connect 34 0 25 0;
+#X connect 34 1 33 0;
+#X connect 34 2 32 0;
+#X connect 34 3 13 1;
+#X restore 22 216 pd gfsm_markov_next_guts;
+#X obj 185 260 outlet;
+#X connect 3 0 6 0;
+#X connect 10 0 11 0;
+#X connect 13 0 4 0;
+#X connect 13 1 5 0;
+#X connect 13 2 14 0;
diff --git a/gfsm/src/gfsm_state-help.pd b/gfsm/src/gfsm_state-help.pd
new file mode 100644
index 0000000..e26ace2
--- /dev/null
+++ b/gfsm/src/gfsm_state-help.pd
@@ -0,0 +1,55 @@
+#N canvas 232 0 651 599 10;
+#X obj 85 569 gfsm;
+#X text 15 569 SEE ALSO:;
+#X text 41 6 gfsm_state : position "pointer" for finite-state automata
+;
+#X text 267 563 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 17 79 INLETS:;
+#X text 35 93 1 - control messages;
+#X text 255 82 OUTLETS:;
+#X text 271 95 1 - value outlet;
+#X text 18 30 SYNTAX: gfsm_state [FSM_NAME [STATE_ID]];
+#X text 52 47 FSM_NAME - symbolic name of a gfsm_automaton;
+#X text 52 61 STATE_ID - numeric Id of the target state;
+#X obj 26 531 print gfsm-state-out;
+#X msg 44 182 id;
+#X text 164 185 "id" : get current state Id;
+#X text 135 205 "set ID" : set current state Id;
+#X msg 50 205 set 0;
+#X msg 26 127 automaton;
+#X msg 31 149 automaton fsm-help;
+#X text 197 128 "automaton" : use an object-local machine;
+#X text 163 151 "automaton NAME" : use a shared machine named NAME
+;
+#X msg 58 239 degree;
+#X text 137 240 "degree" : get number of outgoing arcs (linear time)
+;
+#X msg 58 295 arc_first;
+#X msg 58 317 arc_next;
+#X msg 59 382 arc_reset;
+#X obj 26 508 gfsm_state fsm-help 0;
+#X text 229 398 arcs are output as a list:;
+#X text 277 414 NEXT_STATEID LO HI WEIGHT;
+#X text 306 359 (negative labels are ignored);
+#X msg 58 345 arc_seek 202 -1;
+#X text 208 294 "arc_first" : get first outgoing arc;
+#X text 214 318 "arc_next" : get next available outgoing arc (maybe
+first);
+#X text 173 344 "arc_seek LO HI" : get next arc with labels LO:HI;
+#X text 207 383 "arc_reset" : close internal arc iterator;
+#X msg 54 447 add_weight 1 -1 101 0.9;
+#X text 233 450 "add_weight ID LO HI W" : add W to 1st arc to state
+ID;
+#X text 416 463 with labels LO:HI;
+#X text 271 479 (implicitly resets arc iterator);
+#X connect 12 0 25 0;
+#X connect 15 0 25 0;
+#X connect 16 0 25 0;
+#X connect 17 0 25 0;
+#X connect 20 0 25 0;
+#X connect 22 0 25 0;
+#X connect 23 0 25 0;
+#X connect 24 0 25 0;
+#X connect 25 0 11 0;
+#X connect 29 0 25 0;
+#X connect 34 0 25 0;
diff --git a/gfsm/src/lkpin.tfst b/gfsm/src/lkpin.tfst
new file mode 100644
index 0000000..a9adbc9
--- /dev/null
+++ b/gfsm/src/lkpin.tfst
@@ -0,0 +1,4 @@
+0 1 2 2
+1 2 2 2
+2 3 3 3
+3
diff --git a/gfsm/src/lkptest.tfst b/gfsm/src/lkptest.tfst
new file mode 100644
index 0000000..11f371e
--- /dev/null
+++ b/gfsm/src/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/src/pd_algebra.c b/gfsm/src/pd_algebra.c
new file mode 100644
index 0000000..eecde1e
--- /dev/null
+++ b/gfsm/src/pd_algebra.c
@@ -0,0 +1,299 @@
+/*=============================================================================*\
+ * File: pd_algebra.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pd_gfsm.h>
+#include <pd_automaton.h>
+#include <m_pd.h>
+
+/*--------------------------------------------------------------------
+ * DEBUG
+ *--------------------------------------------------------------------*/
+//#define PDFSM_DEBUG 1
+
+/*=====================================================================
+ * Structures and Types
+ *=====================================================================*/
+//(none)
+
+/*=====================================================================
+ * pd_gfsm_automaton_obj: Utilities
+ *=====================================================================*/
+//(none)
+
+/*=====================================================================
+ * pd_gfsm_automaton_obj: Algebra
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * complement
+ */
+static void pd_gfsm_automaton_complement(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_complement(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("complement"));
+}
+
+/*--------------------------------------------------------------------
+ * closure
+ */
+static void pd_gfsm_automaton_closure(t_pd_gfsm_automaton_obj *x, t_float nf)
+{
+ gfsm_automaton_n_closure(x->x_automaton_pd->x_automaton, (guint)nf);
+ pd_gfsm_automaton_obj_outlet_float(x, gensym("closure"), nf);
+}
+
+/*--------------------------------------------------------------------
+ * compose
+ */
+static void pd_gfsm_automaton_compose(t_pd_gfsm_automaton_obj *x, t_symbol *fsm2_name)
+{
+ t_pd_gfsm_automaton_pd *fsm2_pd = pd_gfsm_automaton_pd_find(fsm2_name);
+ if (!fsm2_pd) {
+ error("pd_gfsm_automaton_compose(): no fsm named '%s'", fsm2_name->s_name);
+ return;
+ } else {
+ ++fsm2_pd->x_refcnt;
+ gfsm_automaton_compose(x->x_automaton_pd->x_automaton, fsm2_pd->x_automaton);
+ pd_gfsm_automaton_pd_release(fsm2_pd);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("compose"), fsm2_name);
+}
+
+/*--------------------------------------------------------------------
+ * concat
+ */
+static void pd_gfsm_automaton_concat(t_pd_gfsm_automaton_obj *x, t_symbol *fsm2_name)
+{
+ t_pd_gfsm_automaton_pd *fsm2_pd = pd_gfsm_automaton_pd_find(fsm2_name);
+ if (!fsm2_pd) {
+ error("pd_gfsm_automaton_concat(): no fsm named '%s'", fsm2_name->s_name);
+ return;
+ } else {
+ ++fsm2_pd->x_refcnt;
+ gfsm_automaton_concat(x->x_automaton_pd->x_automaton, fsm2_pd->x_automaton);
+ pd_gfsm_automaton_pd_release(fsm2_pd);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("concat"), fsm2_name);
+}
+
+/*--------------------------------------------------------------------
+ * determinize
+ */
+static void pd_gfsm_automaton_determinize(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_determinize(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("determinize"));
+}
+
+/*--------------------------------------------------------------------
+ * difference
+ */
+static void pd_gfsm_automaton_difference(t_pd_gfsm_automaton_obj *x, t_symbol *fsm2_name)
+{
+ t_pd_gfsm_automaton_pd *fsm2_pd = pd_gfsm_automaton_pd_find(fsm2_name);
+ if (!fsm2_pd) {
+ error("pd_gfsm_automaton_difference(): no fsm named '%s'", fsm2_name->s_name);
+ return;
+ } else {
+ ++fsm2_pd->x_refcnt;
+ gfsm_automaton_difference(x->x_automaton_pd->x_automaton, fsm2_pd->x_automaton);
+ pd_gfsm_automaton_pd_release(fsm2_pd);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("difference"), fsm2_name);
+}
+
+/*--------------------------------------------------------------------
+ * intersection
+ */
+static void pd_gfsm_automaton_intersect(t_pd_gfsm_automaton_obj *x, t_symbol *fsm2_name)
+{
+ t_pd_gfsm_automaton_pd *fsm2_pd = pd_gfsm_automaton_pd_find(fsm2_name);
+ if (!fsm2_pd) {
+ error("pd_gfsm_automaton_intersect(): no fsm named '%s'", fsm2_name->s_name);
+ return;
+ } else {
+ ++fsm2_pd->x_refcnt;
+ gfsm_automaton_intersect(x->x_automaton_pd->x_automaton, fsm2_pd->x_automaton);
+ pd_gfsm_automaton_pd_release(fsm2_pd);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("intersect"), fsm2_name);
+}
+
+/*--------------------------------------------------------------------
+ * invert
+ */
+static void pd_gfsm_automaton_invert(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_invert(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("invert"));
+}
+
+/*--------------------------------------------------------------------
+ * product
+ */
+static void pd_gfsm_automaton_product(t_pd_gfsm_automaton_obj *x, t_symbol *fsm2_name)
+{
+ t_pd_gfsm_automaton_pd *fsm2_pd = pd_gfsm_automaton_pd_find(fsm2_name);
+ if (!fsm2_pd) {
+ error("pd_gfsm_automaton_product(): no fsm named '%s'", fsm2_name->s_name);
+ return;
+ } else {
+ ++fsm2_pd->x_refcnt;
+ gfsm_automaton_product(x->x_automaton_pd->x_automaton, fsm2_pd->x_automaton);
+ pd_gfsm_automaton_pd_release(fsm2_pd);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("intersect"), fsm2_name);
+}
+
+/*--------------------------------------------------------------------
+ * project
+ */
+static void pd_gfsm_automaton_project(t_pd_gfsm_automaton_obj *x, t_float which)
+{
+ gfsm_automaton_project(x->x_automaton_pd->x_automaton,
+ (which==0 ? gfsmLSLower : gfsmLSUpper));
+ pd_gfsm_automaton_obj_outlet_float(x, gensym("project"), which);
+}
+
+/*--------------------------------------------------------------------
+ * prune
+ */
+static void pd_gfsm_automaton_connect(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_connect(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("connect"));
+}
+
+/*--------------------------------------------------------------------
+ * renumber
+ */
+static void pd_gfsm_automaton_renumber(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_renumber_states(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("renumber"));
+}
+
+
+/*--------------------------------------------------------------------
+ * reverse
+ */
+static void pd_gfsm_automaton_reverse(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_reverse(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("reverse"));
+}
+
+/*--------------------------------------------------------------------
+ * rmepsilon
+ */
+static void pd_gfsm_automaton_rmepsilon(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_rmepsilon(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("rmepsilon"));
+}
+
+/*--------------------------------------------------------------------
+ * union
+ */
+static void pd_gfsm_automaton_union(t_pd_gfsm_automaton_obj *x, t_symbol *fsm2_name)
+{
+ t_pd_gfsm_automaton_pd *fsm2_pd = pd_gfsm_automaton_pd_find(fsm2_name);
+ if (!fsm2_pd) {
+ error("pd_gfsm_automaton_union(): no fsm named '%s'", fsm2_name->s_name);
+ return;
+ }
+ else if (fsm2_pd != x->x_automaton_pd) {
+ ++fsm2_pd->x_refcnt;
+ gfsm_automaton_union(x->x_automaton_pd->x_automaton, fsm2_pd->x_automaton);
+ pd_gfsm_automaton_pd_release(fsm2_pd);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("union"), fsm2_name);
+}
+
+
+/*=====================================================================
+ * setup
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: setup()
+ */
+void pd_gfsm_algebra_setup(t_class *automaton_class)
+{
+ //-- methods: algebra
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_complement,
+ gensym("complement"), A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_closure,
+ gensym("closure"), A_DEFFLOAT, A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_compose,
+ gensym("compose"), A_SYMBOL, A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_concat,
+ gensym("concat"), A_SYMBOL, A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_determinize,
+ gensym("determinize"), A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_difference,
+ gensym("difference"), A_SYMBOL, A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_intersect,
+ gensym("intersect"), A_SYMBOL, A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_invert,
+ gensym("invert"), A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_product,
+ gensym("product"), A_SYMBOL, A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_project,
+ gensym("project"), A_DEFFLOAT, A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_connect,
+ gensym("connect"), A_NULL);
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_connect,
+ gensym("prune"), A_NULL); //-- backwards-compatible alias
+
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_renumber,
+ gensym("renumber"), A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_reverse,
+ gensym("reverse"), A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_rmepsilon,
+ gensym("rmepsilon"), A_NULL);
+
+ class_addmethod(automaton_class, (t_method)pd_gfsm_automaton_union,
+ gensym("union"), A_SYMBOL, A_NULL);
+}
diff --git a/gfsm/src/pd_alphabet.c b/gfsm/src/pd_alphabet.c
new file mode 100644
index 0000000..480a74a
--- /dev/null
+++ b/gfsm/src/pd_alphabet.c
@@ -0,0 +1,494 @@
+/*=============================================================================*\
+ * File: pd_alphabet.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd: alphabet
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pd_alphabet.h>
+#include <pd_io.h>
+#include <string.h>
+
+/*=====================================================================
+ * DEBUG
+ *=====================================================================*/
+//#define ALPHABET_DEBUG
+
+/*=====================================================================
+ * Pd Constants
+ *=====================================================================*/
+static t_class *pd_gfsm_alphabet_pd_class;
+static t_class *pd_gfsm_alphabet_obj_class;
+
+/*=====================================================================
+ * pd_gfsm_alphabet_pd: Methods
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_pd: new
+ */
+static void *pd_gfsm_alphabet_pd_new(t_symbol *name)
+{
+ t_pd_gfsm_alphabet_pd *x = (t_pd_gfsm_alphabet_pd *)pd_new(pd_gfsm_alphabet_pd_class);
+
+#ifdef ALPHABET_DEBUG
+ post("pd_gfsm_alphabet_pd_new() called ; name=%s ; x=%p",
+ (name ? name->s_name : "(null)"),
+ x);
+#endif
+
+ //-- defaults
+ x->x_refcnt = 0;
+ x->x_name = name;
+ x->x_alphabet = (gfsmAlphabet*)gfsm_pd_atom_alphabet_new();
+
+ //-- bindings
+ if (name != &s_) pd_bind((t_pd*)x, name);
+
+ return (void *)x;
+}
+
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_pd: free
+ */
+static void pd_gfsm_alphabet_pd_free(t_pd_gfsm_alphabet_pd *x)
+{
+#ifdef ALPHABET_DEBUG
+ post("pd_gfsm_alphabet_pd_free() called ; x=%p", x);
+#endif
+
+ if (x->x_alphabet) gfsm_pd_atom_alphabet_free((gfsmPdAtomAlphabet*)(x->x_alphabet));
+
+ /* unbind the symbol of the name of hashtable in pd's global namespace */
+ if (x->x_name != &s_) pd_unbind((t_pd*)x, x->x_name);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_pd: find
+ */
+t_pd_gfsm_alphabet_pd *pd_gfsm_alphabet_pd_find(t_symbol *name)
+{
+ if (name != &s_)
+ return (t_pd_gfsm_alphabet_pd*)pd_findbyclass(name,pd_gfsm_alphabet_pd_class);
+ return NULL;
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_pd: get
+ */
+t_pd_gfsm_alphabet_pd *pd_gfsm_alphabet_pd_get(t_symbol *name)
+{
+ t_pd_gfsm_alphabet_pd *x = pd_gfsm_alphabet_pd_find(name);
+ if (!x) {
+ x = (t_pd_gfsm_alphabet_pd*)pd_gfsm_alphabet_pd_new(name);
+ x->x_refcnt = 0;
+ }
+ return x;
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_pd: release
+ */
+void pd_gfsm_alphabet_pd_release(t_pd_gfsm_alphabet_pd *x)
+{
+ if (x) {
+ if (x->x_refcnt) --x->x_refcnt;
+ if (!x->x_refcnt) pd_gfsm_alphabet_pd_free(x);
+ }
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_pd: setup
+ */
+void pd_gfsm_alphabet_pd_setup(void)
+{
+ //-- class
+ pd_gfsm_alphabet_pd_class = class_new(gensym("gfsm_alphabet_pd"),
+ (t_newmethod)pd_gfsm_alphabet_pd_new,
+ (t_method)pd_gfsm_alphabet_pd_free,
+ sizeof(t_pd_gfsm_alphabet_pd),
+ CLASS_PD,
+ A_DEFSYM,
+ A_NULL);
+}
+
+
+/*=====================================================================
+ * pd_gfsm_alphabet: Methods
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: new
+ */
+static void *pd_gfsm_alphabet_obj_new(t_symbol *name)
+{
+ t_pd_gfsm_alphabet_obj *x = (t_pd_gfsm_alphabet_obj *)pd_new(pd_gfsm_alphabet_obj_class);
+
+#ifdef ALPHABET_DEBUG
+ post("pd_gfsm_alphabet_obj_new() called: name=%s ; x=%p",
+ (name ? name->s_name : "(null)"),
+ x);
+#endif
+
+ //-- defaults
+ x->x_alphabet_pd = NULL;
+
+ //-- bindings
+ x->x_alphabet_pd = pd_gfsm_alphabet_pd_get(name);
+ x->x_alphabet_pd->x_refcnt++;
+
+ //-- outlets
+ x->x_labout = outlet_new(&x->x_obj, &s_float); //-- label / "char" outlet
+ x->x_keyout = outlet_new(&x->x_obj, &s_anything); //-- atom outlet
+
+ return (void *)x;
+}
+
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: free
+ */
+static void pd_gfsm_alphabet_obj_free(t_pd_gfsm_alphabet_obj *x)
+{
+#ifdef ALPHABET_DEBUG
+ post("pd_gfsm_alphabet_obj_free() called: x=%p", x);
+#endif
+
+ pd_gfsm_alphabet_pd_release(x->x_alphabet_pd);
+
+ //-- do we need to do this?
+ outlet_free(x->x_labout);
+ outlet_free(x->x_keyout);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: set
+ */
+static void pd_gfsm_alphabet_obj_alphabet(t_pd_gfsm_alphabet_obj *x, t_symbol *name)
+{
+#ifdef ALPHABET_DEBUG
+ post("pd_gfsm_alphabet_obj_alphabet() called ; oldname=%p=%s ; newname=%p=%s",
+ x->x_alphabet_pd->x_name, x->x_alphabet_pd->x_name->s_name, name, name->s_name);
+#endif
+ if (name == x->x_alphabet_pd->x_name) return;
+ pd_gfsm_alphabet_pd_release(x->x_alphabet_pd);
+
+ x->x_alphabet_pd = pd_gfsm_alphabet_pd_get(name);
+ ++x->x_alphabet_pd->x_refcnt;
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: load
+ */
+static void pd_gfsm_alphabet_obj_load(t_pd_gfsm_alphabet_obj *x, t_symbol *s)
+{
+ gfsmError *errp = NULL;
+ gfsm_alphabet_load_filename(x->x_alphabet_pd->x_alphabet, s->s_name, &errp);
+ if (errp != NULL) {
+ error("gfsm_alphabet: load %s: %s", s->s_name, errp->message);
+ g_error_free(errp);
+ }
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: print
+ */
+static void pd_gfsm_alphabet_obj_print(t_pd_gfsm_alphabet_obj *x)
+{
+ gfsmError *errp = NULL;
+ gfsmIOHandle *ioh = pd_gfsm_console_handle_new();
+ gfsm_alphabet_save_handle(x->x_alphabet_pd->x_alphabet, ioh, &errp);
+ if (errp != NULL) {
+ error("gfsm_alphabet: print: %s", errp->message);
+ g_error_free(errp);
+ }
+ pd_gfsm_console_handle_free(ioh);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: save
+ */
+static void pd_gfsm_alphabet_obj_save(t_pd_gfsm_alphabet_obj *x, t_symbol *s)
+{
+ gfsmError *errp = NULL;
+ gfsm_alphabet_save_filename(x->x_alphabet_pd->x_alphabet, s->s_name, &errp);
+ if (errp != NULL) {
+ error("gfsm_alphabet: save %s: %s", s->s_name, errp->message);
+ g_error_free(errp);
+ }
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: clear
+ */
+static void pd_gfsm_alphabet_obj_clear(t_pd_gfsm_alphabet_obj *x)
+{
+ gfsm_alphabet_clear(x->x_alphabet_pd->x_alphabet);
+}
+
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: outlet_pair
+ */
+static void pd_gfsm_alphabet_obj_outlet_pair(t_pd_gfsm_alphabet_obj *x, t_float lab, t_atom *a)
+{
+ if (a) {
+ switch (a->a_type) {
+ case A_SYMBOL:
+ outlet_symbol(x->x_keyout, a->a_w.w_symbol);
+ break;
+ case A_FLOAT:
+ outlet_float(x->x_keyout, a->a_w.w_float);
+ break;
+ default:
+ outlet_symbol(x->x_keyout, atom_getsymbol(a));
+ break;
+ }
+ } else {
+ outlet_bang(x->x_keyout);
+ }
+
+ if (lab != gfsmNoLabel) outlet_float(x->x_obj.ob_outlet, lab);
+ else outlet_bang(x->x_obj.ob_outlet);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: insert
+ */
+static void pd_gfsm_alphabet_obj_insert(t_pd_gfsm_alphabet_obj *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc < 1) {
+ error("pd_gfsm_alphabet_obj_insert(): no atom to insert?");
+ return;
+ }
+ t_float labf = argc > 1 ? atom_getfloat(argv+1) : (t_float)gfsmNoLabel;
+
+ gfsm_alphabet_get_full(x->x_alphabet_pd->x_alphabet, argv, (gfsmLabelVal)labf);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: atom2label
+ */
+static void pd_gfsm_alphabet_obj_atom2label(t_pd_gfsm_alphabet_obj *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc < 1) {
+ error("pd_gfsm_alphabet_obj_atom2label(): no arguments?");
+ return;
+ }
+ t_float labf = (t_float)(gfsm_alphabet_find_label(x->x_alphabet_pd->x_alphabet, argv));
+
+ pd_gfsm_alphabet_obj_outlet_pair(x, labf, argv);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: atom2label_force
+ */
+static void pd_gfsm_alphabet_obj_atom2label_force(t_pd_gfsm_alphabet_obj *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc < 1) {
+ error("pd_gfsm_alphabet_obj_atom2label_force(): no arguments?");
+ return;
+ }
+ t_float labf = (t_float)(gfsm_alphabet_get_label(x->x_alphabet_pd->x_alphabet, argv));
+
+ pd_gfsm_alphabet_obj_outlet_pair(x, labf, argv);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: label2atom
+ */
+static void pd_gfsm_alphabet_obj_label2atom(t_pd_gfsm_alphabet_obj *x, t_float labf)
+{
+ t_atom *key = (t_atom*)gfsm_alphabet_find_key(x->x_alphabet_pd->x_alphabet, (gfsmLabelVal)labf);
+
+ if (key==NULL) pd_gfsm_alphabet_obj_outlet_pair(x, labf, NULL);
+ else pd_gfsm_alphabet_obj_outlet_pair(x, labf, key);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: label2atom_force
+ */
+static void pd_gfsm_alphabet_obj_label2atom_force(t_pd_gfsm_alphabet_obj *x, t_float labf)
+{
+ t_atom *key = (t_atom*)gfsm_alphabet_find_key(x->x_alphabet_pd->x_alphabet,
+ (gfsmLabelVal)labf);
+ if (key==NULL) {
+ t_atom labatom;
+ SETFLOAT(&labatom, labf);
+ gfsm_alphabet_insert(x->x_alphabet_pd->x_alphabet, &labatom, (gfsmLabelVal)labf);
+ pd_gfsm_alphabet_obj_outlet_pair(x, labf, &labatom);
+ }
+ else {
+ pd_gfsm_alphabet_obj_outlet_pair(x, labf, key);
+ }
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: rmatom()
+ */
+static void pd_gfsm_alphabet_obj_rmatom(t_pd_gfsm_alphabet_obj *x, t_symbol *sel, int argc, t_atom *argv)
+{
+ if (argc < 1) return;
+ gfsm_alphabet_remove_key(x->x_alphabet_pd->x_alphabet, argv);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet_obj: rmlabel()
+ */
+static void pd_gfsm_alphabet_obj_rmlabel(t_pd_gfsm_alphabet_obj *x, t_float labf)
+{
+ gfsm_alphabet_remove_label(x->x_alphabet_pd->x_alphabet, (gfsmLabelVal)labf);
+}
+
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_alphabet: setup
+ */
+void pd_gfsm_alphabet_setup(void)
+{
+ //-- pd_gfsm_alphabet_pd
+ pd_gfsm_alphabet_pd_setup();
+
+ //-- class
+ pd_gfsm_alphabet_obj_class = class_new(gensym("gfsm_alphabet"),
+ (t_newmethod)pd_gfsm_alphabet_obj_new,
+ (t_method)pd_gfsm_alphabet_obj_free,
+ sizeof(t_pd_gfsm_alphabet_obj),
+ CLASS_DEFAULT,
+ A_DEFSYM,
+ A_NULL);
+
+ //-- methods: I/O
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_print,
+ gensym("print"),
+ A_NULL);
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_load,
+ gensym("load"),
+ A_SYMBOL,
+ A_NULL);
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_save,
+ gensym("save"),
+ A_SYMBOL,
+ A_NULL);
+
+
+ //-- methods: whole-object manipulation
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_clear,
+ gensym("clear"),
+ A_NULL);
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_alphabet,
+ gensym("alphabet"),
+ A_DEFSYM,
+ A_NULL);
+
+
+ //-- methods: insert
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_insert,
+ gensym("insert"),
+ A_GIMME,
+ A_NULL);
+
+ //-- methods: safe access: atom->label
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_atom2label,
+ gensym("atom2char"),
+ A_GIMME,
+ A_NULL);
+ /*
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_atom2label,
+ gensym("a2c"),
+ A_GIMME,
+ A_NULL);
+ */
+
+ //-- methods: destructive access: atom->label
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_atom2label_force,
+ gensym("atom2char!"),
+ A_GIMME,
+ A_NULL);
+ /*
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_atom2label_force,
+ gensym("a2c!"),
+ A_GIMME,
+ A_NULL);
+ */
+
+
+ //-- methods: safe access: label->atom
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_label2atom,
+ gensym("char2atom"),
+ A_FLOAT,
+ A_NULL);
+ /*
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_label2atom,
+ gensym("c2a"),
+ A_FLOAT,
+ A_NULL);
+ */
+
+ //-- methods: destructive access: label->atom
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_label2atom_force,
+ gensym("char2atom!"),
+ A_FLOAT,
+ A_NULL);
+ /*
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_label2atom_force,
+ gensym("c2a!"),
+ A_FLOAT,
+ A_NULL);
+ */
+
+ //-- methods: removal
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_rmatom,
+ gensym("rmatom"),
+ A_GIMME,
+ A_NULL);
+ class_addmethod(pd_gfsm_alphabet_obj_class,
+ (t_method)pd_gfsm_alphabet_obj_rmlabel,
+ gensym("rmchar"),
+ A_FLOAT,
+ A_NULL);
+
+
+ //-- help symbol
+ class_sethelpsymbol(pd_gfsm_alphabet_obj_class, gensym("gfsm_alphabet-help.pd"));
+}
diff --git a/gfsm/src/pd_alphabet.h b/gfsm/src/pd_alphabet.h
new file mode 100644
index 0000000..e426fd4
--- /dev/null
+++ b/gfsm/src/pd_alphabet.h
@@ -0,0 +1,78 @@
+/*=============================================================================*\
+ * File: pd_alphabet.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifndef _PD_GFSM_ALPHABET_H
+#define _PD_GFSM_ALPHABET_H
+
+#include <m_pd.h>
+#include <gfsm.h>
+#include <atom_alphabet.h>
+
+
+/*--------------------------------------------------------------
+ * pd_gfsm_alphabet
+ */
+typedef struct _pd_gfsm_alphabet_pd
+{
+ t_pd x_pd;
+ t_symbol *x_name;
+ size_t x_refcnt;
+ gfsmAlphabet *x_alphabet; //-- really a (gfsmPdAtomAlphabet*)
+} t_pd_gfsm_alphabet_pd;
+
+
+/*--------------------------------------------------------------
+ * pd_gfsm_alphabet
+ */
+typedef struct _pd_gfsm_alphabet_obj
+{
+ t_object x_obj;
+ t_pd_gfsm_alphabet_pd *x_alphabet_pd;
+ t_outlet *x_labout;
+ t_outlet *x_keyout;
+} t_pd_gfsm_alphabet_obj;
+
+
+/*--------------------------------------------------------------
+ * pd_gfsm_alphabet: methods
+ */
+//-- finds pd_gfsm_alphabet named 'name', returns NULL if it doesn't exist
+t_pd_gfsm_alphabet_pd *pd_gfsm_alphabet_pd_find(t_symbol *name);
+
+//-- finds pd_gfsm_alphabet named 'name', creating it if it doesn't exist
+t_pd_gfsm_alphabet_pd *pd_gfsm_alphabet_pd_get(t_symbol *name);
+
+//-- releases one reference to pd_gfsm_alphabet named 'name', possibly freeing the pd_gfsm_alphabet
+void pd_gfsm_alphabet_pd_release(t_pd_gfsm_alphabet_pd *x);
+
+/*--------------------------------------------------------------
+ * setup methods
+ */
+void pd_gfsm_alphabet_setup(void);
+
+
+#endif /* _PD_GFSM_ALPHABET_H */
diff --git a/gfsm/src/pd_automaton.c b/gfsm/src/pd_automaton.c
new file mode 100644
index 0000000..47ce4cd
--- /dev/null
+++ b/gfsm/src/pd_automaton.c
@@ -0,0 +1,765 @@
+/*=============================================================================*\
+ * File: pd_automaton.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pd_automaton.h>
+#include <pd_io.h>
+#include <m_pd.h>
+
+/*--------------------------------------------------------------------
+ * DEBUG
+ *--------------------------------------------------------------------*/
+//#define PDFSM_DEBUG 1
+
+/*=====================================================================
+ * Structures and Types
+ *=====================================================================*/
+static t_class *pd_gfsm_automaton_pd_class;
+static t_class *pd_gfsm_automaton_obj_class;
+
+/*=====================================================================
+ * pd_gfsm_automaton_pd: Methods
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_pd: new()
+ */
+static void *pd_gfsm_automaton_pd_new(t_symbol *name)
+{
+ t_pd_gfsm_automaton_pd *x = (t_pd_gfsm_automaton_pd *)pd_new(pd_gfsm_automaton_pd_class);
+
+ //-- debug
+#ifdef PDFSM_DEBUG
+ post("pd_gfsm_automaton_pd_new() called; name=%s ; x=%p\n", name->s_name, x);
+#endif
+
+ //-- defaults
+ x->x_refcnt = 0;
+ x->x_name = name;
+ x->x_automaton = gfsm_automaton_new();
+
+ //-- bindings
+ if (name != &s_) pd_bind((t_pd*)x, name);
+
+ return (void *)x;
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_pd: free()
+ */
+static void pd_gfsm_automaton_pd_free(t_pd_gfsm_automaton_pd *x)
+{
+#ifdef PDFSM_DEBUG
+ post("pd_gfsm_automaton_pd_free() called ; x=%p", x);
+#endif
+
+ if (x->x_automaton) gfsm_automaton_free(x->x_automaton);
+ x->x_automaton = NULL;
+
+ /* unbind the symbol of the name of hashtable in pd's global namespace */
+ if (x->x_name != &s_) pd_unbind((t_pd*)x, x->x_name);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_pd: setup()
+ */
+void pd_gfsm_automaton_pd_setup(void)
+{
+ //-- class
+ pd_gfsm_automaton_pd_class = class_new(gensym("pd_gfsm_automaton_pd"),
+ (t_newmethod)pd_gfsm_automaton_pd_new,
+ (t_method)pd_gfsm_automaton_pd_free,
+ sizeof(t_pd_gfsm_automaton_pd),
+ CLASS_PD,
+ A_DEFSYM,
+ A_NULL);
+}
+
+/*=====================================================================
+ * Utilities
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_pd_find()
+ */
+t_pd_gfsm_automaton_pd *pd_gfsm_automaton_pd_find(t_symbol *name)
+{
+ if (name != &s_)
+ return (t_pd_gfsm_automaton_pd*)pd_findbyclass(name,pd_gfsm_automaton_pd_class);
+ return NULL;
+}
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_pd_get()
+ */
+t_pd_gfsm_automaton_pd *pd_gfsm_automaton_pd_get(t_symbol *name)
+{
+ t_pd_gfsm_automaton_pd *x = pd_gfsm_automaton_pd_find(name);
+ if (!x) {
+ x = (t_pd_gfsm_automaton_pd*)pd_gfsm_automaton_pd_new(name);
+ x->x_refcnt = 0;
+ }
+ return x;
+}
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_pd: release()
+ */
+void pd_gfsm_automaton_pd_release(t_pd_gfsm_automaton_pd *x)
+{
+ if (x) {
+ if (x->x_refcnt) --x->x_refcnt;
+ if (!x->x_refcnt) pd_gfsm_automaton_pd_free(x);
+ }
+}
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_obj: outlet_symbol()
+ */
+void pd_gfsm_automaton_obj_outlet_symbol(t_pd_gfsm_automaton_obj *x, t_symbol *sel, t_symbol *val)
+{
+ SETSYMBOL(x->x_argv, val);
+ outlet_anything(x->x_valout, sel, 1, x->x_argv);
+}
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_obj: outlet_symbol()
+ */
+void pd_gfsm_automaton_obj_outlet_symbol_float(t_pd_gfsm_automaton_obj *x, t_symbol *sel, t_symbol *sym, t_float f)
+{
+ SETSYMBOL(x->x_argv, sym);
+ SETFLOAT(x->x_argv+1, f);
+ outlet_anything(x->x_valout, sel, 2, x->x_argv);
+}
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_obj: outlet_float()
+ */
+void pd_gfsm_automaton_obj_outlet_float(t_pd_gfsm_automaton_obj *x, t_symbol *sel, t_float f)
+{
+ SETFLOAT(x->x_argv, f);
+ outlet_anything(x->x_valout, sel, 1, x->x_argv);
+}
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_obj: outlet_float_2()
+ */
+void pd_gfsm_automaton_obj_outlet_float_2(t_pd_gfsm_automaton_obj *x, t_symbol *sel, t_float f1, t_float f2)
+{
+ SETFLOAT(x->x_argv , f1);
+ SETFLOAT(x->x_argv+1, f2);
+ outlet_anything(x->x_valout, sel, 2, x->x_argv);
+}
+
+/*--------------------------------------------------------------------
+ * Utilties: pd_gfsm_automaton_obj: outlet_bang()
+ */
+void pd_gfsm_automaton_obj_outlet_bang(t_pd_gfsm_automaton_obj *x, t_symbol *sel)
+{
+ SETSYMBOL(x->x_argv, &s_bang);
+ outlet_anything(x->x_valout, sel, 1, x->x_argv);
+}
+
+
+
+/*=====================================================================
+ * pd_gfsm_automaton_obj: Methods
+ *=====================================================================*/
+
+/*=====================================================================
+ * Constructors, etc.
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: new
+ */
+static void *pd_gfsm_automaton_obj_new(t_symbol *name)
+{
+ t_pd_gfsm_automaton_obj *x =
+ (t_pd_gfsm_automaton_obj *)pd_new(pd_gfsm_automaton_obj_class);
+
+#ifdef PDFSM_DEBUG
+ post("pd_gfsm_automaton_obj_new() called: name=%s ; x=%p",
+ (name ? name->s_name : "(null)"),
+ x);
+#endif
+
+ //-- defaults
+ //x->x_automaton_pd = NULL;
+
+ //-- bindings
+ x->x_automaton_pd = pd_gfsm_automaton_pd_get(name);
+ x->x_automaton_pd->x_refcnt++;
+
+ //-- outlets
+ x->x_valout = outlet_new(&x->x_obj, &s_anything); //-- value outlet
+
+ return (void *)x;
+}
+
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: free
+ */
+static void pd_gfsm_automaton_obj_free(t_pd_gfsm_automaton_obj *x)
+{
+#ifdef PDFSM_DEBUG
+ post("pd_gfsm_automaton_obj_free() called: x=%p", x);
+#endif
+
+ pd_gfsm_automaton_pd_release(x->x_automaton_pd);
+
+ //-- do we need to do this?
+ outlet_free(x->x_valout);
+}
+
+/*=====================================================================
+ * automaton_obj: Basic Accessors
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: automaton
+ */
+static void pd_gfsm_automaton_obj_automaton(t_pd_gfsm_automaton_obj *x, t_symbol *name)
+{
+ if (name != x->x_automaton_pd->x_name) {
+ pd_gfsm_automaton_pd_release(x->x_automaton_pd);
+ x->x_automaton_pd = pd_gfsm_automaton_pd_get(name);
+ ++x->x_automaton_pd->x_refcnt;
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("automaton"), name);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: size()
+ */
+static void pd_gfsm_automaton_obj_size(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ if (argc > 0) {
+ gfsmStateId n = (gfsmStateId)atom_getfloatarg(0,argc,argv);
+ gfsm_automaton_reserve(x->x_automaton_pd->x_automaton, n);
+ }
+ pd_gfsm_automaton_obj_outlet_float
+ (x, sel, (t_float)gfsm_automaton_n_states(x->x_automaton_pd->x_automaton));
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: clear()
+ */
+static void pd_gfsm_automaton_obj_clear(t_pd_gfsm_automaton_obj *x)
+{
+ gfsm_automaton_clear(x->x_automaton_pd->x_automaton);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("clear"));
+}
+
+/*=====================================================================
+ * automaton_obj: flags
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: root()
+ */
+static void pd_gfsm_automaton_obj_root(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ gfsmStateId q0;
+ if (argc > 0) {
+ q0 = (gfsmStateId)atom_getintarg(0,argc,argv);
+ gfsm_automaton_set_root(x->x_automaton_pd->x_automaton, q0);
+ } else {
+ q0 = gfsm_automaton_get_root(x->x_automaton_pd->x_automaton);
+ }
+
+ if (q0==gfsmNoState) pd_gfsm_automaton_obj_outlet_bang(x, sel);
+ else pd_gfsm_automaton_obj_outlet_float(x, sel, (t_float)q0);
+}
+
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: weighted()
+ */
+static void pd_gfsm_automaton_obj_weighted(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ if (argc > 0)
+ x->x_automaton_pd->x_automaton->flags.is_weighted = atom_getboolarg(0,argc,argv);
+ pd_gfsm_automaton_obj_outlet_float
+ (x, sel, (t_float)(x->x_automaton_pd->x_automaton->flags.is_weighted));
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: transducer()
+ */
+static void pd_gfsm_automaton_obj_transducer(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ if (argc > 0)
+ x->x_automaton_pd->x_automaton->flags.is_transducer = atom_getboolarg(0,argc,argv);
+ pd_gfsm_automaton_obj_outlet_float
+ (x, sel, (t_float)(x->x_automaton_pd->x_automaton->flags.is_transducer));
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: semiring()
+ */
+static void pd_gfsm_automaton_obj_semiring(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ t_symbol *srsym;
+ if (argc > 0) {
+ srsym = atom_getsymbolarg(0,argc,argv);
+ gfsm_automaton_set_semiring_type(x->x_automaton_pd->x_automaton,
+ gfsm_sr_name_to_type(srsym->s_name));
+ }
+ srsym = gensym(gfsm_sr_type_to_name(x->x_automaton_pd->x_automaton->sr->type));
+ pd_gfsm_automaton_obj_outlet_symbol(x, sel, srsym);
+}
+
+/*=====================================================================
+ * automaton_obj: state properties
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: final()
+ */
+static void pd_gfsm_automaton_obj_final(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ gboolean ans = FALSE;
+ t_float qf = atom_getfloatarg(0,argc,argv);
+ if (qf<0) qf = -qf;
+ if (argc > 1) {
+ ans = atom_getboolarg(1,argc,argv);
+ gfsm_automaton_set_final_state(x->x_automaton_pd->x_automaton, (gfsmStateId)qf, ans);
+ } else {
+ ans = gfsm_automaton_is_final_state(x->x_automaton_pd->x_automaton, (gfsmStateId)qf);
+ }
+ pd_gfsm_automaton_obj_outlet_float_2(x, sel, qf, (t_float)ans);
+}
+
+
+/*=====================================================================
+ * automaton_obj: states & arcs
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: add_state()
+ */
+static void pd_gfsm_automaton_obj_add_state(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ gfsmStateId id;
+ if (argc>0) id = (gfsmStateId)atom_getfloatarg(0,argc,argv);
+ else id = gfsmNoState;
+
+ id = gfsm_automaton_ensure_state(x->x_automaton_pd->x_automaton, id);
+ pd_gfsm_automaton_obj_outlet_float(x, sel, (t_float)id);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: add_arc()
+ */
+static void pd_gfsm_automaton_obj_add_arc(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ t_float qsrc=0, qdst=0;
+ t_float clo=0, chi=0;
+ t_float w=0;
+ if (argc < 2) {
+ error("gfsm_automaton: add_arc(): not enough arguments!");
+ return;
+ }
+ switch (argc) {
+ case 5: //-- +from, +to, +lo, +hi, +weight
+ w = atom_getfloat(argv+4);
+ case 4: //-- +from, +to, +lo, +hi, -weight
+ chi = atom_getfloat(argv+3);
+ case 3: //-- +from, +to, +lo, -hi, -weight
+ clo = atom_getfloat(argv+2);
+ case 2: //-- +from, +to, -lo, -hi, -weight
+ default:
+ qdst = atom_getfloat(argv+1);
+ qsrc = atom_getfloat(argv);
+
+ if (qdst<0) qdst = -qdst;
+ if (qsrc<0) qsrc = -qsrc;
+ break;
+ }
+
+ gfsm_automaton_add_arc(x->x_automaton_pd->x_automaton,
+ (gfsmStateId)qsrc,
+ (gfsmStateId)qdst,
+ (gfsmLabelId)clo,
+ (gfsmLabelId)chi,
+ (gfsmWeight)w);
+
+#ifdef PDFSM_DEBUG
+ post("pd_gfsm_automaton_obj_add_arc(): node(qsrc=%ld).out_degree=%u",
+ qsrc,
+ gfsm_automaton_out_degree(x->x_automaton_pd->x_automaton, qsrc));
+#endif
+
+ //-- output
+ SETFLOAT(x->x_argv , (t_float)qsrc);
+ SETFLOAT(x->x_argv+1, (t_float)qdst);
+ SETFLOAT(x->x_argv+2, (t_float)clo);
+ SETFLOAT(x->x_argv+3, (t_float)chi);
+ SETFLOAT(x->x_argv+4, (t_float)w);
+ outlet_anything(x->x_valout, sel, 5, x->x_argv);
+}
+
+/*=====================================================================
+ * automaton_obj: Text I/O
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: print()
+ */
+static void pd_gfsm_automaton_obj_print(t_pd_gfsm_automaton_obj *x)
+{
+ gfsmError *errp = NULL;
+ gfsmIOHandle *ioh = pd_gfsm_console_handle_new();
+ gfsm_automaton_print_handle(x->x_automaton_pd->x_automaton,
+ ioh, NULL,NULL,NULL, &errp);
+ if (errp) {
+ error("gfsm_automaton: print(): Error: %s\n", errp->message);
+ g_error_free(errp);
+ }
+ pd_gfsm_console_handle_free(ioh);
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("print"));
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: load_txt()
+ */
+static void pd_gfsm_automaton_obj_load_txt(t_pd_gfsm_automaton_obj *x, t_symbol *s)
+{
+ gfsmError *errp = NULL;
+ gfsm_automaton_compile_filename(x->x_automaton_pd->x_automaton, s->s_name, &errp);
+ if (errp) {
+ error("gfsm_automaton: load_txt(%s): Error: %s\n", s->s_name, errp->message);
+ g_error_free(errp);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("load"), s);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: save_txt()
+ */
+static void pd_gfsm_automaton_obj_save_txt(t_pd_gfsm_automaton_obj *x, t_symbol *s)
+{
+ gfsmError *errp = NULL;
+ gfsm_automaton_print_filename(x->x_automaton_pd->x_automaton, s->s_name, &errp);
+ if (errp) {
+ error("gfsm_automaton: save_txt(%s): Error: %s\n", s->s_name, errp->message);
+ g_error_free(errp);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("save"), s);
+}
+
+
+/*=====================================================================
+ * automaton_obj: Binary I/O
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: load_bin()
+ */
+static void pd_gfsm_automaton_obj_load_bin(t_pd_gfsm_automaton_obj *x, t_symbol *s)
+{
+ gfsmError *errp = NULL;
+ gfsm_automaton_load_bin_filename(x->x_automaton_pd->x_automaton, s->s_name, &errp);
+ if (errp) {
+ error("gfsm_automaton: load_bin(%s): Error: %s\n", s->s_name, errp->message);
+ g_error_free(errp);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("load_bin"), s);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: save_bin()
+ */
+static void pd_gfsm_automaton_obj_save_bin(t_pd_gfsm_automaton_obj *x, t_symbol *s, t_float zlevel)
+{
+ gfsmError *errp = NULL;
+ gfsm_automaton_save_bin_filename(x->x_automaton_pd->x_automaton, s->s_name, (int)zlevel, &errp);
+ if (errp) {
+ error("gfsm_automaton: save_bin(%s,%d): Error: %s\n", s->s_name, (int)zlevel, errp->message);
+ g_error_free(errp);
+ }
+ pd_gfsm_automaton_obj_outlet_symbol_float(x, gensym("save_bin"), s, (int)zlevel);
+}
+
+
+/*=====================================================================
+ * automaton_obj: info
+ */
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: info()
+ */
+static void pd_gfsm_automaton_obj_info(t_pd_gfsm_automaton_obj *x)
+{
+ gfsmAutomaton *fsm = x->x_automaton_pd->x_automaton;
+ guint n_eps_i, n_eps_o, n_eps_io;
+
+#define bool2char(b) ((b) ? 'y' : 'n')
+
+ post("-- GFSM Automaton Info --");
+ post("%-24s: %s", "Name", x->x_automaton_pd->x_name->s_name);
+ post("%-24s: %s", "Semiring", gfsm_sr_type_to_name(fsm->sr->type));
+ post("%-24s: %c", "Transducer?", bool2char(gfsm_automaton_is_transducer(fsm)));
+ post("%-24s: %c", "Weighted?", bool2char(gfsm_automaton_is_weighted(fsm)));
+ post("%-24s: %c", "Deterministic?", bool2char(fsm->flags.is_deterministic));
+ post("%-24s: %s", "Sort Mode", gfsm_arc_sortmode_to_name(gfsm_automaton_sortmode(fsm)));
+ if (fsm->root_id == gfsmNoState)
+ post("%-24s: %s", "Initial state", "(none)");
+ else
+ post("%-24s: %u", "Initial state", fsm->root_id);
+ post("%-24s: %u", "# of states", gfsm_automaton_n_states(fsm));
+ post("%-24s: %u", "# of final states", gfsm_automaton_n_final_states(fsm));
+ post("%-24s: %u", "# of arcs", gfsm_automaton_n_arcs_full(fsm, &n_eps_i, &n_eps_o, &n_eps_io));
+ post("%-24s: %u", "# of i/o epsilon arcs", n_eps_io);
+ post("%-24s: %u", "# of input epsilon arcs", n_eps_i);
+ post("%-24s: %u", "# of output epsilon arcs", n_eps_o);
+ post("%-24s: %c", "cyclic?", bool2char(gfsm_automaton_is_cyclic(fsm)));
+ //...
+
+#undef bool2char
+
+ pd_gfsm_automaton_obj_outlet_bang(x, gensym("info"));
+}
+
+
+/*=====================================================================
+ * automaton_obj: draw
+ */
+
+/*--------------------------------------------------------------------
+ * automaton_obj: draw_dot()
+ */
+static void pd_gfsm_automaton_obj_draw_dot(t_pd_gfsm_automaton_obj *x, GIMME_ARGS)
+{
+ t_pd_gfsm_alphabet_pd *ialph=NULL, *oalph=NULL, *salph=NULL;
+ t_symbol
+ *filename = atom_getsymbolarg(0,argc,argv),
+ *title = x->x_automaton_pd->x_name,
+ *fontname = NULL;
+ float
+ width=0,
+ height=0,
+ nodesep=0,
+ ranksep=0;
+ int fontsize=0;
+ gboolean
+ portrait=FALSE,
+ vertical=FALSE;
+ gfsmError *errp = NULL;
+ int i;
+
+ for (i=1; i < argc; i++) {
+ t_symbol *opt = atom_getsymbolarg(i,argc,argv);
+
+ //--debug
+ //post("gfsm_automaton: draw_dot: checking option '%s'", opt->s_name);
+
+ if (opt==gensym("ilabels")) {
+ if (ialph) pd_gfsm_alphabet_pd_release(ialph);
+ ialph = pd_gfsm_alphabet_pd_find(atom_getsymbolarg(++i,argc,argv));
+ if (ialph) ialph->x_refcnt++;
+ }
+ else if (opt==gensym("olabels")) {
+ if (oalph) pd_gfsm_alphabet_pd_release(oalph);
+ oalph = pd_gfsm_alphabet_pd_find(atom_getsymbolarg(++i,argc,argv));
+ if (oalph) oalph->x_refcnt++;
+ }
+ else if (opt==gensym("slabels")) {
+ if (salph) pd_gfsm_alphabet_pd_release(salph);
+ salph = pd_gfsm_alphabet_pd_find(atom_getsymbolarg(++i,argc,argv));
+ if (salph) salph->x_refcnt++;
+ }
+ else if (opt==gensym("title")) title = atom_getsymbolarg(++i,argc,argv);
+ else if (opt==gensym("width")) width = atom_getfloatarg(++i,argc,argv);
+ else if (opt==gensym("height")) height = atom_getfloatarg(++i,argc,argv);
+ else if (opt==gensym("fontsize")) fontsize = atom_getintarg(++i,argc,argv);
+ else if (opt==gensym("fontname")) fontname = atom_getsymbolarg(++i,argc,argv);
+ else if (opt==gensym("portrait")) portrait = atom_getboolarg(++i,argc,argv);
+ else if (opt==gensym("vertical")) vertical = atom_getboolarg(++i,argc,argv);
+ else if (opt==gensym("nodesep")) nodesep = atom_getfloatarg(++i,argc,argv);
+ else if (opt==gensym("ranksep")) ranksep = atom_getfloatarg(++i,argc,argv);
+ else {
+ char buf[64];
+ atom_string(argv+i, buf, 64);
+ error("gfsm_automaton: draw_dot: unknown option '%s' ignored", buf);
+ }
+ }
+
+ gfsm_automaton_draw_dot_filename_full(x->x_automaton_pd->x_automaton,
+ filename->s_name,
+ (ialph ? ialph->x_alphabet : NULL),
+ (oalph ? oalph->x_alphabet : NULL),
+ (salph ? salph->x_alphabet : NULL),
+ title->s_name,
+ width,
+ height,
+ fontsize,
+ (fontname ? fontname->s_name : NULL),
+ portrait,
+ vertical,
+ nodesep,
+ ranksep,
+ &errp);
+
+ if (errp) {
+ error("gfsm_automaton: draw_dot(%s): Error: %s\n", filename->s_name, errp->message);
+ g_error_free(errp);
+ }
+
+ //-- cleanup
+ if (ialph) pd_gfsm_alphabet_pd_release(ialph);
+ if (oalph) pd_gfsm_alphabet_pd_release(oalph);
+ if (salph) pd_gfsm_alphabet_pd_release(salph);
+
+ pd_gfsm_automaton_obj_outlet_symbol(x, gensym("draw_dot"), filename);
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton_obj: setup()
+ */
+static void pd_gfsm_automaton_obj_setup(void)
+{
+ //-- class
+ pd_gfsm_automaton_obj_class = class_new(gensym("gfsm_automaton"),
+ (t_newmethod)pd_gfsm_automaton_obj_new,
+ (t_method)pd_gfsm_automaton_obj_free,
+ sizeof(t_pd_gfsm_automaton_obj),
+ CLASS_DEFAULT,
+ A_DEFSYM,
+ A_NULL);
+
+ //-- methods: automaton
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_automaton,
+ gensym("automaton"),
+ A_DEFSYM, A_NULL);
+
+ //-- methods: flags
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_root,
+ gensym("root"),
+ A_GIMME, A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_weighted,
+ gensym("weighted"),
+ A_GIMME, A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_transducer,
+ gensym("transducer"),
+ A_GIMME, A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_semiring,
+ gensym("semiring"),
+ A_GIMME, A_NULL);
+
+ //-- methods: size
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_size,
+ gensym("size"),
+ A_GIMME, A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_clear,
+ gensym("clear"),
+ A_NULL);
+
+ //-- methods: state properties
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_final,
+ gensym("final"),
+ A_GIMME, A_NULL);
+
+ //-- methods: states & arcs
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_add_state,
+ gensym("add_state"),
+ A_GIMME, A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_add_arc,
+ gensym("add_arc"),
+ A_GIMME, //-- qsrc,qdst,clo,chi,weight
+ A_NULL);
+
+
+ //-- methods: I/O: text
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_print,
+ gensym("print"),
+ A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_load_txt,
+ gensym("load"),
+ A_SYMBOL, A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_save_txt,
+ gensym("save"),
+ A_SYMBOL, A_NULL);
+
+ //-- methods: I/O: binary
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_load_bin,
+ gensym("load_bin"),
+ A_SYMBOL, A_NULL);
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_save_bin,
+ gensym("save_bin"),
+ A_SYMBOL, A_DEFFLOAT, A_NULL);
+
+ //-- methods: info
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_info,
+ gensym("info"),
+ A_NULL);
+
+ //-- methods: draw
+ class_addmethod(pd_gfsm_automaton_obj_class,
+ (t_method)pd_gfsm_automaton_obj_draw_dot,
+ gensym("draw_dot"),
+ A_GIMME, A_NULL);
+
+ //-- help symbol
+ class_sethelpsymbol(pd_gfsm_automaton_obj_class, gensym("gfsm_automaton-help.pd"));
+}
+
+
+/*=====================================================================
+ * automaton setup
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_automaton: setup()
+ */
+void pd_gfsm_automaton_setup(void)
+{
+ pd_gfsm_automaton_pd_setup();
+ pd_gfsm_automaton_obj_setup();
+ pd_gfsm_algebra_setup(pd_gfsm_automaton_obj_class);
+}
diff --git a/gfsm/src/pd_automaton.h b/gfsm/src/pd_automaton.h
new file mode 100644
index 0000000..ed95954
--- /dev/null
+++ b/gfsm/src/pd_automaton.h
@@ -0,0 +1,85 @@
+/*=============================================================================*\
+ * File: pd_automaton.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+/*=====================================================================
+ * Protos
+ *=====================================================================*/
+#ifndef PD_GFSM_AUTOMATON_H
+#define PD_GFSM_AUTOMATON_H
+
+/*----------------------------------------------------------------------
+ * includes
+ */
+#include <m_pd.h>
+#include <gfsm.h>
+#include <pd_alphabet.h>
+
+/*--------------------------------------------------------------
+ * pd_fsm_automaton_pd
+ */
+typedef struct _pd_gfsm_automaton_pd
+{
+ t_pd x_pd;
+ t_symbol *x_name;
+ size_t x_refcnt;
+ gfsmAutomaton *x_automaton;
+} t_pd_gfsm_automaton_pd;
+
+typedef struct _pd_gfsm_automaton_obj
+{
+ t_object x_obj;
+ t_pd_gfsm_automaton_pd *x_automaton_pd;
+ t_atom x_argv[5];
+ t_outlet *x_valout;
+} t_pd_gfsm_automaton_obj;
+
+/*--------------------------------------------------------------------
+ * utility macros
+ */
+#define atom_getboolarg(which,argc,argv) (atom_getintarg(which,argc,argv)==0 ? FALSE : TRUE)
+#define GIMME_ARGS t_symbol *sel, int argc, t_atom *argv
+
+/*----------------------------------------------------------------------
+ * utilities
+ */
+t_pd_gfsm_automaton_pd *pd_gfsm_automaton_pd_find(t_symbol *name);
+t_pd_gfsm_automaton_pd *pd_gfsm_automaton_pd_get(t_symbol *name);
+void pd_gfsm_automaton_pd_release(t_pd_gfsm_automaton_pd *x);
+
+void pd_gfsm_automaton_obj_outlet_symbol(t_pd_gfsm_automaton_obj *x, t_symbol *sel, t_symbol *val);
+void pd_gfsm_automaton_obj_outlet_float(t_pd_gfsm_automaton_obj *x, t_symbol *sel, t_float f);
+void pd_gfsm_automaton_obj_outlet_float_2(t_pd_gfsm_automaton_obj *x, t_symbol *sel, t_float f1, t_float f2);
+void pd_gfsm_automaton_obj_outlet_bang(t_pd_gfsm_automaton_obj *x, t_symbol *sel);
+
+/*----------------------------------------------------------------------
+ * setup routines
+ */
+extern void pd_gfsm_algebra_setup(t_class *automaton_class);
+
+void pd_gfsm_automaton_setup(void);
+
+#endif /* PD_GFSM_AUTOMATON_H */
diff --git a/gfsm/src/pd_gfsm.c b/gfsm/src/pd_gfsm.c
new file mode 100644
index 0000000..2deb6c8
--- /dev/null
+++ b/gfsm/src/pd_gfsm.c
@@ -0,0 +1,93 @@
+/*=============================================================================*\
+ * File: pd_gfsm.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pd_gfsm.h>
+#include <pd_alphabet.h>
+
+#define USE_AUTOMATA
+
+#ifdef USE_AUTOMATA
+# include <pd_automaton.h>
+# include <pd_state.h>
+#endif
+
+/*=====================================================================
+ * Structures and Types
+ *=====================================================================*/
+static t_class *pd_gfsm_dummy_class;
+
+/*=====================================================================
+ * pd_gfsm_dummy
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_dummy: new()
+ */
+static void *pd_gfsm_dummy_new(void)
+{
+ t_pd_gfsm_dummy *x = (t_pd_gfsm_dummy *)pd_new(pd_gfsm_dummy_class);
+ return (void *)x;
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_dummy: free()
+ */
+static void pd_gfsm_dummy_free(t_pd_gfsm_dummy *x)
+{}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_dummy: setup()
+ */
+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");
+
+ //-- library
+ pd_gfsm_alphabet_setup();
+#ifdef USE_AUTOMATA
+ pd_gfsm_automaton_setup();
+ pd_gfsm_state_setup();
+#endif
+
+ //-- class (dummy)
+ pd_gfsm_dummy_class = class_new(gensym("gfsm"),
+ (t_newmethod)pd_gfsm_dummy_new,
+ (t_method)pd_gfsm_dummy_free,
+ sizeof(t_pd_gfsm_dummy),
+ CLASS_DEFAULT,
+ A_NULL);
+
+ //-- help symbol
+ class_sethelpsymbol(pd_gfsm_dummy_class, gensym("gfsm-help.pd"));
+}
diff --git a/gfsm/src/pd_gfsm.h b/gfsm/src/pd_gfsm.h
new file mode 100644
index 0000000..e65069e
--- /dev/null
+++ b/gfsm/src/pd_gfsm.h
@@ -0,0 +1,54 @@
+/*=============================================================================*\
+ * File: pd_gfsm.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+/*=====================================================================
+ * Protos
+ *=====================================================================*/
+#ifndef PD_GFSM_H
+#define PD_GFSM_H
+
+/*----------------------------------------------------------------------
+ * includes
+ */
+#include <m_pd.h>
+#include <gfsm.h>
+
+/*----------------------------------------------------------------------
+ * structures and types
+ */
+typedef struct _pd_gfsm_dummy
+{
+ t_object x_obj;
+} t_pd_gfsm_dummy;
+
+
+/*----------------------------------------------------------------------
+ * setup routines
+ */
+void gfsm_setup(void);
+
+#endif /* PD_GFSM_H */
diff --git a/gfsm/src/pd_io.c b/gfsm/src/pd_io.c
new file mode 100644
index 0000000..5f82c2c
--- /dev/null
+++ b/gfsm/src/pd_io.c
@@ -0,0 +1,75 @@
+/*=============================================================================*\
+ * File: pd_io.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd: I/O
+ *
+ * Copyright (c) 2006 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pd_io.h>
+
+/*=====================================================================
+ * I/O utilities
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_console_handle_flush()
+ */
+static void pd_gfsm_console_handle_flush(gfsmPosGString *pgs)
+{
+ if (pgs->gs->len) post(pgs->gs->str);
+ g_string_truncate(pgs->gs,0);
+ pgs->pos = 0;
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_console_handle_new()
+ */
+gfsmIOHandle *pd_gfsm_console_handle_new(void)
+{
+ GString *gs = g_string_new("");
+ gfsmPosGString *pgs = g_new(gfsmPosGString,1);
+ gfsmIOHandle *ioh;
+ pgs->gs = gs;
+ pgs->pos = 0;
+
+ ioh = gfsmio_new_gstring(pgs);
+ ioh->flush_func = (gfsmIOFlushFunc)pd_gfsm_console_handle_flush;
+
+ return ioh;
+}
+
+/*--------------------------------------------------------------------
+ * pd_gfsm_console_handle_free()
+ */
+void pd_gfsm_console_handle_free(gfsmIOHandle *ioh)
+{
+ gfsmPosGString *pgs = (gfsmPosGString*)ioh->handle;
+ gfsmio_flush(ioh);
+ g_string_free(pgs->gs,TRUE);
+ g_free(pgs);
+ g_free(ioh);
+}
diff --git a/gfsm/src/pd_io.h b/gfsm/src/pd_io.h
new file mode 100644
index 0000000..83de85b
--- /dev/null
+++ b/gfsm/src/pd_io.h
@@ -0,0 +1,47 @@
+/*=============================================================================*\
+ * File: pd_io.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd; I/O
+ *
+ * Copyright (c) 2006 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+/*=====================================================================
+ * Protos
+ *=====================================================================*/
+#ifndef PD_GFSM_IO_H
+#define PD_GFSM_IO_H
+
+/*----------------------------------------------------------------------
+ * includes
+ */
+#include <m_pd.h>
+#include <gfsm.h>
+
+/*----------------------------------------------------------------------
+ * I/O stuff
+ */
+gfsmIOHandle *pd_gfsm_console_handle_new(void);
+
+void pd_gfsm_console_handle_free(gfsmIOHandle *ioh);
+
+#endif /* PD_GFSM_IO_H */
diff --git a/gfsm/src/pd_state.c b/gfsm/src/pd_state.c
new file mode 100644
index 0000000..b7cd938
--- /dev/null
+++ b/gfsm/src/pd_state.c
@@ -0,0 +1,303 @@
+/*=============================================================================*\
+ * File: pd_state.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pd_state.h>
+
+/*=====================================================================
+ * Structures and Types
+ *=====================================================================*/
+static t_class *pd_gfsm_state_class;
+
+
+/*=====================================================================
+ * pd_gfsm_state: Methods
+ *=====================================================================*/
+
+/*=====================================================================
+ * Constructors, etc.
+ */
+
+/*--------------------------------------------------------------------
+ * new()
+ */
+static void *pd_gfsm_state_new(t_symbol *sel, int argc, t_atom *argv)
+{
+ t_symbol *name = &s_;
+ t_pd_gfsm_state *x = (t_pd_gfsm_state *)pd_new(pd_gfsm_state_class);
+
+ //-- defaults
+ x->x_id = gfsmNoState;
+ gfsm_arciter_close(&x->x_arci);
+ x->x_open = FALSE;
+
+ //-- args
+ if (argc > 0) {
+ name = atom_getsymbolarg(0,argc,argv);
+ if (argc > 1) x->x_id = (gfsmStateId)atom_getfloatarg(1,argc,argv);
+ }
+
+ //-- bindings
+ x->x_automaton_pd = pd_gfsm_automaton_pd_get(name);
+ x->x_automaton_pd->x_refcnt++;
+
+ //-- outlets
+ x->x_valout = outlet_new(&x->x_obj, &s_anything); //-- value outlet
+
+ return (void *)x;
+}
+
+/*--------------------------------------------------------------------
+ * free
+ */
+static void pd_gfsm_state_free(t_pd_gfsm_state *x)
+{
+ gfsm_arciter_close(&x->x_arci);
+ pd_gfsm_automaton_pd_release(x->x_automaton_pd);
+
+ //-- do we need to do this?
+ outlet_free(x->x_valout);
+}
+
+/*=====================================================================
+ * Basic Accessors
+ */
+
+/*--------------------------------------------------------------------
+ * automaton
+ */
+static void pd_gfsm_state_automaton(t_pd_gfsm_state *x, t_symbol *name)
+{
+ gfsm_arciter_close(&x->x_arci);
+ x->x_open = FALSE;
+
+ if (name == x->x_automaton_pd->x_name) return;
+ pd_gfsm_automaton_pd_release(x->x_automaton_pd);
+
+ x->x_automaton_pd = pd_gfsm_automaton_pd_get(name);
+ ++x->x_automaton_pd->x_refcnt;
+}
+
+
+/*--------------------------------------------------------------------
+ * id
+ */
+static void pd_gfsm_state_id(t_pd_gfsm_state *x)
+{
+ SETSYMBOL(x->x_argv, gensym("id"));
+ if (x->x_id==gfsmNoState) SETSYMBOL(x->x_argv, &s_bang);
+ else SETFLOAT(x->x_argv, (t_float)(x->x_id));
+ outlet_anything(x->x_valout, gensym("id"), 1, x->x_argv);
+}
+
+/*--------------------------------------------------------------------
+ * set
+ */
+static void pd_gfsm_state_set(t_pd_gfsm_state *x, t_floatarg qf)
+{
+ if (qf<0) qf = -qf;
+ gfsm_arciter_close(&x->x_arci);
+ x->x_open = FALSE;
+ x->x_id = gfsm_automaton_ensure_state(x->x_automaton_pd->x_automaton, (gfsmStateId)qf);
+}
+
+/*--------------------------------------------------------------------
+ * degree
+ */
+static void pd_gfsm_state_degree(t_pd_gfsm_state *x)
+{
+ gfsmState *s = gfsm_automaton_find_state(x->x_automaton_pd->x_automaton, x->x_id);
+ SETFLOAT(x->x_argv, (s ? (t_float)gfsm_state_out_degree(s) : 0));
+ outlet_anything(x->x_valout, gensym("degree"), 1, x->x_argv);
+}
+
+/*=====================================================================
+ * Navigation
+ */
+
+/*--------------------------------------------------------------------
+ * utility: outlet_arc()
+ */
+static void pd_gfsm_state_outlet_arc(t_pd_gfsm_state *x, t_symbol *sel)
+{
+ //outlet_anything(x->x_opout, op, 0, NULL);
+ if (gfsm_arciter_ok(&x->x_arci)) {
+ gfsmArc *a = gfsm_arciter_arc(&x->x_arci);
+ SETFLOAT(x->x_argv, (t_float)(a->target));
+ SETFLOAT(x->x_argv+1, (t_float)(a->lower));
+ SETFLOAT(x->x_argv+2, (t_float)(a->upper));
+ SETFLOAT(x->x_argv+3, (t_float)(a->weight));
+ outlet_anything(x->x_valout, sel, 4, x->x_argv);
+ }
+ else {
+ SETSYMBOL(x->x_argv, &s_bang);
+ outlet_anything(x->x_valout, sel, 1, x->x_argv);
+ }
+}
+
+/*--------------------------------------------------------------------
+ * arc_first
+ */
+static void pd_gfsm_state_arc_first(t_pd_gfsm_state *x)
+{
+ gfsm_arciter_close(&x->x_arci);
+ gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id);
+ x->x_open = TRUE;
+ pd_gfsm_state_outlet_arc(x, gensym("arc_first"));
+}
+
+/*--------------------------------------------------------------------
+ * arc_next
+ */
+static void pd_gfsm_state_arc_next(t_pd_gfsm_state *x)
+{
+ gfsmState *s = gfsm_automaton_find_state(x->x_automaton_pd->x_automaton, x->x_id);
+ if (s) {
+ if (x->x_open && gfsm_arciter_ok(&x->x_arci)) {
+ gfsm_arciter_next(&x->x_arci);
+ } else if (!x->x_open) {
+ gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id);
+ x->x_open = TRUE;
+ }
+ }
+ pd_gfsm_state_outlet_arc(x, gensym("arc_next"));
+}
+
+/*--------------------------------------------------------------------
+ * arc_seek
+ */
+static void pd_gfsm_state_arc_seek(t_pd_gfsm_state *x, t_float flo, t_float fhi)
+{
+ gfsmState *s = gfsm_automaton_find_state(x->x_automaton_pd->x_automaton, x->x_id);
+ if (s) {
+ if (x->x_open && gfsm_arciter_ok(&x->x_arci)) {
+ gfsm_arciter_next(&x->x_arci);
+ } else if (!x->x_open) {
+ gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id);
+ x->x_open = TRUE;
+ }
+ }
+ gfsm_arciter_seek_both(&x->x_arci,
+ (flo < 0 ? gfsmNoLabel : ((gfsmLabelVal)flo)),
+ (fhi < 0 ? gfsmNoLabel : ((gfsmLabelVal)fhi)));
+ pd_gfsm_state_outlet_arc(x, gensym("arc_seek"));
+}
+
+
+/*--------------------------------------------------------------------
+ * arc_reset
+ */
+static void pd_gfsm_state_arc_reset(t_pd_gfsm_state *x)
+{
+ gfsm_arciter_close(&x->x_arci);
+ x->x_open = FALSE;
+}
+
+/*--------------------------------------------------------------------
+ * add_weight
+ */
+static void pd_gfsm_state_add_weight(t_pd_gfsm_state *x,
+ t_float fto,
+ t_float flo,
+ t_float fhi,
+ t_float w)
+{
+ gfsmStateId to = (fto < 0 ? (-fto) : ((gfsmStateId)fto));
+ gfsmLabelVal lo = (flo < 0 ? gfsmNoLabel : ((gfsmLabelVal)flo));
+ gfsmLabelVal hi = (fhi < 0 ? gfsmNoLabel : ((gfsmLabelVal)fhi));
+
+ if (x->x_open) pd_gfsm_state_arc_reset(x);
+
+ gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id);
+ gfsm_arciter_seek_both(&x->x_arci, lo, hi);
+
+ if (gfsm_arciter_ok(&x->x_arci)) {
+ gfsm_arciter_arc(&x->x_arci)->weight += w;
+ } else {
+ if (lo==gfsmNoLabel) lo = gfsmEpsilon;
+ if (hi==gfsmNoLabel) hi = gfsmEpsilon;
+ gfsm_automaton_add_arc(x->x_automaton_pd->x_automaton, x->x_id, to, lo, hi, w);
+ }
+
+ pd_gfsm_state_arc_reset(x);
+}
+
+
+
+/*=====================================================================
+ * Setup
+ */
+
+/*--------------------------------------------------------------------
+ * setup()
+ */
+void pd_gfsm_state_setup(void)
+{
+ //-- class
+ pd_gfsm_state_class = class_new(gensym("gfsm_state"),
+ (t_newmethod)pd_gfsm_state_new,
+ (t_method)pd_gfsm_state_free,
+ sizeof(t_pd_gfsm_state),
+ CLASS_DEFAULT,
+ A_GIMME, A_NULL);
+
+ //-- methods: automaton
+ class_addmethod(pd_gfsm_state_class,
+ (t_method)pd_gfsm_state_automaton,
+ gensym("automaton"),
+ A_DEFSYM, A_NULL);
+
+ //-- methods: id
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_id,
+ gensym("id"), A_NULL);
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_set,
+ gensym("set"), A_DEFFLOAT, A_NULL);
+
+ //-- methods: degree
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_degree,
+ gensym("degree"), A_NULL);
+
+ //-- methods: navigation
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_first,
+ gensym("arc_first"), A_NULL);
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_next,
+ gensym("arc_next"), A_NULL);
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_seek,
+ gensym("arc_seek"), A_FLOAT, A_FLOAT, A_NULL);
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_reset,
+ gensym("arc_reset"), A_NULL);
+
+ //-- methods: manipulation
+ class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_add_weight,
+ gensym("add_weight"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
+
+ //-- help symbol
+ class_sethelpsymbol(pd_gfsm_state_class, gensym("gfsm_state-help.pd"));
+}
diff --git a/gfsm/src/pd_state.h b/gfsm/src/pd_state.h
new file mode 100644
index 0000000..b2e7576
--- /dev/null
+++ b/gfsm/src/pd_state.h
@@ -0,0 +1,58 @@
+/*=============================================================================*\
+ * File: pd_state.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state automata for Pd
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * See file LICENSE for further informations on licensing terms.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+/*=====================================================================
+ * Protos
+ *=====================================================================*/
+#ifndef PD_GFSM_STATE_H
+#define PD_GFSM_STATE_H
+
+/*----------------------------------------------------------------------
+ * includes
+ */
+#include <pd_automaton.h>
+
+/*--------------------------------------------------------------
+ * pd_fsm_automaton_pd
+ */
+typedef struct _pd_gfsm_state
+{
+ t_object x_obj;
+ t_pd_gfsm_automaton_pd *x_automaton_pd;
+ gfsmStateId x_id;
+ gfsmArcIter x_arci;
+ gboolean x_open;
+ t_atom x_argv[4];
+ t_outlet *x_valout;
+} t_pd_gfsm_state;
+
+/*----------------------------------------------------------------------
+ * setup routines
+ */
+void pd_gfsm_state_setup(void);
+
+#endif /* PD_GFSM_STATE_H */
diff --git a/gfsm/src/test-alphabet.pd b/gfsm/src/test-alphabet.pd
new file mode 100644
index 0000000..4434b96
--- /dev/null
+++ b/gfsm/src/test-alphabet.pd
@@ -0,0 +1,3 @@
+#N canvas 0 0 450 300 10;
+#X obj 366 21 fsm;
+#X obj 130 127 fsm_alphabet;
diff --git a/gfsm/src/test-alphabet2.pd b/gfsm/src/test-alphabet2.pd
new file mode 100644
index 0000000..04e5928
--- /dev/null
+++ b/gfsm/src/test-alphabet2.pd
@@ -0,0 +1,44 @@
+#N canvas 484 16 460 391 10;
+#X obj 33 324 print LEFT;
+#X obj 112 324 print RIGHT;
+#X msg 24 13 alphabet foo;
+#X msg 30 37 alphabet;
+#X msg 132 7 insert x;
+#X msg 136 29 insert life 42;
+#X msg 201 79 atom2char x;
+#X msg 218 135 char2atom 42;
+#X msg 262 246 clear;
+#X msg 204 100 a2c life;
+#X msg 219 154 c2a 1;
+#X msg 262 274 print;
+#X floatatom 316 171 8 0 0 0 - - -;
+#X msg 317 191 insert z \$1;
+#X msg 405 190 c2a \$1;
+#X floatatom 408 171 5 0 0 0 - - -;
+#X msg 325 95 a2c \$1;
+#X msg 321 42 x;
+#X msg 349 42 life;
+#X msg 385 41 z;
+#X obj 324 73 symbol;
+#X obj 33 302 gfsm_alphabet foo;
+#X connect 2 0 21 0;
+#X connect 3 0 21 0;
+#X connect 4 0 21 0;
+#X connect 5 0 21 0;
+#X connect 6 0 21 0;
+#X connect 7 0 21 0;
+#X connect 8 0 21 0;
+#X connect 9 0 21 0;
+#X connect 10 0 21 0;
+#X connect 11 0 21 0;
+#X connect 12 0 13 0;
+#X connect 13 0 21 0;
+#X connect 14 0 21 0;
+#X connect 15 0 14 0;
+#X connect 16 0 21 0;
+#X connect 17 0 20 0;
+#X connect 18 0 20 0;
+#X connect 19 0 20 0;
+#X connect 20 0 16 0;
+#X connect 21 0 0 0;
+#X connect 21 1 1 0;
diff --git a/gfsm/src/test-automaton.pd b/gfsm/src/test-automaton.pd
new file mode 100644
index 0000000..6cdf837
--- /dev/null
+++ b/gfsm/src/test-automaton.pd
@@ -0,0 +1,260 @@
+#N canvas 31 7 974 447 10;
+#X obj 13 7 gfsm;
+#X obj 22 324 gfsm_automaton;
+#X obj 22 359 print GFSM-1;
+#X msg 26 70 automaton;
+#X msg 24 29 automaton a1;
+#X obj 16 91 s \$0-fsm;
+#X obj 23 300 r \$0-fsm;
+#X msg 153 75 size;
+#X floatatom 237 34 5 0 0 0 - - -;
+#X obj 237 16 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X floatatom 144 34 5 0 0 0 - - -;
+#X msg 257 15 0;
+#X msg 145 13 42;
+#X floatatom 375 18 5 0 0 0 - - -;
+#X msg 347 17 0;
+#X floatatom 388 61 5 0 0 0 - - -;
+#X floatatom 517 34 5 0 0 0 - - -;
+#X floatatom 560 33 5 0 0 0 - - -;
+#X floatatom 603 33 5 0 0 0 - - -;
+#X floatatom 644 34 5 0 0 0 - - -;
+#X obj 543 59 pack 0 0 0 0 0;
+#X obj 494 24 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 494 57 t b b;
+#X msg 569 7 0;
+#X msg 495 105 add_arc \$1 \$2 \$3 \$4 \$5;
+#X obj 144 98 s \$0-fsm;
+#X obj 237 97 s \$0-fsm;
+#X obj 349 121 s \$0-fsm;
+#X obj 496 126 s \$0-fsm;
+#X msg 104 148 load test.tfst;
+#X msg 103 188 save tmp.tfst;
+#X msg 229 148 load_bin test.gfst;
+#X msg 250 304 save_bin tmp.gfst;
+#X msg 26 202 print;
+#X msg 22 179 clear;
+#X msg 18 158 info;
+#X obj 17 226 s \$0-fsm;
+#X obj 88 246 s \$0-fsm;
+#X obj 236 338 s \$0-fsm;
+#X msg 437 170 complement;
+#X msg 450 211 closure \$1;
+#X floatatom 466 193 5 0 0 0 - - -;
+#X obj 437 370 s \$0-fsm;
+#X obj 16 132 bng 20 250 50 0 \$0-draw-s empty DRAW 0 -6 0 8 -24198
+-1 -1;
+#X obj 450 193 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 457 236 compose a2;
+#X msg 462 264 concat a2;
+#X obj 51 6 zexy;
+#X obj 495 84 lister;
+#X msg 25 48 automaton a2;
+#X msg 464 291 determinize;
+#X msg 469 319 difference a2;
+#X msg 475 343 intersect a2;
+#X obj 603 368 s \$0-fsm;
+#X msg 598 148 invert;
+#X msg 607 174 product a2;
+#X msg 621 217 project \$1;
+#X floatatom 638 196 5 0 0 0 - - -;
+#X obj 619 198 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 631 269 reverse;
+#X msg 631 296 rmepsilon;
+#X msg 634 320 union a2;
+#X msg 103 168 load test2.tfst;
+#X msg 233 169 load_bin test2.gfst;
+#X msg 238 190 load_bin test3.gfst;
+#X obj 46 131 tgl 20 0 \$0-drawmode-s empty mode 0 -6 0 8 -225271 -1
+-1 0 1;
+#X msg 246 74 root;
+#X msg 237 51 root \$1;
+#X floatatom 618 8 5 0 0 0 - - -;
+#X msg 144 52 size \$1;
+#X msg 349 37 final \$1;
+#X obj 430 61 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 365 79 pack 0 0;
+#X msg 363 99 final \$1 \$2;
+#X msg 637 343 renumber;
+#X msg 252 282 load_bin tmp.gfst;
+#N canvas 0 0 450 300 flags 0;
+#X obj 26 67 s \$0-fsm;
+#X msg 36 21 weighted \$1;
+#X obj 19 21 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X msg 39 43 weighted;
+#X obj 145 19 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 155 65 s \$0-fsm;
+#X msg 162 19 transducer \$1;
+#X msg 165 41 transducer;
+#X obj 30 220 s \$0-fsm;
+#X msg 40 196 semiring;
+#X msg 30 174 semiring \$1;
+#X msg 29 125 boolean;
+#X msg 90 125 log;
+#X msg 122 126 real;
+#X msg 160 125 trivial;
+#X msg 218 125 tropical;
+#X obj 30 153 symbol;
+#X msg 286 125 OTHER;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
+#X connect 3 0 0 0;
+#X connect 4 0 6 0;
+#X connect 6 0 5 0;
+#X connect 7 0 5 0;
+#X connect 9 0 8 0;
+#X connect 10 0 8 0;
+#X connect 11 0 16 0;
+#X connect 12 0 16 0;
+#X connect 13 0 16 0;
+#X connect 14 0 16 0;
+#X connect 15 0 16 0;
+#X connect 16 0 10 0;
+#X connect 17 0 16 0;
+#X restore 711 65 pd flags;
+#X obj 600 8 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 361 336 concat a1;
+#X floatatom 689 35 5 0 0 0 - - -;
+#X obj 366 59 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 113 360 s \$0-fsm-out;
+#X obj 741 16 pool;
+#X msg 94 120 automaton fsm-help;
+#X msg 105 220 load gfsm-help.tfst;
+#N canvas 22 7 466 454 draw 0;
+#X obj 361 16 zexy;
+#X obj 26 15 r \$0-draw-s;
+#X obj 68 68 f \$0;
+#X obj 68 110 s \$0-fsm;
+#X obj 68 47 t b;
+#X obj 99 352 t b;
+#X obj 98 418 shell;
+#X obj 172 20 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 69 331 shell;
+#X obj 125 215 r \$0-drawmode-s;
+#X obj 67 238 demux 0 1;
+#X obj 240 214 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X msg 68 89 draw_dot \$1draw.dot;
+#X obj 67 136 r \$0-fsm-out;
+#X obj 67 158 route draw_dot;
+#X obj 67 180 symbol;
+#X msg 48 295 dotgv.sh \$1;
+#X msg 145 294 dotty \$1;
+#X obj 67 203 t s s;
+#X obj 98 372 symbol;
+#X msg 98 395 rm -f \$1;
+#X connect 1 0 4 0;
+#X connect 2 0 12 0;
+#X connect 4 0 2 0;
+#X connect 5 0 19 0;
+#X connect 7 0 4 0;
+#X connect 8 1 5 0;
+#X connect 9 0 10 1;
+#X connect 10 0 16 0;
+#X connect 10 1 17 0;
+#X connect 11 0 10 1;
+#X connect 12 0 3 0;
+#X connect 13 0 14 0;
+#X connect 14 0 15 0;
+#X connect 15 0 18 0;
+#X connect 16 0 8 0;
+#X connect 17 0 8 0;
+#X connect 18 0 10 0;
+#X connect 18 1 19 1;
+#X connect 19 0 20 0;
+#X connect 20 0 6 0;
+#X restore 16 251 pd draw;
+#X msg 258 216 load_bin lkptest.gfst;
+#X msg 261 238 load_bin lkpin.gfst;
+#X obj 21 385 gfsm_automaton a1;
+#X obj 22 404 gfsm_automaton a2;
+#X msg 626 245 connect;
+#X msg 739 352 clear;
+#X connect 1 0 2 0;
+#X connect 1 0 81 0;
+#X connect 3 0 5 0;
+#X connect 4 0 5 0;
+#X connect 6 0 1 0;
+#X connect 7 0 25 0;
+#X connect 8 0 67 0;
+#X connect 9 0 8 0;
+#X connect 10 0 69 0;
+#X connect 11 0 8 0;
+#X connect 12 0 10 0;
+#X connect 13 0 70 0;
+#X connect 14 0 13 0;
+#X connect 15 0 72 0;
+#X connect 16 0 20 0;
+#X connect 17 0 20 1;
+#X connect 18 0 20 2;
+#X connect 19 0 20 3;
+#X connect 20 0 48 1;
+#X connect 21 0 22 0;
+#X connect 22 0 48 0;
+#X connect 22 1 20 0;
+#X connect 23 0 16 0;
+#X connect 23 0 17 0;
+#X connect 23 0 18 0;
+#X connect 23 0 19 0;
+#X connect 24 0 28 0;
+#X connect 29 0 37 0;
+#X connect 30 0 37 0;
+#X connect 31 0 38 0;
+#X connect 32 0 38 0;
+#X connect 33 0 36 0;
+#X connect 34 0 36 0;
+#X connect 35 0 36 0;
+#X connect 39 0 42 0;
+#X connect 40 0 42 0;
+#X connect 41 0 40 0;
+#X connect 44 0 41 0;
+#X connect 45 0 42 0;
+#X connect 46 0 42 0;
+#X connect 48 0 24 0;
+#X connect 49 0 5 0;
+#X connect 50 0 42 0;
+#X connect 51 0 42 0;
+#X connect 52 0 42 0;
+#X connect 54 0 53 0;
+#X connect 55 0 53 0;
+#X connect 56 0 53 0;
+#X connect 57 0 56 0;
+#X connect 58 0 57 0;
+#X connect 59 0 53 0;
+#X connect 60 0 53 0;
+#X connect 61 0 53 0;
+#X connect 62 0 37 0;
+#X connect 63 0 38 0;
+#X connect 64 0 38 0;
+#X connect 66 0 26 0;
+#X connect 67 0 26 0;
+#X connect 68 0 17 0;
+#X connect 68 0 18 0;
+#X connect 68 0 19 0;
+#X connect 69 0 25 0;
+#X connect 70 0 27 0;
+#X connect 71 0 72 1;
+#X connect 72 0 73 0;
+#X connect 73 0 27 0;
+#X connect 74 0 53 0;
+#X connect 75 0 38 0;
+#X connect 77 0 68 0;
+#X connect 78 0 42 0;
+#X connect 79 0 20 4;
+#X connect 80 0 15 0;
+#X connect 83 0 5 0;
+#X connect 84 0 37 0;
+#X connect 86 0 38 0;
+#X connect 87 0 38 0;
+#X connect 90 0 53 0;
+#X connect 91 0 53 0;
diff --git a/gfsm/src/test-automaton2.pd b/gfsm/src/test-automaton2.pd
new file mode 100644
index 0000000..f503014
--- /dev/null
+++ b/gfsm/src/test-automaton2.pd
@@ -0,0 +1,196 @@
+#N canvas 110 261 845 398 10;
+#X obj 13 7 gfsm;
+#X obj 23 362 print GFSM-1;
+#X obj 116 362 print GFSM-2;
+#X obj 208 363 print GFSM-3;
+#X msg 26 70 automaton;
+#X msg 24 29 automaton a1;
+#X obj 16 91 s \$0-fsm;
+#X obj 93 294 r \$0-fsm;
+#X msg 153 75 size;
+#X floatatom 237 34 5 0 0 0 - - -;
+#X obj 237 16 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 237 51 set_root \$1;
+#X msg 246 74 get_root;
+#X msg 144 52 reserve \$1;
+#X floatatom 144 34 5 0 0 0 - - -;
+#X msg 257 15 0;
+#X msg 145 13 42;
+#X msg 349 37 is_final \$1;
+#X floatatom 375 18 5 0 0 0 - - -;
+#X msg 347 17 0;
+#X floatatom 388 61 5 0 0 0 - - -;
+#X msg 360 60 0;
+#X msg 363 80 set_final \$1 1;
+#X floatatom 517 34 5 0 0 0 - - -;
+#X floatatom 560 33 5 0 0 0 - - -;
+#X floatatom 603 33 5 0 0 0 - - -;
+#X floatatom 644 34 5 0 0 0 - - -;
+#X obj 543 59 pack 0 0 0 0 0;
+#X obj 494 24 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 494 57 t b b;
+#X msg 569 7 0;
+#X msg 495 105 add_arc \$1 \$2 \$3 \$4 \$5;
+#X obj 144 98 s \$0-fsm;
+#X obj 237 97 s \$0-fsm;
+#X obj 349 102 s \$0-fsm;
+#X obj 496 126 s \$0-fsm;
+#X msg 104 148 load test.tfst;
+#X msg 103 188 save tmp.tfst;
+#X msg 229 148 load_bin test.gfst;
+#X msg 234 232 save_bin tmp.gfst;
+#X msg 26 202 print;
+#X msg 22 179 clear;
+#X msg 18 158 info;
+#X obj 16 224 s \$0-fsm;
+#X obj 95 209 s \$0-fsm;
+#X obj 228 254 s \$0-fsm;
+#X msg 437 170 complement;
+#X msg 450 211 closure \$1;
+#X floatatom 466 193 5 0 0 0 - - -;
+#X obj 437 370 s \$0-fsm;
+#X obj 16 132 bng 20 250 50 0 \$0-draw-s empty DRAW 0 -6 0 8 -24198
+-1 -1;
+#X obj 450 193 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 457 236 compose a2;
+#X msg 462 264 concat a2;
+#X obj 51 6 zexy;
+#X obj 495 84 lister;
+#X msg 25 48 automaton a2;
+#X msg 464 291 determinize;
+#X msg 469 319 difference a2;
+#X msg 475 343 intersect a2;
+#X obj 603 368 s \$0-fsm;
+#X msg 603 165 invert;
+#X msg 612 191 product a2;
+#X msg 626 234 project \$1;
+#X floatatom 643 213 5 0 0 0 - - -;
+#X obj 624 215 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 631 262 prune;
+#X msg 636 286 reverse;
+#X msg 636 313 rmepsilon;
+#X msg 639 337 union a2;
+#X msg 103 168 load test2.tfst;
+#X msg 233 169 load_bin test2.gfst;
+#X obj 92 318 gfsm_automaton a2;
+#X msg 238 190 load_bin test3.gfst;
+#X floatatom 626 5 5 0 0 0 - - -;
+#N canvas 0 0 466 454 draw 0;
+#X obj 67 25 r \$0-draw-s;
+#X obj 68 68 f \$0;
+#X msg 176 74 save_bin \$1draw.gfst;
+#X obj 176 98 s \$0-fsm;
+#X obj 68 162 shell;
+#X obj 68 47 t b;
+#X obj 68 91 t f f;
+#X msg 69 237 dotgv.sh \$1draw.dot;
+#X obj 171 311 f \$0;
+#X obj 172 291 t b;
+#X obj 171 357 shell;
+#X obj 172 20 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 68 137 gfsmdraw \$1draw.gfst -F \$1draw.dot;
+#X msg 171 334 rm -f \$1draw.gfst \$1draw.dot;
+#X obj 142 270 shell;
+#X msg 220 236 dotty \$1draw.dot;
+#X obj 169 183 r \$0-drawmode-s;
+#X obj 111 206 demux 0 1;
+#X obj 110 163 t b;
+#X obj 111 184 f \$0;
+#X obj 284 182 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X connect 0 0 5 0;
+#X connect 1 0 6 0;
+#X connect 2 0 3 0;
+#X connect 4 1 18 0;
+#X connect 5 0 1 0;
+#X connect 6 0 12 0;
+#X connect 6 1 2 0;
+#X connect 7 0 14 0;
+#X connect 8 0 13 0;
+#X connect 9 0 8 0;
+#X connect 11 0 5 0;
+#X connect 12 0 4 0;
+#X connect 13 0 10 0;
+#X connect 14 1 9 0;
+#X connect 15 0 14 0;
+#X connect 16 0 17 1;
+#X connect 17 0 7 0;
+#X connect 17 1 15 0;
+#X connect 18 0 19 0;
+#X connect 19 0 17 0;
+#X connect 20 0 17 1;
+#X restore 71 118 pd draw;
+#X obj 44 130 tgl 20 0 \$0-drawmode-s empty mode 0 -6 0 8 -225271 -1
+-1 0 1;
+#X msg 152 120 automaton fsm-help-2;
+#X connect 4 0 6 0;
+#X connect 5 0 6 0;
+#X connect 7 0 72 0;
+#X connect 8 0 32 0;
+#X connect 9 0 11 0;
+#X connect 10 0 9 0;
+#X connect 11 0 33 0;
+#X connect 12 0 33 0;
+#X connect 13 0 32 0;
+#X connect 14 0 13 0;
+#X connect 15 0 9 0;
+#X connect 16 0 14 0;
+#X connect 17 0 34 0;
+#X connect 18 0 17 0;
+#X connect 19 0 18 0;
+#X connect 20 0 22 0;
+#X connect 21 0 20 0;
+#X connect 22 0 34 0;
+#X connect 23 0 27 0;
+#X connect 24 0 27 1;
+#X connect 25 0 27 2;
+#X connect 26 0 27 3;
+#X connect 27 0 55 1;
+#X connect 28 0 29 0;
+#X connect 29 0 55 0;
+#X connect 29 1 27 0;
+#X connect 30 0 23 0;
+#X connect 30 0 24 0;
+#X connect 30 0 25 0;
+#X connect 30 0 26 0;
+#X connect 31 0 35 0;
+#X connect 36 0 44 0;
+#X connect 37 0 44 0;
+#X connect 38 0 45 0;
+#X connect 39 0 45 0;
+#X connect 40 0 43 0;
+#X connect 41 0 43 0;
+#X connect 42 0 43 0;
+#X connect 46 0 49 0;
+#X connect 47 0 49 0;
+#X connect 48 0 47 0;
+#X connect 51 0 48 0;
+#X connect 52 0 49 0;
+#X connect 53 0 49 0;
+#X connect 55 0 31 0;
+#X connect 56 0 6 0;
+#X connect 57 0 49 0;
+#X connect 58 0 49 0;
+#X connect 59 0 49 0;
+#X connect 61 0 60 0;
+#X connect 62 0 60 0;
+#X connect 63 0 60 0;
+#X connect 64 0 63 0;
+#X connect 65 0 64 0;
+#X connect 66 0 60 0;
+#X connect 67 0 60 0;
+#X connect 68 0 60 0;
+#X connect 69 0 60 0;
+#X connect 70 0 44 0;
+#X connect 71 0 45 0;
+#X connect 72 0 1 0;
+#X connect 73 0 45 0;
+#X connect 74 0 24 0;
+#X connect 74 0 25 0;
+#X connect 74 0 26 0;
+#X connect 77 0 6 0;
diff --git a/gfsm/src/test-fsm.pd b/gfsm/src/test-fsm.pd
new file mode 100644
index 0000000..ed74881
--- /dev/null
+++ b/gfsm/src/test-fsm.pd
@@ -0,0 +1,2 @@
+#N canvas 0 0 450 300 10;
+#X obj 166 146 fsm;
diff --git a/gfsm/src/test-markov.pd b/gfsm/src/test-markov.pd
new file mode 100644
index 0000000..7ab52e8
--- /dev/null
+++ b/gfsm/src/test-markov.pd
@@ -0,0 +1,211 @@
+#N canvas 79 27 832 322 10;
+#X obj 21 23 bng 20 250 50 0 \$0-draw-s empty DRAW 0 -6 0 8 -24198
+-1 -1;
+#N canvas 0 0 466 454 draw 0;
+#X obj 361 16 zexy;
+#X obj 67 25 r \$0-draw-s;
+#X obj 68 68 f \$0;
+#X obj 67 177 shell;
+#X obj 68 47 t b;
+#X obj 68 91 t f f;
+#X msg 68 252 dotgv.sh \$1draw.dot;
+#X obj 170 326 f \$0;
+#X obj 171 306 t b;
+#X obj 170 372 shell;
+#X obj 172 20 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 170 349 rm -f \$1draw.gfst \$1draw.dot;
+#X obj 141 285 shell;
+#X msg 219 251 dotty \$1draw.dot;
+#X obj 168 198 r \$0-drawmode-s;
+#X obj 110 221 demux 0 1;
+#X obj 109 178 t b;
+#X obj 110 199 f \$0;
+#X obj 283 197 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 176 98 s \$0-markov;
+#X msg 176 74 save_bin \$1draw;
+#X msg 68 137 gfsmdraw -i \$1draw.lab -o \$1draw.lab \$1draw.gfst -F
+\$1draw.dot;
+#X connect 1 0 4 0;
+#X connect 2 0 5 0;
+#X connect 3 1 16 0;
+#X connect 4 0 2 0;
+#X connect 5 0 21 0;
+#X connect 5 1 20 0;
+#X connect 6 0 12 0;
+#X connect 7 0 11 0;
+#X connect 8 0 7 0;
+#X connect 10 0 4 0;
+#X connect 11 0 9 0;
+#X connect 12 1 8 0;
+#X connect 13 0 12 0;
+#X connect 14 0 15 1;
+#X connect 15 0 6 0;
+#X connect 15 1 13 0;
+#X connect 16 0 17 0;
+#X connect 17 0 15 0;
+#X connect 18 0 15 1;
+#X connect 20 0 19 0;
+#X connect 21 0 3 0;
+#X restore 22 47 pd draw;
+#X obj 34 203 r \$0-markov;
+#X obj 104 6 bng 15 250 50 0 empty empty empty 0 -6 0 8 -225280 -1
+-1;
+#X obj 104 24 openpanel;
+#X msg 104 90 load_bin \$1;
+#X obj 104 68 symbol;
+#X msg 111 45 markov;
+#X obj 103 110 s \$0-markov;
+#X obj 204 6 bng 15 250 50 0 empty empty empty 0 -6 0 8 -228992 -1
+-1;
+#X obj 204 68 symbol;
+#X obj 203 110 s \$0-markov;
+#X obj 204 24 savepanel;
+#X msg 204 90 save_bin \$1;
+#X msg 211 45 markov2;
+#X obj 49 22 tgl 20 0 \$0-drawmode-s empty mode 0 -6 0 8 -225271 -1
+-1 0 1;
+#X msg 336 8 fsm info;
+#X msg 342 28 clear;
+#X obj 336 75 s \$0-markov;
+#X msg 339 151 next;
+#X obj 339 172 s \$0-markov;
+#X obj 339 108 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 339 127 metro 500;
+#X obj 302 153 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X floatatom 364 107 6 0 0 0 - - -;
+#X msg 382 255 add1 \$1;
+#X floatatom 341 207 5 0 0 0 - - -;
+#X msg 382 208 foo;
+#X msg 413 208 bar;
+#X msg 442 209 baz;
+#X obj 382 279 s \$0-markov;
+#X obj 34 225 gfsm_markov markov;
+#X obj 384 234 symbol;
+#X floatatom 481 210 5 0 0 0 - - -;
+#X msg 522 211 foo;
+#X msg 553 211 bar;
+#X msg 582 212 baz;
+#X obj 522 282 s \$0-markov;
+#X obj 524 237 symbol;
+#X msg 521 258 addi1 \$1;
+#X msg 349 51 set;
+#X floatatom 538 57 5 0 0 0 - - -;
+#X msg 480 138 add1 \$1;
+#X floatatom 480 119 5 0 0 0 - - -;
+#X obj 539 170 s \$0-markov;
+#X floatatom 513 11 5 0 0 0 - - -;
+#X obj 480 29 metro 100;
+#X obj 480 11 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 480 98 + 1;
+#X floatatom 649 59 5 0 0 0 - - -;
+#X floatatom 591 121 5 0 0 0 - - -;
+#X floatatom 624 13 5 0 0 0 - - -;
+#X obj 591 31 metro 100;
+#X obj 591 13 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 591 100 + 1;
+#X msg 591 140 addi1 \$1;
+#X obj 480 77 random 16;
+#X obj 591 79 random 16;
+#X obj 34 260 spigot;
+#X obj 83 262 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 687 207 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 687 227 metro 2000;
+#X floatatom 715 208 5 0 0 0 - - -;
+#X msg 689 247 set;
+#X obj 689 267 s \$0-markov;
+#X obj 667 227 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X floatatom 692 117 5 0 0 0 - - -;
+#X msg 692 137 addi \$1 42 5;
+#X obj 32 284 print MARKOV-LO;
+#X obj 155 284 print MARKOV-HI;
+#X obj 175 241 print MARKOV-X;
+#X obj 152 262 spigot;
+#X obj 201 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X floatatom 706 52 5 0 0 0 - - -;
+#X msg 705 70 add \$1 24 5;
+#X msg 138 192 set 0 \, next;
+#X obj 176 219 spigot;
+#X obj 224 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X msg 162 45 big;
+#X msg 270 44 big2;
+#X msg 49 73 markov2;
+#X connect 2 0 31 0;
+#X connect 3 0 4 0;
+#X connect 4 0 6 0;
+#X connect 5 0 8 0;
+#X connect 6 0 5 0;
+#X connect 7 0 6 0;
+#X connect 9 0 12 0;
+#X connect 10 0 13 0;
+#X connect 12 0 10 0;
+#X connect 13 0 11 0;
+#X connect 14 0 10 0;
+#X connect 16 0 18 0;
+#X connect 17 0 18 0;
+#X connect 19 0 20 0;
+#X connect 21 0 22 0;
+#X connect 22 0 19 0;
+#X connect 24 0 22 1;
+#X connect 25 0 30 0;
+#X connect 26 0 25 0;
+#X connect 27 0 32 0;
+#X connect 28 0 32 0;
+#X connect 29 0 32 0;
+#X connect 31 0 58 0;
+#X connect 31 1 71 0;
+#X connect 31 2 75 0;
+#X connect 31 2 76 0;
+#X connect 32 0 25 0;
+#X connect 33 0 39 0;
+#X connect 34 0 38 0;
+#X connect 35 0 38 0;
+#X connect 36 0 38 0;
+#X connect 38 0 39 0;
+#X connect 39 0 37 0;
+#X connect 40 0 18 0;
+#X connect 41 0 56 1;
+#X connect 42 0 44 0;
+#X connect 43 0 42 0;
+#X connect 45 0 46 1;
+#X connect 46 0 56 0;
+#X connect 47 0 46 0;
+#X connect 48 0 43 0;
+#X connect 49 0 57 1;
+#X connect 50 0 55 0;
+#X connect 51 0 52 1;
+#X connect 52 0 57 0;
+#X connect 53 0 52 0;
+#X connect 54 0 50 0;
+#X connect 55 0 44 0;
+#X connect 56 0 48 0;
+#X connect 57 0 54 0;
+#X connect 58 0 68 0;
+#X connect 59 0 58 1;
+#X connect 60 0 61 0;
+#X connect 61 0 63 0;
+#X connect 61 0 65 0;
+#X connect 62 0 61 1;
+#X connect 63 0 64 0;
+#X connect 66 0 67 0;
+#X connect 67 0 44 0;
+#X connect 71 0 69 0;
+#X connect 72 0 71 1;
+#X connect 73 0 74 0;
+#X connect 74 0 44 0;
+#X connect 75 0 31 0;
+#X connect 76 0 70 0;
+#X connect 77 0 76 1;
+#X connect 78 0 6 0;
+#X connect 79 0 10 0;
+#X connect 80 0 6 0;
diff --git a/gfsm/src/test-state.pd b/gfsm/src/test-state.pd
new file mode 100644
index 0000000..2ee2b77
--- /dev/null
+++ b/gfsm/src/test-state.pd
@@ -0,0 +1,427 @@
+#N canvas 430 0 616 494 10;
+#X obj 13 7 gfsm;
+#X msg 23 84 automaton;
+#X msg 21 43 automaton a1;
+#X obj 51 6 zexy;
+#X msg 22 62 automaton a2;
+#X obj 30 285 r \$0-state;
+#X obj 19 332 print STATE-1;
+#X obj 136 76 s \$0-state;
+#X msg 150 48 id;
+#X msg 136 27 set \$1;
+#X floatatom 153 9 5 0 0 0 - - -;
+#X obj 19 308 gfsm_state a1;
+#X obj 135 10 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 218 11 degree;
+#X obj 218 74 s \$0-state;
+#X msg 25 147 arc_first;
+#X msg 29 171 arc_next;
+#X obj 243 314 gfsm_automaton a1;
+#X obj 243 180 bng 15 250 50 0 empty empty empty 0 -6 0 8 -225280 -1
+-1;
+#X obj 243 198 openpanel;
+#X msg 243 264 load_bin \$1;
+#X obj 243 335 print A1-1;
+#X obj 254 293 r \$0-fsm;
+#X obj 337 226 bng 20 250 50 0 \$0-draw-s empty DRAW 0 -6 0 8 -24198
+-1 -1;
+#N canvas 0 0 466 454 draw 0;
+#X obj 361 16 zexy;
+#X obj 67 25 r \$0-draw-s;
+#X obj 68 68 f \$0;
+#X msg 176 74 save_bin \$1draw.gfst;
+#X obj 176 98 s \$0-fsm;
+#X obj 68 162 shell;
+#X obj 68 47 t b;
+#X obj 68 91 t f f;
+#X msg 69 237 dotgv.sh \$1draw.dot;
+#X obj 171 311 f \$0;
+#X obj 172 291 t b;
+#X obj 171 357 shell;
+#X obj 172 20 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 68 137 gfsmdraw \$1draw.gfst -F \$1draw.dot;
+#X msg 171 334 rm -f \$1draw.gfst \$1draw.dot;
+#X obj 142 270 shell;
+#X msg 220 236 dotty \$1draw.dot;
+#X obj 169 183 r \$0-drawmode-s;
+#X obj 111 206 demux 0 1;
+#X obj 110 163 t b;
+#X obj 111 184 f \$0;
+#X obj 284 182 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X connect 1 0 6 0;
+#X connect 2 0 7 0;
+#X connect 3 0 4 0;
+#X connect 5 1 19 0;
+#X connect 6 0 2 0;
+#X connect 7 0 13 0;
+#X connect 7 1 3 0;
+#X connect 8 0 15 0;
+#X connect 9 0 14 0;
+#X connect 10 0 9 0;
+#X connect 12 0 6 0;
+#X connect 13 0 5 0;
+#X connect 14 0 11 0;
+#X connect 15 1 10 0;
+#X connect 16 0 15 0;
+#X connect 17 0 18 1;
+#X connect 18 0 8 0;
+#X connect 18 1 16 0;
+#X connect 19 0 20 0;
+#X connect 20 0 18 0;
+#X connect 21 0 18 1;
+#X restore 338 250 pd draw;
+#X obj 365 226 tgl 20 0 \$0-drawmode-s empty mode 0 -6 0 8 -225271
+-1 -1 0 1;
+#X msg 250 219 test3.gfst;
+#X obj 243 242 symbol;
+#X obj 115 141 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 38 17 452 375 weight_sum 0;
+#X obj 34 11 inlet;
+#X msg 34 61 arc_first;
+#X msg 46 88 arc_next;
+#X obj 34 292 f 0;
+#X obj 238 59 0;
+#X obj 34 177 route arc_first arc_next;
+#X obj 34 203 route bang;
+#X obj 99 222 t b l;
+#X obj 129 244 unpack 0 0 0 0;
+#X obj 222 268 + 0;
+#X obj 178 267 t f f;
+#X obj 87 11 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 34 323 outlet;
+#X obj 34 224 t b;
+#X obj 34 143 gfsm_state a1 0;
+#X obj 45 119 r \$0-state;
+#X obj 88 323 s \$0-wsum-out;
+#X obj 113 13 r \$0-wsum-in;
+#X obj 71 250 delay 1;
+#X obj 34 33 t b b b;
+#X msg 290 56 stop;
+#X floatatom 240 293 5 0 0 0 - - -;
+#X obj 322 168 until;
+#X connect 0 0 19 0;
+#X connect 1 0 14 0;
+#X connect 2 0 14 0;
+#X connect 3 0 12 0;
+#X connect 3 0 16 0;
+#X connect 4 0 9 1;
+#X connect 5 0 6 0;
+#X connect 5 1 6 0;
+#X connect 6 0 13 0;
+#X connect 6 1 7 0;
+#X connect 7 0 18 0;
+#X connect 7 1 8 0;
+#X connect 8 3 9 0;
+#X connect 9 0 10 0;
+#X connect 9 0 21 0;
+#X connect 10 0 9 1;
+#X connect 10 1 3 1;
+#X connect 11 0 19 0;
+#X connect 13 0 3 0;
+#X connect 14 0 5 0;
+#X connect 15 0 14 0;
+#X connect 17 0 19 0;
+#X connect 18 0 2 0;
+#X connect 19 0 1 0;
+#X connect 19 1 4 0;
+#X connect 19 2 20 0;
+#X connect 20 0 18 0;
+#X restore 115 161 pd weight_sum;
+#X obj 114 332 s \$0-state-out;
+#X floatatom 114 182 8 0 0 0 - - -;
+#X obj 114 224 print WSUM;
+#X obj 252 97 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 302 0 392 492 rand_arc 0;
+#X obj 40 9 inlet;
+#X obj 83 9 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1
+;
+#X msg 41 56 arc_first;
+#X msg 56 93 arc_next;
+#X obj 41 177 route arc_first arc_next;
+#X obj 41 203 route bang;
+#X obj 150 244 unpack 0 0 0 0;
+#X obj 41 451 outlet;
+#X obj 41 143 gfsm_state a1 0;
+#X obj 77 122 r \$0-state;
+#X obj 257 73 s \$0-wsum-in;
+#X obj 259 95 r \$0-wsum-out;
+#X obj 259 142 random 131072;
+#X obj 259 116 t b f;
+#X obj 259 166 / 131072;
+#X obj 259 190 * 1;
+#X obj 41 224 t b;
+#X obj 243 316 moses 0;
+#X obj 259 213 * -1;
+#X obj 243 271 + 0;
+#X obj 243 294 t f f;
+#X obj 242 335 t b b;
+#X obj 128 403 spigot;
+#X obj 165 381 0;
+#X obj 192 381 1;
+#X obj 106 306 spigot;
+#X obj 106 222 t b l l;
+#X obj 286 335 t b b;
+#X obj 169 284 0;
+#X obj 143 284 1;
+#X obj 107 10 r \$0-randarc-in;
+#X obj 92 451 s \$0-randarc-out;
+#X obj 81 326 delay 1;
+#X obj 41 30 t b b b;
+#X msg 177 127 stop;
+#X connect 0 0 33 0;
+#X connect 1 0 33 0;
+#X connect 2 0 8 0;
+#X connect 3 0 8 0;
+#X connect 4 0 5 0;
+#X connect 4 1 5 0;
+#X connect 5 0 16 0;
+#X connect 5 1 26 0;
+#X connect 6 3 19 0;
+#X connect 8 0 4 0;
+#X connect 9 0 8 0;
+#X connect 11 0 13 0;
+#X connect 12 0 14 0;
+#X connect 13 0 12 0;
+#X connect 13 1 15 1;
+#X connect 14 0 15 0;
+#X connect 15 0 18 0;
+#X connect 16 0 7 0;
+#X connect 16 0 31 0;
+#X connect 17 0 21 0;
+#X connect 17 1 27 0;
+#X connect 18 0 19 1;
+#X connect 19 0 20 0;
+#X connect 20 0 17 0;
+#X connect 20 1 19 1;
+#X connect 21 0 29 0;
+#X connect 21 1 23 0;
+#X connect 22 0 7 0;
+#X connect 22 0 31 0;
+#X connect 23 0 22 1;
+#X connect 24 0 22 1;
+#X connect 25 0 32 0;
+#X connect 26 0 25 0;
+#X connect 26 1 22 0;
+#X connect 26 2 6 0;
+#X connect 27 0 24 0;
+#X connect 27 1 28 0;
+#X connect 28 0 25 1;
+#X connect 29 0 25 1;
+#X connect 30 0 33 0;
+#X connect 32 0 3 0;
+#X connect 33 0 2 0;
+#X connect 33 1 10 0;
+#X connect 33 2 34 0;
+#X connect 34 0 32 0;
+#X restore 252 116 pd rand_arc;
+#X obj 395 113 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 102 2 392 492 rand_incr 0;
+#X obj 40 9 inlet;
+#X obj 83 9 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1
+;
+#X obj 41 54 s \$0-randarc-in;
+#X obj 43 76 r \$0-randarc-out;
+#X obj 42 98 route bang;
+#X obj 41 30 t b;
+#X obj 42 177 gfsm_automaton a1;
+#X obj 209 157 unpack 0 0 0 0;
+#X obj 55 154 r \$0-automaton;
+#X msg 42 131 root;
+#X obj 42 199 route root;
+#X obj 42 221 route bang;
+#X obj 107 336 outlet;
+#X obj 211 337 outlet;
+#X obj 271 335 outlet;
+#X msg 8 247 root 0;
+#X obj 107 254 t f f;
+#X obj 137 295 s \$0-state;
+#X msg 137 274 set \$1;
+#X obj 326 336 outlet;
+#X connect 0 0 5 0;
+#X connect 1 0 5 0;
+#X connect 3 0 4 0;
+#X connect 4 0 9 0;
+#X connect 4 1 7 0;
+#X connect 5 0 2 0;
+#X connect 6 0 10 0;
+#X connect 7 0 16 0;
+#X connect 7 1 13 0;
+#X connect 7 2 14 0;
+#X connect 7 3 19 0;
+#X connect 8 0 6 0;
+#X connect 9 0 6 0;
+#X connect 10 0 11 0;
+#X connect 11 0 15 0;
+#X connect 11 1 16 0;
+#X connect 15 0 6 0;
+#X connect 16 0 12 0;
+#X connect 16 1 18 0;
+#X connect 18 0 17 0;
+#X restore 395 132 pd rand_incr;
+#X obj 254 157 print RAND_ARC;
+#X obj 336 33 s \$0-state;
+#X obj 326 54 s \$0-fsm;
+#X obj 13 105 s \$0-automaton;
+#X obj 326 12 r \$0-automaton;
+#X obj 21 197 s \$0-state-a;
+#X obj 19 262 r \$0-state-a;
+#X obj 195 192 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 230 140 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 470 10 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X floatatom 493 10 5 0 0 0 - - -;
+#X obj 471 30 metro 1000;
+#X obj 417 300 gfsm_alphabet alph1;
+#X obj 518 214 bng 15 250 50 0 empty empty empty 0 -6 0 8 -225280 -1
+-1;
+#X obj 518 232 openpanel;
+#X obj 518 254 symbol;
+#X msg 518 275 load \$1;
+#X obj 452 342 print RI-ATOM;
+#X msg 419 273 char2atom \$1;
+#X floatatom 436 245 5 0 0 0 - - -;
+#X obj 452 321 fromsymbol;
+#N canvas 0 0 450 300 ri_print 0;
+#X obj 48 22 inlet;
+#X obj 101 22 inlet;
+#X obj 155 22 inlet;
+#X obj 206 22 inlet;
+#X obj 319 22 inlet;
+#X obj 93 97 spigot;
+#X obj 93 57 pack 0 0 0 0;
+#X obj 93 122 unpack 0 0 0 0;
+#X obj 124 196 print RI-LO;
+#X obj 186 155 print RI-WT;
+#X obj 155 175 print RI-HI;
+#X obj 93 215 print RI-NXT;
+#X connect 0 0 6 0;
+#X connect 1 0 6 1;
+#X connect 2 0 6 2;
+#X connect 3 0 6 3;
+#X connect 4 0 5 1;
+#X connect 5 0 7 0;
+#X connect 6 0 5 0;
+#X connect 7 0 11 0;
+#X connect 7 1 8 0;
+#X connect 7 2 10 0;
+#X connect 7 3 9 0;
+#X restore 420 160 pd ri_print;
+#X obj 488 131 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 114 203 spigot;
+#X obj 162 203 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 253 138 spigot;
+#X obj 301 138 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 29 410 grattsdict;
+#X obj 247 417 gvol~;
+#X obj 246 454 dac~;
+#X obj 470 51 t b b;
+#X obj 475 100 spigot;
+#X msg 506 80 0;
+#X msg 534 80 1;
+#X obj 548 456 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 0 0 450 300 load_dict 0;
+#X obj 31 16 inlet;
+#X obj 31 38 t b;
+#X msg 31 67 load /home/moocow/src/pd/externs/ratts/dict/beep-b.txt
+cr;
+#X obj 33 108 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X restore 30 391 pd load_dict;
+#X obj 31 371 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 366 367 gpratts~ 10 \$0p /gpratts;
+#X obj 171 396 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X msg 171 417 \; pd dsp \$1;
+#X obj 434 74 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 435 103 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 424 202 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 367 340 route 0;
+#X connect 1 0 40 0;
+#X connect 2 0 40 0;
+#X connect 4 0 40 0;
+#X connect 5 0 11 0;
+#X connect 8 0 7 0;
+#X connect 9 0 7 0;
+#X connect 10 0 9 0;
+#X connect 11 0 6 0;
+#X connect 11 0 30 0;
+#X connect 12 0 10 0;
+#X connect 13 0 14 0;
+#X connect 15 0 42 0;
+#X connect 16 0 42 0;
+#X connect 17 0 21 0;
+#X connect 18 0 19 0;
+#X connect 19 0 27 0;
+#X connect 20 0 17 0;
+#X connect 22 0 17 0;
+#X connect 26 0 27 0;
+#X connect 27 0 20 0;
+#X connect 28 0 29 0;
+#X connect 29 0 31 0;
+#X connect 29 0 44 0;
+#X connect 31 0 60 0;
+#X connect 33 0 34 0;
+#X connect 34 0 45 0;
+#X connect 34 0 62 0;
+#X connect 35 0 36 0;
+#X connect 36 0 58 0;
+#X connect 36 0 55 0;
+#X connect 36 0 79 0;
+#X connect 36 1 58 1;
+#X connect 36 2 58 2;
+#X connect 36 3 58 3;
+#X connect 41 0 39 0;
+#X connect 41 0 38 0;
+#X connect 43 0 11 0;
+#X connect 46 0 48 0;
+#X connect 47 0 48 1;
+#X connect 48 0 67 0;
+#X connect 49 1 57 0;
+#X connect 50 0 51 0;
+#X connect 51 0 52 0;
+#X connect 52 0 53 0;
+#X connect 53 0 49 0;
+#X connect 55 0 49 0;
+#X connect 56 0 55 0;
+#X connect 57 0 54 0;
+#X connect 57 0 80 0;
+#X connect 59 0 58 4;
+#X connect 60 0 32 0;
+#X connect 61 0 60 1;
+#X connect 62 0 37 0;
+#X connect 63 0 62 1;
+#X connect 65 0 66 0;
+#X connect 65 0 66 1;
+#X connect 67 0 69 0;
+#X connect 67 0 77 0;
+#X connect 67 1 68 0;
+#X connect 68 0 36 0;
+#X connect 68 0 78 0;
+#X connect 69 0 68 1;
+#X connect 70 0 68 1;
+#X connect 72 0 64 0;
+#X connect 73 0 72 0;
+#X connect 74 0 65 0;
+#X connect 74 1 71 0;
+#X connect 74 1 70 0;
+#X connect 75 0 76 0;
+#X connect 80 1 74 0;
diff --git a/gfsm/src/test-state2.pd b/gfsm/src/test-state2.pd
new file mode 100644
index 0000000..a9983d0
--- /dev/null
+++ b/gfsm/src/test-state2.pd
@@ -0,0 +1,415 @@
+#N canvas 346 27 616 494 10;
+#X obj 13 7 gfsm;
+#X msg 23 84 automaton;
+#X msg 21 43 automaton a1;
+#X obj 51 6 zexy;
+#X msg 22 62 automaton a2;
+#X obj 30 285 r \$0-state;
+#X obj 19 332 print STATE-1;
+#X obj 136 76 s \$0-state;
+#X msg 150 48 id;
+#X msg 136 27 set \$1;
+#X floatatom 153 9 5 0 0 0 - - -;
+#X obj 19 308 gfsm_state a1;
+#X obj 135 10 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 218 11 degree;
+#X obj 218 74 s \$0-state;
+#X msg 19 164 arc_first;
+#X msg 23 188 arc_next;
+#X obj 243 314 gfsm_automaton a1;
+#X obj 243 180 bng 15 250 50 0 empty empty empty 0 -6 0 8 -225280 -1
+-1;
+#X obj 243 198 openpanel;
+#X msg 243 264 load_bin \$1;
+#X obj 243 335 print A1-1;
+#X obj 254 293 r \$0-fsm;
+#X obj 337 226 bng 20 250 50 0 \$0-draw-s empty DRAW 0 -6 0 8 -24198
+-1 -1;
+#N canvas 0 0 466 454 draw 0;
+#X obj 361 16 zexy;
+#X obj 67 25 r \$0-draw-s;
+#X obj 68 68 f \$0;
+#X msg 176 74 save_bin \$1draw.gfst;
+#X obj 176 98 s \$0-fsm;
+#X obj 68 162 shell;
+#X obj 68 47 t b;
+#X obj 68 91 t f f;
+#X msg 69 237 dotgv.sh \$1draw.dot;
+#X obj 171 311 f \$0;
+#X obj 172 291 t b;
+#X obj 171 357 shell;
+#X obj 172 20 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 68 137 gfsmdraw \$1draw.gfst -F \$1draw.dot;
+#X msg 171 334 rm -f \$1draw.gfst \$1draw.dot;
+#X obj 142 270 shell;
+#X msg 220 236 dotty \$1draw.dot;
+#X obj 169 183 r \$0-drawmode-s;
+#X obj 111 206 demux 0 1;
+#X obj 110 163 t b;
+#X obj 111 184 f \$0;
+#X obj 284 182 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X connect 1 0 6 0;
+#X connect 2 0 7 0;
+#X connect 3 0 4 0;
+#X connect 5 1 19 0;
+#X connect 6 0 2 0;
+#X connect 7 0 13 0;
+#X connect 7 1 3 0;
+#X connect 8 0 15 0;
+#X connect 9 0 14 0;
+#X connect 10 0 9 0;
+#X connect 12 0 6 0;
+#X connect 13 0 5 0;
+#X connect 14 0 11 0;
+#X connect 15 1 10 0;
+#X connect 16 0 15 0;
+#X connect 17 0 18 1;
+#X connect 18 0 8 0;
+#X connect 18 1 16 0;
+#X connect 19 0 20 0;
+#X connect 20 0 18 0;
+#X connect 21 0 18 1;
+#X restore 338 250 pd draw;
+#X obj 365 226 tgl 20 0 \$0-drawmode-s empty mode 0 -6 0 8 -225271
+-1 -1 0 1;
+#X obj 243 242 symbol;
+#X obj 115 141 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 486 0 310 377 weight_sum 1;
+#X obj 34 11 inlet;
+#X msg 34 104 arc_next;
+#X obj 34 309 f 0;
+#X obj 209 82 0;
+#X obj 99 228 unpack 0 0 0 0;
+#X obj 193 252 + 0;
+#X obj 98 253 t f f;
+#X obj 87 11 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 34 340 outlet;
+#X obj 34 157 gfsm_state a1 0;
+#X obj 70 136 r \$0-state;
+#X obj 88 340 s \$0-wsum-out;
+#X obj 113 13 r \$0-wsum-in;
+#X obj 34 80 until;
+#X obj 34 204 route bang;
+#X obj 34 225 t b b;
+#X obj 34 182 route arc_next;
+#X obj 34 33 t b b b b;
+#X msg 101 104 arc_reset;
+#X connect 0 0 17 0;
+#X connect 1 0 9 0;
+#X connect 2 0 8 0;
+#X connect 2 0 11 0;
+#X connect 3 0 5 1;
+#X connect 4 3 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 5 1;
+#X connect 6 1 2 1;
+#X connect 7 0 17 0;
+#X connect 9 0 16 0;
+#X connect 10 0 9 0;
+#X connect 12 0 17 0;
+#X connect 13 0 1 0;
+#X connect 14 0 15 0;
+#X connect 14 1 4 0;
+#X connect 15 0 2 0;
+#X connect 15 1 13 1;
+#X connect 16 0 14 0;
+#X connect 17 0 13 0;
+#X connect 17 1 3 0;
+#X connect 17 2 18 0;
+#X connect 17 3 13 1;
+#X connect 18 0 9 0;
+#X restore 115 161 pd weight_sum;
+#X obj 114 332 s \$0-state-out;
+#X obj 114 224 print WSUM;
+#X obj 252 97 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 298 9 405 465 rand_arc 0;
+#X obj 40 9 inlet;
+#X obj 83 9 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1
+;
+#X msg 41 98 arc_next;
+#X obj 136 266 unpack 0 0 0 0;
+#X obj 41 415 outlet;
+#X obj 41 163 gfsm_state a1 0;
+#X obj 76 140 r \$0-state;
+#X obj 243 97 s \$0-wsum-in;
+#X obj 245 119 r \$0-wsum-out;
+#X obj 245 166 random 131072;
+#X obj 245 140 t b f;
+#X obj 245 190 / 131072;
+#X obj 245 214 * 1;
+#X obj 229 334 moses 0;
+#X obj 245 237 * -1;
+#X obj 229 289 + 0;
+#X obj 229 312 t f f;
+#X obj 106 327 spigot;
+#X obj 143 304 0;
+#X obj 170 304 1;
+#X obj 107 10 r \$0-randarc-in;
+#X obj 92 415 s \$0-randarc-out;
+#X obj 41 76 until;
+#X obj 41 220 route bang;
+#X obj 106 244 t l l;
+#X obj 228 353 t b;
+#X obj 272 353 t b;
+#X obj 106 348 t l b;
+#X obj 41 348 t b b;
+#X obj 41 197 route arc_next;
+#X msg 107 97 arc_reset;
+#X obj 41 30 t b b b b;
+#X connect 0 0 31 0;
+#X connect 1 0 31 0;
+#X connect 2 0 5 0;
+#X connect 3 3 15 0;
+#X connect 5 0 29 0;
+#X connect 6 0 5 0;
+#X connect 8 0 10 0;
+#X connect 9 0 11 0;
+#X connect 10 0 9 0;
+#X connect 10 1 12 1;
+#X connect 11 0 12 0;
+#X connect 12 0 14 0;
+#X connect 13 0 25 0;
+#X connect 13 1 26 0;
+#X connect 14 0 15 1;
+#X connect 15 0 16 0;
+#X connect 16 0 13 0;
+#X connect 16 1 15 1;
+#X connect 17 0 27 0;
+#X connect 18 0 17 1;
+#X connect 19 0 17 1;
+#X connect 20 0 31 0;
+#X connect 22 0 2 0;
+#X connect 23 0 28 0;
+#X connect 23 1 24 0;
+#X connect 24 0 17 0;
+#X connect 24 1 3 0;
+#X connect 25 0 18 0;
+#X connect 26 0 19 0;
+#X connect 27 0 21 0;
+#X connect 27 0 4 0;
+#X connect 27 1 22 1;
+#X connect 28 0 4 0;
+#X connect 28 0 21 0;
+#X connect 28 1 22 1;
+#X connect 29 0 23 0;
+#X connect 30 0 5 0;
+#X connect 31 0 22 0;
+#X connect 31 1 30 0;
+#X connect 31 2 7 0;
+#X connect 31 3 22 1;
+#X restore 252 116 pd rand_arc;
+#X obj 395 113 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 102 2 392 492 rand_incr 0;
+#X obj 40 9 inlet;
+#X obj 83 9 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1
+;
+#X obj 41 54 s \$0-randarc-in;
+#X obj 43 76 r \$0-randarc-out;
+#X obj 42 98 route bang;
+#X obj 41 30 t b;
+#X obj 42 177 gfsm_automaton a1;
+#X obj 209 157 unpack 0 0 0 0;
+#X obj 55 154 r \$0-automaton;
+#X msg 42 131 root;
+#X obj 42 199 route root;
+#X obj 42 221 route bang;
+#X obj 107 336 outlet;
+#X obj 211 337 outlet;
+#X obj 271 335 outlet;
+#X msg 8 247 root 0;
+#X obj 107 254 t f f;
+#X obj 137 295 s \$0-state;
+#X msg 137 274 set \$1;
+#X obj 326 336 outlet;
+#X connect 0 0 5 0;
+#X connect 1 0 5 0;
+#X connect 3 0 4 0;
+#X connect 4 0 9 0;
+#X connect 4 1 7 0;
+#X connect 5 0 2 0;
+#X connect 6 0 10 0;
+#X connect 7 0 16 0;
+#X connect 7 1 13 0;
+#X connect 7 2 14 0;
+#X connect 7 3 19 0;
+#X connect 8 0 6 0;
+#X connect 9 0 6 0;
+#X connect 10 0 11 0;
+#X connect 11 0 15 0;
+#X connect 11 1 16 0;
+#X connect 15 0 6 0;
+#X connect 16 0 12 0;
+#X connect 16 1 18 0;
+#X connect 18 0 17 0;
+#X restore 395 132 pd rand_incr;
+#X obj 254 157 print RAND_ARC;
+#X obj 336 33 s \$0-state;
+#X obj 326 54 s \$0-fsm;
+#X obj 13 105 s \$0-automaton;
+#X obj 326 12 r \$0-automaton;
+#X obj 13 214 s \$0-state-a;
+#X obj 19 262 r \$0-state-a;
+#X obj 195 192 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 230 140 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 470 10 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X floatatom 493 10 5 0 0 0 - - -;
+#X obj 471 30 metro 1000;
+#X obj 417 300 gfsm_alphabet alph1;
+#X obj 518 214 bng 15 250 50 0 empty empty empty 0 -6 0 8 -225280 -1
+-1;
+#X obj 518 232 openpanel;
+#X obj 518 254 symbol;
+#X msg 518 275 load \$1;
+#X obj 481 375 print RI-ATOM;
+#X msg 419 273 char2atom \$1;
+#X floatatom 436 245 5 0 0 0 - - -;
+#X obj 482 332 fromsymbol;
+#N canvas 0 0 450 300 ri_print 0;
+#X obj 48 22 inlet;
+#X obj 101 22 inlet;
+#X obj 155 22 inlet;
+#X obj 206 22 inlet;
+#X obj 319 22 inlet;
+#X obj 93 97 spigot;
+#X obj 93 57 pack 0 0 0 0;
+#X obj 93 122 unpack 0 0 0 0;
+#X obj 124 196 print RI-LO;
+#X obj 186 155 print RI-WT;
+#X obj 155 175 print RI-HI;
+#X obj 93 215 print RI-NXT;
+#X connect 0 0 6 0;
+#X connect 1 0 6 1;
+#X connect 2 0 6 2;
+#X connect 3 0 6 3;
+#X connect 4 0 5 1;
+#X connect 5 0 7 0;
+#X connect 6 0 5 0;
+#X connect 7 0 11 0;
+#X connect 7 1 8 0;
+#X connect 7 2 10 0;
+#X connect 7 3 9 0;
+#X restore 420 160 pd ri_print;
+#X obj 488 131 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 114 181 spigot;
+#X obj 162 181 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 253 138 spigot;
+#X obj 301 138 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 29 410 grattsdict;
+#X obj 470 51 t b b;
+#X obj 475 100 spigot;
+#X msg 506 80 0;
+#X msg 534 80 1;
+#X obj 548 456 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 0 0 450 300 load_dict 0;
+#X obj 31 16 inlet;
+#X obj 31 38 t b;
+#X msg 31 67 load /home/moocow/src/pd/externs/ratts/dict/beep-b.txt
+cr;
+#X obj 33 108 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X restore 30 391 pd load_dict;
+#X obj 31 371 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 243 365 gpratts~ 10 \$0p /gpratts;
+#X obj 30 432 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X msg 30 453 \; pd dsp \$1;
+#X obj 434 74 bng 15 250 20 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 435 103 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 424 202 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 367 340 route 0;
+#X msg 202 284 info;
+#X msg 13 141 arc_reset;
+#X msg 250 219 markov.gfst;
+#X msg 538 211 markov.lab;
+#X floatatom 114 204 8 0 0 0 - - -;
+#X obj 481 355 spigot;
+#X obj 533 354 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 145 359 ms8a~ p gpr;
+#X connect 1 0 38 0;
+#X connect 2 0 38 0;
+#X connect 4 0 38 0;
+#X connect 5 0 11 0;
+#X connect 8 0 7 0;
+#X connect 9 0 7 0;
+#X connect 10 0 9 0;
+#X connect 11 0 6 0;
+#X connect 11 0 29 0;
+#X connect 12 0 10 0;
+#X connect 13 0 14 0;
+#X connect 15 0 40 0;
+#X connect 16 0 40 0;
+#X connect 17 0 21 0;
+#X connect 18 0 19 0;
+#X connect 19 0 26 0;
+#X connect 20 0 17 0;
+#X connect 22 0 17 0;
+#X connect 26 0 20 0;
+#X connect 27 0 28 0;
+#X connect 31 0 32 0;
+#X connect 32 0 60 0;
+#X connect 33 0 34 0;
+#X connect 34 0 56 0;
+#X connect 34 0 53 0;
+#X connect 34 1 56 1;
+#X connect 34 2 56 2;
+#X connect 34 3 56 3;
+#X connect 39 0 37 0;
+#X connect 39 0 36 0;
+#X connect 41 0 11 0;
+#X connect 44 0 46 0;
+#X connect 45 0 46 1;
+#X connect 46 0 63 0;
+#X connect 47 1 55 0;
+#X connect 48 0 49 0;
+#X connect 49 0 50 0;
+#X connect 50 0 51 0;
+#X connect 51 0 47 0;
+#X connect 53 0 47 0;
+#X connect 54 0 53 0;
+#X connect 55 0 76 0;
+#X connect 55 0 82 0;
+#X connect 57 0 56 4;
+#X connect 58 0 81 0;
+#X connect 59 0 58 1;
+#X connect 60 0 35 0;
+#X connect 61 0 60 1;
+#X connect 63 0 65 0;
+#X connect 63 1 64 0;
+#X connect 64 0 34 0;
+#X connect 65 0 64 1;
+#X connect 66 0 64 1;
+#X connect 68 0 62 0;
+#X connect 69 0 68 0;
+#X connect 70 0 84 0;
+#X connect 70 0 84 1;
+#X connect 70 1 66 0;
+#X connect 71 0 72 0;
+#X connect 76 1 70 0;
+#X connect 77 0 17 0;
+#X connect 78 0 40 0;
+#X connect 79 0 26 0;
+#X connect 80 0 50 0;
+#X connect 81 0 30 0;
+#X connect 82 0 52 0;
+#X connect 83 0 82 1;
diff --git a/gfsm/src/test.lab b/gfsm/src/test.lab
new file mode 100644
index 0000000..a339b5f
--- /dev/null
+++ b/gfsm/src/test.lab
@@ -0,0 +1,5 @@
+<epsilon> 0
+a 1
+b 2
+c 3
+foo 42
diff --git a/gfsm/src/test.tfst b/gfsm/src/test.tfst
new file mode 100644
index 0000000..e07da8c
--- /dev/null
+++ b/gfsm/src/test.tfst
@@ -0,0 +1,3 @@
+0 1 1 1 0
+1 2 2 2 0
+2
diff --git a/gfsm/src/test2.lab b/gfsm/src/test2.lab
new file mode 100644
index 0000000..08f153a
--- /dev/null
+++ b/gfsm/src/test2.lab
@@ -0,0 +1,6 @@
+<epsilon> 0
+a 1
+b 2
+c 3
+foo 42
+x 1
diff --git a/gfsm/src/test2.tfst b/gfsm/src/test2.tfst
new file mode 100644
index 0000000..e5e2be6
--- /dev/null
+++ b/gfsm/src/test2.tfst
@@ -0,0 +1,4 @@
+0 1 3 30 0
+0 2 4 40 0
+1 0
+2 0
diff --git a/gfsm/src/test3.tfst b/gfsm/src/test3.tfst
new file mode 100644
index 0000000..e124810
--- /dev/null
+++ b/gfsm/src/test3.tfst
@@ -0,0 +1,4 @@
+0 1 3 30 0.3
+0 2 4 40 0.7
+1 0
+2 0