Index: /cpp/LICENSE.txt
===================================================================
--- /cpp/LICENSE.txt	(revision 110)
+++ /cpp/LICENSE.txt	(revision 110)
@@ -0,0 +1,452 @@
+If  you  are  using any  part of  Framsticks GDK or GenoFX  for  a  project
+which   is   not  a  part  of  Framsticks   software,   please   explicitly
+acknowledge GDK or GenoFX and make a link to Framsticks, www.framsticks.com
+
+---
+
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 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.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, 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 library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, 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 companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the 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.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
Index: p/README
===================================================================
--- /cpp/README	(revision 109)
+++ 	(revision )
@@ -1,22 +1,0 @@
-=== Building GDK test applications ===
-
-make -f frams/Makefile-GDK gdk_tests
-
-=== Source locations ===
-
-  +- common          - general compatibility layer & utilities
-  +- frams           - framsticks modules
-      +- _demos      - GDK test applications
-      +- config      - GDK elements declarations
-      +- errmgr      - error manager (logging/messaging)
-      +- genetic     - genetic module
-      |  +- oper     - genetic operators
-      |  +- conv     - genetic converters
-      +- model       - parts, joints, neurons
-      +- neuro       - neural net simulation
-      |   +- impl    - neuron classes implementations
-      +- param       - c++/properties access objects
-      +- util        - framsticks-related utilities
-      +- virtfile    - object oriented FILE* replacement
-      +- vm
-          +- classes - virtual machine c++ interfaces
Index: /cpp/README.txt
===================================================================
--- /cpp/README.txt	(revision 110)
+++ /cpp/README.txt	(revision 110)
@@ -0,0 +1,24 @@
+_____ Building GDK test applications _____
+
+make -f frams/Makefile-GDK gdk_tests
+
+
+_____ Source directories _____
+
+  +- common          - general compatibility layer & utilities
+  +- frams           - framsticks modules
+      +- _demos      - GDK test applications
+      +- config      - GDK elements declarations
+      +- errmgr      - error manager (logging/messaging)
+      +- genetic     - genetic module
+      |  +- oper     - genetic operators and GenoFX
+      |  +- conv     - genetic converters
+      +- model       - parts, joints, neurons
+      +- neuro       - neural net simulation
+      |   +- impl    - neuron classes implementations
+      +- param       - c++/properties access objects
+      +- util        - framsticks-related utilities
+      +- virtfile    - object-oriented FILE* replacement
+      +- vm
+          +- classes - c++ interfaces for the framsticks virtual machine
+
Index: /cpp/_old/f0-fuzzy/geno_f0Fuzzy.cpp
===================================================================
--- /cpp/_old/f0-fuzzy/geno_f0Fuzzy.cpp	(revision 110)
+++ /cpp/_old/f0-fuzzy/geno_f0Fuzzy.cpp	(revision 110)
@@ -0,0 +1,1312 @@
+#include <math.h> //HUGE_VAL
+#include "geno_f0Fuzzy.h"
+#include "neuroimpl-fuzzy.h"
+#include "neuroimpl-fuzzy-f0.h"
+#include "rndutil.h"
+#include "model.h"
+
+#define FIELDSTRUCT Geno_f0Fuzzy
+static ParamEntry GENO7param_tab[]=   //external access to f0Fuzzy genetic parameters
+{
+{"Genetics: f0-fuzzy",1,8,},
+{"f0Fuzzy_maxSets",0,0,"Max. sets","d 0 999",FIELD(maximumSetsNr),"Maximum number of fuzzy sets",},
+{"f0Fuzzy_maxRules",0,0,"Max. rules","d 0 999",FIELD(maximumRulesNr),"Maximum number of fuzzy rules",},
+{"f0Fuzzy_prob0",0,0,"Add new fuzzy set (with simple rule)","f 0 1",FIELD(probtab[F0Fuzzy_ADDSET]),"Probability of adding new fuzzy set with simple rule, which uses this set (1=proceed on all genes, 0.1=proceed on ten percent)",},
+{"f0Fuzzy_prob1",0,0,"Remove fuzzy set","f 0 1",FIELD(probtab[F0Fuzzy_REMSET]),"Probability of removing fuzzy set (1=proceed on all genes, 0.1=proceed on ten percent)",},
+{"f0Fuzzy_prob2",0,0,"Add new rule","f 0 1",FIELD(probtab[F0Fuzzy_ADDRULE]),"Probability of adding new rule (1=proceed on all genes, 0.1=proceed on ten percent)",},
+{"f0Fuzzy_prob3",0,0,"Remove rule","f 0 1",FIELD(probtab[F0Fuzzy_REMRULE]),"Probability of removing rule (1=proceed on all genes, 0.1=proceed on ten percent)",},
+{"f0Fuzzy_prob4",0,0,"Add new input/output to existing rule","f 0 1",FIELD(probtab[F0Fuzzy_MODRULE]),"Probability of adding new input or output to exisitng rule (1=proceed on all genes, 0.1=proceed on ten percent)",},
+{"f0Fuzzy_prob5",0,0,"Remove input/output from existing rule","f 0 1",FIELD(probtab[F0Fuzzy_MOD2RULE]),"Probability of removing input or output from exisitng rule (1=proceed on all genes, 0.1=proceed on ten percent)",},
+{0,},
+};
+#undef FIELDSTRUCT
+
+Geno_f0Fuzzy::Geno_f0Fuzzy()
+{
+  par.setParamTab(GENO7param_tab);
+  par.select(this);
+  supported_format='0';
+  name="Fuzzy control system";
+  maximumSetsNr=50;
+  maximumRulesNr=100;
+  probtab[F0Fuzzy_ADDSET] = 0.01;
+  probtab[F0Fuzzy_REMSET] = 0.0112;
+  probtab[F0Fuzzy_ADDRULE]= 0.01;
+  probtab[F0Fuzzy_REMRULE]= 0.0222; //when new set is created, new rule (using this new set) is also created but when rule is removed, unused set are removed too
+  probtab[F0Fuzzy_MODRULE] = 0.005;
+  probtab[F0Fuzzy_MOD2RULE] = 0.005;
+}
+
+char *Geno_f0Fuzzy::getSimplest()
+{
+  return "p:\np:1\nj:0,1\nn:d=\"G\",j=0\nn:d=\"|\",j=0\nn:d=\"Fuzzy: ns=1, nr=1, fs=-1;0;0;1;, fr=0;0:0;0/\"\nn:d=\"ChSel:ch=0\"\nc:2, 0\nc:3, 2\nc:1, 3\n";
+};
+
+int Geno_f0Fuzzy::markDuplicatedSets(const double fuzzySets1[], const int setsNr1, const double fuzzySets2[], const int setsNr2, int transTable[], const int setsNr3)
+{
+  if(setsNr1+setsNr2!=setsNr3) return -1;
+  int i, j;
+  for(i=0;i<setsNr1;i++)
+    for(j=0;j<setsNr2;j++)
+      if((fuzzySets1[4*i]==fuzzySets2[4*j])&&(fuzzySets1[4*i+1]==fuzzySets2[4*j+1])&&
+         (fuzzySets1[4*i+2]==fuzzySets2[4*j+2])&&(fuzzySets1[4*i+3]==fuzzySets2[4*j+3]))
+           transTable[setsNr1+j]=i; //mark equal sets
+  return 0;
+}
+
+
+int Geno_f0Fuzzy::nearestSet(double set[4], double sets[], int setsNr)
+{
+  int i, nearest=0;
+  double disCur, disNear;
+
+  disCur=disNear=10; //the largest distance i between -1;-1;-1;-1 and 1;1;1;1, and equals 8.
+  for(i=0;i<setsNr;i++)
+  {
+    disCur=fabs(sets[4*i]-set[0])+fabs(sets[4*i+1]-set[1])+
+           fabs(sets[4*i+2]-set[2])+fabs(sets[4*i+3]-set[3]);
+    if(disCur<disNear){ nearest=i; disNear=disCur; }
+  }
+
+  return nearest;
+}
+
+int Geno_f0Fuzzy::changeSetsNumeration(SString &rules, int transTable[], int nrItems)
+{
+  //for each rule (from rules string), change number of fuzzy set into new one
+  int pos=0;
+  SString oneRule, newRules;
+  while(rules.getNextToken(pos, oneRule, '/'))
+  {
+    SString cond, dec, nrStr;
+    int p=0, setNr;
+    char temp[10];
+    oneRule.getNextToken(p, cond, ':');
+    oneRule.getNextToken(p, dec, '/');
+    p=0;
+    while(cond.getNextToken(p, nrStr, ';')) //first: input number
+    {
+      newRules += nrStr; newRules += ";";
+      cond.getNextToken(p, nrStr, ';'); //then fuzzy set nr
+      if((setNr=atoi(nrStr))>=nrItems)
+        sprintf(temp, "%i", setNr); //might occur when new fuzzy set and new fuzzy rule added - does not need to be transformated
+      else
+        sprintf(temp, "%i", transTable[setNr]); //transformate set number
+      newRules += temp;
+      if(p<cond.len())
+        newRules += ";";
+    }
+    p=0; newRules += ":";
+    while(dec.getNextToken(p, nrStr, ';')) //first: output number
+    {
+      newRules += nrStr; newRules += ";";
+      dec.getNextToken(p, nrStr, ';'); //then fuzzy set nr
+      if((setNr=atoi(nrStr))>=nrItems)
+        sprintf(temp, "%i", setNr); //might occur when new fuzzy set and new fuzzy rule added - does not need to be transformated
+      else
+        sprintf(temp, "%i", transTable[setNr]); //transformate set number
+      newRules += temp;
+      if(p<dec.len())
+        newRules += ";";
+    }
+    newRules += "/";
+  }
+
+  rules=newRules;
+  return 0;
+}
+
+int Geno_f0Fuzzy::removeUnusedSets(SString &sets, SString rules, int &setsNr, int transTable[])
+{
+  //for each rule (from rules string), change number of fuzzy set into new one
+  int pos=0, i, nrUsedSets, *transTableOryginal = new int[setsNr];
+  bool *setUsed = new bool[setsNr], unusedPresent;
+  SString oneRule, newSets, nrStr;
+  for(i=0;i<setsNr;i++) { setUsed[i]=false; transTableOryginal[i]=transTable[i];} //copy oryginal values of trans table
+
+  //mark used sets
+  while(rules.getNextToken(pos, oneRule, '/'))
+  {
+    SString cond, dec;
+    int p=0, setNr;
+    oneRule.getNextToken(p, cond, ':');
+    oneRule.getNextToken(p, dec, '/');
+    p=0;
+    while(cond.getNextToken(p, nrStr, ';')) //first: input number
+    {
+      cond.getNextToken(p, nrStr, ';'); //then fuzzy set nr
+      setNr=atoi(nrStr);
+      if((setNr>=setsNr)||(setNr<0)) setNr=randomN(setsNr); //if everything ok, impossible to happen
+      setUsed[setNr]=true;
+    }
+    p=0;
+    while(dec.getNextToken(p, nrStr, ';')) //first: output number
+    {
+      dec.getNextToken(p, nrStr, ';'); //then fuzzy set nr
+      setNr=atoi(nrStr);
+      if((setNr>=setsNr)||(setNr<0)) setNr=randomN(setsNr); //if everything ok,impossible to happen
+      setUsed[setNr]=true;
+    }
+  }
+
+  for(i=0, nrUsedSets=0, unusedPresent=false;i<setsNr;i++)
+    if(setUsed[i]==false)
+    {
+      unusedPresent=true;
+      //change numbers in transTable - some set will be removed, so further renumeration is needed
+      for(int j=0;j<setsNr;j++) if(transTableOryginal[j]>i) transTable[j]--;
+    }
+    else
+      nrUsedSets++;
+
+  SAFEDELETEARRAY(transTableOryginal)
+
+  if(!unusedPresent)
+  {
+    SAFEDELETEARRAY(setUsed)
+    return 0; //all sets are necessery
+  }
+
+  //remove from new fuzzy sets unused sets
+  pos=0;
+  newSets="";
+  int semicol=0, nrOfSet=0;
+  SString tempSet="";
+  while(sets.getNextToken(pos, nrStr, ';'))
+  {
+    tempSet += nrStr; tempSet += ';';
+    if(++semicol==4)
+    {
+      if(setUsed[nrOfSet])
+        newSets += tempSet;
+      tempSet="";
+      semicol=0;
+      nrOfSet++;
+    }
+  }
+
+  setsNr=nrUsedSets;
+  sets=newSets;
+
+  SAFEDELETEARRAY(setUsed)
+
+  return 1;
+}
+
+int Geno_f0Fuzzy::removeExcessiveInOut(SString &rules, int inputsNr, int outputsNr)
+{
+  SString newRules, oneRule;
+  int pos, i;
+  char tempChar50[50];
+
+  pos=0;
+  while(rules.getNextToken(pos, oneRule, '/'))
+  {
+    SString cond, dec, nrStr, newInput, newOutput;
+    int p=0;
+    bool *usedInOut, first;
+
+    oneRule.getNextToken(p, cond, ':');
+    oneRule.getNextToken(p, dec, '/');
+
+    //create input table
+    usedInOut = new bool[inputsNr]; for(i=0;i<inputsNr;i++) usedInOut[i]=false;
+    //create new rule, which omits double inputs
+    p=0; newInput=""; first=true;
+    while(cond.getNextToken(p, nrStr, ';')) //first: input number
+    {
+      int inNr=atoi(nrStr), setNr;
+      cond.getNextToken(p, nrStr, ';'); //then fuzzy set nr
+      setNr=atoi(nrStr);
+      if(!usedInOut[inNr]) //not used yet
+      {
+        if(!first) newInput += ';';
+        first=false;
+        sprintf(tempChar50, "%i;%i", inNr, setNr);
+        newInput += tempChar50;
+        usedInOut[inNr]=true;
+      }
+    }
+    SAFEDELETEARRAY(usedInOut)
+
+    //create output table
+    usedInOut = new bool[outputsNr]; for(i=0;i<outputsNr;i++) usedInOut[i]=false;
+    //create new rule, which omits double outputs
+    p=0; newOutput=""; first=true;
+    while(dec.getNextToken(p, nrStr, ';')) //first: output number
+    {
+      int outNr=atoi(nrStr), setNr;
+      dec.getNextToken(p, nrStr, ';'); //then fuzzy set nr
+      setNr=atoi(nrStr);
+      if(!usedInOut[outNr]) //not used yet
+      {
+        if(!first) newOutput += ';';
+        first=false;
+        sprintf(tempChar50, "%i;%i", outNr, setNr);
+        newOutput += tempChar50;
+        usedInOut[outNr]=true;
+      }
+    }
+    SAFEDELETEARRAY(usedInOut)
+
+    newRules += newInput + ":" + newOutput + "/";
+  }
+
+  rules=newRules;
+
+  return 0;
+}
+
+int Geno_f0Fuzzy::removeExcessiveRules(SString &rules, int setsNr, int &rulesNr)
+{
+  int *rulDef, //for each rule, remembers number of inputs and number of outputs used (in rule)
+      **rulesBody, //for each rule, remembers: nr input, nr fuzzy set ... nr output, nr fuzzy set ...
+      i, j, k, l, nrRulesToRemove, pos, unimpTemp;
+  const int original_rulesNr=rulesNr;
+  bool *rulesToRemove = new bool[original_rulesNr];
+  SString newRules, oneRule;
+
+  for(i=0;i<original_rulesNr;i++) rulesToRemove[i]=false;
+  //create space for rules definition: number of inputs and outputs for each rule
+  rulDef = new int[2*original_rulesNr];
+  if(FuzzyF0String::countInputsOutputs(rules, rulDef, original_rulesNr))
+  {
+    SAFEDELETEARRAY(rulDef)
+    SAFEDELETEARRAY(rulesToRemove)
+    return -1; //error while parsing rules string
+  }
+  //create space for rules
+  rulesBody = new int*[original_rulesNr];   //list of rules that will contain rules body
+  for (i=0;i<original_rulesNr;i++) rulesBody[i] = new int[2*(rulDef[2*i]+rulDef[2*i+1])];  //each rule can have different number of inputs and outputs
+  //get from string rules body into integer variables
+  if(FuzzyF0String::convertStrToRules(rules, rulDef, rulesBody, setsNr, original_rulesNr, unimpTemp))
+  {
+    SAFEDELETEARRAY(rulDef)
+    if(rulesBody) for(i=0;i<original_rulesNr;i++) SAFEDELETEARRAY(rulesBody[i])
+    SAFEDELETEARRAY(rulesBody)
+    SAFEDELETEARRAY(rulesToRemove)
+    return -2; //error while parsing rules string
+  }
+
+  nrRulesToRemove=0;
+  for(i=0;i<original_rulesNr;i++) //for every rule...
+    for(j=i+1;j<original_rulesNr;j++) //...compare with further rule's...
+    {
+      int similarity=0;
+      if(rulDef[2*j]!=rulDef[2*i]) continue;// do not check rules with different number of inputs
+      for(k=0;k<rulDef[2*i];k++) //..conditional part rule i
+        for(l=0;l<rulDef[2*j];l++) //..conditional part rule j
+          if((rulesBody[i][k]==rulesBody[j][l])&&(rulesBody[i][k+1]==rulesBody[j][l+1])) //if inputs nr and fuzzy sets nr are the same
+            similarity++; //increase similarity number
+      //every input and fuzzy set number of rule j equals input and fuzzy set nr of rule i
+      if((similarity==rulDef[2*j])&&(similarity==rulDef[2*i]))
+      {
+        if(!rulesToRemove[j]) nrRulesToRemove++; //because might happen, that rule is mark to remove more than once
+        rulesToRemove[j]=true;
+      }
+    }
+
+  if(nrRulesToRemove>=original_rulesNr) //in fact, it is impossible; but it's safe to protect
+  {
+    SAFEDELETEARRAY(rulDef)
+    if(rulesBody) for(i=0;i<original_rulesNr;i++) SAFEDELETEARRAY(rulesBody[i])
+    SAFEDELETEARRAY(rulesBody)
+    SAFEDELETEARRAY(rulesToRemove)
+    return -3; //error while comparing rules
+  }
+
+  if(nrRulesToRemove>0)
+  {
+    int nrOfRule=0;
+    //copy rules, which are not to be removed
+    pos=0; newRules="";
+    while(rules.getNextToken(pos, oneRule, '/'))
+      if(!rulesToRemove[nrOfRule++]) newRules += oneRule + "/";
+    rulesNr -= nrRulesToRemove;
+    rules = newRules;
+  }
+
+  SAFEDELETEARRAY(rulDef)
+  if(rulesBody) for(i=0;i<original_rulesNr;i++) SAFEDELETEARRAY(rulesBody[i])
+  SAFEDELETEARRAY(rulesBody)
+  SAFEDELETEARRAY(rulesToRemove)
+
+  return 0;
+};
+
+int Geno_f0Fuzzy::sortSet(double set[4])
+{
+  int i,j;
+  double fTemp;
+  for(i=0;i<4;i++)
+  {
+    if(set[i]>1) set[i]=1;
+    if(set[i]<-1) set[i]=-1;
+    for(j=0;j<4;j++)
+      if((i>j)&&(set[i]<set[j]))
+      {fTemp=set[i];set[i]=set[j];set[j]=fTemp;};
+  }
+  return 0;
+}
+
+int Geno_f0Fuzzy::computeSet(double newSet[4])
+{ //parameters: most probably size of support and core
+  double core = min(fabs(0.15+0.25*RndGen.GaussStd()), 2.0), //core can not be bigger 2
+         coreStart = RndGen.Uni(-1,1);
+
+  if(0.5<rnd01)
+  {
+    newSet[0] = coreStart - min(fabs(0.15*RndGen.GaussStd()), 2.0);
+    newSet[1] = coreStart;
+    newSet[2] = newSet[1] + core;
+    newSet[3] = newSet[2] + min(fabs(0.15*RndGen.GaussStd()), 2.0);
+  }
+  else
+  {
+    newSet[2] = coreStart;
+    newSet[3] = newSet[2] + min(fabs(0.15*RndGen.GaussStd()), 2.0);
+    newSet[1] = newSet[2] - core;
+    newSet[0] = newSet[1] - min(fabs(0.15*RndGen.GaussStd()), 2.0);
+  }
+
+  sortSet(newSet);
+
+  return 0;
+}
+
+int Geno_f0Fuzzy::mutate(char *&g, float &chg,int &method)
+{
+  int const maxTrialNr=10; //maximum number of mutating trial, if for some reason drawed mutation can not be done
+  SString fuzzyGeno, finalGenotype, tok, newRulesStr, newSetsStr;
+  int newSetsNr, newRulesNr;
+  int i, pos, genoUsed, genoAdded, genoRemoved, nrTrials;
+  int *transTable;
+  char tempChar50[50];
+  bool mutated;
+
+  Model model(Geno(g, '0')); //create a model from genotype
+  Neuro *fuzzy=findNeuro(&model, Neuro::getClass("Fuzzy"));
+  if (!fuzzy) return GENOPER_OPFAIL; //if not present, fail
+  const int inputsNr=fuzzy->getInputCount(); //get number of inputs
+  const int outputsNr=NI_FuzzyNeuro::countOuts(&model, fuzzy); //count number of outputs
+
+  //get neuron four properties
+  SyntParam pi=fuzzy->classProperties();
+  model.open();
+  const int setsNr=pi.getIntById("ns");
+  const int rulesNr=pi.getIntById("nr");
+  const SString setsStr=pi.getStringById("fs");
+  const SString rulesStr=pi.getStringById("fr");
+
+  if((inputsNr<=0)||(outputsNr<=0)||
+     (setsStr.len()==0)||(rulesStr.len()==0)||(setsNr<=0)||(rulesNr<=0)) return GENOPER_OPFAIL; //ERROR
+
+  //find out the real length of genotype
+  fuzzyGeno = setsStr+", "+rulesStr;
+  genoRemoved=genoAdded=genoUsed=0; //1 geno is i.e. -0.325; but this are 7 characters! so, 1 is used, 6 are unused
+  for(i=0;i<fuzzyGeno.len();i++) //count genes in fuzzy genotype
+    if((fuzzyGeno[i]==';')||(fuzzyGeno[i]=='/')||(fuzzyGeno[i]==':')) genoUsed++;
+
+  //mutation - drawing
+  mutated=false;
+  for(nrTrials=0;(nrTrials<maxTrialNr)&&(!mutated);nrTrials++)
+  {
+    newSetsStr=""; newRulesStr=""; newSetsNr=0; newRulesNr=0;
+    switch(method=roulette(probtab, F0Fuzzy_COUNT))
+    {
+      case F0Fuzzy_ADDSET: //add new fuzzy set
+            if(setsNr>=maximumSetsNr) break;
+            double newSetD[4];
+            computeSet(newSetD); //draw set and rank rising
+            if(sprintf(tempChar50, "%.4lf;%.4lf;%.4lf;%.4lf;", newSetD[0], newSetD[1], newSetD[2], newSetD[3]) != EOF) //in fact, always true
+            {
+              newSetsStr = setsStr + tempChar50;
+              //add new rule, using fresh new created fuzzy set (in premise part) - prevents removing of new fuzzy set
+              if((sprintf(tempChar50, "%i;%i:%i;%i/", randomN(inputsNr), setsNr, randomN(outputsNr), randomN(setsNr+1)) != EOF)&& //in fact, always true; but if not, nothing wrong happens
+                 (rulesNr<maximumRulesNr))
+                { newRulesStr = rulesStr + tempChar50; newRulesNr=rulesNr+1; genoAdded+=4; }
+              newSetsNr=setsNr+1; //one more fuzzy set
+              genoAdded+=4; //four gens added
+              mutated=true;
+            }
+            break;
+      case F0Fuzzy_REMSET:{ //remove existing fuzzy set
+            if(setsNr<=1) break;
+            int setToRemove=randomN(setsNr), foundSetsPartNr=0;
+            pos=0;
+            //copy sets before set to remove
+            while((foundSetsPartNr!=4*setToRemove)&&(setsStr.getNextToken(pos, tok, ';')))
+              { newSetsStr += tok + ";"; foundSetsPartNr++; }
+            double removedSet[4];
+            //omit four numbers - one fuzzy set - and remember parameters of removed set
+            for(int ii=0;(ii<4)&&(setsStr.getNextToken(pos, tok, ';'));ii++) removedSet[ii]=atoi(tok);
+            //copy sets after set to remove
+            while(setsStr.getNextToken(pos, tok, ';'))
+              { newSetsStr += tok + ";"; foundSetsPartNr++; }
+            newSetsNr=setsNr-1;
+            newRulesNr=rulesNr;
+            //find the nearest set to removed one
+            double *newSets = new double[4*setsNr];
+            if(FuzzyF0String::convertStrToSets(newSetsStr, newSets, newSetsNr)!=0)
+              { SAFEDELETEARRAY(newSets) break; }
+            transTable = new int[setsNr];
+            for(int ii=0;ii<setToRemove;ii++) transTable[ii] = ii;
+            for(int ii=setToRemove;ii<setsNr;ii++) transTable[ii] = ii-1; //transformate
+            transTable[setToRemove]=nearestSet(removedSet, newSets, newSetsNr); //in rules, replace removed set with found nearest
+            SAFEDELETEARRAY(newSets)
+            //transformate old fuzzy sets number into new fuzzy sets number, according to transTable table
+            newRulesStr=rulesStr;
+            changeSetsNumeration(newRulesStr, transTable, setsNr);
+            SAFEDELETEARRAY(transTable)
+            //remove inputs/outputs which are unnecessery
+            //remove rules which are unnecessery: conditional part must be unique
+            //CAUTION: rules string and number of rules might change
+            if((removeExcessiveInOut(newRulesStr, inputsNr, outputsNr)<0)||
+               (removeExcessiveRules(newRulesStr, newSetsNr, newRulesNr)<0))
+               break;
+            genoRemoved+=4;
+            mutated=true;
+            break;
+            }
+      case F0Fuzzy_ADDRULE:{ //add new fuzzy rule
+            if(rulesNr>=maximumRulesNr) break;
+            SString tempSString;
+            bool ruleOk=true;
+            int nrIns=1+randomN(inputsNr), //draw number of inputs between {1,..,inputsNr}
+                nrOuts=1+randomN(outputsNr); //draw number of outputs between {1,..,outputsNr}
+            for(i=0;((i<(nrIns+nrOuts))&&(ruleOk));i++)
+              if(sprintf(tempChar50, "%i;%i", (i<nrIns)?randomN(inputsNr):randomN(outputsNr), randomN(setsNr)) != EOF) //write: in/out nr ; fuzzy set nr
+              {
+                tempSString += tempChar50;
+                if(i+1==nrIns) //end of conditional part
+                  tempSString += ':';
+                else if (i+1==nrIns+nrOuts) //end of rule
+                  tempSString += '/';
+                else
+                  tempSString += ';';
+              }
+              else
+                ruleOk = false; //error while transformating, do not add this rule
+            if(ruleOk)
+            {
+              tempSString = tempSString + rulesStr;
+              int temp_newRulesNr = rulesNr+1;
+              if((removeExcessiveInOut(tempSString, inputsNr, outputsNr)<0)||
+                 (removeExcessiveRules(tempSString, setsNr, temp_newRulesNr)<0)||
+                 (temp_newRulesNr != rulesNr+1)) //new added rule was removed, so there was no mutation in fact!
+                break;
+              newSetsStr = setsStr; newSetsNr = setsNr;//do not change sets
+              newRulesStr = tempSString; newRulesNr = temp_newRulesNr; //replace with new one
+              genoAdded+=2*(nrIns+outputsNr); //gens added: input, set, ... , output, set, ...
+              mutated=true;
+            }
+            break;
+            }
+      case F0Fuzzy_REMRULE:{ //remove existing fuzzy rule
+            if(rulesNr<=1) break;
+            int ruleToRemove=randomN(rulesNr), foundRuleNr=0;
+            pos=0;
+            //copy rules before rule to remove
+            while((foundRuleNr!=ruleToRemove)&&(rulesStr.getNextToken(pos, tok, '/')))
+              { newRulesStr += tok + "/"; foundRuleNr++; }
+            //omit this rule
+            rulesStr.getNextToken(pos, tok, '/');
+            for(int ii=0;ii<tok.len();ii++) if((tok[ii]==';')||(tok[ii]==':')||(tok[ii]=='/')) genoRemoved++;
+            //copy rules after rule to remove
+            while(rulesStr.getNextToken(pos, tok, '/'))
+              { newRulesStr += tok + "/"; foundRuleNr++; }
+            newRulesNr = rulesNr-1;
+            newSetsNr = setsNr; newSetsStr = setsStr;
+            // after removing of the rule, an unused fuzzy set(s) may occur
+            //create space for new transformation table
+            int *transTable = new int [newSetsNr];
+            for(int ii=0;ii<newSetsNr;ii++) transTable[ii]=ii; //formula 1:1 - no renumeration needed now
+            int oldSetNr=newSetsNr; //remember number of sets used in new genotype, but before reduction
+            //remove unused sets; if any set was removed, renumeration is needed
+            if(removeUnusedSets(newSetsStr, newRulesStr, newSetsNr, transTable))
+              changeSetsNumeration(newRulesStr, transTable, oldSetNr); //renumerate new sets
+            SAFEDELETEARRAY(transTable);
+            mutated=true;
+            break;
+            }
+      case F0Fuzzy_MODRULE:{ //modify fuzzy rule: add new input/output
+            int ruleToChange=randomN(rulesNr), foundRuleNr=0;
+            SString modRule, cond, dec, tempStr;
+            pos=0;
+            //copy rules before rule to change
+            while((foundRuleNr!=ruleToChange)&&(rulesStr.getNextToken(pos, tok, '/')))
+              { newRulesStr += tok + "/"; foundRuleNr++; }
+            //change this rule
+            rulesStr.getNextToken(pos, modRule, '/');
+            //copy rules after rule to remove
+            while(rulesStr.getNextToken(pos, tok, '/'))
+              { newRulesStr += tok + "/"; foundRuleNr++; }
+            pos=0;
+            modRule.getNextToken(pos, cond, ':');
+            modRule.getNextToken(pos, dec, '/');
+            if(0.5<rnd01) //add input
+            { if(sprintf(tempChar50, ";%i;%i", randomN(inputsNr), randomN(setsNr)) != EOF) //write: in nr ; fuzzy set nr
+                cond += tempChar50;
+              else break;
+            }
+            else //add output
+            { if(sprintf(tempChar50, ";%i;%i", randomN(outputsNr), randomN(setsNr)) != EOF) //write: in nr ; fuzzy set nr
+                dec += tempChar50;
+              else break;
+            }
+            tempStr = newRulesStr + cond + ":" + dec + "/";
+            int temp_rulesNr = rulesNr;
+            if((removeExcessiveInOut(tempStr, inputsNr, outputsNr)<0)||
+               (removeExcessiveRules(tempStr, setsNr, temp_rulesNr)<0)||
+               (temp_rulesNr != rulesNr)) //new added in/out caused duplicated rule, so this mutation is not ok - try other
+              break;
+            newRulesStr = tempStr;
+            newRulesNr = rulesNr; newSetsStr = setsStr; newSetsNr = setsNr;
+            genoAdded+=2;
+            mutated=true;
+            break;
+            }
+      case F0Fuzzy_MOD2RULE:{ //modify fuzzy rule: remove existing input/output
+            int ruleToChange=randomN(rulesNr), foundRuleNr=0;
+            SString modRule, cond, dec, tempStr;
+            pos=0;
+            //copy rules before rule to change
+            while((foundRuleNr!=ruleToChange)&&(rulesStr.getNextToken(pos, tok, '/')))
+              { newRulesStr += tok + "/"; foundRuleNr++; }
+            //change this rule
+            rulesStr.getNextToken(pos, modRule, '/');
+            //copy rules after rule to remove
+            while(rulesStr.getNextToken(pos, tok, '/'))
+              { newRulesStr += tok + "/"; foundRuleNr++; }
+            pos=0;
+            modRule.getNextToken(pos, cond, ':');
+            modRule.getNextToken(pos, dec, '/');
+            pos=0;
+            if(0.5<rnd01) //remove input
+            {
+              int nrIns=0;
+              while(cond.getNextToken(pos, tok, ';'))nrIns++;
+              nrIns = 1 + nrIns/2; //odd number of semicolons, so 1 + ...
+              if(nrIns<=1) break; //can not remove - only one input!
+              int nrInToRem=randomN(nrIns), insFound=0;
+              //copy inputs before one to remove
+              while((insFound<nrInToRem)&&(cond.getNextToken(pos, tok, ';')))
+              {
+                if(insFound>0) tempStr += ";"; //add semic. before input number
+                tempStr += tok + ";"; //input number
+                cond.getNextToken(pos, tok, ';');
+                tempStr += tok; //set number
+                insFound++;
+              }
+              if((!cond.getNextToken(pos, tok, ';'))||(!cond.getNextToken(pos, tok, ';'))) //ommit selected input
+                break; //error
+              //copy inputs after one to remove
+              while(cond.getNextToken(pos, tok, ';'))
+              {
+                tempStr += ";"; tempStr += tok + ";"; //input number
+                cond.getNextToken(pos, tok, ';');
+                tempStr += tok; //set number
+              }
+              modRule = newRulesStr + tempStr + ":" + dec + "/";
+            }
+            else //remove output
+            {
+              int nrOuts=0;
+              while(dec.getNextToken(pos, tok, ';'))nrOuts++;
+              nrOuts = 1 + nrOuts/2; //odd number of semicolons, so 1 + ...
+              if(nrOuts<=1) break; //can not remove - only one input!
+              int nrOutToRem=randomN(nrOuts), outsFound=0;
+              //copy outputs before one to remove
+              while((outsFound<nrOutToRem)&&(dec.getNextToken(pos, tok, ';')))
+              {
+                if(outsFound>0) tempStr += ";"; //add semic. before output number
+                tempStr += tok + ";"; //output number
+                dec.getNextToken(pos, tok, ';');
+                tempStr += tok; //set number
+                outsFound++;
+              }
+              if((!dec.getNextToken(pos, tok, ';'))||(!dec.getNextToken(pos, tok, ';'))) //ommit selected output
+                break; //error
+              //copy outputs after one to remove
+              while(dec.getNextToken(pos, tok, ';'))
+              {
+                tempStr += ";"; tempStr += tok + ";"; //output number
+                dec.getNextToken(pos, tok, ';');
+                tempStr += tok; //set number
+              }
+              modRule = newRulesStr + cond + ":" + tempStr + "/";
+            }
+            tempStr = newRulesStr + modRule;
+            int temp_rulesNr = rulesNr;
+            if((removeExcessiveInOut(tempStr, inputsNr, outputsNr)<0)||
+               (removeExcessiveRules(tempStr, setsNr, temp_rulesNr)<0)||
+               (temp_rulesNr != rulesNr)) //removed in/out caused duplicated rule, so this mutation is not ok - try other
+              break;
+            newRulesStr = tempStr;
+            newRulesNr = rulesNr; newSetsStr = setsStr; newSetsNr = setsNr;
+            genoRemoved+=2;
+            // after removing of an input/output from the rule, an unused fuzzy set may occur
+            //create space for new transformation table
+            int *transTable = new int [newSetsNr];
+            for(int ii=0;ii<newSetsNr;ii++) transTable[ii]=ii; //formula 1:1 - no renumeration needed now
+            int oldSetNr=newSetsNr; //remember number of sets used in new genotype, but before reduction
+            //remove unused sets; if any set was removed, renumeration is needed
+            if(removeUnusedSets(newSetsStr, newRulesStr, newSetsNr, transTable))
+              changeSetsNumeration(newRulesStr, transTable, oldSetNr); //renumerate new sets
+            SAFEDELETEARRAY(transTable);
+            mutated=true;
+            break;
+            }
+    }
+  }
+
+  if(!mutated)
+    return GENOPER_OPFAIL;
+
+  //update new genotype
+  pi.setIntById("ns", newSetsNr);
+  pi.setIntById("nr", newRulesNr);
+  pi.setStringById("fs",newSetsStr);
+  pi.setStringById("fr",newRulesStr);
+  pi.update(); //force commit changes
+  model.close();
+  //get creature whole genotype
+  finalGenotype=model.getF0Geno().getGene();
+
+  //replace old genotype with new one
+  free(g);
+  g=strdup((const char*)finalGenotype);
+
+  chg=(float)(genoAdded+genoRemoved)/(genoAdded+genoRemoved+max(genoUsed-genoRemoved, 0));
+
+  return GENOPER_OK;
+}
+
+int Geno_f0Fuzzy::checkOrValidate(char *&geno, bool repair)
+//checks or validates genotype (depends on repair param)
+{ //all genotype received, but only fuzzy part is to be validated!!!
+  //"Fuzzy: [declarations], [sets], [rules]"
+  SString tok, repairedSets, repairedRules, finalGenotype;
+  char tempChar50[50];
+  int pos=0, i, j, setsFound, rulesFound;
+  double set[4];
+
+  Model model(Geno(geno,'0'));
+  if (!(model.isValid())) { if(repair) return GENOPER_OK; else return 1; } //ERROR
+  Neuro *fuzzy=findNeuro(&model, Neuro::getClass("Fuzzy"));
+  if (!fuzzy) { if(repair) return GENOPER_OK; else return 1; } //ERROR
+  const int inputsDeclared=fuzzy->getInputCount();
+  const int outputsDeclared=NI_FuzzyNeuro::countOuts(&model,fuzzy);
+  if((inputsDeclared<=0)||(outputsDeclared<=0))
+    { if(repair) return GENOPER_OK; else return 1; } //ERROR
+
+  //get neuron four properties
+  SyntParam pi=fuzzy->classProperties();
+  model.open();
+  int setsDeclared=pi.getIntById("ns");
+  int rulesDeclared=pi.getIntById("nr");
+  const SString fuzzySets=pi.getStringById("fs");
+  const SString fuzzyRules=pi.getStringById("fr");
+
+  //unrepairable errors: there must be some string!
+  if((fuzzySets.len()==0)||(fuzzyRules.len()==0))
+    if(repair) return GENOPER_OK; //ERROR
+    else return 2; //ERROR
+
+  if((!repair)&&((setsDeclared<=0)||(rulesDeclared<=0)))
+    return 2; //ERROR
+
+  //repair if corrupted
+  if(setsDeclared<=0)setsDeclared=1;
+  if(rulesDeclared<=0)rulesDeclared=1;
+
+  //now fuzzy sets are defined; each number is separated with semicolon.
+  //acceptables signs are: digits, commas, colons, semicolons.
+  i=j=0; setsFound=0;
+  while (j<fuzzySets.len())
+  {
+    SString acceptSigns; //string with acceptable signs
+    fuzzySets.getNextToken(j,tok,';');
+    if(tok.len()==0) { if(!repair) return j; else continue; }//might happen, when two semicolons stand side by side
+    //copy only acceptable signs
+    for(int ii=0;ii<tok.len();ii++)
+      if(strchr("0123456789.-;", tok[ii])) acceptSigns += tok[ii];
+      else if(!repair) return j;
+    set[i]=atof(acceptSigns);
+    if(set[i]<-1) { if(!repair) return j; else set[i] = -1; }//out of range
+    if(set[i]>1) { if(!repair) return j; else set[i] = 1; }//out of range
+    if(set[i]==HUGE_VAL) { if(!repair) return j; else set[i] = (i>0?set[i-1]:-1); }//sets must not be decreasing
+
+    if(++i==4)
+    {
+      //check if sets are rank rising
+      if((set[0]>set[1])||(set[1]>set[2])||(set[2]>set[3]))
+        { if(!repair) return j; else sortSet(set); }
+      if(sprintf(tempChar50, "%.4lf;%.4lf;%.4lf;%.4lf;", set[0], set[1], set[2], set[3]) != EOF)
+        {i=0; setsFound++; repairedSets += tempChar50;} //copy correct value
+    }
+
+    if((setsFound==setsDeclared)&&(repair))
+      break; //found enough sets - if there were some sets left, omit them
+  }
+  // valitadion: if there were more sets than declares, nothing happens, because pointer is now after comma (end of all sets)
+  // checking: error
+  if((setsFound!=setsDeclared)&&(!repair))
+    return j; //ERROR - wrong number of fuzzy sets in definition or abnormal end of the string
+
+  //now fuzzy rules are defined; each number is separated with semicolon, conditional and decisional part is separated with colon, rules are separated with slash
+  //acceptables signs are: digits, semicolons, colons, slashes.
+  i=0; rulesFound=0; pos=0;
+  while (pos<fuzzyRules.len()) //to the end of string - process loop for each rule
+  {
+    SString ruleSStr, ruleCondisSStr, ruleDecisSStr, nrSStr, acceptSigns;
+    int posRule=0, colons, i, posTemp, inputsUsedNr, outputsUsedNr;
+    int *inoutUsed, posOld;
+    bool firstInput, firstOutput;
+
+    posOld=pos; acceptSigns = "";
+    fuzzyRules.getNextToken(pos,ruleSStr,'/');
+    for(int ii=0;ii<pos-posOld;ii++)
+      if(strchr("0123456789;:/", ruleSStr[ii]))
+        acceptSigns += ruleSStr[ii];
+      else if(!repair) return j+pos; //ERROR - unacceptable sign
+    //cut conditional part
+    acceptSigns.getNextToken(posRule,ruleCondisSStr,':');
+    //cut decisional part
+    acceptSigns.getNextToken(posRule,ruleDecisSStr,'/');
+
+    //check, how many inputs is used:
+    colons=posRule=0;
+    while(++posRule<ruleCondisSStr.len())
+      if(ruleCondisSStr[posRule]==';') colons++;
+    if(!(colons%2)) //nr of colons must be odd. this rule is corrupted
+      {if(!repair) return j+pos; else continue; }//check another rule
+
+    inputsUsedNr=(colons+1)/2; //count nr of inputs
+    if((inputsUsedNr>inputsDeclared)&&(!repair))
+      return j+pos; //ERROR: too many inputs
+    //when repair: if inputsUsedNr > declared, do nothing, because later in loop it is checked whether
+    //there is no duplicate input number (the only possible way of situation where inputsUsedNr > declared)
+
+    //check how many outputs is used:
+    colons=posRule=0;
+    while(++posRule<ruleDecisSStr.len())
+      if(ruleDecisSStr[posRule]==';') colons++;
+    if(!(colons%2)) //nr of colons must be odd. this rule is corrupted - omit one
+      {if(!repair) return j+pos; else continue; }//check another rule
+
+    outputsUsedNr=(colons+1)/2; //count nr of outputs
+    if((outputsUsedNr>outputsDeclared)&&(!repair))
+      return j+pos; //ERROR: too many outputs
+    //when repair: if outputsUsedNr > declared, do nothing, because later in loop it is checked, wether
+    //there is no duplicate output number (the only possible way of situation where outputsUsedNr > declared)
+    inoutUsed = new int[max(inputsDeclared,outputsDeclared)];
+    for(i=0;i<max(inputsDeclared,outputsDeclared);i++) inoutUsed[i]=0; //0=unused, -1 = used by input, +1 used by output
+    firstInput=true; firstOutput=true;
+    //check, whether inputs/outputs or fuzzy set nr is not out of range
+    //and check, whether there is no duplicate input/output number
+    for(i=0,posTemp=0;i<inputsUsedNr+outputsUsedNr;i++)
+    {
+      int tempVal;
+      if(i==inputsUsedNr) posTemp=0; //because in decision string - parse string from begin
+      if(i<inputsUsedNr) //concern inputs
+      {
+        //check input
+        acceptSigns = ""; posOld=posTemp;
+        ruleCondisSStr.getNextToken(posTemp,nrSStr,';');
+        for(int ii=0;ii<nrSStr.len();ii++)
+          if(strchr("0123456789", nrSStr[ii]))
+            acceptSigns += nrSStr[ii];
+          else if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} //ERROR - out of range
+        tempVal=atoi(acceptSigns);
+        if(tempVal<0)
+          {if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else tempVal=0;}
+        if(tempVal>=inputsDeclared)
+          {if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else tempVal=inputsDeclared-1; }
+        if(inoutUsed[tempVal]==-1) //input is used
+        {
+          ruleCondisSStr.getNextToken(posTemp,nrSStr,';'); //omit input and fuzzy set
+          if(i+1 == inputsUsedNr) repairedRules += ":"; //the end of conditional part - must be here, because of continue
+          if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else continue;//next for loop
+        }
+        else
+          inoutUsed[tempVal]=-1; //used by input
+        if(!firstInput) repairedRules += ";"; //before input there is semicolon, except of begin of the rule
+        firstInput=false;
+        //tempVal now has a correct value
+        sprintf(tempChar50, "%i;", tempVal);
+        //correct input number:
+        repairedRules += tempChar50;
+        //check fuzzy set nr
+        acceptSigns = ""; posOld=posTemp;
+        ruleCondisSStr.getNextToken(posTemp,nrSStr,';');
+        for(int ii=0;ii<nrSStr.len();ii++)
+          if(strchr("0123456789", nrSStr[ii]))
+            acceptSigns += nrSStr[ii];
+          else if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;}
+      }
+      else //concern output
+      {
+        //check output
+        acceptSigns = ""; posOld=posTemp;
+        ruleDecisSStr.getNextToken(posTemp,nrSStr,';');
+        for(int ii=0;ii<nrSStr.len();ii++)
+          if(strchr("0123456789", nrSStr[ii]))
+            acceptSigns += nrSStr[ii];
+          else if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;}
+        tempVal=atoi(acceptSigns);
+        if(tempVal<0)
+          {if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else tempVal=0;}
+        if(tempVal>=outputsDeclared)
+          {if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else tempVal=outputsDeclared-1; }
+        if(inoutUsed[tempVal]==1) //output is used
+        {
+          ruleDecisSStr.getNextToken(posTemp,nrSStr,';'); //omit output and fuzzy set
+          if (i+1 == inputsUsedNr+outputsUsedNr) repairedRules += "/"; //the end of decisional part - must be here, because of continue
+          if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else continue; //next for loop
+        }
+        else
+          inoutUsed[tempVal]=1; //used by output
+        if(!firstOutput) repairedRules += ";"; //before output there is semicolon, except of begin of the decisional part of the rule
+        firstOutput=false;
+        //tempVal now has a correct value
+        sprintf(tempChar50, "%i;", tempVal);
+        //correct output number:
+        repairedRules += tempChar50;
+        //check fuzzy set nr
+        acceptSigns = ""; posOld=posTemp;
+        ruleDecisSStr.getNextToken(posTemp,nrSStr,';');
+        for(int ii=0;ii<nrSStr.len();ii++)
+          if(strchr("0123456789", nrSStr[ii]))
+            acceptSigns += nrSStr[ii];
+          else if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;}
+      }
+      tempVal=atoi(acceptSigns);
+      if(tempVal<0)
+        {if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else tempVal=0;}
+      if(tempVal>=setsFound)
+        {if(!repair) {SAFEDELETEARRAY(inoutUsed) return j+pos;} else tempVal=setsFound-1; }
+      //tempVal now has a correct value
+      sprintf(tempChar50, "%i", tempVal);
+      //correct set number:
+      repairedRules += tempChar50;
+      if(i+1 == inputsUsedNr) repairedRules += ":"; //the end of conditional part
+      else if (i+1 == inputsUsedNr+outputsUsedNr) repairedRules += "/"; //the end of decisional part
+    }
+    SAFEDELETEARRAY(inoutUsed)
+    rulesFound++;
+    if ((rulesFound>=rulesDeclared)&&(repair))
+      break; //if there was more rules - omit them by not parsing any more
+    if ((rulesFound>rulesDeclared)&&(!repair))
+      return j+pos; // ERROR - too many rules - stop parsing
+  }
+
+  if ((rulesFound!=rulesDeclared)&&(!repair))
+    return j+pos; // ERROR - wrong number of rules (too few)
+
+  if(rulesFound<1) //could happen, when there is one rule and it is unrepairable
+  {
+    if(sprintf(tempChar50, "%i;%i:%i;%i/", randomN(inputsDeclared), randomN(setsFound), randomN(outputsDeclared), randomN(setsFound)) != EOF)
+      repairedRules += tempChar50; //add simple random rule
+    else //on error - add zeros
+      repairedRules += "0;0:0;0/"; //add the simplies rule, but almost impossible to happen
+    rulesFound=1;
+  }
+
+  //when changing sets numerations, rules might change and equals
+  if((repair)&&(removeExcessiveRules(repairedRules, setsFound, rulesFound)<0))
+    return GENOPER_OPFAIL; //ERROR
+
+  //update new genotype
+  pi.setIntById("ns", setsFound);
+  pi.setIntById("nr", rulesFound);
+  pi.setStringById("fs",repairedSets);
+  pi.setStringById("fr",repairedRules);
+  pi.update(); //force commit changes
+  model.close();
+  //get creature whole genotype
+  finalGenotype=model.getF0Geno().getGene();
+
+  //replace old genotype with new one
+  free(geno);
+  geno=strdup((const char*)finalGenotype);
+
+  return GENOPER_OK;
+};
+
+int Geno_f0Fuzzy::checkValidity(const char *geno)
+{
+  char *genoCopy=strdup(geno);
+  int res=checkOrValidate(genoCopy, false); //false = on errors do not repair but return error position
+  free(genoCopy);
+  return res;
+};
+
+int Geno_f0Fuzzy::validate(char *&geno)
+{
+  checkOrValidate(geno, true); //true = on errors try to repair but might be unrepairable
+  return GENOPER_OK;
+};
+
+int Geno_f0Fuzzy::crossOver(char *&g1, char *&g2, float &chg1,float &chg2)
+{ //both bodies should be the same; the only difference should be in fuzzy neuron
+
+  SString finalGenotype, tok1, tok2;
+  SString fuzzyGeno1, fuzzyGeno2, newSet, sets3, rules3;
+  int setsNr3, rulesNr3;
+  int i, j, k, unimpTemp;
+  int *transTable, *parentsIn, *parentsOut, *parentRules, *rulDef1, *rulDef2, *rulDef3, **rulesBody1, **rulesBody2;
+  int genoUsed1, genoUsed2, copied1, copied2, rulesTaken1, rulesTaken2, rulesUsed3, selectedRule1, selectedRule2;
+  int inputsUsed, outputsUsed;
+  char tempChar50[50];
+  double *fuzzySets1, *fuzzySets2, *fuzzySets3;
+
+  Model model1(Geno(g1,'0'));
+  Model model2(Geno(g2,'0'));
+  Neuro *fuzzy1=findNeuro(&model1, Neuro::getClass("Fuzzy"));
+  Neuro *fuzzy2=findNeuro(&model2, Neuro::getClass("Fuzzy"));
+  if (!fuzzy1 || !fuzzy2) return GENOPER_OPFAIL; //ERROR
+  const int inputsNr1=fuzzy1->getInputCount();
+  const int inputsNr2=fuzzy2->getInputCount();
+  const int outputsNr1=NI_FuzzyNeuro::countOuts(&model1,fuzzy1);
+  const int outputsNr2=NI_FuzzyNeuro::countOuts(&model2,fuzzy2);
+  if((inputsNr1<=0)||(outputsNr1<=0)||(inputsNr2<=0)||(outputsNr2<=0)||
+     (inputsNr1!=inputsNr2)||(outputsNr1!=outputsNr2)) return GENOPER_OPFAIL; //ERROR
+
+  //get neurons four properties
+  SyntParam pi1=fuzzy1->classProperties();
+  SyntParam pi2=fuzzy2->classProperties();
+  model1.open();
+  model2.open();
+  const int setsNr1=pi1.getIntById("ns");
+  const int setsNr2=pi2.getIntById("ns");
+  const int rulesNr1=pi1.getIntById("nr");
+  const int rulesNr2=pi2.getIntById("nr");
+  const SString sets1=pi1.getStringById("fs");
+  const SString sets2=pi2.getStringById("fs");
+  const SString rules1=pi1.getStringById("fr");
+  const SString rules2=pi2.getStringById("fr");
+
+  if((sets1.len()==0)||(rules1.len()==0)||(sets2.len()==0)||(rules2.len()==0)||
+     (setsNr1<=0)||(rulesNr1<=0)||(setsNr2<=0)||(rulesNr2<=0))
+    return GENOPER_OPFAIL; //ERROR
+
+  //find out the real length of genotype - count number of semicolons
+  genoUsed1 = 0; //1 geno is i.e. -0.325; but this are 7 characters! so, 1 is used, 6 are unused
+  fuzzyGeno1 = sets1+", "+rules1;
+  for(i=0;i<fuzzyGeno1.len();i++)
+    if((fuzzyGeno1[i]==';')||(fuzzyGeno1[i]=='/')||(fuzzyGeno1[i]==':')) genoUsed1++;
+  genoUsed2 = 0; //1 geno is i.e. -0.325; but this are 7 characters! so, 1 is used, 6 are unused
+  fuzzyGeno2 = sets2+", "+rules2;
+  for(i=0;i<fuzzyGeno2.len();i++)
+    if((fuzzyGeno2[i]==';')||(fuzzyGeno2[i]=='/')||(fuzzyGeno2[i]==':')) genoUsed2++;
+
+
+  // -------------------------------------
+  // ------- cross over sets part --------
+  // -------------------------------------
+
+  copied1=copied2=0; //how many gens (in whole rules and whole sets) were copied (without changeing!) from parent 1 / 2 ?
+
+  fuzzySets1 = new double[4*setsNr1]; fuzzySets2 = new double[4*setsNr2];
+  FuzzyF0String::convertStrToSets(sets1, fuzzySets1, setsNr1);
+  FuzzyF0String::convertStrToSets(sets2, fuzzySets2, setsNr2);
+
+  //in fact, there is no crossing over of sets, but copy all parents' sets
+  //with marking duplicated sets
+  setsNr3 = setsNr1+setsNr2;
+  transTable = new int[setsNr3];
+  for(i=0;i<setsNr1+setsNr2;i++) transTable[i]=-2; //all sets are taken to descendant
+  if(markDuplicatedSets(fuzzySets1, setsNr1, fuzzySets2, setsNr2, transTable, setsNr3)!=0)
+    {
+      SAFEDELETEARRAY(fuzzySets1) SAFEDELETEARRAY(fuzzySets2) SAFEDELETEARRAY(transTable)
+      return GENOPER_OPFAIL; //ERROR
+    }
+
+  fuzzySets3 = new double[4*setsNr3];
+  j=0; sets3 = "";
+  //copy sets from parent 1 and 2
+  for(i=0;(i<setsNr1+setsNr2)&&(j<setsNr3);i++)
+    if(transTable[i]==-2) //this set is marked to be taken
+    {
+      if(i<setsNr1)
+      {
+        fuzzySets3[4*j]=fuzzySets1[4*i]; fuzzySets3[4*j+1]=fuzzySets1[4*i+1];
+        fuzzySets3[4*j+2]=fuzzySets1[4*i+2]; fuzzySets3[4*j+3]=fuzzySets1[4*i+3];
+      }
+      else
+      {
+        fuzzySets3[4*j]=fuzzySets2[4*(i-setsNr1)]; fuzzySets3[4*j+1]=fuzzySets2[4*(i-setsNr1)+1];
+        fuzzySets3[4*j+2]=fuzzySets2[4*(i-setsNr1)+2]; fuzzySets3[4*j+3]=fuzzySets2[4*(i-setsNr1)+3];
+      };
+      if(sprintf(tempChar50, "%.4lf;%.4lf;%.4lf;%.4lf;", fuzzySets3[4*j], fuzzySets3[4*j+1], fuzzySets3[4*j+2], fuzzySets3[4*j+3]) != EOF)
+      {
+        transTable[i] = j++; //remember, from which set it was copy: [4]=2 means that fuzzy set [4] from parent 1 was copy into descendant fuzzy set [2]. when i>setsNr1, substract setsNr1 from value to obtain number of fuzzy set from parent 2
+        sets3 += tempChar50;
+      }
+      else
+      {
+        SAFEDELETEARRAY(fuzzySets1)
+        SAFEDELETEARRAY(fuzzySets2)
+        SAFEDELETEARRAY(fuzzySets3)
+        SAFEDELETEARRAY(transTable)
+        return GENOPER_OPFAIL; //ERROR
+      }
+    }
+
+  // -------------------------------------
+  // ------- cross over rules part -------
+  // -------------------------------------
+
+  rules3="";
+  //draw number of fuzzy rules for the descendant
+  rulesNr3 = min(rulesNr1,rulesNr2) + randomN(abs(rulesNr1-rulesNr2)+1);
+
+  rulDef1 = new int[2*rulesNr1]; //for each rule, remembers number of inputs and number of outputs used (in rule)
+  rulDef2 = new int[2*rulesNr2];
+  rulDef3 = new int[2*rulesNr3]; //it will be filled later, with random values
+
+  FuzzyF0String::countInputsOutputs(rules1, rulDef1, rulesNr1);
+  FuzzyF0String::countInputsOutputs(rules2, rulDef2, rulesNr2);
+  for(i=0;i<2*rulesNr3;i++) rulDef3[i]=-1; //unknown number of inputs/outputs
+
+  //create space for rules from parent 1 and 2
+  rulesBody1 = new int*[rulesNr1];   //list of rules that will contain rules body
+  for (i=0;i<rulesNr1;i++) rulesBody1[i] = new int[2*(rulDef1[2*i]+rulDef1[2*i+1])];  //each rule can have different number of inputs and outputs
+  rulesBody2 = new int*[rulesNr2];   //list of rules that will contain rules body
+  for (i=0;i<rulesNr2;i++) rulesBody2[i] = new int[2*(rulDef2[2*i]+rulDef2[2*i+1])];  //each rule can have different number of inputs and outputs
+
+  FuzzyF0String::convertStrToRules(rules1, rulDef1, rulesBody1, setsNr1, rulesNr1, unimpTemp);
+  FuzzyF0String::convertStrToRules(rules2, rulDef2, rulesBody2, setsNr2, rulesNr2, unimpTemp);
+
+  //draw rules from both parents
+  parentRules = new int[rulesNr1+rulesNr2];
+  for(i=0;i<rulesNr1+rulesNr2;i++) parentRules[i]=-1; //any rule is taken yet
+
+  rulesTaken1=rulesTaken2=rulesUsed3=0;
+  while(rulesUsed3<rulesNr3)
+  {
+   //draw rule from parent 1
+   selectedRule1=-1;
+   if(rulesTaken1<rulesNr1) //if there are some rules left in parent 1
+   {
+    //select random rule from parent 1
+    k=randomN(rulesNr1);
+    if(parentRules[k]==-1) selectedRule1=k;
+    else //if rule is taken, search the nearest free
+      for(j=0;j<rulesNr1;j++)
+        if(parentRules[(k+j)%rulesNr1]==-1) { selectedRule1=(k+j)%rulesNr1; j=rulesNr1; }
+        else if(parentRules[abs((k-j)%rulesNr1)]==-1) { selectedRule1=abs((k-j)%rulesNr1); j=rulesNr1; }
+   }
+   if (selectedRule1==-1) //all rules are taken from parent 1
+     break;
+
+   //draw rule from parent 2
+   selectedRule2=-1;
+   if(rulesTaken2<rulesNr2) //if there are some rules left in parent 2
+   {
+    //select random rule from parent 2
+    k=randomN(rulesNr2);
+    if(parentRules[rulesNr1+k]==-1) { parentRules[rulesNr1+k]=-2; selectedRule2=k; } //mark as 'taken'
+    else //if rule is taken, search the nearest free
+      for(j=0;j<rulesNr2;j++)
+        if(parentRules[rulesNr1+(k+j)%rulesNr2]==-1) {selectedRule2=(k+j)%rulesNr2; j=rulesNr2; }
+        else if(parentRules[rulesNr1+abs((k-j)%rulesNr2)]==-1) { selectedRule2=abs((k-j)%rulesNr2); j=rulesNr2; }
+   }
+
+   if (selectedRule2==-1) //all rules are taken from parent 1
+     break;
+
+   parentRules[selectedRule1]=-2;  //mark as 'taken'
+   parentRules[rulesNr1+selectedRule2]=-2;
+
+   //draw number of inputs and outputs in new rule, (created by crossing over of 2 parents)
+   rulDef3[2*rulesUsed3] = min(rulDef1[2*selectedRule1], rulDef2[2*selectedRule2]) + randomN(abs(rulDef1[2*selectedRule1]-rulDef2[2*selectedRule2])+1); //random number of inputs
+   rulDef3[2*rulesUsed3+1] = min(rulDef1[2*selectedRule1+1], rulDef2[2*selectedRule2+1]) + randomN(abs(rulDef1[2*selectedRule1+1]-rulDef2[2*selectedRule2+1])+1); //random number of outputs
+
+   int nrInputsP1 = rulDef1[2*selectedRule1], nrInputsP2 = rulDef2[2*selectedRule2],       //some variables' names
+       nrOutputsP1 = rulDef1[2*selectedRule1+1], nrOutputsP2 = rulDef2[2*selectedRule2+1], //become now more understandable
+       nrInputsP3 = rulDef3[2*rulesUsed3], nrOutputsP3 = rulDef3[2*rulesUsed3+1];
+
+   //prepare drawing inputs from parent 1 and 2
+   int sumParentsInputs = nrInputsP1+nrInputsP2;
+   parentsIn = new int[sumParentsInputs]; //size: parent's 1 and 2 number of inputs
+
+   for(i=0;i<sumParentsInputs;i++) parentsIn[i]=-1; //not taken yet
+   //search for duplicated output and mark one of them outputs as 'taken'
+   for(i=0;i<nrInputsP1;i++)
+     for(j=0;j<nrInputsP2;j++)
+       if(rulesBody1[selectedRule1][2*i]==rulesBody2[selectedRule2][2*j]) //if inputs numbers are the same,
+       {
+         bool takenP1=rnd01<0.5; //draw, which input should be mark as taken
+         if (takenP1) parentsIn[i]=-2;
+         else parentsIn[j+nrInputsP1]=-2;
+       }
+
+   //now drawig is well prepared
+   inputsUsed=0;
+   while(inputsUsed<nrInputsP3) //loop as long, as inputs taken (from p1&p2) < length of descendant's input part
+   {
+     //draw input (which was not used yet) from both parents
+     do k=randomN(sumParentsInputs);
+     while (parentsIn[k]!=-1); //draw as long, as input is not taken yet
+     if(k<nrInputsP1) //concerns input from parent 1
+       sprintf(tempChar50, "%i;%i", rulesBody1[selectedRule1][2*k], transTable[rulesBody1[selectedRule1][2*k+1]]); //get input and transformated fuzzy set nr
+     else  //concerns input from parent 2
+       sprintf(tempChar50, "%i;%i", rulesBody2[selectedRule2][2*(k-nrInputsP1)], transTable[setsNr1+rulesBody2[selectedRule2][2*(k-nrInputsP1)+1]]); //get input and transformated fuzzy set nr. setsNr1+ because transTable is sum of setsNr1+setsNr2
+     rules3 += tempChar50;
+     if (inputsUsed+1<nrInputsP3) rules3 += ";";
+     inputsUsed++; parentsIn[k]=-2; //mark as taken
+   }
+   rules3 += ":";
+
+   SAFEDELETEARRAY(parentsIn)
+
+   //prepare drawing outputs from parent 1 and 2
+   int sumParentsOutputs = nrOutputsP1+nrOutputsP2;
+   parentsOut = new int[sumParentsOutputs]; //size: parent's 1 and 2 number of inputs
+
+   for(i=0;i<sumParentsOutputs;i++) parentsOut[i]=-1; //not taken yet
+   //search duplicated output and mark one of them outputs as 'taken'
+   for(i=0;i<nrOutputsP1;i++)
+     for(j=0;j<nrOutputsP2;j++)
+       if(rulesBody1[selectedRule1][2*(i+nrInputsP1)]==rulesBody2[selectedRule2][2*(j+nrInputsP2)]) //if outputs numbers are the same,
+       {
+         bool takenP1=rnd01<0.5; //draw, which input should be mark as taken
+         if (takenP1) parentsOut[i]=-2;
+         else parentsOut[j+nrOutputsP1]=-2;
+       }
+
+   //now drawig is well prepared
+   outputsUsed=0;
+   while(outputsUsed<nrOutputsP3) //loop as long, as outputs taken (from p1&p2) < length of descendant's output part
+   {
+     //draw output (which was not used yet) from both parents
+     do k=randomN(sumParentsOutputs);
+     while (parentsOut[k]!=-1); //draw as long, as output is not taken yet
+     if(k<nrOutputsP1) //concerns output from parent 1
+       sprintf(tempChar50, "%i;%i", rulesBody1[selectedRule1][2*(k+nrInputsP1)], transTable[rulesBody1[selectedRule1][2*(k+nrInputsP1)+1]]); //get output and transformated fuzzy set nr
+     else  //concerns output from parent 2
+       sprintf(tempChar50, "%i;%i", rulesBody2[selectedRule2][2*(k-nrOutputsP1+nrInputsP2)], transTable[setsNr1+rulesBody2[selectedRule2][2*(k-nrOutputsP1+nrInputsP2)+1]]); //get output and transformated fuzzy set nr
+     rules3 += tempChar50;
+     if (outputsUsed+1<nrOutputsP3) rules3 += ";";
+     outputsUsed++; parentsOut[k]=-2; //mark as taken
+   }
+   rules3 += "/";
+
+   SAFEDELETEARRAY(parentsOut)
+
+   rulesUsed3++; rulesTaken1++; rulesTaken2++;
+  }
+
+  //if there is no more rules pairs, and descendant needs more rules, copy rules from 'bigger' parent
+  if(rulesTaken1<rulesNr1)
+  {
+    for(j=0;(j<rulesNr1)&&(rulesUsed3<rulesNr3);j++)
+      if(parentRules[j]==-1) //search for not taken rule
+      {
+        parentRules[j]=-2; //taken
+        rulDef3[2*rulesUsed3] = rulDef1[2*j]; rulDef3[2*rulesUsed3+1] = rulDef1[2*j+1]; //copy whole rule - do not change number of inputs and outputs
+        for(k=0;k<rulDef3[2*rulesUsed3]+rulDef3[2*rulesUsed3+1];k++) //copy conditional and decisional part
+        {
+          sprintf(tempChar50, "%i;%i", rulesBody1[j][2*k], transTable[rulesBody1[j][2*k+1]]);
+          rules3 += tempChar50;
+          if(k+1==rulDef3[2*rulesUsed3]) //if end of inputs, put colon
+            rules3 += ":";
+          else if(k+1==rulDef3[2*rulesUsed3]+rulDef3[2*rulesUsed3+1]) //if end of outputs, put slash
+            rules3 += "/";
+          else
+            rules3 += ";";
+        }
+        rulesUsed3++; rulesTaken1++;
+        copied1+=2*k; //all inputs, fuzzy sets, ..., all outputs, fuzzy sets
+      }
+  }
+  if(rulesTaken2<rulesNr2)
+    for(j=0;(j<rulesNr2)&&(rulesUsed3<rulesNr3);j++)
+      if(parentRules[rulesNr1+j]==-1) //search for not taken rule
+      {
+        selectedRule2=j; parentRules[rulesNr1+j]=-2; //taken
+        rulDef3[2*rulesUsed3] = rulDef2[2*j]; rulDef3[2*rulesUsed3+1] = rulDef2[2*j+1]; //copy whole rule - do not change number of inputs and outputs
+        for(k=0;k<rulDef3[2*rulesUsed3]+rulDef3[2*rulesUsed3+1];k++) //copy conditional and decisional part
+        {
+          sprintf(tempChar50, "%i;%i", rulesBody2[j][2*k], transTable[setsNr1+rulesBody2[j][2*k+1]]);
+          rules3 += tempChar50;
+          if(k+1==rulDef3[2*rulesUsed3]) //if end of inputs, put colon
+            rules3 += ":";
+          else if(k+1==rulDef3[2*rulesUsed3]+rulDef3[2*rulesUsed3+1]) //if end of outputs, put slash
+            rules3 += "/";
+          else
+            rules3 += ";";
+        }
+        rulesUsed3++; rulesTaken2++;
+        copied2+=2*k; //all outputs, fuzzy sets, ..., all outputs, fuzzy sets 
+      }
+
+  //no need to normalize before removing unused sets, because correct (new) number of fuzzy set already written in rules string
+
+  //delete 'old' transTable
+  SAFEDELETEARRAY(transTable)
+
+  //create space for new transformation table
+  transTable=new int [setsNr3];
+  for(int ii=0;ii<setsNr3;ii++) transTable[ii]=ii; //formula 1:1 - no renumeration needed now
+
+  int oldSetNr=setsNr3; //remember number of sets used in new genotype, but before reduction
+  //remove unused sets; if any set was removed, renumeration is needed
+  if(removeUnusedSets(sets3, rules3, setsNr3, transTable))
+    changeSetsNumeration(rules3, transTable, oldSetNr); //renumerate new sets
+  //after renumeration, excessive rule or input/output may occur
+  if((removeExcessiveInOut(rules3, inputsNr1, outputsNr1)<0)||
+     (removeExcessiveRules(rules3, setsNr3, rulesNr3)<0))
+  { //should not occur
+    SAFEDELETEARRAY(rulDef1) SAFEDELETEARRAY(rulDef2) SAFEDELETEARRAY(rulDef3)
+    SAFEDELETEARRAY(transTable) SAFEDELETEARRAY(parentRules) SAFEDELETEARRAY(parentsIn) SAFEDELETEARRAY(parentsOut)
+    SAFEDELETEARRAY(fuzzySets1) SAFEDELETEARRAY(fuzzySets2) SAFEDELETEARRAY(fuzzySets3)
+    if(rulesBody1) for(i=0;i<rulesNr1;i++) SAFEDELETEARRAY(rulesBody1[i])
+    if(rulesBody2) for(i=0;i<rulesNr2;i++) SAFEDELETEARRAY(rulesBody2[i])
+    SAFEDELETEARRAY(rulesBody1) SAFEDELETEARRAY(rulesBody2)
+    return GENOPER_OPFAIL; //did not successed
+  }
+//---------------------  end of crossing over  --------------------------------
+
+  if( (sets3.len()==0)||(rules3.len()==0) ) //shold not occur, but for safety:
+    {sets3="-1;0;0;1;"; rules3="0;0:0;0/"; setsNr3=1; rulesNr3=1; }
+
+  //update new genotype
+  pi1.setIntById("ns", setsNr3);
+  pi1.setIntById("nr", rulesNr3);
+  pi1.setStringById("fs",sets3);
+  pi1.setStringById("fr",rules3);
+  pi1.update(); //force commit changes
+  model1.close();
+  //get creature whole genotype
+  finalGenotype=model1.getF0Geno().getGene();
+
+  //replace old genotype with new one
+  free(g1);
+  g1=strdup((const char*)finalGenotype);
+
+  chg1=1-(float)copied1/genoUsed1;
+  chg2=1-(float)copied2/genoUsed2;
+
+  SAFEDELETEARRAY(rulDef1)
+  SAFEDELETEARRAY(rulDef2)
+  SAFEDELETEARRAY(rulDef3)
+  SAFEDELETEARRAY(transTable)
+  SAFEDELETEARRAY(parentRules)
+  SAFEDELETEARRAY(parentsIn)
+  SAFEDELETEARRAY(parentsOut)
+  SAFEDELETEARRAY(fuzzySets1)
+  SAFEDELETEARRAY(fuzzySets2)
+  SAFEDELETEARRAY(fuzzySets3)
+  if(rulesBody1) for(i=0;i<rulesNr1;i++) SAFEDELETEARRAY(rulesBody1[i])
+  if(rulesBody2) for(i=0;i<rulesNr2;i++) SAFEDELETEARRAY(rulesBody2[i])
+  SAFEDELETEARRAY(rulesBody1)
+  SAFEDELETEARRAY(rulesBody2)
+
+  return GENOPER_OK;
+};
+
+
+
Index: /cpp/_old/f0-fuzzy/geno_f0Fuzzy.h
===================================================================
--- /cpp/_old/f0-fuzzy/geno_f0Fuzzy.h	(revision 110)
+++ /cpp/_old/f0-fuzzy/geno_f0Fuzzy.h	(revision 110)
@@ -0,0 +1,102 @@
+#ifndef _GENO_f0Fuzzy_H_
+#define _GENO_f0Fuzzy_H_
+
+/// Table of probabilities - names used in project facilitate reading
+
+#define F0Fuzzy_ADDSET   0
+#define F0Fuzzy_REMSET   1
+#define F0Fuzzy_ADDRULE  2
+#define F0Fuzzy_REMRULE  3
+#define F0Fuzzy_MODRULE  4
+#define F0Fuzzy_MOD2RULE 5
+#define F0Fuzzy_COUNT    6
+
+#include "sstring.h"
+#include "geno_fx.h"
+
+class Geno_f0Fuzzy : public Geno_fx
+{
+private:
+  /** Function finds number of nearest fuzzy (in list of sets) to given fuzzy set
+    \param set fuzzy set to be matched
+    \param sets fuzzy sets list
+    \param setsNr number of fuzzy sets in list
+    @return number of the nearest fuzzy set in sets list
+  **/
+  int nearestSet(double set[4], double sets[], int setsNr);
+  /** Function changes numeration of fuzzy sets numbers in fuzzy rules string, according to transformation table.
+    \param rules fuzzy rules string
+    \param transTable table of fuzzy sets transformation - [old_number]=new_number
+    \param nrItems number of old fuzzy sets
+    @return success or failure
+  **/
+  int changeSetsNumeration(SString &rules, int transTable[], int nrItems);
+  /** Function checks which fuzzy sets are used in rules and removed unused from fuzzy sets string, filling
+    appropriate values into transformation table.
+    \param sets fuzzy sets string
+    \param rules fuzzy rules string
+    \param setsNr number of fuzzy sets (input value: before removing, output value: after removing)
+    \param transTable table of fuzzy sets transformation - [old_number]=new_number
+    @return success or failure
+  **/
+  int removeUnusedSets(SString &sets, SString rules, int &setsNr, int transTable[]);
+  /** Function checks every rule whether input or output number does not duplicace in one rule. If so, removes
+    excessive input or output.
+    \param rules fuzzy rules string
+    \param inputsNr number of system inputs
+    \param outputsNr number of system outputs
+    @return success or failure
+  **/
+  int removeExcessiveInOut(SString &rules, int inputsNr, int outputsNr);
+  /** Function checks rule-based system whether there there is no duplicate rule's premise part. If so, removes
+    excessive one.
+    \param rules fuzzy rules string
+    \param inputsNr number of system inputs
+    \param outputsNr number of system outputs
+    @return success or failure
+  **/
+  int removeExcessiveRules(SString &rules, int setsNr, int &rulesNr);
+  /** Function sorts given fuzzy sets in not decreasing rank.
+    \param set fuzzy set
+    @return success or failure
+  **/
+  int sortSet(double set[4]);
+  /** Function calculates randomly new fuzzy set, using random gauss routines from rndutil.h.
+    \param newSet values (4 numbers) of new fuzzy set
+    @return success or failure
+  **/
+  int computeSet(double newSet[4]);
+  /** Function conducts checkValidity od validate procedures, depending on repair parameter.
+    \param geno given input genotype (if repair=true and needs to be repaired and it was possible to repair,
+    also output genotype)
+    \param repair flag whether repair genotype (if needed) or not
+    @return success or failure
+  **/
+  int checkOrValidate(char *&geno, bool repair);
+  /**
+    Function compares fuzzy sets from two creatures and mark duplicated fuzzy sets.
+    \param fuzzySets1 fuzzy sets from creature #1
+    \param setsNr1 number of fuzzy sets from creature #1
+    \param fuzzySets2 fuzzy sets from creature #2
+    \param setsNr2 number of fuzzy sets from creature #2
+    \param transTable table which remembers numbers of duplicated sets
+    \param setsNr3 number of fuzzy sets from creatures #1 + #2
+    @return success or failure
+  **/
+  int markDuplicatedSets(const double fuzzySets1[], const int setsNr1, const double fuzzySets2[], const int setsNr2, int transTable[], const int setsNr3);
+public:
+
+  double probtab[F0Fuzzy_COUNT]; //table of probabilities - see #define above
+  int maximumSetsNr;    //total number of sets can not be greater than maximum
+  int maximumRulesNr;   //total number of rules can not be greater than maximum
+
+  Geno_f0Fuzzy();
+  char *getSimplest();
+  int mutate(char *&g, float &chg,int &method);
+  int crossOver(char *&g1, char *&g2, float &chg1, float &chg2);
+  int checkValidity(const char *geno);
+  int validate(char *&);
+};
+
+#endif
+
Index: /cpp/_old/f0-fuzzy/neuroimpl-fuzzy-f0.cpp
===================================================================
--- /cpp/_old/f0-fuzzy/neuroimpl-fuzzy-f0.cpp	(revision 110)
+++ /cpp/_old/f0-fuzzy/neuroimpl-fuzzy-f0.cpp	(revision 110)
@@ -0,0 +1,132 @@
+/// this is a module included into neuroimpl-fuzzy
+/// it converts string parameters - fuzzy sets and fuzzy rules - into appropriate variables
+
+#include "neuroimpl-fuzzy-f0.h"
+// nonstd z powodu max()
+#include "nonstd.h"
+
+//this part concerns fuzzy sets transformation
+
+/** This function converts given string into numbers representing fuzzy sets */
+int FuzzyF0String::convertStrToSets(const SString& str, double numbers[], int nrOfSets)
+{
+  int pos=0;
+  SString t;
+  int have=0;
+  int maxnumbers=4*nrOfSets; //number of semicolons should be equal 4*nrOfSets
+
+  while (str.getNextToken(pos,t,';'))
+    if (have>=maxnumbers)
+      break;
+    else
+      numbers[have++]=atof(t);
+
+  //check if number of read numbers (separated with semicolon) is equal to declared
+  if (have != 4*nrOfSets)
+    return -1; //number of sets found is lower than declared!
+
+  //check corectness of sets - must not be decreasing
+  for(int i=0;i<nrOfSets;i++)
+    if((numbers[4*i]>numbers[4*i+1])||(numbers[4*i+1]>numbers[4*i+2])||(numbers[4*i+2]>numbers[4*i+3]))
+      return -2; //error
+
+  return 0;
+}
+
+//this part concerns fuzzy rules transformation
+
+/** This function counts number of inputs and outputs given in string consisting fuzzy rules.
+It counts number of separators:
+; between inputs/outputs and fuzzy sets number
+: between conditional and decision part of a rule
+/ end of rule
+*/
+int FuzzyF0String::countInputsOutputs(const char* str, int ruldef[], int rulesNr)
+{ //ruledef will remember counted number of inputs and outputs for every rule
+  const char* t;
+  int separators=0, inouts=0;
+
+  for(t=str;*t;t++)
+  {
+    while(isdigit(*t))
+      t++; //only count, does not care about numbers now
+    if (!*t)
+      break; //end of the string - get out of 'for' loop
+    if ( (*t==';')||(*t==':')||(*t=='/') ) //found sth different than digit - it must be a separator
+    {
+      separators++; //one of separators
+      if (*t!=';') // end of [conditional part of] rule
+      {
+	if (inouts >= 2*rulesNr) //more rules declared in string than declared in rulesNr
+	  return -2;
+        ruldef[inouts]=(separators+1)/2; //cause fuzzy sets - for 1 in/out there are 2 semicolons
+	separators=0;  //begin counting number of in/out from zero
+	inouts++; //next part of rule / or next rule
+      }
+    }
+    else // illegal character
+      return -1;
+  }
+
+  //check, if nr of found rules is equal to declared
+  if (inouts == 2*rulesNr) //each rule has a conditional part (inputs) and decisional part (outputs)
+    return 0;
+  else
+    return -5; // ShowMessage("Inconsistent number of rules!");
+}
+
+/** This function converts given string into variable 'rules' that remembers all inputs/outputs and fuzzy set.
+The procedure is conduct according to ruledef, calculated earlier.*/
+int FuzzyF0String::convertStrToRules(const SString& str, const int ruledef[], int **rules, int setsNr, int rulesNr, int &maxOutputNr)
+{
+  int pos=0, j, k, len=str.len();
+  int dNr=0, sNr=0;
+  int inNr, outNr; //number of inputs/outputs and corresponding fuzzy sets
+  SString t;
+  bool conditional=true; //which part of rule: conditional or decisional
+
+  maxOutputNr=0; //sets maximum output nr found in rules string
+
+  //check corectness of the string: number semicolon ... separated with colon or slash
+  while(pos<len)
+  {
+    while((pos<len)&&(isdigit(str.charAt(pos)))) pos++;
+    if(!(pos<len))
+      break; //end of the string
+    if(str.charAt(pos)!=';')
+      if((str.charAt(pos)==':')&&(conditional))
+        {sNr++; conditional=false;}
+      else if((str.charAt(pos)=='/')&&(!conditional))
+        {dNr++; conditional=true;}
+      else
+        return -4; //error - illegal character
+    pos++;
+  }
+  if( (dNr!=sNr) || (dNr!=rulesNr) )
+    return -5; //error - wrong number of rules
+
+  pos=0;
+
+  for(j=0;j<rulesNr;j++)
+  { //sum of inputs and outputs
+    inNr = 2*ruledef[2*j];
+    outNr = 2*ruledef[2*j+1];
+    for(k=0;k<inNr+outNr;k++)
+    {
+      t = ""; //clear previous value
+      //cuts next integer values
+      while ( (pos<len)&&(isdigit(str.charAt(pos))) )
+        t += str.charAt(pos++);
+      pos++;
+      rules[j][k]=atol(t); //convert cut out string into number
+      //fuzzy sets - odd index table - are counted from 0,
+      //so if 5 fuzzy sets declared, values acceptable are 0,1,2,3,4
+      if ( ((k%2)!=0) && (rules[j][k] >= setsNr) )
+      	return -1;
+      if((k>=inNr)&&((k%2)==0))
+        maxOutputNr=max(maxOutputNr,rules[j][k]);
+    }
+  }
+  return 0;
+};
+
Index: /cpp/_old/f0-fuzzy/neuroimpl-fuzzy-f0.h
===================================================================
--- /cpp/_old/f0-fuzzy/neuroimpl-fuzzy-f0.h	(revision 110)
+++ /cpp/_old/f0-fuzzy/neuroimpl-fuzzy-f0.h	(revision 110)
@@ -0,0 +1,19 @@
+/// this is a modul included into neuroimpl-fuzzy
+/// it converts string parameters - fuzzy sets and fuzzy rules - into appropriate variables
+
+#ifndef _neuroimpl_fuzzy_f0_h
+#define _neuroimpl_fuzzy_f0_h
+
+#include <ctype.h>
+#include "sstring.h"
+
+class FuzzyF0String
+{
+  public:
+  static int convertStrToSets(const SString& str, double numbers[], int nrOfSets);
+  static int countInputsOutputs(const char* str, int ruldef[], int rulesNr);
+  static int convertStrToRules(const SString& str, const int ruledef[], int **rules, int setsNr, int rulesNr, int &maxOutputNr);
+};
+
+#endif
+
Index: /cpp/_old/f0-fuzzy/neuroimpl-fuzzy.cpp
===================================================================
--- /cpp/_old/f0-fuzzy/neuroimpl-fuzzy.cpp	(revision 110)
+++ /cpp/_old/f0-fuzzy/neuroimpl-fuzzy.cpp	(revision 110)
@@ -0,0 +1,204 @@
+#include "neuroimpl-fuzzy.h"
+#include "neuroimpl-fuzzy-f0.h"
+
+int NI_FuzzyNeuro::countOuts(const Model *m, const Neuro *fuzzy)
+{
+  int outputs=0;
+  for(int i=0;i<m->getNeuroCount();i++)
+     for(int in=0;in<m->getNeuro(i)->getInputCount();in++)
+        if (m->getNeuro(i)->getInput(in)==fuzzy) outputs++;
+  return outputs;
+}
+
+int NI_FuzzyNeuro::lateinit()
+{
+  int i, maxOutputNr;
+
+  //check correctness of given parameters: string must not be null, sets&rules number > 0
+  if((fuzzySetsNr<1)||(rulesNr<1)||(fuzzySetString.len()==0)||(fuzzyRulesString.len()==0))
+    return 0; //error
+
+  // this part contains transformation of fuzzy sets
+  fuzzySets = new double[4*fuzzySetsNr]; //because every fuzzy set consist of 4 numbers
+  // converts fuzzy string from f0 to table of fuzzy numbers type 'double'
+  // (fill created space with numbers taken from string)
+  // also checks whether number of fuzzy sets in the string equals declared in the definition
+  if (FuzzyF0String::convertStrToSets(fuzzySetString, fuzzySets, fuzzySetsNr) != 0)
+    return 0; //error
+
+  // this part contains transformation of fuzzy rules and defuzzyfication parameters
+  rulesDef = new int[2*rulesNr];    //for each rule remembers number of inputs and outputs
+  //check correctness of string and fill in the rulesDef
+  if (FuzzyF0String::countInputsOutputs(fuzzyRulesString, rulesDef, rulesNr) == 0)
+  {
+    defuzzParam = new double[rulesNr]; // parameters used in defuzyfication process
+    // create space for rules according to rulesDef
+    rules = new int*[rulesNr];   //list of rules...
+    for (i=0; i<rulesNr; i++)    //...that contains rules body
+    {
+      rules[i] = new int[2*(rulesDef[2*i]+rulesDef[2*i+1])];  //each rule can have different number of inputs and outputs
+      defuzzParam[i] = 0; //should be done a little bit earlier, but why do not use this loop?
+    }
+    // fill created space with numbers taken from string
+    if (FuzzyF0String::convertStrToRules(fuzzyRulesString, rulesDef, rules, fuzzySetsNr, rulesNr, maxOutputNr) != 0)
+      return 0; //error
+  }
+  else
+    return 0; //error
+
+  setChannelCount(countOuts(neuro->owner, neuro));
+  return 1; //success
+}
+
+NI_FuzzyNeuro::~NI_FuzzyNeuro()
+{
+  if(rules) //delete rows and columns of **rules
+  {
+    for (int i=0; i<rulesNr; i++) SAFEDELETEARRAY(rules[i])
+    SAFEDELETEARRAY(rules)
+  }
+  SAFEDELETEARRAY(defuzzParam)
+  SAFEDELETEARRAY(rulesDef)
+  SAFEDELETEARRAY(fuzzySets)
+}
+
+int NI_FuzzyNeuro::GetFuzzySetParam(int set_nr, double &left, double &midleft, double &midright, double &right)
+{
+  if ( (set_nr>=0) && (set_nr<fuzzySetsNr) )
+  {
+    left = fuzzySets[4*set_nr];
+    midleft = fuzzySets[4*set_nr+1];
+    midright = fuzzySets[4*set_nr+2];
+    right = fuzzySets[4*set_nr+3];
+    return 0;
+  }
+  else
+    return 1;
+};
+
+/** Function conduct fuzzyfication of inputs and calculates - according to rules - crisp multi-channel output */
+void NI_FuzzyNeuro::go()
+{
+  if (Fuzzyfication()!=0)
+    return;
+  if (Defuzzyfication()!=0)
+    return;
+};
+
+/**
+* Function conduct fuzzyfication process - calculates minimum membership function (of every input) for each rule,
+* and writes results into defuzzParam - variable that contains data necessary for defuzzyfication
+*/
+int NI_FuzzyNeuro::Fuzzyfication()
+{
+  int i, j, nrIn, inputNr, nrFuzzySet;
+  double minimumCut; // actual minimal level of cut (= min. membership function)
+
+  // sets defuzzyfication parameters for each rule:
+  for (i=0; i<rulesNr; i++)
+  {
+    nrIn = rulesDef[2*i]; // nr of inputs in rule #i
+    minimumCut = 2; // the highest value of membership function is 1.0, so this value will definitely change
+    for (j=0; (j<nrIn)&&(minimumCut>0); j++) //minimumCut can not be <0, so if =0 then stop calculations
+    {
+      nrFuzzySet = rules[i][j*2 + 1]; // j*2 moves pointer through each output, +1 moves to nr of fuzzy set
+      inputNr = rules[i][j*2]; // as above but gives input number
+      minimumCut = min( minimumCut, TrapeziumFuzz(nrFuzzySet, getWeightedInputState(inputNr))); // value of membership function for this input and given fuzzy set
+    }
+    if ( (minimumCut>1) || (minimumCut<0) )
+      return 1;
+    defuzzParam[i] = minimumCut;
+  }
+  return 0;
+};
+
+/**
+* Function calculates value of the membership function of the set given by wchich_fuzzy_set for given crisp value input_val
+* In other words, this function fuzzyficates given crisp value with given fuzzy set, returning it's membership function
+* @param which_fuzzy_set - 0 < number of set < fuzzySetsNr
+* @param input_val - crisp value of input in range <-1; 1>
+* @return value of membership function (of given input for given set) in range <0;1> or, if error occur, negative value
+*/
+double NI_FuzzyNeuro::TrapeziumFuzz(int which_fuzzy_set, double input_val)
+{
+  double range=0, left=0, midleft=0, midright=0, right=0;
+
+  if ( (which_fuzzy_set < 0) || (which_fuzzy_set > fuzzySetsNr) )
+    return -2;
+  if ( (input_val < -1) || (input_val > 1) )
+    return -3;
+
+  if (GetFuzzySetParam(which_fuzzy_set, left, midleft, midright, right) != 0)
+    return -4;
+
+  if ( (input_val < left) || (input_val > right) ) // greather than right value
+    return 0;
+  else if ( (input_val >= midleft) && (input_val <= midright) ) // in the core of fuzzy set
+    return 1;
+  else if ( (input_val >= left) && (input_val < midleft) ) // at the left side of trapezium
+  {
+    range = fabs(midleft - left);
+    return fabs(input_val-left)/((range>0)?range:1); // quotient of distance between input and extreme left point of trapezium and range of rising side, or 1
+  }
+  else if ( (input_val > midright) && (input_val <= right) ) // at the right side of trapezium
+  {
+    range = fabs(right - midright);
+    return fabs(right-input_val)/((range>0)?range:1); // quotient of distance between input and extreme right point of trapezium and range of falling side, or 1
+  };
+
+  // should not occur
+  return 0;
+
+};
+
+/**
+* Function conducts defuzzyfication process: multi-channel output values are calculates with singleton method (method of high).
+* For each rules, all outputs fuzzy sets are taken and cut at 'cut-level', that is at minumum membership function (of current rule).
+* For all neuro pseudo-outputs, answer is calculated according to prior computations.
+* In fact, there is one output with multi-channel answer and appropriate values are given to right channels.
+*/
+int NI_FuzzyNeuro::Defuzzyfication()
+{
+  int i, j, nrIn, nrOut, out, set, outputsNr;
+  double *numerators, *denominators, midleft, midright, unimp;
+
+  outputsNr = getChannelCount();
+
+  numerators = new double[outputsNr];
+  denominators = new double[outputsNr];
+
+  for(i=0;i<outputsNr;i++) numerators[i] = denominators[i] = 0;
+
+  // for each rule...
+  for (i=0; i<rulesNr; i++)
+  {
+    nrIn = rulesDef[2*i]; // number of inputs in rule #i
+    nrOut = rulesDef[2*i + 1]; // number of outputs in rule #i
+    // ...calculate each output's product of middle fuzzy set value and minimum membership function (numerator) and sum of minimum membership function (denominator)
+    for (j=0; j<nrOut; j++)
+    {
+      out = rules[i][2*nrIn + 2*j]; //number of j-output
+      set = rules[i][2*nrIn + 2*j + 1]; //number of fuzzy set attributed to j-output
+      if (GetFuzzySetParam(set, unimp, midleft, midright, unimp) != 0) // gets range of core of given fuzzy set
+        { SAFEDELETEARRAY(denominators) SAFEDELETEARRAY(numerators) return 1; }
+      //defuzzParam[i] = minimum membership function for rule #i - calculated in fuzzyfication block
+      // defuzzyfication method of singletons (high): (fuzzy set modal value) * (minimum membership value)
+      numerators[out] += ((midleft + midright)/2.0) * defuzzParam[i];
+      denominators[out] += defuzzParam[i];
+    }
+  }
+
+  for (i=0; i<outputsNr; i++)
+  {
+    if (denominators[i] == 0)
+      setState(0, i);
+    else
+      setState(numerators[i]/denominators[i], i);
+  }
+
+  SAFEDELETEARRAY(denominators)
+  SAFEDELETEARRAY(numerators)
+
+  return 0;
+};
+
Index: /cpp/_old/f0-fuzzy/neuroimpl-fuzzy.h
===================================================================
--- /cpp/_old/f0-fuzzy/neuroimpl-fuzzy.h	(revision 110)
+++ /cpp/_old/f0-fuzzy/neuroimpl-fuzzy.h	(revision 110)
@@ -0,0 +1,67 @@
+#ifndef _NEUROIMPLFUZZY_H_
+#define _NEUROIMPLFUZZY_H_
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "neuroimpl.h"
+#include "sstring.h"
+
+extern ParamEntry NI_FuzzyNeuro_tab[];
+
+/** Does the fuzzyfication process (of inputs) and defuzzyfication proces (of outpurs) - represents fuzzy rules
+*/
+class NI_FuzzyNeuro : public NeuroImpl
+{
+private:
+
+  double *fuzzySets;    /// list of four digits which represents fuzzy sets: [0]-l, [1]-m, [2]-n, [3]-r, ...  fuzzySet[4*i] = left, fuzzySet[4*i + 1] = midleft, fuzzySet[4*i + 2] = midright, fuzzySet[4*i + 3] = right
+
+  /** Determines, which fuzzy set is connected with each input of neuron. For instance third rule:
+  *   'IF input3 = fuzzy set #3 AND input5 = fuzzy set #1 then output2 = fuzzy set #6 AND output7 = fuzzy set #5'
+  *   the variables shoul have values as shown below:
+  *   RulesDef[4]=2; RulesDef[5]=2; //rule 3: 2 inputs, 2 outputs
+  *   Rules[2][0]=3, Rules[2][1]=3, Rules[2][2]=5, Rules[2][3]=1, Rules[2][4]=2, Rules[2][5]=6, Rules[2][6]=7, Rules[2][3]=5
+  */
+  int *rulesDef;    ///list of rules definitions: nr of inputs in rule 1, nr of outputs in rule 1, ... and so on for each rule
+  int **rules;      ///list of rules body: input nr, fuzzy set nr, ... , output nr, fuzzy set nr, ... and so on for each rule
+
+  /**
+  *  Sets defuzzyfication parameters: determines - for each rule - cut level <0;1> (minimum membership function of current rule).
+  *  In fact, defuzzParam remembers the values from 'first layer' - fuzzyfication layer (see neuron at documentation)
+  *  i.e. rule 1: defuzzParam[0] = 0.3522
+  */
+  double *defuzzParam; /// i.e.: defuzParam[5] = 0.455 means that rule #6 has got a minimum membership function (of given inputs set for this rule) at value 0.455 (it's cut level)
+
+protected:
+
+  ///Fuzzy functions
+  double TrapeziumFuzz(int which_fuzzy_set, double input_val);
+  int Fuzzyfication();
+  int Defuzzyfication();
+  int GetFuzzySetParam(int set_nr, double &left, double &midleft, double &midright, double &right);
+
+public:
+
+  int fuzzySetsNr;      /// number of fuzzy sets
+  int rulesNr;      ///number of rules
+  SString fuzzySetString; /// strings containing all fuzzy sets given in f0
+  SString fuzzyRulesString; /// strings containing all fuzzy rules given in f0
+
+  NI_FuzzyNeuro() {paramentries=NI_FuzzyNeuro_tab; fuzzySets=defuzzParam=NULL; rulesDef=NULL; rules=NULL;}
+  ~NI_FuzzyNeuro();
+  NeuroImpl* makeNew() { return new NI_FuzzyNeuro(); };
+  void go();
+  int lateinit();
+  /** Function build model based on given genotype and conts number of neurons connected with fuzzy neuro,
+    also checks number of fuzzy neuron inputs.
+    \param genotype genotype to be scanned
+    \param inputs number of fuzzy neuron inputs
+    \param output number of fuzzy neuron outputs (= number of neurons connected to fuzzy neuron)
+    @return success or failure
+  **/
+  static int countOuts(const Model *m, const Neuro *fuzzy);
+  
+};
+
+#endif
Index: /cpp/_old/f4/conv_f4.cpp
===================================================================
--- /cpp/_old/f4/conv_f4.cpp	(revision 110)
+++ /cpp/_old/f4/conv_f4.cpp	(revision 110)
@@ -0,0 +1,304 @@
+/**
+ *  conv_f4.cpp - f4 genotype functions.
+ *
+ *  f4genotype - f4 format genotype conversions for Framsticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *  Copyright (C) 2001-2003  Maciej Komosinski
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "conv_f4.h"
+#include "framsg.h"
+#include "geno_fx.h" //for GENOPER_OK constant
+
+#ifdef DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+GenoConv_F40::GenoConv_F40()
+{
+  name = "f4 converter";
+  in_format  = '4';
+  out_format = '0';
+  mapsupport = 1;
+  info = "Developmental encoding";
+}
+
+
+SString GenoConv_F40::convert(SString &in, MultiMap * map)
+{
+  int res;
+  f4_Model * model = new f4_Model();
+  res = model->buildFromF4(in);
+  if (GENOPER_OK != res) return SString();  // oops
+  if (NULL != map)
+    // generate to-f0 conversion map
+    model->getCurrentToF0Map(*map);
+  SString out = model->getF0Geno().getGene();
+  delete model;
+  return out;
+}
+
+
+GenoConv_F41_TestOnly::GenoConv_F41_TestOnly()
+{
+  name = "test-only approximate f4 -> f0 converter";
+  in_format  = '4';
+  out_format = '1';
+  mapsupport = 0;
+  info = "This is for testing.  Do not use in production! (adam)";
+}
+
+
+SString GenoConv_F41_TestOnly::convert(SString &in, MultiMap * map)
+{
+  int res;
+  f4_Model * model = new f4_Model();
+  res = model->buildFromF4(in);
+  if (GENOPER_OK != res) return SString();  // oops
+  SString out;
+  model->toF1Geno(out);
+  delete model;
+  return out;
+}
+
+
+f4_Model::f4_Model() : Model()
+{
+  cells = NULL;
+}
+
+f4_Model::~f4_Model()
+{
+  if (cells) delete cells;
+}
+
+int f4_Model::buildFromF4(SString &geno)
+{
+  int i;
+
+  error = GENOPER_OK;
+  errorpos = -1;
+
+  // build cells, and simulate
+  if (cells) delete cells;
+  cells = new f4_Cells(geno, 0);
+  if (GENOPER_OK != cells->geterror())
+  {
+    error = cells->geterror();
+    errorpos = cells->geterrorpos();
+    //delete cells;
+    return error;
+  }
+
+  cells->simulate();
+  if (GENOPER_OK != cells->geterror())
+  {
+    error = cells->geterror();
+    errorpos = cells->geterrorpos();
+    return error;
+  }
+
+  // reset recursive traverse flags
+  for(i=0; i<cells->nc; i++)
+    cells->C[i]->recProcessedFlag = 0;
+
+  open(); // begin model build
+
+  // process every cell
+  int res;
+  for(i=0; i<cells->nc; i++)
+  {
+    res = buildModelRec(cells->C[i]);
+    if (res)
+    {
+      FramMessage("f4_Model", "buildModelRec", "Error in building Model", 2);
+      error = res;
+      break;
+    }
+  }
+
+  res = close();
+  if (0 == res) // invalid
+    error = -10;
+
+  return error;
+}
+
+
+f4_Cell * f4_Model::getStick(f4_Cell * C)
+{
+  if (T_STICK4 == C->type) return C;
+  if (NULL != C->dadlink)
+    return getStick(C->dadlink);
+  // we have no more dadlinks, find any stick
+  for (int i=0; i<cells->nc; i++)
+    if (cells->C[i]->type == T_STICK4)
+      return cells->C[i];
+  // none!
+  FramMessage("f4_Model", "getStick", "Not a single stick", 2);
+  return NULL;
+}
+
+
+/// updated by Macko to follow new GDK standards (no more neuroitems)
+int f4_Model::buildModelRec(f4_Cell * C)
+{
+  int partidx;
+  int j, res;
+  MultiRange range;
+
+  if (C->recProcessedFlag)
+    // already processed
+    return 0;
+
+  // mark it processed
+  C->recProcessedFlag = 1;
+
+  // make sure parent is a stick
+  if (NULL != C->dadlink)
+    if (C->dadlink->type != T_STICK4)
+    {
+      C->dadlink = getStick(C->dadlink);
+    }
+
+  // make sure its parent is processed first
+  if (NULL != C->dadlink)
+  {
+    res = buildModelRec(C->dadlink);
+    if (res) return res;
+  }
+
+  char tmpLine[100];
+
+  range = C->genoRange;
+  if (C->type == T_STICK4)
+  {
+    int jj_p1_refno;  // save for later
+    // first end is connected to dad, or new
+    if (C->dadlink == NULL)
+    {
+      // new part object for firstend
+      // coordinates are left to be computed by Model
+      sprintf(tmpLine, "p:m=1,fr=%g,ing=%g,as=%g",
+        /*1.0/C->P.mass,*/ C->P.friction, C->P.ingest, C->P.assim
+        //C->firstend.x, C->firstend.y, C->firstend.z
+        );
+      partidx = singleStepBuild(tmpLine, &range );
+      if (partidx < 0) return -1;
+      jj_p1_refno = partidx;
+    } else {
+      // adjust mass/vol of first endpoint
+      jj_p1_refno = C->dadlink->p2_refno;
+      Part * p1 = getPart(jj_p1_refno);
+      p1->mass += 1.0;
+//      p1->volume += 1.0/C->P.mass;
+    }
+    // new part object for lastend
+    sprintf(tmpLine, "p:m=1,fr=%g,ing=%g,as=%g",
+        //C->lastend.x, C->lastend.y, C->lastend.z
+        /*"vol=" 1.0/C->P.mass,*/ C->P.friction, C->P.ingest, C->P.assim
+      );
+    partidx = singleStepBuild(tmpLine, &range );
+    if (partidx < 0) return -2;
+    C->p2_refno = partidx;
+
+    // new joint object
+    // check that the part references are valid
+    int jj_p2_refno = C->p2_refno;
+    if ((jj_p1_refno < 0) || (jj_p1_refno >= getPartCount())) return -11;
+    if ((jj_p2_refno < 0) || (jj_p2_refno >= getPartCount())) return -12;
+    sprintf(tmpLine, "j:p1=%ld,p2=%ld,dx=%g,dy=0,dz=0,rx=%g,ry=0,rz=%g"\
+      ",stam=%g",
+      jj_p1_refno, jj_p2_refno,
+      // relative position -- always (len, 0, 0), along the stick
+      // this is optional!
+      C->P.len,
+      // relative rotation
+      C->xrot, C->zrot,
+      //C->P.ruch,   // rotstif
+      C->P.odpor
+    );
+    partidx = singleStepBuild(tmpLine, &range );
+    if (partidx < 0) return -13;
+    C->joint_refno = partidx;
+  }
+
+  if (C->type == T_NEURON4) ///<this case was updated by MacKo
+  {
+    // new neuron object
+    // it is linked to a part (not a joint!)
+    int p_refno = C->dadlink->p2_refno;
+    if ((p_refno < 0) || (p_refno >= getPartCount())) return -21;
+    // joint_refno is currently not used
+    sprintf(tmpLine, "n:p=%ld,d=\"N:in=%g,fo=%g,si=%g\"",
+      p_refno,
+      C->inertia, C->force, C->sigmo);
+    partidx = singleStepBuild(tmpLine, &range );
+    if (partidx < 0) return -22;
+    C->neuro_refno = partidx;
+    int n_refno = C->neuro_refno;
+
+    if (C->ctrl)
+    {
+      if (1 == C->ctrl)
+        sprintf(tmpLine, "n:j=%d,d=\"@:p=%g\"",   C->dadlink->joint_refno, C->P.ruch);
+      else
+        sprintf(tmpLine, "n:j=%d,d=\"|:p=%g,r=%g\"",C->dadlink->joint_refno, C->P.ruch, C->mz);
+      partidx = singleStepBuild(tmpLine, &range );
+      if (partidx < 0) return -32;
+      sprintf(tmpLine, "c:%d,%d",partidx,n_refno);
+      if (singleStepBuild(tmpLine, &range )<0) return -33;
+    }
+
+    for (j=0; j<C->nolink; j++)
+    {
+      if (NULL != C->links[j]->from)
+        buildModelRec(C->links[j]->from);
+
+      tmpLine[0]=0;
+      if (1 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"*\"",p_refno);
+      if (2 == C->links[j]->t) sprintf(tmpLine, "n:j=%d,d=\"G\"", C->dadlink->joint_refno);
+      if (3 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"T\"",p_refno);
+      if (4 == C->links[j]->t) sprintf(tmpLine, "n:p=%d,d=\"S\"",p_refno);
+      int from=-1;
+      if (tmpLine[0]) //input from receptor
+      {
+        from=singleStepBuild(tmpLine, &range );
+        if (from<0) return -34;
+      } /*could be 'else'...*/
+      if (NULL != C->links[j]->from) // input from another neuron
+         from=C->links[j]->from->neuro_refno;
+      if (from>=0)
+      {
+        sprintf(tmpLine, "c:%d,%d,%g", n_refno,from,C->links[j]->w);
+        if (singleStepBuild(tmpLine, &range ) < 0) return -35;
+      }
+    }
+  }
+  return 0;
+}
+
+
+void f4_Model::toF1Geno(SString &out)
+{
+  cells->toF1Geno(out);
+}
+
+
Index: /cpp/_old/f4/conv_f4.h
===================================================================
--- /cpp/_old/f4/conv_f4.h	(revision 110)
+++ /cpp/_old/f4/conv_f4.h	(revision 110)
@@ -0,0 +1,73 @@
+/**
+ *  conv_f4.h - f4 conversion functions.
+ *
+ *  f4genotype - f4 format genotype conversions for FramSticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *  Copyright (C) 2001-2003  Maciej Komosinski
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _CONV_F4_H_
+#define _CONV_F4_H_
+
+#include "model.h"
+#include "modelparts.h"
+#include "genoconv.h"
+#include "f4_general.h"
+
+
+// The f4->f0 converter
+class GenoConv_F40: public GenoConverter
+{
+ public:
+  GenoConv_F40();
+  SString convert(SString &in, MultiMap * map);
+};
+
+
+// a test-only f4->f1 converter, approximates only
+class GenoConv_F41_TestOnly: public GenoConverter
+{
+ public:
+  GenoConv_F41_TestOnly();
+  SString convert(SString &in, MultiMap * map);
+};
+
+
+// A Model descendant, which support build from an f4 genotype.
+class f4_Model: public Model
+{
+ public:
+  f4_Model();
+  ~f4_Model();
+  int      buildFromF4(SString &geno);
+  void     toF1Geno(SString &out);       // output to f1 format, approximation
+ private:
+  f4_Cells * cells;
+  int        buildModelRec(f4_Cell * ndad);
+  /**
+   * Get a cell which is a stick, by traversing dadlinks.
+   */
+  f4_Cell *  getStick(f4_Cell * C);
+  int        error;
+  int        errorpos;
+};
+
+
+#endif
+
Index: /cpp/_old/f4/f4_general.cpp
===================================================================
--- /cpp/_old/f4/f4_general.cpp	(revision 110)
+++ /cpp/_old/f4/f4_general.cpp	(revision 110)
@@ -0,0 +1,1408 @@
+/*
+ *  f4_general.cpp - f4 genotype functions.
+ *
+ *  f4genotype - f4 format genotype conversions for FramSticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "f4_general.h"
+#include "nonstd.h"
+#include "framsg.h"
+#include "model.h" // for min and max attributes
+#include "geno_fx.h" //for GENOPER_ constants
+#include <stdio.h>
+#include <math.h>
+
+#ifdef DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+f4_Props::f4_Props()
+{
+  len      = 1.0;
+  curv     = 0.0;
+  mass     = 1.0; 
+  friction = 0.4;
+  ruch     = 0.25; // bio
+  assim    = 0.25; // bio
+  odpor    = 0.25; // bio
+  ingest   = 0.25; // bio
+  twist    = 0.0;
+  energ    = 1.0;
+  normalizeBiol4();
+}
+
+void f4_Props::normalizeBiol4()
+{
+  // must sum to 1
+  double sum = ruch + assim + odpor + ingest;
+  if (0 == sum)
+  {
+    ruch = assim = odpor = ingest = 0.25;
+  } else {
+    ruch   /= sum;
+    assim  /= sum;
+    odpor  /= sum;
+    ingest /= sum;
+  }
+}
+
+void f4_Props::executeModifier(char modif)
+{
+  switch (modif)
+  {
+   case 'L': len += (2.5 - len) * 0.3;
+             len = min(len, Model::getMaxJoint().d.x); break;
+   case 'l': len += (0.3 - len) * 0.3;
+             len = max(len, Model::getMinJoint().d.x); break;
+   case 'C': curv += ( 2.0 - curv) * 0.25;  break;
+   case 'c': curv += (-2.0 - curv) * 0.25;  break;
+   case 'Q': twist += ( 1.58 - twist) * 0.3; break;
+   case 'q': twist += (-1.58 - twist) * 0.3; break;
+   case 'A': assim += (1 - assim) * 0.8; normalizeBiol4(); break;
+   case 'a': assim -= assim * 0.4;       normalizeBiol4(); break;
+   case 'I': ingest += (1 - ingest) * 0.8;   normalizeBiol4(); break;
+   case 'i': ingest -= ingest * 0.4;         normalizeBiol4(); break;
+   case 'S': odpor += (1 - odpor) * 0.8; normalizeBiol4(); break;
+   case 's': odpor -= odpor * 0.4;       normalizeBiol4(); break;
+   case 'M': ruch += (1 - ruch) * 0.8;   normalizeBiol4(); break;
+   case 'm': ruch -= ruch * 0.4;         normalizeBiol4(); break;
+   case 'F': friction += (4 - friction) * 0.2; break;
+   case 'f': friction -= friction * 0.2;       break;
+   case 'W': mass += (2.0 - mass) * 0.3;   break;
+   case 'w': mass += (0.5 - mass) * 0.3;   break;
+   case 'E': energ += (10.0 - energ) * 0.1; break;
+   case 'e': energ -= energ * 0.1;          break;
+  }
+}
+
+void f4_Props::adjust()
+{
+  len = 0.5*len + 0.5*stdProps.len;
+  curv = 0.66 * curv;
+  twist = 0.66 * twist;
+}
+
+f4_Props stdProps;
+
+
+void rolling_dec(double * v) {
+  *v -= 0.7853;  // 0.7853981  45 degrees
+}
+void rolling_inc(double * v) {
+  *v += 0.7853;  // 0.7853981  45 degrees
+}
+
+
+int scanrec(const char * s, unsigned int slen, char stopchar)
+{
+  unsigned int i = 0;
+  //DB( printf("    scan('%s', '%c')\n", s, stopchar); )
+  while (1)
+  {
+    if (i >= slen)  // ran out the string, should never happen with correct string
+      return 1;
+    if (stopchar == s[i])  // bumped into stopchar
+      return i;
+    if (i < slen-1)  
+    { // s[i] is not the last char
+      if (s[i] == '(') 
+      {
+        i += 2+scanrec(s+i+1, slen-i-1, ')');
+        continue;
+      }
+      if (s[i] == '<') 
+      {
+        i += 2+scanrec(s+i+1, slen-i-1, '>');
+        continue;
+      }
+      if (s[i] == '#') 
+      {
+        i += 2+scanrec(s+i+1, slen-i-1, '>');
+        continue;
+      }
+    }
+    // s[i] a non-special character
+    i++;
+  }
+  return i;
+}
+
+
+f4_Cell::f4_Cell(int nname,
+    f4_Cell * ndad, int nangle, f4_Props newP)
+{
+  name    = nname;
+  type    = T_UNDIFF4;
+  dadlink = ndad;
+  org     = NULL;
+  genot   = NULL;
+  gcur    = NULL;
+  active  = 1;
+  repeat.null();
+  //genoRange.clear(); -- implicit
+
+  anglepos   = nangle;
+  commacount = 0;
+  childcount = 0;
+  P          = newP;
+  rolling    = 0;
+  xrot       = 0;
+  zrot       = 0;
+  //OM = Orient_1;
+  ctrl    = 0;
+  state   = 0;
+  inertia = 0.8;
+  force   = 0.04;
+  sigmo   = 2;
+  nolink = 0;
+
+  // adjust firstend and OM if there is a stick dad
+  if (ndad != NULL)
+  {
+    // make sure it is a stick (and not a stick f4_Cell!)
+    if (T_STICK4 == ndad->type)
+    {
+      //firstend = ndad->lastend;
+      //OM = ndad->OM;
+      ndad->childcount++;
+    }
+    if (T_NEURON4 == ndad->type)
+    {
+      state   = ndad->state;
+      inertia = ndad->inertia;
+      force   = ndad->force;
+      sigmo   = ndad->sigmo;
+    }
+  }
+  // adjust lastend
+  //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
+  mz = 1;
+}
+
+
+f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur,
+    f4_Cell * ndad, int nangle, f4_Props newP)
+{
+  name    = nname;
+  type    = T_UNDIFF4;
+  dadlink = ndad;
+  org     = nO;
+  genot   = ngeno;
+  gcur    = ngcur;
+  active = 1;
+  repeat.null();
+  //genoRange.clear(); -- implicit
+  // preserve geno range of parent cell
+  if (NULL != ndad)
+    genoRange.add( ndad->genoRange );
+
+  anglepos   = nangle;
+  commacount = 0;
+  childcount = 0;
+  P          = newP;
+  rolling    = 0;
+  xrot       = 0;
+  zrot       = 0;
+  //OM = Orient_1;
+  ctrl    = 0;
+  state   = 0;
+  inertia = 0.8;
+  force   = 0.04;
+  sigmo   = 2;
+  nolink = 0;
+
+  // adjust firstend and OM if there is a stick dad
+  if (ndad != NULL)
+  {
+    // make sure it is a stick (and not a stick f4_Cell!)
+    if (T_STICK4 == ndad->type) {
+      //firstend = ndad->lastend;
+      //OM = ndad->OM;
+      ndad->childcount++;
+    }
+    if (T_NEURON4 == ndad->type) 
+    {
+      state   = ndad->state;
+      inertia = ndad->inertia;
+      force   = ndad->force;
+      sigmo   = ndad->sigmo;
+    }
+  }
+  // adjust lastend
+  //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
+  mz = 1;
+}
+
+
+f4_Cell::~f4_Cell()
+{
+  // remove links
+  if (nolink)
+  {
+    int i;
+    for (i=nolink-1; i>=0; i--)
+      delete links[i];
+    nolink=0;
+  }
+}
+
+
+/* return codes:
+    >1 error at pos
+     0  halt development for a cycle
+    -1  development finished OK
+*/
+int f4_Cell::onestep()
+{
+  int i, j, k, relfrom, t;
+  double w;
+  f4_Cell * tmp;
+  f4_Cell * tneu;
+  if (gcur == NULL)
+  {
+    active = 0;
+    return 0;  // stop
+  }
+  while ( NULL != gcur )
+  {
+    //DB( printf("  %d (%d) executing '%c' %d\n", name, type, gcur->name, gcur->pos); )
+    // currently this is the last one processed
+    // the current genotype code is processed
+    genoRange.add( gcur->pos );
+    switch (gcur->name)
+    {
+    case '<':
+      // cell division!
+      //DB( printf("  div! %d\n", name); )
+
+      // error: sticks cannot divide
+      if (T_STICK4 == type) {
+        // cannot fix
+        org->setError(gcur->pos);
+        return 1;  // stop
+      }
+
+      // undiff divides
+      if (T_UNDIFF4 == type) {
+        // commacount is set only when daughter turns into X
+        // daughter cell
+        // adjust new len
+        f4_Props newP = P;
+        newP.adjust();
+        tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
+         this,  commacount, newP);
+        tmp->repeat = repeat;
+        repeat.null();
+        org->addCell( tmp );
+      }
+      // a neuron divides: create a new, duplicate links
+      if (T_NEURON4 == type) {
+        // daughter cell
+        tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
+          // has the same dadlink
+          this->dadlink, commacount, P);
+        tmp->repeat = repeat;
+        repeat.null();
+        // it is a neuron from start
+        tmp->type = T_NEURON4;
+        // duplicate links
+        f4_CellLink * ll;
+        for (i=0; i<nolink; i++) {
+          ll = links[i];
+          tmp->addlink(ll->from, ll->w, ll->t);
+        }
+        org->addCell( tmp );
+      }
+      // adjustments for this cell
+      gcur = gcur->child;
+      // halt development
+      return 0;
+
+    case '>':
+      // finish
+      // see if there is a repet count
+      if (repeat.top > 0)
+      { // there is a repeat counter
+        if (!repeat.first()->isNull())
+        { // repeat counter is not null
+          repeat.first()->dec();
+          if (repeat.first()->count > 0)
+          {
+            // return to repeat
+            gcur = repeat.first()->node->child;
+          } else {
+            // continue
+            gcur = repeat.first()->node->child2;
+            repeat.pop();
+          }
+          break;
+        } else {
+          repeat.pop();
+        }
+      } else {
+        // error: still undiff
+        if (T_UNDIFF4 == type)
+        {
+          // fix it: insert an 'X'
+          f4_node * insertnode = new f4_node('X', NULL, gcur->pos);
+          if (org->setRepairInsert(gcur->pos, gcur, insertnode))
+            // not in repair mode, release
+            delete insertnode;
+          return 1;
+        }
+        repeat.null();
+        active = 0;  // stop
+        // eat up rest
+        gcur = NULL;
+        return 0;
+      }
+
+    case '#':
+      // repetition marker
+      if (repeat.top >= repeat_stack::stackSize)
+      {
+        // repepeat pointer stack is full, cannot remember this one.
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      repeat.push( repeat_ptr(gcur, gcur->i1) );
+      gcur = gcur->child;
+      break;
+
+    case ',':
+      commacount++;
+      gcur = gcur->child;
+      break;
+
+    case 'r':  case 'R':
+      // error: if neuron
+      if (T_NEURON4 == type) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      switch (gcur->name) {
+       case 'r':   rolling_dec( &rolling ); break;
+       case 'R':   rolling_inc( &rolling ); break;
+      }
+      gcur = gcur->child;
+      break;
+
+    case 'l':  case 'L':
+    case 'c':  case 'C':
+    case 'q':  case 'Q':
+    case 'a':  case 'A':
+    case 'i':  case 'I':
+    case 's':  case 'S':
+    case 'm':  case 'M':
+    case 'f':  case 'F':
+    case 'w':  case 'W':
+    case 'e':  case 'E':
+      // error: if neuron
+      if (T_NEURON4 == type) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      P.executeModifier(gcur->name);
+      gcur = gcur->child;
+      break;
+
+    case 'X':
+      // turn undiff. cell into a stick
+      // error: already differentiated
+      if (T_UNDIFF4 != type) {
+        // fix: delete this node
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      type = T_STICK4;
+      // fix dad commacount and own anglepos
+      if (NULL != dadlink) {
+        dadlink->commacount++;
+        anglepos = dadlink->commacount;
+      }
+      // change of type halts developments, see comment at 'N'
+      gcur = gcur->child;
+      return 0;
+
+    case 'N':
+      // turn undiff. cell into a neuron
+      // error: already differentiated
+      if (T_UNDIFF4 != type) {
+        // fix: delete this node
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      // error: if no previous
+      if (NULL == dadlink) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      type = T_NEURON4;
+      // change of type also halts development, to give other
+      // cells a chance for adjustment.  Namely, it is important
+      // to wait for other cells to turn N before adding links
+      gcur = gcur->child;
+      return 0;
+
+    case '@':
+    case '|':
+      // neuron rotating / bending
+      j = 1;
+      if ('@' == gcur->name) j = 1; // rot
+      if ('|' == gcur->name) j = 2; // bend
+      // error: not a neuron (undiff)
+      if (T_UNDIFF4 == type) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      // error: not a neuron (stick)
+      if (T_NEURON4 != type) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      // error: already has control
+      if (ctrl != 0) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      // make neuron ctrl = 1 or 2
+      ctrl = j;
+      gcur = gcur->child;
+      break;
+
+    case '[':
+      // link to neuron
+      // error: not a neuron
+      if (T_NEURON4 != type) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      // input ('*', 'G', 'T', 'S', or %d)
+      t       = gcur->i1;
+      relfrom = gcur->l1;
+      w       = gcur->f1;
+      if (t>0) {
+        // * or G
+        tneu = NULL;
+      } else {
+        // input from other neuron
+        // find neuron at relative i
+        // find own index
+        j = 0; k = 0;
+        for(i=0; i<org->nc; i++) {
+          if (org->C[i]->type == T_NEURON4) k++;
+          if (org->C[i] == this) {j=k-1; break;}
+        }
+        // find index of incoming
+        j = j + relfrom;
+        if (j<0) goto wait_link;
+        if (j>=org->nc) goto wait_link;
+        // find that neuron
+        k = 0;
+        for(i=0; i<org->nc; i++) {
+          if (org->C[i]->type == T_NEURON4) k++;
+          if (j == (k-1)) break;
+        }
+        if (i>=org->nc) goto wait_link;
+        tneu = org->C[i];
+      }
+      // add link
+      // error: could not add link (too many?)
+      if (addlink(tneu, w, t)) {
+        // cannot fix
+        org->setError(gcur->pos);
+        return 1;  // stop
+      }
+      gcur = gcur->child;
+      break;
+    wait_link:
+      // wait for other neurons to develop
+      // if there are others still active
+      active = 0;
+      j = 0;
+      for(i=0; i<org->nc; i++) {
+        if (org->C[i]->active) j++;
+      }
+      if (j>0)
+        return 0;  // there is other active, halt, try again
+      // no more actives, cannot add link, ignore, but treat not as an error
+      gcur = gcur->child;
+      break;
+
+    case ':':
+      // neuron parameter
+      // error: not a neuron
+      if (T_NEURON4 != type) {
+        // fix: delete it
+        org->setRepairRemove(gcur->pos, gcur);
+        return 1;  // stop
+      }
+      j = (int)gcur->l1;
+      switch ((char)gcur->i1) {
+       case '!': 
+        if (j) force += (1.0 - force) * 0.2;
+        else   force -= force * 0.2; break;
+       case '=': 
+        if (j) inertia += (1.0 - inertia) * 0.2;
+        else   inertia -= inertia * 0.2; break;
+       case '/': 
+        if (j) sigmo *= 1.4;
+        else   sigmo /= 1.4; break;
+       default:
+         org->setRepairRemove(gcur->pos, gcur);
+         return 1;  // stop
+      }
+      gcur = gcur->child;
+      break;
+
+    case ' ':
+      // space has no effect, should not occur
+      // fix: delete it
+      org->setRepairRemove(gcur->pos, gcur);
+      gcur = gcur->child;
+      break;
+
+    default:
+      // error: unknown code
+      char buf[40];
+      sprintf(buf, "unknown code '%c'", gcur->name);
+      FramMessage("f4_Cell", "onestep", buf, 2);
+      // fix: delete it
+      org->setRepairRemove(gcur->pos, gcur);
+      return 1; // stop
+    }
+  }
+  active = 0;  // done
+  return 0;
+}
+
+
+int f4_Cell::addlink(f4_Cell * nfrom, double nw, long nt)
+{
+  if (nolink >= MAXINPUTS-1) return -1; // full!
+  links[nolink] = new f4_CellLink(nfrom, nw, nt);
+  nolink++;
+  return 0;
+}
+
+
+void f4_Cell::adjustRec()
+{
+  //f4_OrientMat rot;
+  int     i;
+
+  if (recProcessedFlag)
+    // already processed
+    return;
+
+  // mark it processed
+  recProcessedFlag = 1;
+
+  // make sure its parent is processed first
+  if (NULL != dadlink)
+    dadlink->adjustRec();
+
+  // count children
+  childcount = 0;
+  for(i=0; i<org->nc; i++)
+  {
+    if (org->C[i]->dadlink == this)
+      if (org->C[i]->type == T_STICK4)
+        childcount++;
+  }
+
+  if (type == T_STICK4)
+  {
+    if (NULL == dadlink)
+    {
+      //firstend = Pt3D_0;
+      // rotation due to rolling
+      xrot = rolling;
+      mz = 1;
+    } else {
+      //firstend = dadlink->lastend;
+      f4_Props Pdad = dadlink->P;
+      f4_Props Padj = Pdad;
+      Padj.adjust();
+
+      //rot = Orient_1;
+
+      // rotation due to rolling
+      xrot = rolling +
+        // rotation due to twist
+        Pdad.twist;
+      if (dadlink->commacount <= 1)
+      {
+        // rotation due to curvedness
+        zrot = Padj.curv;
+      } else {
+        zrot = Padj.curv +
+          // GDK uses 3.141 instead of PI!
+          (anglepos * 1.0/(dadlink->commacount+1) - 0.5) * 3.141 * 2.0;
+      }
+
+      //rot = rot * f4_OrientMat(yOz, xrot);
+      //rot = rot * f4_OrientMat(xOy, zrot);
+      // rotation relative to parent stick
+      //OM = rot * OM;
+
+      // rotation in world coordinates
+      //OM =  ((f4_OrientMat)dadlink->OM) * OM;
+      mz = dadlink->mz / dadlink->childcount;
+    }
+    //Pt3D lastoffset = (Orient)OM * (Pt3D(1,0,0)*P.len);
+    //lastend = firstend + lastoffset;
+  }
+}
+
+
+
+f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, long nt)
+{
+  from = nfrom;
+  w    = nw;
+  t    = nt;
+}
+
+
+
+f4_Cells::f4_Cells(f4_node * genome, int nrepair)
+{
+  // create ancestor cell
+  repair = nrepair;
+  error  = 0;
+  errorpos = -1;
+  repair_remove = NULL;
+  repair_parent = NULL;
+  repair_insert = NULL;
+  tmpcel = NULL;
+  f4rootnode = NULL;
+
+  C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps);
+  nc   = 1;
+}
+
+
+f4_Cells::f4_Cells(SString & genome, int nrepair)
+{
+  int res;
+  repair = nrepair;
+  error  = 0;
+  errorpos = -1;
+  repair_remove = NULL;
+  repair_parent = NULL;
+  repair_insert = NULL;
+  tmpcel = NULL;
+  f4rootnode = NULL;
+
+  // transform geno from string to nodes
+  f4rootnode = new f4_node();
+  res = f4_processrec((const char*)genome, (unsigned)0, f4rootnode);
+  if ((res<0) || (1 != f4rootnode->childCount()))
+  {
+    error = GENOPER_OPFAIL;
+    errorpos = -1;
+  }
+
+  // create ancestor cell
+  C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child,
+    NULL, 0, stdProps);
+  nc   = 1;
+}
+
+f4_Cells::~f4_Cells()
+{
+  // release cells
+  int i;
+  if (nc)
+  {
+    for (i=nc-1; i>=0; i--)
+      delete C[i];
+    nc = 0;
+  }
+  if (f4rootnode)
+    delete f4rootnode;
+}
+
+
+int f4_Cells::onestep()
+{
+  int i, ret, oldnc, ret2;
+  oldnc = nc;
+  ret=0;
+  for (i=0; i<oldnc; i++) {
+    ret2 = C[i]->onestep();
+    if (ret2>0) {
+      // error
+      C[i]->active = 0;  // stop
+      return 0;
+    }
+    // if still active
+    if (C[i]->active)
+      ret=1;
+  }
+  return ret;
+}
+
+
+int f4_Cells::simulate()
+{
+  int i;
+  error = GENOPER_OK;
+
+  for (i=0; i<nc; i++)  C[i]->active = 1;
+
+  // execute onestep() in a cycle
+  while (onestep()) ;
+
+  if (GENOPER_OK != error) return error;
+
+  // fix neuron attachements
+  for(i=0; i<nc; i++)
+    if (C[i]->type == T_NEURON4) {
+      while (T_NEURON4 == C[i]->dadlink->type) {
+        C[i]->dadlink = C[i]->dadlink->dadlink;
+      }
+  }
+
+  // there should be no undiff. cells
+  // make undifferentiated cells sticks
+  for (i=0; i<nc ; i++)
+    if (C[i]->type == T_UNDIFF4) {
+      C[i]->type = T_STICK4;
+      //seterror();
+  }
+
+  // recursive adjust
+  // reset recursive traverse flags
+  for(i=0; i<nc; i++)
+    C[i]->recProcessedFlag = 0;
+  // process every cell
+  for(i=0; i<nc; i++)
+    C[i]->adjustRec();
+
+  //DB( printf("Cell simulation done, %d cells. \n", nc); )
+
+  return error;
+}
+
+
+void f4_Cells::addCell(f4_Cell * newcell)
+{
+  if (nc >= MAX4CELLS-1) {
+    delete newcell;
+    return;
+  }
+  C[nc] = newcell;
+  nc++;
+}
+
+
+void f4_Cells::setError(int nerrpos)
+{
+  error = GENOPER_OPFAIL;
+  errorpos = nerrpos;
+}
+
+void f4_Cells::setRepairRemove(int nerrpos, f4_node * rem)
+{
+  if (!repair) {
+    // not in repair mode, treat as repairable error
+    error = GENOPER_REPAIR;
+    errorpos = nerrpos;
+  } else {
+    error = GENOPER_REPAIR;
+    errorpos = nerrpos;
+    repair_remove = rem;
+  }
+}
+
+int f4_Cells::setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert)
+{
+  if (!repair) {
+    // not in repair mode, treat as repairable error
+    error = GENOPER_REPAIR;
+    errorpos = nerrpos;
+    return -1;
+  } else {
+    error = GENOPER_REPAIR;
+    errorpos = nerrpos;
+    repair_parent = parent;
+    repair_insert = insert;
+    return 0;
+  }
+}
+
+void f4_Cells::repairGeno(f4_node * geno, int whichchild)
+{
+  // assemble repaired geno, if the case
+  if (!repair) return;
+  if ((NULL==repair_remove) && (NULL==repair_insert)) return;
+  // traverse genotype tree, remove / insert node
+  f4_node * g2;
+  if (1==whichchild) g2 = geno->child;
+    else             g2 = geno->child2;
+  if (NULL == g2)
+    return;
+  if (g2 == repair_remove) {
+    f4_node * oldgeno;
+    geno->removeChild(g2);
+    if (g2->child) {
+      // add g2->child as child to geno
+      if (1==whichchild) geno->child  = g2->child;
+        else             geno->child2 = g2->child;
+      g2->child->parent = geno;
+    }
+    oldgeno = g2;
+    oldgeno->child = NULL;
+    delete oldgeno;
+    if (NULL == geno->child) return;
+    // check this new
+    repairGeno(geno, whichchild);
+    return;
+  }
+  if (g2 == repair_parent) {
+    geno->removeChild(g2);
+    geno->addChild(repair_insert);
+    repair_insert->parent = geno;
+    repair_insert->child  = g2;
+    repair_insert->child2 = NULL;
+    g2->parent = repair_insert;
+  }
+  // recurse
+  if (g2->child)  repairGeno(g2, 1);
+  if (g2->child2) repairGeno(g2, 2);
+}
+
+
+void f4_Cells::toF1Geno(SString &out)
+{
+  if (tmpcel) delete tmpcel;
+  tmpcel = new f4_Cell(-1, NULL, 0, stdProps);
+  out = "";
+  toF1GenoRec(0, out);
+  delete tmpcel;
+}
+
+
+void f4_Cells::toF1GenoRec(int curc, SString &out)
+{
+  int i, j, ccount;
+  f4_Cell * thisti;
+  f4_Cell * thneu;
+  char buf[200];
+
+  if (curc >= nc) return;
+
+  if (T_STICK4 != C[curc]->type) return;
+
+  thisti = C[curc];
+  if (NULL != thisti->dadlink)  
+    *tmpcel = *(thisti->dadlink);
+
+  // adjust length, curvedness, etc.
+  tmpcel->P.adjust();
+  while (tmpcel->P.len > thisti->P.len)
+  {
+    tmpcel->P.executeModifier('l');
+    out += "l";
+  }
+  while (tmpcel->P.len < thisti->P.len) 
+  {
+    tmpcel->P.executeModifier('L');
+    out += "L";
+  }
+  while (tmpcel->P.curv > thisti->P.curv) 
+  {
+    tmpcel->P.executeModifier('c');
+    out += "c";
+  }
+  while (tmpcel->P.curv < thisti->P.curv) 
+  {
+    tmpcel->P.executeModifier('C');
+    out += "C";
+  }
+  while (thisti->rolling > 0.0f) {
+    rolling_dec( &(thisti->rolling) );
+    out += "R";
+  }
+  while (thisti->rolling < 0.0f) {
+    rolling_inc( &(thisti->rolling) );
+    out += "r";
+  }
+
+  // output X for this stick
+  out += "X";
+
+  // neurons attached to it
+  for (i=0; i<nc; i++)
+    if (C[i]->type == T_NEURON4) {
+      if (C[i]->dadlink == thisti) {
+        thneu = C[i];
+        out += "[";
+        // ctrl
+        if (1 == thneu->ctrl) out += "@";
+        if (2 == thneu->ctrl) out += "|";
+        // links
+        for (j=0; j<thneu->nolink; j++) 
+        {
+          if (j) out += ",";
+          if (NULL == thneu->links[j]->from) 
+          {
+            // sensory
+            if (1 == thneu->links[j]->t) out += "*";
+            if (2 == thneu->links[j]->t) out += "G";
+            if (3 == thneu->links[j]->t) out += "T";
+            if (4 == thneu->links[j]->t) out += "S";
+          } else {
+            sprintf(buf, "%d", thneu->links[j]->from->name - thneu->name);
+            out += buf;
+          }
+          out += ":";
+          // weight
+          sprintf(buf, "%g", thneu->links[j]->w );
+          out += buf;
+        }
+        out += "]";
+    }
+  }
+
+  // sticks connected to it
+  if (thisti->commacount>=2)
+    out += "(";
+
+  ccount=1;
+  for (i=0; i<nc; i++)
+   if (C[i]->type == T_STICK4)
+    if (C[i]->dadlink == thisti) {
+      while (ccount < (C[i])->anglepos) {
+        ccount++;
+        out += ",";
+      }
+      toF1GenoRec(i, out);
+  }
+  while (ccount < thisti->commacount) {
+    ccount++;
+    out += ",";
+  }
+
+  if (thisti->commacount >= 2)
+    out += ")";
+}
+
+
+
+// to organize a f4 genotype in a tree structure
+
+f4_node::f4_node()
+{
+  name   = '?';
+  parent = NULL;
+  child  = NULL;
+  child2 = NULL;
+  pos    = -1;
+}
+
+f4_node::f4_node(char nname, f4_node * nparent, int npos)
+{
+  name   = nname;
+  parent = nparent;
+  child  = NULL;
+  child2 = NULL;
+  pos    = npos;
+  if (parent) parent->addChild(this);
+}
+
+f4_node::~f4_node()
+{
+  // (destroy() copied here for efficiency)
+  // children are destroyed (recursively) through the destructor
+  if (NULL != child2)  delete child2;
+  if (NULL != child)   delete child;
+}
+
+int f4_node::addChild(f4_node * nchi)
+{
+  if (NULL==child) {
+    child = nchi;
+    return 0;
+  }
+  if (NULL==child2) {
+    child2 = nchi;
+    return 0;
+  }
+  return -1;
+}
+
+int f4_node::removeChild(f4_node * nchi)
+{
+  if (nchi==child2) {
+    child2 = NULL;
+    return 0;
+  }
+  if (nchi==child) {
+    child = NULL;
+    return 0;
+  }
+  return -1;
+}
+
+int f4_node::childCount()
+{
+  if (NULL!=child) {
+    if (NULL!=child2) return 2;
+                 else return 1;
+  } else {
+    if (NULL!=child2) return 1;
+                 else return 0;
+  }
+}
+
+int f4_node::count()
+{
+  int c=1;
+  if (NULL!=child)  c+=child->count();
+  if (NULL!=child2) c+=child2->count();
+  return c;
+}
+
+f4_node * f4_node::ordNode(int n)
+{
+  int n1;
+  if (0 == n) return this;
+  n--;
+  if (NULL != child) {
+    n1 = child->count();
+    if (n<n1) return child->ordNode(n);
+    n -= n1;
+  }
+  if (NULL != child2) {
+    n1 = child2->count();
+    if (n<n1) return child2->ordNode(n);
+    n -= n1;
+  }
+  return NULL;
+}
+
+f4_node * f4_node::randomNode()
+{
+  int n, i;
+  n = count();
+  // pick a random node, between 0 and n-1
+  i = (int)( ((float)n-0.0001) / RAND_MAX * rand());
+  return ordNode(i);
+}
+
+f4_node * f4_node::randomNodeWithSize(int min, int max)
+{
+  // try random nodes, and accept if size in range
+  // limit to maxlim tries
+  int i, n, maxlim;
+  f4_node * nod = NULL;
+  maxlim = count();
+  for (i=0; i<maxlim; i++) {
+    nod = randomNode();
+    n = nod->count();
+    if ((n>=min) && (n<=max)) return nod;
+  }
+  // failed, doesn't matter
+  return nod;
+}
+
+void f4_node::sprint(SString & out)
+{
+  char buf2[20];
+  // special case: repetition code
+  if ('#' == name)
+  {
+    out += "#";
+    if (i1 != 1) {
+      sprintf(buf2, "%d", i1);
+      out += buf2;
+    }
+  } else {
+  // special case: neuron link
+  if ('[' == name) {
+    out += "[";
+    if (i1>0) {
+      // sensor input
+      if (1==i1) out += "*";
+      if (2==i1) out += "G";
+      if (3==i1) out += "T";
+      if (4==i1) out += "S";
+    } else {
+      sprintf(buf2, "%ld", l1);
+      out += buf2;
+    }
+    sprintf(buf2, ":%g]", f1);
+    out += buf2;
+  } else if (':' == name) {
+    sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
+    out += buf2;
+  } else {
+    buf2[0] = name;
+    buf2[1] = 0;
+    out += buf2;
+  }}
+  if (NULL != child)     child->sprint(out);
+  // if two children, make sure last char is a '>'
+  if (2 == childCount())
+    if (0 == out[0]) out += ">"; else
+      if ('>' != out[out.len()-1]) out += ">";
+  if (NULL != child2)    child2->sprint(out);
+  // make sure last char is a '>'
+  if (0 == out[0]) out += ">"; else
+    if ('>' != out[out.len()-1]) out += ">";
+}
+
+void f4_node::sprintAdj(char *& buf)
+{
+  unsigned int len;
+  // build in a SString, with initial size
+  SString out(strlen(buf)+2000);
+  out="";
+
+  sprint(out);
+
+  // very last '>' can be omitted
+  len = out.len();
+  if (len>1)
+    if ('>' == out[len-1]) { (out.directWrite())[len-1]=0; out.endWrite();};
+  // copy back to string
+  // if new is longer, reallocate buf
+  if (len+1 > strlen(buf)) {
+    buf = (char*) realloc(buf, len+1 );
+  }
+  strcpy(buf, (const char*) out);
+}
+
+f4_node * f4_node::duplicate()
+{
+  f4_node * copy;
+  copy = new f4_node(*this);
+  copy->parent = NULL;  // set later
+  copy->child  = NULL;
+  copy->child2 = NULL;
+  if (NULL != child ) {
+    copy->child  = child ->duplicate();
+    copy->child ->parent = copy;
+  }
+  if (NULL != child2 ) {
+    copy->child2 = child2->duplicate();
+    copy->child2->parent = copy;
+  }
+  return copy;
+}
+
+
+void f4_node::destroy()
+{
+  // children are destroyed (recursively) through the destructor
+  if (NULL != child2)  delete child2;
+  if (NULL != child)   delete child;
+}
+
+
+// scan genotype string and build tree
+// return >1 for error (errorpos)
+int f4_processrec(const char * genot, unsigned pos0, f4_node * parent)
+{
+  int i, j, t, res;
+  char tc1, tc2;
+  long relfrom;
+  double w;
+  unsigned gpos, oldpos;
+  f4_node * node1, * par;
+
+  gpos = pos0;
+  par = parent;
+  if (gpos >= strlen(genot) ) return 1;
+  while (gpos<strlen(genot)) {
+    //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); )
+    switch (genot[gpos]) {
+    case '<':
+      // cell division!
+      //DB( printf("  div! %d\n", name); )
+
+      // find out genotype start for child
+      j = scanrec(genot+gpos+1, strlen(genot+gpos+1), '>');
+
+      node1 = new f4_node('<', par, gpos);
+      par = node1;
+      res = f4_processrec(genot, gpos+1,   par);
+      if (res) return res;
+      if (gpos+j+2 < strlen(genot)) {
+        res = f4_processrec(genot, gpos+j+2, par);
+        if (res) return res;
+      } else {  // ran out
+        node1 = new f4_node('>', par, strlen(genot)-1 );
+        par = node1;
+      }
+      // adjustments
+      gpos++;
+      return 0;  // OK
+
+    case '>':
+      node1 = new f4_node('>', par, gpos );
+      par = node1;
+      gpos = strlen(genot);
+      return 0;  // OK
+
+    case '#':
+      // repetition marker, 1 by default
+      if (sscanf(genot+gpos, "#%d", &i) != 1) i=1;
+      // find out genotype start for continuation
+      j = scanrec(genot+gpos+1, strlen(genot+gpos+1), '>');
+      // skip number
+      oldpos = gpos;
+      gpos++;
+      while ((genot[gpos]>='0') && (genot[gpos]<='9')) gpos++;
+      node1 = new f4_node('#', par, oldpos );
+      node1->i1 = i;
+      par = node1;
+      res = f4_processrec(genot, gpos,   node1);
+      if (res) return res;
+      if (oldpos+j+2 < strlen(genot) ) {
+        res = f4_processrec(genot, oldpos+j+2, node1);
+        if (res) return res;
+      } else {  // ran out
+        node1 = new f4_node('>', par, strlen(genot)-1 );
+      }
+      return 0;  // OK
+
+    // 'simple' nodes:
+    case ',':
+    case 'l':  case 'L':
+    case 'c':  case 'C':
+    case 'q':  case 'Q':
+    case 'r':  case 'R':
+    case 'X':  case 'N':
+    case '@':  case '|':
+    case 'a':  case 'A':
+    case 's':  case 'S':
+    case 'm':  case 'M':
+    case 'i':  case 'I':
+    case 'f':  case 'F':
+    case 'w':  case 'W':
+    case 'e':  case 'E':
+      node1 = new f4_node(genot[gpos], par, gpos );
+      par = node1;
+      gpos++;
+      break;
+
+    case '[':
+      // link to neuron
+      // input (%d, '*', 'G', 'T', 'S')
+      t = -1;
+      if (sscanf(genot+gpos, "[%ld:%lf]", &relfrom, &w) == 2) t=0;
+      else if (sscanf(genot+gpos, "[*:%lf]", &w) == 1) t=1;
+      else if (sscanf(genot+gpos, "[G:%lf]", &w) == 1) t=2;
+      else if (sscanf(genot+gpos, "[T:%lf]", &w) == 1) t=3;
+      else if (sscanf(genot+gpos, "[S:%lf]", &w) == 1) t=4;
+      // error: no correct format
+      if (t<0) return gpos+1+1;
+      node1 = new f4_node('[', par, gpos );
+      node1->i1 = t;
+      node1->l1 = relfrom;
+      node1->f1 = w;
+      par = node1;
+      j = scanrec(genot+gpos+1, strlen(genot+gpos+1), ']');
+      gpos += j+2;
+      break;
+
+    case ':':
+      // neuron parameter  +! -! += -= +/ or -/
+      if (sscanf(genot+gpos, ":%c%c:", &tc1, &tc2) != 2)
+        // error: incorrect format
+        return gpos+1+1;
+      if ('+' == tc1) j=1;
+      else if ('-' == tc1) j=0;
+      else return gpos+1+1;
+      switch (tc2) {
+       case '!':  case '=':  case '/':  break;
+       default:
+        return gpos+1+1;
+      }
+      node1 = new f4_node(':', par, gpos );
+      node1->l1 = j;
+      node1->i1 = (int)tc2;
+      par = node1;
+      j = scanrec(genot+gpos+1, strlen(genot+gpos+1), ':');
+      gpos += j+2;
+      break;
+
+    case ' ':
+    case '\n':
+    case '\t':
+      // whitespace: ignore
+      //node1 = new f4_node(' ', par, gpos );
+      //par = node1;
+      gpos++;
+      break;
+
+    default:
+      //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
+      //add it, build will give the error or repair
+      node1 = new f4_node(genot[gpos], par, gpos );
+      par = node1;
+      gpos++;
+      break;
+    }
+  }
+  // should end with a '>'
+  if (par)
+    if ('>' != par->name) {
+      node1 = new f4_node('>', par, strlen(genot)-1 );
+      par = node1;
+  }
+  return 0;  // OK
+}
+
+
+f4_node * f4_processtree(const char * geno)
+{
+  f4_node * root;
+  int res;
+  root = new f4_node();
+  res = f4_processrec(geno, 0, root);
+  if (res) return NULL;
+  //DB( printf("test f4  "); )
+  DB(
+    if (root->child) {
+      char * buf = (char*) malloc( 300 );
+      DB( printf("(%d) ", root->child->count() ); )
+      buf[0]=0;
+      root->child->sprintAdj(buf);
+      DB( printf("%s\n", buf); )
+      free(buf);
+    }
+  )
+  return root->child;
+}
+
Index: /cpp/_old/f4/f4_general.h
===================================================================
--- /cpp/_old/f4/f4_general.h	(revision 110)
+++ /cpp/_old/f4/f4_general.h	(revision 110)
@@ -0,0 +1,249 @@
+/*
+ *  f4_general.h - f4 genotype functions.
+ *
+ *  f4genotype - f4 format genotype conversions for FramSticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _F4_GENERAL_H_
+#define _F4_GENERAL_H_
+
+#include "f4_orientmat.h"
+#include "3d.h"
+#include "sstring.h"
+#include "multirange.h"
+
+#ifdef DMALLOC
+#include <dmalloc.h>
+#endif
+
+
+class f4_Props
+{
+ public:
+  // fill with default values
+  f4_Props();
+  // must sum to 1
+  void normalizeBiol4();
+  void executeModifier(char modif);
+  void adjust();
+
+  double len;      // length (dlug)
+  double curv;     // curvedness (skr)
+  double mass;
+  double friction;
+  double ruch;
+  double assim;
+  double odpor;
+  double ingest;  // ingestion (wchl)
+  double twist;
+  double energ;
+};
+
+extern f4_Props stdProps;
+
+
+// rolling (one-time)
+void rolling_dec(double * v);
+void rolling_inc(double * v);
+
+
+class f4_node;   // later
+class f4_Cell;   // later
+class f4_Cells;  // later
+
+
+// cell types
+#define T_UNDIFF4 40
+#define T_STICK4  41
+#define T_NEURON4 42
+
+int scanrec(const char * s, unsigned int slen, char stopchar);
+
+
+class f4_CellLink;
+#define MAXINPUTS 100
+
+// an abstract cell type, extension of part/stick -- for developmental encoding
+class f4_Cell
+{
+public:
+  class repeat_ptr
+  {
+   public:
+    repeat_ptr() : node(NULL), count(-1) { };
+    repeat_ptr(f4_node * a, int b) : node(a), count(b) { };
+    inline void null() { node = NULL; count = -1; };
+    inline bool isNull() const { return ((node == NULL) || (count <= 0)); };
+    inline void dec() { count--; };
+    f4_node *  node;  // ptr to repetition code
+    char       count; // repetition counter
+  };
+
+  class repeat_stack  // a stack of repet_ptr's
+  {
+   public:
+    repeat_stack() { top=0; };
+    inline void null() { top=0; };
+    inline void push(repeat_ptr A) { if (top>=stackSize) return; ptr[top]=A; top++; };
+    inline void pop() { if (top>0) top--; };
+    inline repeat_ptr * first() { return &(ptr[top-(top>0)]); };
+    static const int stackSize = 4;  // max 4 nested levels
+    repeat_ptr ptr[stackSize];
+    short int top;  // top of the stack
+  };
+
+  f4_Cell(int nname,
+    f4_Cell * ndad, int nangle, f4_Props newP);
+  f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur,
+    f4_Cell * ndad, int nangle, f4_Props newP);
+  ~f4_Cell();
+
+  int onestep();	// execute one simulation step (till a division)
+
+  int   addlink(f4_Cell * nfrom, double nw, long nt);
+  void  adjustRec();
+
+  int        name;     // name (number)
+  int        type;     // type
+  f4_Cell *  dadlink;
+  f4_Cells * org;	// uplink to organism
+
+  f4_node *  genot;	  // genotype
+  f4_node *  gcur;        // current genotype execution pointer
+  int        active;      // whether development is still active
+  repeat_stack repeat;
+  int        recProcessedFlag;  // used during recursive traverse
+  // remember the genotype codes affecting this cell so far
+  MultiRange genoRange;
+
+  f4_Props     P;             // properties
+  int          anglepos;      // number of position within dad's children (,)
+  int          childcount;    // number of children
+  int          commacount;    // number of postitions at lastend (>=childcount)
+  double       rolling;       // rolling angle ('R') (around x)
+  double       xrot;
+  double       zrot;          // horizontal rotation angle due to
+                              // branching (around z)
+  //Pt3D         firstend;      // coord.s of first end (connects to parent)
+  //Pt3D         lastend;       // last end
+  //f4_OrientMat OM;
+  double       mz;            // freedom in z
+  long         p2_refno;   // number of last end part object, used in f0
+  long         joint_refno;   // number of the joint object, used in f0
+  long         neuro_refno;   // number of the neuro object, used in f0
+
+  long         ctrl;  // neuron type
+  double       state;
+  double       inertia;
+  double       force;
+  double       sigmo;
+  f4_CellLink* links[MAXINPUTS];
+  int          nolink;
+};
+
+
+// an input link to a neuron
+class f4_CellLink
+{
+public:
+               f4_CellLink(f4_Cell * nfrom, double nw, long nt);
+  f4_Cell *    from;
+  // type: 0: input, 1 '*', 2 'G', 3 'T', 4 'S'
+  long         t;
+  double       w;
+};
+
+
+// a collection of cells, like Organism, for developmental encoding
+#define MAX4CELLS 100
+class f4_Cells
+{
+ public:
+  f4_Cells(f4_node * genome, int nrepair);
+  f4_Cells(SString &genome, int nrepair);
+  ~f4_Cells();
+  void addCell(f4_Cell * newcell);
+  void toF1Geno(SString &out);       // output to f1 format, approximation
+  int  onestep();       // simulate all parts for one step
+  int  simulate();      // simulate development, return error (0 for ok)
+  // for error reporting / genotype fixing
+  int  geterror() { return error;};
+  int  geterrorpos() { return errorpos;};
+  void setError(int nerrpos);
+  void setRepairRemove(int nerrpos, f4_node * rem);
+  int  setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert);
+  void repairGeno(f4_node * geno, int whichchild);
+
+  // the cells
+  f4_Cell * C[MAX4CELLS];
+  int       nc;
+
+private:
+  // for error reporting / genotype fixing
+  int repair;
+  int error;
+  int errorpos;
+  f4_node * repair_remove;
+  f4_node * repair_parent;
+  f4_node * repair_insert;
+  void toF1GenoRec(int curc, SString &out);
+  f4_Cell * tmpcel;		// needed by toF1Geno
+  f4_node * f4rootnode;          // used by constructor
+};
+
+
+/**
+ * Class to organize a f4 genotype in a tree structure.
+ */
+class f4_node
+{
+public:
+  char      name;	// one-letter 'name'
+  f4_node * parent;	// parent link, or NULL
+  f4_node * child;	// child, or NULL
+  f4_node * child2;	// second child, or NULL
+  int       pos;        // original position in string
+  int       i1;		// internal int  parameter1
+  long      l1;		// internal long parameter1
+  double    f1;		// internal double parameter1
+
+            f4_node();
+            f4_node(char nname, f4_node * nparent, int npos);
+            ~f4_node();
+  int       addChild(f4_node * nchi);
+  int       removeChild(f4_node * nchi);
+  int       childCount();	// return no of children, 0, 1, or 2
+  int       count();	// return no of nodes (recursive)
+  f4_node * ordNode(int n);	// returns the nth subnode (0-)
+  f4_node * randomNode();	// returns a random subnode
+  f4_node * randomNodeWithSize(int min, int max);	// returns a random subnode with given size
+  void      sprintAdj(char *& buf);	// print recursively
+  f4_node * duplicate();         // create duplicate copy. recursive.
+  void      destroy();	// release memory. recursive.
+private:
+  void     sprint(SString & out);	// print recursively
+};
+
+// convert f4 geno string to tree structure (internal)
+f4_node * f4_processtree(const char * geno);
+int f4_processrec(const char * genot, unsigned pos0, f4_node * parent);
+
+
+#endif
Index: /cpp/_old/f4/f4_orientmat.cpp
===================================================================
--- /cpp/_old/f4/f4_orientmat.cpp	(revision 110)
+++ /cpp/_old/f4/f4_orientmat.cpp	(revision 110)
@@ -0,0 +1,65 @@
+/*
+ *  f4_orientmat.cpp - Extension of Orient with matrix multiplication.
+ *
+ *  f4genotype - f4 format genotype conversions for FramSticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "f4_orientmat.h"
+#include <math.h>
+
+
+f4_OrientMat::f4_OrientMat(XYZplanes plane, float angle) 
+{
+  switch(plane) 
+  {
+   case xOy:
+    x.x = cos(angle); x.y = -sin(angle); x.z = 0.0;
+    y.x = sin(angle); y.y =  cos(angle); y.z = 0.0;
+    z.x = 0.0;        z.y = 0.0;         z.z = 1.0;
+    break;
+   case xOz:
+    x.x = cos(angle); x.y = 0.0; x.z = -sin(angle);
+    y.x = 0.0;        y.y = 1.0; y.z = 0.0;
+    z.x = sin(angle); z.y = 0.0; z.z = cos(angle);
+    break;
+   case yOz:
+    x.x = 1.0;  x.y = 0.0;        x.z = 0.0;
+    y.x = 0.0;  y.y = cos(angle); y.z = -sin(angle);
+    z.x = 0.0;  z.y = sin(angle); z.z =  cos(angle);
+    break;
+  }
+} 
+
+
+// M3 = this * M2;
+f4_OrientMat f4_OrientMat::operator*(const Orient & M2)
+{
+  f4_OrientMat M3;
+  M3.x.x = x.x * M2.x.x + x.y * M2.y.x + x.z * M2.z.x;
+  M3.x.y = x.x * M2.x.y + x.y * M2.y.y + x.z * M2.z.y;
+  M3.x.z = x.x * M2.x.z + x.y * M2.y.z + x.z * M2.z.z;
+  M3.y.x = y.x * M2.x.x + y.y * M2.y.x + y.z * M2.z.x;
+  M3.y.y = y.x * M2.x.y + y.y * M2.y.y + y.z * M2.z.y;
+  M3.y.z = y.x * M2.x.z + y.y * M2.y.z + y.z * M2.z.z;
+  M3.z.x = z.x * M2.x.x + z.y * M2.y.x + z.z * M2.z.x;
+  M3.z.y = z.x * M2.x.y + z.y * M2.y.y + z.z * M2.z.y;
+  M3.z.z = z.x * M2.x.z + z.y * M2.y.z + z.z * M2.z.z;
+  return M3;
+}
Index: /cpp/_old/f4/f4_orientmat.h
===================================================================
--- /cpp/_old/f4/f4_orientmat.h	(revision 110)
+++ /cpp/_old/f4/f4_orientmat.h	(revision 110)
@@ -0,0 +1,44 @@
+/*
+ *  f4_orientmat.h - Extension of Orient with matrix multiplication.
+ *
+ *  f4genotype - f4 format genotype conversions for FramSticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _F4_ORIENTMAT_H_
+#define _F4_ORIENTMAT_H_
+
+#include "3d.h"
+
+typedef enum {
+   xOy, xOz, yOz
+} XYZplanes;
+
+class f4_OrientMat: public Orient 
+{ 
+ public:
+  f4_OrientMat() : Orient() {};
+  f4_OrientMat(const Orient & o) : Orient(o) {};
+  /// matrix multiplication
+  f4_OrientMat operator*(const Orient & M2);
+  /// rotation matrix in a given cartesian plane
+  f4_OrientMat(XYZplanes plane, float angle);
+};
+
+#endif
Index: /cpp/_old/f4/geno_f4.cpp
===================================================================
--- /cpp/_old/f4/geno_f4.cpp	(revision 110)
+++ /cpp/_old/f4/geno_f4.cpp	(revision 110)
@@ -0,0 +1,641 @@
+/*
+ *  geno_f4.cpp - f4 genetic operators.
+ *
+ *  f4genotype - f4 format genotype conversions for FramSticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *  Copyright (C) 2001-2004  Maciej Komosinski
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "geno_f4.h"
+#include "nonstd.h"
+#include "sstring.h"
+#include "framsg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+
+#define FIELDSTRUCT Geno_f4
+
+static ParamEntry GENO4param_tab[]=
+{
+ {"Genetics: f4",1,F4_COUNT+F4_ADD_COUNT,},
+ {"f4_mut_add", 0, 0, "Add node", "f 0 100 50", FIELD(prob[F4_ADD]),"mutation: probability of adding a node", },
+ {"f4_mut_add_div", 0, 0, "- add division", "f 0 100 20", FIELD(probadd[F4_ADD_DIV]),"add node mutation: probability of adding a division", },
+ {"f4_mut_add_conn", 0, 0, "- add connection", "f 0 100 15", FIELD(probadd[F4_ADD_CONN]),"add node mutation: probability of adding a neural connection", },
+ {"f4_mut_add_neupar", 0, 0, "- add neuron property", "f 0 100 5", FIELD(probadd[F4_ADD_NEUPAR]),"add node mutation: probability of adding a neuron property/modifier", },
+ {"f4_mut_add_rep", 0, 0, "- add repetition", "f 0 100 10",FIELD(probadd[F4_ADD_REP]),"add node mutation: probability of adding a repetition", },
+ {"f4_mut_add_simp", 0, 0, "- add simple node", "f 0 100 50",FIELD(probadd[F4_ADD_SIMP]),"add node mutation: probability of adding a random, simple gene", },
+ {"f4_mut_del", 0, 0, "Delete node", "f 0 100 20", FIELD(prob[F4_DEL]),"mutation: probability of deleting a node", },
+ {"f4_mut_mod", 0, 0, "Modify node", "f 0 100 30", FIELD(prob[F4_MOD]),"mutation: probability of changing a node", },
+ {0,},
+};
+
+#undef FIELDSTRUCT
+
+
+Geno_f4::Geno_f4()
+{
+   supported_format='4';
+   par.setParamTab(GENO4param_tab);
+   par.select(this);
+   par.setDefault();
+
+   mutation_method_names=new char*[F4_COUNT+F4_ADD_COUNT-1];
+   int index=0;
+   mutation_method_names[index++]="added division";
+   mutation_method_names[index++]="added neural connection";
+   mutation_method_names[index++]="added neuron property";
+   mutation_method_names[index++]="added repetition gene";
+   mutation_method_names[index++]="added a simple node";
+   mutation_method_names[index++]="deleted a node";
+   mutation_method_names[index++]="modified a node";
+   if (index!=F4_COUNT+F4_ADD_COUNT-1) FramMessage("Geno_f4","Constructor","Mutation names init error",3);
+}
+
+int Geno_f4::ValidateRec(f4_node * geno, int retrycount) const
+{
+  // ! the genotype is geno->child (not geno) !
+  // build from it with repair on
+
+  f4_Cells cells( geno->child, 1);
+  cells.simulate();  //we should simulate?!
+
+  // errors not fixed:
+  if (GENOPER_OPFAIL == cells.geterror())
+  {
+    if (cells.geterrorpos() >= 0) return 1+cells.geterrorpos();
+    return GENOPER_OPFAIL;
+  }
+  // errors can be fixed
+  if (GENOPER_REPAIR == cells.geterror())
+  {
+    cells.repairGeno(geno, 1);
+    // note: geno might have been fixed
+    // check again
+    int res2 = GENOPER_OK;
+    if (retrycount>0)
+      res2 = ValidateRec( geno, retrycount-1 );
+
+    if (res2==GENOPER_OK) return GENOPER_REPAIR;
+    return res2;
+  }
+  // no errors:
+  return GENOPER_OK;
+}
+
+
+int Geno_f4::validate(char *& geno)
+{
+  // convert geno to tree, then try to validate 20 times
+  f4_node root;
+  if (f4_processrec(geno, 0, &root) || root.childCount()!=1) return GENOPER_OK; // cannot repair
+  if (ValidateRec( &root, 20 )==GENOPER_REPAIR) // if repaired, make it back to string
+  {
+    geno[0]=0;
+    root.child->sprintAdj(geno);
+  }
+  return GENOPER_OK;
+}
+
+
+int Geno_f4::checkValidity(const char * geno)
+{
+  f4_node root;
+  int res = f4_processrec(geno, 0, &root);
+  if (res) return res;  // errorpos, >0
+  if (root.childCount()!=1) return 1; //earlier: GENOPER_OPFAIL
+  f4_Cells cells( root.child, 0);
+  cells.simulate();
+  if (cells.geterror()==GENOPER_OPFAIL || cells.geterror()==GENOPER_REPAIR)
+  {
+    if (cells.geterrorpos() >= 0) return 1+cells.geterrorpos();
+      else return 1; //earlier: GENOPER_OPFAIL;
+  } else return GENOPER_OK;
+}
+
+
+int Geno_f4::MutateOne(f4_node *& g,int &method) const
+{
+  // ! the genotype is g->child (not g) !
+
+  // codes that can be changed (apart being added/deleted)
+  #define MUT_CHAN_CODES "<[#"
+  #define ADD_SIMPLE_CODES ",XlLcCrRaAiIsSmMfFwWeEN@|"
+  #define REP_MAXCOUNT 19
+
+  f4_node * n1, * n2, * n3, * n4, * n5;
+  int i, j;
+
+  // do the mutation
+  // pick a random node
+  n1 = g->child->randomNode();
+  //DB( printf("%c\n", n1->name); )
+
+  switch(roulette(prob,F4_COUNT))
+  {
+    case F4_ADD:
+    {
+      // add a node
+      switch(method=roulette(probadd,F4_ADD_COUNT))
+      {
+        case F4_ADD_DIV:
+        {
+          // add division ('<')
+          n3 = n1->parent;
+          n3->removeChild(n1);
+          n2 = new f4_node('<', n3, n3->pos );
+          n2->addChild(n1);
+          // new cell is stick or neuron
+          // "X>" or "N>"
+          double pr = rnd01;
+          pr -= 0.5;
+          if (pr<0) n3 = new f4_node('X', n2, n2->pos);
+          else
+          {
+            pr -= 0.5;
+            if (pr<0)
+            {
+              // if neuron, make muscle and add a link
+              n3 = new f4_node('N', n2, n2->pos);
+              if (randomN(2) == 0)
+                n4 = new f4_node('|', n3, n2->pos);
+              else
+                n4 = new f4_node('@', n3, n2->pos);
+              n5 = new f4_node('[', n4, n2->pos);
+              linkNodeMakeRandom(n5);
+            }
+          }
+          new f4_node('>', n3, n3->pos);
+          n1->parent = n2;
+          // now with 50% chance swap children
+          if (randomN(2) == 0)
+          {
+            n3 = n2->child;
+            n2->child = n2->child2;
+            n2->child2 = n3;
+          }
+        }
+        break;
+        case F4_ADD_CONN:
+        {
+          // add link
+          n1->parent->removeChild(n1);
+          n2 = new f4_node('[', n1->parent, n1->parent->pos);
+          linkNodeMakeRandom(n2);
+          n2->addChild(n1);
+          n1->parent = n2;
+        }
+        break;
+        case F4_ADD_NEUPAR:
+        {
+          // add neuron modifier
+          n1->parent->removeChild(n1);
+          n2 = new f4_node(':', n1->parent, n1->parent->pos);
+          nparNodeMakeRandom(n2);
+          n2->addChild(n1);
+          n1->parent = n2;
+        }
+        break;
+        case F4_ADD_REP:
+        {
+          // add repetition ('#')
+          // repeated code (left child) is the original, right child is empty, count is 2
+          n3 = n1->parent;
+          n3->removeChild(n1);
+          n2 = new f4_node('#', n3, n3->pos );
+          n2->i1 = 2;
+          n2->addChild(n1);
+          new f4_node('>', n2, n2->pos);
+          n1->parent = n2;
+        }
+        break;
+        case F4_ADD_SIMP:
+        {
+          // add simple node
+          // choose a simple node from ADD_SIMPLE_CODES
+          n1->parent->removeChild(n1);
+          n2 = new f4_node(ADD_SIMPLE_CODES[randomN(strlen(ADD_SIMPLE_CODES))], n1->parent, n1->parent->pos );
+          n2->addChild(n1);
+          n1->parent = n2;
+        }
+        break;
+      }
+    }
+    break;
+
+    case F4_DEL:
+    {
+      method=F4_ADD_COUNT-1+F4_DEL;
+      // delete a node
+      // must pick a node with parent, and at least one child
+      // already picked a node, but repeat may be needed
+      for (i=0; i<10; i++) {
+        if ((NULL != n1->parent) && (g != n1->parent))
+          if (NULL != n1->child)
+            break;
+        // try a new one
+        n1 = g->child->randomNode();
+      }
+      if ((NULL != n1->parent) && (g != n1->parent))
+      {
+        switch (n1->childCount())
+        {
+         case 0: break;
+         case 1:  // one child
+         {
+            n2 = n1->parent;
+            n2->removeChild(n1);
+            if (NULL != n1->child) {
+              n1->child->parent = n2;
+              n2->addChild(n1->child);
+              n1->child = NULL;
+            }
+            if (NULL != n1->child2) {
+              n1->child2->parent = n2;
+              n2->addChild(n1->child2);
+              n1->child2 = NULL;
+            }
+            // destroy n1
+            n1->parent=NULL;
+            delete n1;
+         }
+         break;
+
+         case 2:  // two children
+         {
+            // two children
+            n2 = n1->parent;
+            n2->removeChild(n1);
+            // n1 has two children. pick one randomly 50-50, destroy other
+            if (randomN(2) == 0)
+            {
+              n1->child->parent = n2;
+              n2->addChild(n1->child);
+              n1->child = NULL;
+              n1->child2->parent = NULL;
+            } else
+            {
+              n1->child2->parent = n2;
+              n2->addChild(n1->child2);
+              n1->child2 = NULL;
+              n1->child->parent = NULL;
+            }
+            // destroy n1
+            n1->parent=NULL;
+            delete n1;
+         }
+         break;
+        }
+      } else return GENOPER_OPFAIL;
+    }
+    break;
+    case F4_MOD:
+    {
+      method=F4_ADD_COUNT-1+F4_MOD;
+      // change a node
+      // the only nodes that are modifiable are MUT_CHAN_CODES
+      // try to get a modifiable node
+      // already picked a node, but repeat may be needed
+      i=0;
+      while (1)
+      {
+        if (strchr(MUT_CHAN_CODES, n1->name)) break;
+        // try a new one
+        n1 = g->child->randomNode();
+        i++;
+        if (i>=20) return GENOPER_OPFAIL;
+      }
+      switch (n1->name) {
+        case '<':
+          // swap children
+          n2 = n1->child; n1->child = n1->child2; n1->child2 = n2;
+          break;
+        case '[':
+          linkNodeChangeRandom(n1);
+          break;
+        case '#':
+          repeatNodeChangeRandom(n1);
+          break;
+      }
+    }
+    break;
+
+    default: //no mutations allowed?
+    return GENOPER_OPFAIL;
+  }
+
+  return GENOPER_OK;
+}
+
+// make a random [ node
+void Geno_f4::linkNodeMakeRandom(f4_node * nn) const
+{
+  int i;
+  float prob1;
+
+  i = 0;
+  // 35% chance one of *GTS
+  prob1 = 1.0f / RAND_MAX * rand();
+  prob1 -= 0.35f;
+  if (prob1 < 0)
+  {
+    // '*', 'G', 'T', or 'S', 1/4 chance each
+    i = 1 + (int)(3.999f / RAND_MAX * rand());
+  }
+  nn->i1 = i;
+  nn->l1 = 0;
+  if (0 == i) {
+     // relative input link
+     nn->l1 = (int)(4.0f * (1.0f /  RAND_MAX * rand() - 0.5f));
+  }
+  // weight
+  nn->f1 = 10.0f * (1.0f / RAND_MAX * rand() - 0.5f);
+}
+
+// change a [ node
+void Geno_f4::linkNodeChangeRandom(f4_node * nn) const      //rewritten by M.K. - should work as before (not tested)
+{
+  int i;
+  float prob2;
+
+  double probs[3]={0.1, 0.3, 0.6};
+  // 10% change type
+  // 30% change link
+  // 60% change weight
+
+  switch (roulette(probs,3))
+  {
+     case 0: // change type
+          i = 0;
+          // * G, 10% chance each
+          prob2 = rnd01 - 0.10f;
+          if (prob2 < 0) i=1; else {prob2 -= 0.10f; if (prob2 < 0) i=2;}
+          nn->i1 = i;
+          break;
+     case 1: // change link
+          if (0 == nn->i1) // relative input link
+             nn->l1 += (int)(2.0f * (rnd01 - 0.5f));
+          break;
+     case 2: // change weight
+          nn->f1 += 1.0f * (rnd01 - 0.5f);
+          break;
+  }
+}
+
+// make a random : node
+void Geno_f4::nparNodeMakeRandom(f4_node * nn) const
+{
+  int sign = (int)( 2.0f / RAND_MAX * rand() );
+  int param = (int)( 3.0f / RAND_MAX * rand() );
+  if (param>2) param=2;
+  nn->l1 = sign;
+  nn->i1 = "!=/"[param];
+}
+
+// change a repeat # node
+void Geno_f4::repeatNodeChangeRandom(f4_node * nn) const
+{
+  int count;
+  float prob1;
+
+  // change count
+  count = nn->i1;
+  prob1 = 1.0f / RAND_MAX * rand();
+  if (prob1 < 0.5f) count++;
+               else count--;
+  if (count<1) count=1;
+  if (count>REP_MAXCOUNT) count=REP_MAXCOUNT;
+  nn->i1 = count;
+}
+
+
+int Geno_f4::MutateOneValid(f4_node *& g,int &method) const
+// mutate one, until a valid genotype is obtained
+{
+  // ! the genotype is g->child (not g) !
+  int i, res;
+  f4_node * gcopy = NULL;
+  // try this max 20 times:
+  //   copy, mutate, then validate
+
+  for (i=0; i<20; i++)
+  {
+    gcopy = g->duplicate();
+
+    res = MutateOne(gcopy,method);
+
+    if (GENOPER_OK != res)
+    {
+      // mutation failed, try again
+      delete gcopy;
+      continue;  // for
+    }
+    // try to validate it
+    res = ValidateRec(gcopy, 10);
+    // accept if it is OK, or was repaired
+    if (GENOPER_OK == res)
+     //(GENOPER_REPAIR == res)
+    {
+      // destroy the original one
+      g->destroy();
+      // make it the new one
+      *g = *gcopy;
+      gcopy->child=NULL;
+      gcopy->child2=NULL;
+      delete gcopy;
+      res = GENOPER_OK;
+      goto retm1v;
+    }
+    delete gcopy;
+  }
+  // attempts failed
+  res = GENOPER_OPFAIL;
+retm1v:
+  return res;
+}
+
+
+int Geno_f4::mutate(char *& g, float & chg,int &method)
+{
+  f4_node *root=new f4_node;
+  if (f4_processrec(g, 0, root) || root->childCount()!=1)
+     {delete root; return GENOPER_OPFAIL;} // could not convert or bad: fail
+  // mutate one node, set chg as this percent
+  chg = 1.0/float(root->child->count());
+  if (MutateOneValid(root,method)!=GENOPER_OK)
+     {delete root; return GENOPER_OPFAIL;}
+  // OK, convert back to string
+  g[0]=0;
+  root->child->sprintAdj(g);
+  delete root;
+  return GENOPER_OK;
+}
+
+
+/*
+int Geno_f4::MutateMany(char *& g, float & chg)
+// check if original is valid, then
+// make a number of mutations
+{
+  int res, n, i;
+  int totNodes = 0;
+  int maxToMut = 0;
+
+  // convert to tree
+  f4_node * root;
+  root = new f4_node();
+  res = f4_processrec(g, 0, root);
+  if (res) {
+    // could not convert, fail
+    goto retm;
+  }
+  if (1 != root->childCount()) {
+    res = GENOPER_OPFAIL;
+    goto retm;
+  }
+
+  // check if original is valid
+  res = ValidateRec( root, 20 );
+  // might have been repaired!
+  if (GENOPER_REPAIR==res) {
+    res = GENOPER_OK;
+  }
+  if (GENOPER_OK != res) {
+    goto retm;
+  }
+
+  // decide number of nodes to mutate
+  // decide maximum number of nodes to mutate: 0.25*nodes, min 2
+  totNodes = root->child->count();
+  maxToMut = (int)( 0.25f * totNodes);
+  if (maxToMut<2) maxToMut=2;
+  if (maxToMut>totNodes) maxToMut=totNodes;
+
+  // decide number of nodes to mutate
+  n = (int)( 0.5f + 1.0f/RAND_MAX * rand() * maxToMut );
+  if (n<1) n=1;
+  if (n>totNodes) n=totNodes;
+  // set chg as this percent
+  chg = ((float)n) / ((float)totNodes);
+  for (i=0; i<n; i++)
+  {
+    res = MutateOneValid(root);
+    if (GENOPER_OK != res)
+    {
+      res = GENOPER_OPFAIL;
+      goto retm;
+    }
+  }
+  // OK, convert back to string
+  g[0]=0;
+  root->child->sprintAdj(g);
+retm:
+  delete root;
+  return res;
+}
+*/
+
+
+int Geno_f4::CrossOverOne(f4_node * g1, f4_node * g2, float chg) const
+{
+  // ! the genotypes are g1->child and g2->child (not g1 g2) !
+  // single offspring in g1
+  int smin, smax;
+  float size;
+  f4_node * n1, * n2, * n1p, * n2p;
+
+  // determine desired size
+  size = (1-chg) * (float)g1->count();
+  smin = (int)(size*0.9f-1);
+  smax = (int)(size*1.1f+1);
+  // get a random node with desired size
+  n1 = g1->child->randomNodeWithSize(smin, smax);
+
+  // determine desired size
+  size = (1-chg) * (float)g2->count();
+  smin = (int)(size*0.9f-1);
+  smax = (int)(size*1.1f+1);
+  // get a random node with desired size
+  n2 = g2->child->randomNodeWithSize(smin, smax);
+
+  // exchange the two nodes:
+  n1p = n1->parent;
+  n2p = n2->parent;
+  n1p->removeChild(n1);
+  n1p->addChild(n2);
+  n2p->removeChild(n2);
+  n2p->addChild(n1);
+  n1->parent = n2p;
+  n2->parent = n1p;
+
+  return GENOPER_OK;
+}
+
+int Geno_f4::crossOver(char *&g1, char *&g2, float &chg1, float &chg2)
+{
+  f4_node root1, root2, *copy1, *copy2;
+
+  // convert genotype strings into tree structures
+  if (f4_processrec(g1,0,&root1) || (root1.childCount()!=1)) return GENOPER_OPFAIL;
+  if (f4_processrec(g2,0,&root2) || (root2.childCount()!=1)) return GENOPER_OPFAIL;
+
+  // decide amounts of crossover, 0.25-0.75
+  // adam: seems 0.1-0.9 -- MacKo
+  chg1 = 0.1f + 0.8f*rnd01;
+  chg2 = 0.1f + 0.8f*rnd01;
+
+  copy1 = root1.duplicate();
+  if (CrossOverOne(copy1, &root2, chg1) != GENOPER_OK) {delete copy1; copy1=NULL;}
+  copy2 = root2.duplicate();
+  if (CrossOverOne(copy2, &root1, chg2) != GENOPER_OK) {delete copy2; copy2=NULL;}
+
+  g1[0]=0;
+  g2[0]=0;
+  if (copy1) {copy1->child->sprintAdj(g1); delete copy1;}
+  if (copy2) {copy2->child->sprintAdj(g2); delete copy2;}
+  if (g1[0] || g2[0]) return GENOPER_OK; else return GENOPER_OPFAIL;
+}
+
+
+
+unsigned long Geno_f4::style(const char *g, int pos)
+{
+  char ch = g[pos];
+  // style categories
+  #define STYL4CAT_MODIFIC "LlRrCcQqAaIiSsMmFfWwEe,"
+  #define STYL4CAT_NEUMOD "[]|@*GTS:+-/!="
+  #define STYL4CAT_DIGIT "0123456789."
+  #define STYL4CAT_REST "XN<># "
+  if (!strchr(STYL4CAT_MODIFIC STYL4CAT_NEUMOD STYL4CAT_DIGIT STYL4CAT_REST, ch))
+    return GENSTYLE_CS(0,GENSTYLE_INVALID);
+  unsigned long style=GENSTYLE_CS(0,GENSTYLE_STRIKEOUT); //default, should be changed below
+  if (strchr("X ", ch))              style=GENSTYLE_CS(0,GENSTYLE_NONE);
+  if (strchr("N", ch))               style=GENSTYLE_RGBS(0,200,0,GENSTYLE_NONE);  
+  if (strchr("<", ch))               style=GENSTYLE_RGBS(0,0,200,GENSTYLE_BOLD);  
+  if (strchr(">", ch))               style=GENSTYLE_RGBS(0,0,100,GENSTYLE_NONE);  
+  if (strchr(STYL4CAT_DIGIT, ch))     style=GENSTYLE_RGBS(100,100,100,GENSTYLE_NONE);
+  if (strchr(STYL4CAT_MODIFIC, ch))   style=GENSTYLE_RGBS(100,100,100,GENSTYLE_NONE);
+  if (strchr(STYL4CAT_NEUMOD, ch))    style=GENSTYLE_RGBS(0,150,0,GENSTYLE_NONE);
+  return style;
+}
+
+
Index: /cpp/_old/f4/geno_f4.h
===================================================================
--- /cpp/_old/f4/geno_f4.h	(revision 110)
+++ /cpp/_old/f4/geno_f4.h	(revision 110)
@@ -0,0 +1,78 @@
+/*
+ *  geno_f4.h - f4 genetic operators.
+ *
+ *  f4genotype - f4 format genotype conversions for FramSticks
+ *
+ *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
+ *  Copyright (C) 2001-2004  Maciej Komosinski
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _GENO_F4_H_
+#define _GENO_F4_H_
+
+#include "f4_general.h"
+#include "nonstd.h"
+#include <stdio.h>
+#include "geno_fx.h"
+#include "param.h"
+
+
+#define F4_ADD           0
+#define F4_DEL           1
+#define F4_MOD           2
+#define F4_COUNT         3
+
+#define F4_ADD_DIV       0
+#define F4_ADD_CONN      1
+#define F4_ADD_NEUPAR    2
+#define F4_ADD_REP       3
+#define F4_ADD_SIMP      4
+#define F4_ADD_COUNT     5
+
+
+class Geno_f4: public Geno_fx
+{
+public:
+  Geno_f4();
+  int validate(char *&);
+  int checkValidity(const char *);
+  int mutate(char *& g, float & chg,int &method);
+  int crossOver(char *&g1, char *&g2, float& chg1, float& chg2);
+  char* getSimplest() {return "X";};
+  unsigned long style(const char *g, int pos);
+
+  // mutation probabilities
+  double prob[F4_COUNT],probadd[F4_ADD_COUNT];
+
+protected:
+  /* int MutateMany(char *& g, float & chg); // not used any more */
+  int  ValidateRec(f4_node * geno, int retrycount) const;
+  int  MutateOne(f4_node *& g,int &method) const;
+  void linkNodeMakeRandom(f4_node * nn) const;
+  void linkNodeChangeRandom(f4_node * nn) const;
+  void nparNodeMakeRandom(f4_node * nn) const;
+  void repeatNodeChangeRandom(f4_node * nn) const;
+  int  MutateOneValid(f4_node * &g,int &method) const;
+  int  CrossOverOne(f4_node *g1, f4_node *g2, float chg) const;
+    // returns GENOPER_OK or GENOPER_OPFAIL
+    // chg: fraction of parent1 genes in child (in g1) (parent2 has the rest)
+};
+
+
+#endif
+
Index: /cpp/_old/f8-to-f1/Makefile
===================================================================
--- /cpp/_old/f8-to-f1/Makefile	(revision 110)
+++ /cpp/_old/f8-to-f1/Makefile	(revision 110)
@@ -0,0 +1,237 @@
+#
+# Framsticks GDK makefile
+#
+
+CXX=g++
+CC=gcc
+
+TARGETS=convtest gdktest genotest neurotest loadertest f0def.xml model.def convtestmw
+
+all: $(TARGETS)
+
+#CXXOPTS= -DNOCREATUREOBJECT -DEASYMAPDEBUG -O2 -Wno-parentheses -Wno-overloaded-virtual -Wno-format -Wunused
+CXXOPTS= -DNOCREATUREOBJECT -DEASYMAPDEBUG -g -Wno-parentheses -Wno-overloaded-virtual -Wno-format -Wunused
+# -DEASYMAPDEBUG is required for convtest
+
+AUTOGENERATED=defassign-f0_joint.h defassign-f0_part.h defassign-f0_neuro.h f0classes.h \
+	defassign-f0_neuroconn.h f0def.xml neurocls-library.h neurocls-factory.h model.def \
+	lemon conv_f8tof1_scanner.cpp conv_f8tof1_grammar.h conv_f8tof1_grammar.c \
+	conv_f8tof1_scanner.h
+
+CONVMODULES=conv_f1.o conv_f8tof1.o
+
+GDKOBJS=list.o advlist.o param.o sstring.o 3d.o model.o modelparts.o errmanager.o \
+	neurolibrary.o geno.o genoconv.o extvalue.o framsg.o callbacks.o syntparam.o \
+	multirange.o multimap.o paramtabobj.o defgenoconv.o sstringutils.o paramobj.o \
+	$(CONVMODULES) conv_f8tof1_scanner.o conv_f8_utils.o
+
+libgdk.a: $(GDKOBJS)
+
+libgenof8.a: geno_f8.o geno_fx.o model.o framsg.o rndutil.o conv_f8_utils.o
+
+CONVTESTOBJS= convtest.o printconvmap.o stdouterr.o virtfile.o
+CONVTESTOBJS2= convtestmw.o printconvmap.o stdouterr.o virtfile.o
+
+convtest: libgdk.a $(CONVTESTOBJS)
+	$(CXX) $(CONVTESTOBJS) -L. -lgdk -o $@
+	
+convtestmw: libgdk.a $(CONVTESTOBJS2) libgenof8.a
+	$(CXX) $(CONVTESTOBJS2) -L. -lgdk -lgenof8 -o $@
+
+GDKTESTOBJS= gdktest.o stdouterr.o virtfile.o
+
+gdktest: libgdk.a $(GDKTESTOBJS)
+	$(CXX) $(GDKTESTOBJS) -L. -lgdk -o $@
+
+GENOTESTOBJS= genotest.o virtfile.o
+
+genotest: libgdk.a $(GENOTESTOBJS)
+	$(CXX) $(GENOTESTOBJS) -L. -lgdk -o $@
+
+NEUROTESTOBJS= neurotest.o stdouterr.o virtfile.o neuroimpl.o neurofactory.o \
+	neuroimpl-simple.o neuroimpl-channels.o neuroimpl-fuzzy.o neuroimpl-fuzzy-f0.o
+
+neurotest: libgdk.a $(NEUROTESTOBJS)
+	$(CXX) $(NEUROTESTOBJS) -L. -lgdk -o $@
+
+LOADERTESTOBJS=genotypeloader.o loadertest.o virtfile.o multiparamload.o stdiofile-autoinit.o stdiofile.o
+
+loadertest: libgdk.a $(LOADERTESTOBJS)
+	$(CXX) $(LOADERTESTOBJS) -L. -lgdk -o $@
+
+neurocls-library.h: f0.def neurocls-library.m4
+	m4 neurocls-library.m4 f0.def >neurocls-library.h
+
+neurocls-factory.h: f0.def neurocls-factory.m4
+	m4 neurocls-factory.m4 f0.def >neurocls-factory.h
+
+f0classes.h: f0.def f0classes.m4
+	m4 f0classes.m4 f0.def >f0classes.h
+
+f0def.xml: f0.def f0defxml.m4
+	m4 f0defxml.m4 f0.def >f0def.xml
+
+model.def: f0-modeldef.m4 f0.def
+	m4 f0-modeldef.m4 f0.def >model.def
+
+defassign-%.h: defassign.m4 f0.def
+	m4 -DUSECLASS=$* defassign.m4 f0.def >$@
+
+neurolibrary.cpp: neurocls-library.h
+neurofactory.cpp: neurocls-factory.h
+modelparts.cpp: f0classes.h defassign-f0_part.h defassign-f0_joint.h \
+		defassign-f0_neuro.h defassign-f0_neuroconn.h
+
+lemon: lemon.c
+	$(CC) -o lemon lemon.c
+
+conv_f8tof1_grammar.c: lemon conv_f8tof1_grammar.y lempar.c
+	./lemon -q conv_f8tof1_grammar.y
+
+conv_f8tof1_scanner.h: conv_f8tof1_scanner.l
+	flex++ --outfile=conv_f8tof1_scanner.cpp --header-file=conv_f8tof1_scanner.h conv_f8tof1_scanner.l
+	
+#############
+
+%.o : %.cpp
+	$(CXX) -c $(CXXOPTS) $<
+
+%.a:
+	rm -f $@
+	ar r $@ $^
+	ranlib $@
+
+clean:
+	rm -f *.o *~ *.bak *.a
+
+fullclean:	clean
+	rm -f $(TARGETS) $(AUTOGENERATED)
+
+prepare: $(AUTOGENERATED) depend
+	rm -f Makefile.bak
+	addhead ../gdk-head.txt *.h *.cpp
+
+depend:
+	makedepend -Y *.cpp
+
+# DO NOT DELETE
+
+3d.o: nonstd.h 3d.h framsg.h
+advlist.o: advlist.h list.h nonstd.h callbacks.h statrick.h
+callbacks.o: callbacks.h list.h nonstd.h statrick.h
+conv_f1.o: conv_f1.h genoconv.h geno.h sstring.h extvalue.h param.h list.h
+conv_f1.o: nonstd.h statrick.h virtfile.h model.h modelparts.h 3d.h
+conv_f1.o: sstringutils.h syntparam.h usertags.h paramtabobj.h advlist.h
+conv_f1.o: callbacks.h framsg.h multirange.h multimap.h
+conv_f8tof1.o: conv_f8tof1.h genoconv.h geno.h sstring.h extvalue.h param.h list.h
+conv_f8tof1.o: nonstd.h statrick.h virtfile.h model.h modelparts.h 3d.h
+conv_f8tof1.o: sstringutils.h syntparam.h usertags.h paramtabobj.h advlist.h
+conv_f8tof1.o: callbacks.h framsg.h multirange.h multimap.h conv_f8_utils.h
+#conv_f8tof1.o: conv_f8tof1_scanner.l conv_f8tof1_scanner.cpp 
+conv_f8tof1.o: lemonglobal.h conv_f8tof1_scanner.h
+conv_f8tof1.o: conv_f8tof1_grammar.y conv_f8tof1_grammar.c
+conv_f8tof1_scanner.o: sstring.h conv_f8tof1_scanner.l conv_f8tof1_scanner.h 
+conv_f8tof1_scanner.o: lexglobal.h lemonglobal.h
+conv_f8_utils.o: sstring.h
+geno_f8.o: geno_f8.h nonstd.h model.h framsg.h rndutil.h
+geno_f8.o: param.h sstring.h geno_fx.h multimap.h conv_f8tof1.h
+geno_f8.o: conv_f8_utils.h
+geno_fx.o: geno_fx.h nonstd.h model.h framsg.h rndutil.h
+convtest.o: genoconv.h geno.h sstring.h extvalue.h param.h list.h nonstd.h
+convtest.o: statrick.h virtfile.h model.h modelparts.h 3d.h sstringutils.h
+convtest.o: syntparam.h usertags.h paramtabobj.h advlist.h callbacks.h
+convtest.o: multimap.h multirange.h conv_f1.h printconvmap.h stdouterr.h
+convtest.o: errmanager.h framsg.h
+convtestmw.o: genoconv.h geno.h sstring.h extvalue.h param.h list.h nonstd.h
+convtestmw.o: statrick.h virtfile.h model.h modelparts.h 3d.h sstringutils.h
+convtestmw.o: syntparam.h usertags.h paramtabobj.h advlist.h callbacks.h
+convtestmw.o: multimap.h multirange.h conv_f1.h printconvmap.h stdouterr.h
+convtestmw.o: errmanager.h framsg.h conv_f8tof1.h conv_f8_utils.h geno_f8.h
+defgenoconv.o: defgenoconv.h genoconv.h geno.h sstring.h extvalue.h param.h
+defgenoconv.o: list.h nonstd.h statrick.h virtfile.h gen-config.h conv_f1.h
+defgenoconv.o: model.h modelparts.h 3d.h sstringutils.h syntparam.h
+defgenoconv.o: usertags.h paramtabobj.h advlist.h callbacks.h
+errmanager.o: errmanager.h list.h nonstd.h sstring.h framsg.h
+extvalue.o: extvalue.h sstring.h param.h list.h nonstd.h statrick.h
+extvalue.o: virtfile.h framsg.h
+framsg.o: nonstd.h framsg.h
+gdktest.o: model.h modelparts.h 3d.h genoconv.h geno.h sstring.h extvalue.h
+gdktest.o: param.h list.h nonstd.h statrick.h virtfile.h sstringutils.h
+gdktest.o: syntparam.h usertags.h paramtabobj.h advlist.h callbacks.h
+gdktest.o: defgenoconv.h stdouterr.h errmanager.h framsg.h
+genoconv.o: nonstd.h genoconv.h geno.h sstring.h extvalue.h param.h list.h
+genoconv.o: statrick.h virtfile.h multimap.h multirange.h
+geno.o: geno.h sstring.h extvalue.h param.h list.h nonstd.h statrick.h
+geno.o: virtfile.h genoconv.h model.h modelparts.h 3d.h sstringutils.h
+geno.o: syntparam.h usertags.h paramtabobj.h advlist.h callbacks.h
+genotest.o: geno.h sstring.h extvalue.h param.h list.h nonstd.h statrick.h
+genotest.o: virtfile.h genoconv.h stdiofile.h sstringutils.h defgenoconv.h
+genotypeloader.o: genotypeloader.h sstring.h multiparamload.h param.h list.h
+genotypeloader.o: nonstd.h statrick.h virtfile.h
+list.o: list.h nonstd.h
+loadertest.o: genotypeloader.h sstring.h multiparamload.h param.h list.h
+loadertest.o: nonstd.h statrick.h virtfile.h
+model.o: nonstd.h model.h modelparts.h 3d.h genoconv.h geno.h sstring.h
+model.o: extvalue.h param.h list.h statrick.h virtfile.h sstringutils.h
+model.o: syntparam.h usertags.h paramtabobj.h advlist.h callbacks.h framsg.h
+model.o: multimap.h multirange.h errmanager.h
+modelparts.o: modelparts.h 3d.h genoconv.h geno.h sstring.h extvalue.h
+modelparts.o: param.h list.h nonstd.h statrick.h virtfile.h sstringutils.h
+modelparts.o: syntparam.h usertags.h paramtabobj.h model.h advlist.h
+modelparts.o: callbacks.h neurolibrary.h multirange.h defassign-f0_neuro.h
+modelparts.o: defassign-f0_part.h defassign-f0_joint.h f0classes.h
+modelparts.o: defassign-f0_neuroconn.h
+multimap.o: multimap.h multirange.h list.h nonstd.h
+multiparamload.o: multiparamload.h param.h sstring.h list.h nonstd.h
+multiparamload.o: statrick.h virtfile.h framsg.h
+multirange.o: multirange.h list.h nonstd.h
+neurofactory.o: neurofactory.h modelparts.h 3d.h genoconv.h geno.h sstring.h
+neurofactory.o: extvalue.h param.h list.h nonstd.h statrick.h virtfile.h
+neurofactory.o: sstringutils.h syntparam.h usertags.h paramtabobj.h
+neurofactory.o: neuroimpl.h model.h advlist.h callbacks.h framsg.h
+neurofactory.o: neuroimplfiles.h neuroimpl-simple.h neuroimpl-channels.h
+neurofactory.o: neuroimpl-fuzzy.h neuroimpl-body-gdk.h neurocls-factory.h
+neuroimpl-channels.o: neuroimpl-channels.h neuroimpl.h model.h modelparts.h
+neuroimpl-channels.o: 3d.h genoconv.h geno.h sstring.h extvalue.h param.h
+neuroimpl-channels.o: list.h nonstd.h statrick.h virtfile.h sstringutils.h
+neuroimpl-channels.o: syntparam.h usertags.h paramtabobj.h advlist.h
+neuroimpl-channels.o: callbacks.h framsg.h
+neuroimpl.o: neuroimpl.h model.h modelparts.h 3d.h genoconv.h geno.h
+neuroimpl.o: sstring.h extvalue.h param.h list.h nonstd.h statrick.h
+neuroimpl.o: virtfile.h sstringutils.h syntparam.h usertags.h paramtabobj.h
+neuroimpl.o: advlist.h callbacks.h framsg.h neurofactory.h
+neuroimpl-fuzzy.o: neuroimpl-fuzzy.h neuroimpl.h model.h modelparts.h 3d.h
+neuroimpl-fuzzy.o: genoconv.h geno.h sstring.h extvalue.h param.h list.h
+neuroimpl-fuzzy.o: nonstd.h statrick.h virtfile.h sstringutils.h syntparam.h
+neuroimpl-fuzzy.o: usertags.h paramtabobj.h advlist.h callbacks.h framsg.h
+neuroimpl-fuzzy.o: neuroimpl-fuzzy-f0.h
+neuroimpl-fuzzy-f0.o: neuroimpl-fuzzy-f0.h sstring.h nonstd.h
+neuroimpl-simple.o: neuroimpl-simple.h neuroimpl.h model.h modelparts.h 3d.h
+neuroimpl-simple.o: genoconv.h geno.h sstring.h extvalue.h param.h list.h
+neuroimpl-simple.o: nonstd.h statrick.h virtfile.h sstringutils.h syntparam.h
+neuroimpl-simple.o: usertags.h paramtabobj.h advlist.h callbacks.h framsg.h
+neurolibrary.o: neurolibrary.h advlist.h list.h nonstd.h callbacks.h
+neurolibrary.o: statrick.h param.h sstring.h virtfile.h modelparts.h 3d.h
+neurolibrary.o: genoconv.h geno.h extvalue.h sstringutils.h syntparam.h
+neurolibrary.o: usertags.h paramtabobj.h neurocls-library.h
+neurotest.o: geno.h sstring.h extvalue.h param.h list.h nonstd.h statrick.h
+neurotest.o: virtfile.h genoconv.h stdiofile.h sstringutils.h defgenoconv.h
+neurotest.o: neuroimpl.h model.h modelparts.h 3d.h syntparam.h usertags.h
+neurotest.o: paramtabobj.h advlist.h callbacks.h framsg.h neurofactory.h
+neurotest.o: stdouterr.h errmanager.h
+param.o: param.h sstring.h list.h nonstd.h statrick.h virtfile.h extvalue.h
+param.o: framsg.h sstringutils.h
+paramobj.o: paramobj.h param.h sstring.h list.h nonstd.h statrick.h
+paramobj.o: virtfile.h extvalue.h
+paramtabobj.o: paramtabobj.h param.h sstring.h list.h nonstd.h statrick.h
+paramtabobj.o: virtfile.h
+printconvmap.o: printconvmap.h sstring.h multimap.h multirange.h list.h
+printconvmap.o: nonstd.h
+sstring.o: sstring.h nonstd.h
+sstringutils.o: sstringutils.h sstring.h virtfile.h framsg.h
+stdiofile-autoinit.o: stdiofile.h virtfile.h sstring.h
+stdiofile.o: stdiofile.h virtfile.h sstring.h nonstd.h nonstd_io.h
+stdouterr.o: stdouterr.h errmanager.h list.h nonstd.h sstring.h framsg.h
+syntparam.o: nonstd.h syntparam.h param.h sstring.h list.h statrick.h
+syntparam.o: virtfile.h paramobj.h
+virtfile.o: virtfile.h
Index: /cpp/_old/f8-to-f1/conv_f8_utils.cpp
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8_utils.cpp	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8_utils.cpp	(revision 110)
@@ -0,0 +1,168 @@
+/*
+ *  conv_f8_utils.cpp
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-09-21.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "conv_f8_utils.h"
+
+using namespace std;
+
+bool containsChars(const SString s, char c[]) {
+const char* str=(const char*)s;
+	for (int i = 0; i < s.len(); i++) {
+		for (int j = 0; j < strlen(c); j++) {
+			if (str[i] == c[j]) {
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+bool containsChar(std::vector<char> tab, char c) {
+	for (int i = 0; i < tab.size(); i++) {
+		if (tab[i] == c) {
+			return true;
+		}
+	}
+	return false;
+}
+
+int reverseFindInSString(const SString s, char c, int index) {
+	if (index > 0) {
+		index = (s.len() - 1 > index) ? index : s.len() - 1; //min(index, s.len() - 1)
+	} else {
+		index = s.len() - 1;
+	}
+	
+const char* str=(const char*)s;
+	for (int i = index; i >= 0; i--) {
+		if (str[i] == c) {
+			return i;
+		}
+	}
+	return -1;
+}
+
+SString trimSString(const SString s) {
+	SString result = "";
+	for (int i = 0; i < s.len(); i++) {
+		char c = s.charAt(i);
+		if (c != ' ' && c != '\t') {
+			result += c;
+		}
+	}
+	return result;
+}
+
+double parseDouble(const SString &s) {
+	const char* str = s;
+	std::istringstream i(str);
+	double x;
+	if (!(i >> x))
+		throw BadConversion("parseDouble(\"" + string(str) + "\")");
+	return x;
+}
+
+int parseInt(const SString &s) {
+	const char* str = s;
+	std::istringstream i(str);
+	int x;
+	if (!(i >> x))
+		throw BadConversion("parseInt(\"" + string(str) + "\")");
+	return x;
+}
+
+SString stringToSString(string str) {
+	return SString(str.c_str());
+}
+
+string sstringToString(SString sstr) {
+	const char* tmp = sstr;
+	return string(tmp);
+}
+
+SString convertReversePolishNotationToNatural(const SString &s) {
+	SString result = "";
+	SString tok = "";
+	int pos = 0;
+	stack<SString> stck;
+	
+	while (s.getNextToken(pos, tok, ';')) {
+		if (tok.len() == 1  && (tok[0] == '+' || tok[0] == '-' || tok[0] == '*' || tok[0] == '/')) {
+			SString s1, s2;
+			if (!stck.empty()) {
+				s1 = stck.top();
+				stck.pop();
+			} else {
+				throw ParseExpressionException("Not enough elements on stack: " + sstringToString(s));
+			}
+			if (!stck.empty()) {
+				s2 = stck.top();
+				stck.pop();
+			} else {
+				throw ParseExpressionException("Not enough elements on stack: " + sstringToString(s));
+			}
+			switch (tok[0]) {
+				case '+': stck.push(s2 + "+" + s1); break;
+				case '-': stck.push(s2 + "-" + s1); break;
+				case '*': stck.push(s2 + "*" + s1); break;
+				case '/': stck.push(s2 + "/" + s1); break;
+			}
+		} else if (tok.len() > 0) {
+			stck.push(tok);
+		}
+	}
+	
+	result = stck.top();	
+	
+	return result;
+}
+
+double parseExpression(const SString &s) {
+	double result = 0;
+	SString tok = "";
+	int pos = 0;
+	stack<double> stck;
+	
+	while (s.getNextToken(pos, tok, ';')) {
+		if (tok.len() == 1  && (tok[0] == '+' || tok[0] == '-' || tok[0] == '*' || tok[0] == '/')) {
+			double n1, n2;
+			if (!stck.empty()) {
+				n1 = stck.top();
+				stck.pop();
+			} else {
+				throw ParseExpressionException("Not enough elements on stack: " + sstringToString(s));
+			}
+			if (!stck.empty()) {
+				n2 = stck.top();
+				stck.pop();
+			} else {
+				throw ParseExpressionException("Not enough elements on stack: " + sstringToString(s));
+			}
+			switch (tok[0]) {
+				case '+': stck.push(n2 + n1); break;
+				case '-': stck.push(n2 - n1); break;
+				case '*': stck.push(n2 * n1); break;
+				case '/': 
+					if (n1 == 0) {
+						throw ParseExpressionException("Division by zero");
+					}
+					stck.push(n2 / n1); 
+					break;
+			}
+		} else if (tok.len() > 0) {
+			stck.push(parseDouble(tok));
+		}/* else {
+		 throw ParseExpressionException("Unrecognized element in input string '" + sstringToString(tmp) + "'");
+		 }*/
+	}
+	
+	result = stck.top();
+	
+	return result;
+}
Index: /cpp/_old/f8-to-f1/conv_f8_utils.h
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8_utils.h	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8_utils.h	(revision 110)
@@ -0,0 +1,45 @@
+/*
+ *  conv_f8_utils.h
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-09-21.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef _CONV_F8_UTILS_H_
+#define _CONV_F8_UTILS_H_
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <stdexcept>
+#include <stack>
+#include <vector>
+#include "sstring.h"
+
+using namespace std;
+
+class BadConversion : public std::runtime_error {
+public:
+	BadConversion(const std::string &s) : std::runtime_error(s)	{ }
+};
+
+class ParseExpressionException : public std::runtime_error {
+public:
+	ParseExpressionException(const std::string &s) : std::runtime_error(s) { }
+};
+
+bool containsChars(const SString s, char c[]);
+bool containsChar(std::vector<char> tab, char c);
+int reverseFindInSString(const SString s, char c, int index = -1);
+SString trimSString(const SString s);
+SString trimSString(const SString s);
+double parseDouble(const SString &s);
+int parseInt(const SString &s);
+SString stringToSString(string str);
+string sstringToString(SString sstr);
+SString convertReversePolishNotationToNatural(const SString &s);
+double parseExpression(const SString &s);
+
+#endif
Index: /cpp/_old/f8-to-f1/conv_f8tof1.cpp
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1.cpp	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1.cpp	(revision 110)
@@ -0,0 +1,790 @@
+/*
+ *  conv_f8tof1.cpp
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-03-21.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "conv_f8tof1.h"
+#include "conv_f8_utils.h"
+#include <sstream>
+#include <string>
+#include <algorithm>
+#include "lexglobal.h"
+#include "conv_f8tof1_scanner.h"
+namespace prs {
+	#include "conv_f8tof1_grammar.c"
+}
+
+#if CONV_DEBUG > 0
+	#include <iostream>
+#endif
+
+#define CONV_DEBUG 0 //0 - off, 1 - minimal, 2 - full
+
+using namespace std;
+
+Lsystem::Lsystem()
+{
+        for(int i=0;i<strlen(GenoConv_F8ToF1::simpleprods);i++)
+        {
+                string s(1,GenoConv_F8ToF1::simpleprods[i]);
+                SString ss(s.c_str());
+        	this->primitiveProductions.insert(make_pair(s, new PrimitiveProduction(ss)));
+        }
+}
+
+Lsystem::~Lsystem() {
+	for (map<string, Production*>::iterator iter = this->productions.begin();
+		 iter != this->productions.end(); iter++) {
+		delete iter->second;
+	}
+	for (map<string, PrimitiveProduction*>::iterator iter = this->primitiveProductions.begin();
+		 iter != this->primitiveProductions.end(); iter++) {
+		delete iter->second;
+	}
+	for (map<string, ParamProduction*>::iterator iter = this->paramProductions.begin(); 
+		 iter != this->paramProductions.end(); iter++) {
+		delete iter->second;
+	}
+	for (vector<NeuronProduction*>::iterator iter = this->neuronProductions.begin();
+		 iter != this->neuronProductions.end(); iter++) {
+		delete *iter;
+	}
+}
+
+PrimitiveProduction* Lsystem::getPrimitiveProduction(SString name) {
+	string sname = sstringToString(name);
+	if (this->primitiveProductions.find(sname) == this->primitiveProductions.end()) {
+		PrimitiveProduction *pp = new PrimitiveProduction(name);
+		this->primitiveProductions.insert(make_pair(sname, pp));
+	}
+	return this->primitiveProductions[sname];
+}
+
+ParamProduction* Lsystem::getParamProduction(SString name) {
+	string sname = sstringToString(name);
+	if (this->paramProductions.find(sname) == this->paramProductions.end()) {
+		ParamProduction *pp = new ParamProduction(name);
+		this->paramProductions.insert(make_pair(sname, pp));
+	}
+	return this->paramProductions[sname];
+}
+
+SString Lsystem::toString() {
+	this->removeEmptySubproductionsAndProductions();
+	SString result = "";
+	result += SString::valueOf(this->iterations) + "\n";
+	for (map<string, double>::iterator it = this->startParams.begin(); 
+		 it != this->startParams.end(); it++) {
+		result += stringToSString(it->first) + "=" + SString::valueOf(it->second) + "\n";
+	}
+	result += SString("---") + "\n";
+	result += stringToSString(this->firstProductionName) + "\n";
+	for (map<string, Production*>::iterator prodIter = this->productions.begin();
+		 prodIter != this->productions.end(); prodIter++) {
+		Production *p = prodIter->second;
+		result += p->name + "(";
+		for (int i = 1; i <= p->parameters.size(); i++) {
+			result += p->parameters.getParameterName(i);
+			if (i < p->parameters.size()) {
+				result += ",";
+			}
+		}
+		result += "):";
+		for (int subprodIter = 0; subprodIter < p->subproductions.size(); subprodIter++) {
+			SubProduction *sp = &(p->subproductions[subprodIter]);
+			for (int condIter = 0; condIter < sp->conditions.size(); condIter++) {
+				Condition *c = &(sp->conditions[condIter]);
+				RelationType r = c->relation;
+				SString op = (r == r_greater) ? ">" : (r == r_greaterEqual) ? ">=" : (r == r_less) ? "<" :
+				(r == r_lessEqual) ? "<=" : (r == r_equal) ? "==" : (r == r_different) ? "!=" : "";
+				result += c->parameter + op + SString::valueOf(c->value);
+				if (condIter != sp->conditions.size() - 1) {
+					result += ",";
+				}
+			}
+			if (sp->conditions.size() > 0) {
+				result += SString("|");
+			}
+			for (vector<ActionStrP>::iterator actionIter = sp->actions.begin();
+				 actionIter != sp->actions.end(); actionIter++) {
+				ActionStrP *a = &(*actionIter);
+				if (a->action == NULL) {
+					continue;
+				}
+				result += a->action->getF8Representation();
+				if (!a->action->ignoreParams) {
+					result += SString("(");
+					for (int paramIter = 0; paramIter < a->params.size(); paramIter++) {
+						result += convertReversePolishNotationToNatural(a->params[paramIter]);
+						if (paramIter != a->params.size() - 1) {
+							result += ",";
+						}
+					}
+					result += SString(")");					
+				}
+			}
+			if (subprodIter != p->subproductions.size() - 1) {
+				result += SString(":");
+			}
+		}
+		result += SString("\n");
+	}	
+	return result;
+}
+
+vector<Action*> Lsystem::getAllActions(bool normal, bool primitives, bool params, bool neurons) {
+	vector<Action*> actions;
+	if (normal) {
+		for (map<string, Production*>::iterator iter = this->productions.begin(); 
+			 iter != this->productions.end(); iter++) {
+			actions.push_back(iter->second);
+		}
+	}
+	if (primitives) {
+		for (map<string, PrimitiveProduction*>::iterator iter = this->primitiveProductions.begin(); 
+			 iter != this->primitiveProductions.end(); iter++) {
+			actions.push_back(iter->second);
+		}
+	}
+	if (params) {
+		for (map<string, ParamProduction*>::iterator iter = this->paramProductions.begin(); 
+			 iter != this->paramProductions.end(); iter++) {
+			actions.push_back(iter->second);
+		}
+	}
+	if (neurons) {
+		for (vector<NeuronProduction*>::iterator iter = this->neuronProductions.begin();
+			 iter != this->neuronProductions.end(); iter++) {
+			actions.push_back(*iter);
+		}
+	}
+	return actions;
+}
+
+void Lsystem::removeEmptySubproductionsAndProductions() {
+	/* po wykonaniu moga pozostac puste subprodukcje (usuwanie wywolan do usunietych wczesniej produkcji
+	 * ale i tak znikna one przy kolejnym wywolaniu, tak wiec ilosc smieci nie powinna byc razaca
+	 */
+	
+	//delete empty subproductions
+	for (map<string, Production*>::iterator prodIter = this->productions.begin();
+		 prodIter != this->productions.end(); prodIter++) {
+		vector<SubProduction> *subproductions = &(prodIter->second->subproductions);
+		for (vector<SubProduction>::iterator i = subproductions->begin(); i != subproductions->end(); /*nothing*/) {
+			if ((*i).actions.size() == 0) {
+				i = subproductions->erase(i);
+			} else {
+				i++;
+			}
+		}
+	}
+	
+	//find empty productions
+	vector<SString> emptyProductionNames;	
+	for (map<string, Production*>::iterator prodIter = this->productions.begin();
+		 prodIter != this->productions.end(); prodIter++) {
+		if (prodIter->second->subproductions.size() == 0 && 
+			sstringToString(prodIter->second->name) != this->firstProductionName) {
+			emptyProductionNames.push_back(prodIter->second->name);
+		}
+	}
+	
+	//delete calls to empty productions
+	for (map<string, Production*>::iterator prodIter = this->productions.begin();
+		 prodIter != this->productions.end(); prodIter++) {
+		vector<SubProduction> *subproductions = &(prodIter->second->subproductions);
+		for (vector<SubProduction>::iterator subProdIter = subproductions->begin();
+			 subProdIter != subproductions->end(); subProdIter++) {
+			SubProduction *sp = &(*subProdIter);
+			for (vector<ActionStrP>::iterator actionIter = sp->actions.begin(); 
+				 actionIter != sp->actions.end(); /*nothing*/) {
+				bool deleted = false;
+				if ((*actionIter).action != NULL) {
+					vector<SString>::iterator result = find(emptyProductionNames.begin(), emptyProductionNames.end(), 
+															(*actionIter).action->name);
+					if (result != emptyProductionNames.end()) { //emptyProductionNames contains the action name
+						actionIter = sp->actions.erase(actionIter);
+						deleted = true;
+					}
+				}
+				if (!deleted) {
+					actionIter++;
+				}
+			}
+		}
+	}
+	
+	//delete empty productions
+	for(int i = 0; i < emptyProductionNames.size(); i++) {
+		this->productions.erase(sstringToString(emptyProductionNames[i]));
+	}
+}
+
+ostream& operator<<(ostream& os, const Condition& c) {
+	RelationType r = c.relation;
+	SString op = (r == r_greater) ? ">" : (r == r_greaterEqual) ? ">=" : (r == r_less) ? "<" :
+	(r == r_lessEqual) ? "<=" : (r == r_equal) ? "==" : (r == r_different) ? "!=" : "";
+	os <<  c.parameter << " " << op << " " << c.value;
+	return os;
+}
+
+const double ParameterCollection::getValue(int position) {
+	string name = this->parameters[position - 1];
+	return this->paramValues[name];
+}
+
+const double ParameterCollection::getValue(SString name) {
+	return this->paramValues[sstringToString(name)];
+}
+
+const SString ParameterCollection::getParameterName(int position) {
+	return stringToSString(this->parameters[position - 1]);
+}
+
+const int ParameterCollection::getParameterPosition(SString name) {
+	for (int i = 0; i < this->parameters.size(); i++) {
+		string &s = this->parameters[i];
+		if (s == sstringToString(name)) {
+			return i + 1;
+		}
+	}
+	return -1;
+}
+
+void ParameterCollection::setValue(int position, double value) {
+	string name = this->parameters[position - 1];
+	this->paramValues[name] = value;
+}
+
+void ParameterCollection::setValue(SString name, double value) {
+	this->paramValues[sstringToString(name)] = value;
+}
+
+void ParameterCollection::addParameter(SString name, int position, double value) {
+	//TODO sprawdzenie czy position > 0
+	string sname = sstringToString(name);
+	if (position == -1) {
+		this->parameters.push_back(sname);
+		this->paramValues[sname] = value;
+	} else {
+		this->parameters.reserve(position);
+		this->parameters.insert(this->parameters.begin() + (position -1), sname);
+		this->paramValues[sname] = value;
+	}
+	//this->paramValues[name] = value;
+}
+
+const int ParameterCollection::size() {
+	return this->parameters.size();
+}
+
+void ParameterCollection::removeParameter(int position) {
+	string name = this->parameters[position - 1];
+	vector<string>::iterator it = this->parameters.begin() + (position - 1);
+	this->parameters.erase(it);
+	this->paramValues.erase(name);
+}
+
+void ParameterCollection::removeParameter(SString name) {
+	int idx = getParameterPosition(name);
+	this->removeParameter(idx);
+}
+
+bool ParameterCollection::paramExist(SString name) {
+	string sname = sstringToString(name);
+	for (vector<string>::iterator it = this->parameters.begin(); it != this->parameters.end(); it++) {
+		if ((*it) == sname) {
+			return true;
+		}
+	}
+	return false;
+}
+
+PrimitiveProduction::PrimitiveProduction(const SString command) {
+	this->f8command = command;
+	this->ignoreParams = true;
+	if (command == SString("[")) {
+		this->f1command = SString("(");
+		this->name = SString("_primitive production '[' => '('");
+	} else if (command == SString("]")) {
+		this->f1command = SString(")");
+		this->name = SString("_primitive production ']' => ')'");
+	} else if (command == SString("^")) {
+		this->f1command = SString(",");
+		this->name = SString("_primitive production '^' => ','");
+	} else {
+		this->f1command = command;
+		this->name = SString("_primitive production '") + command + "'";
+	}
+}
+
+const SString PrimitiveProduction::getF1Genotype(const vector<double> params) {
+#if CONV_DEBUG > 1
+	cout << "@@@@@ Prymityw: " << this->f1command << endl;
+#endif
+	return SString(this->f1command);
+}
+
+const list<ActionP> PrimitiveProduction::getActionList(const vector<double> param) {
+	list<ActionP> l;
+	ActionP ap;
+	ap.action = this;
+	ap.params = param;
+	l.push_back(ap);
+	return l;
+}
+
+const SString PrimitiveProduction::getF8Representation() {
+	return this->f8command;
+}
+
+ParamProduction::ParamProduction(const SString paramName) {
+	this->paramName = paramName;
+	this->name = SString("_param production") + paramName;
+	this->ignoreParams = true;
+}
+
+const SString ParamProduction::getF1Genotype(const vector<double> params) {
+	SString s = SString::valueOf(params[0]);
+#if CONV_DEBUG > 1
+	cout << "@@@@@ Param value: " << this->paramName << ": " << params[0] << endl;
+#endif
+	return s;
+	
+}
+
+const list<ActionP> ParamProduction::getActionList(const vector<double> param) {
+	list<ActionP> l;
+	ActionP ap;
+	ap.action = this;
+	ap.params = param;
+	l.push_back(ap);
+	return l;
+	
+}
+
+const SString ParamProduction::getF8Representation() {
+	return this->paramName;
+}
+
+NeuronProduction::NeuronProduction(const SString body) {
+	this->body = body;
+	this->name = SString("_neuron production") + body;
+	this->ignoreParams = true;
+}
+
+const SString NeuronProduction::getF1Genotype(const vector<double> params) {
+	return this->body;	
+}
+
+const list<ActionP> NeuronProduction::getActionList(const vector<double> param) {
+	list<ActionP> l;
+	ActionP ap;
+	ap.action = this;
+	ap.params = param;
+	l.push_back(ap);
+	return l;
+	
+}
+
+const SString NeuronProduction::getF8Representation() {
+	return this->body;
+}
+
+Production::Production() {
+	this->ignoreParams = false;
+}
+
+const SString Production::getF1Genotype(const vector<double> params) {
+	return SString(); //return empty
+}
+
+const list<ActionP> Production::getActionList(const vector<double> params) {
+	list<ActionP> l;
+#if CONV_DEBUG > 1
+	cout << "params.size(): " << params.size() << ", this->parameters.size(): " << this->parameters.size() << endl;
+#endif
+	for (int i = 0; i < params.size() && i < this->parameters.size(); i++) {
+		this->parameters.setValue(i + 1, params[i]);
+	}
+	
+	//iterate through subproductions
+	for (vector<SubProduction>::iterator subProdIter = this->subproductions.begin();
+		 subProdIter != this->subproductions.end(); subProdIter++) {
+#if CONV_DEBUG > 1
+		cout << "this->subproductions.size(): " << this->subproductions.size() << endl;
+#endif
+		SubProduction &sp = *subProdIter;
+		bool conditionsOK = true;
+		//check conditions of subproduction
+		for (vector<Condition>::iterator condIter = sp.conditions.begin();
+			 condIter != sp.conditions.end(); condIter++) {
+			if (conditionsOK == false) {
+				break; //because it's no use checking further
+			}
+			Condition &c = *condIter;
+			switch (c.relation) {
+				case r_greater:
+					if (this->parameters.getValue(c.parameter) <= c.value) {
+						conditionsOK = false;
+					}
+					break;
+					case r_greaterEqual:
+					if (this->parameters.getValue(c.parameter) < c.value) {
+						conditionsOK = false;
+					}
+					break;
+					case r_less:
+					if (this->parameters.getValue(c.parameter) >= c.value) {
+						conditionsOK = false;
+					}
+					break;
+					case r_lessEqual:
+					if (this->parameters.getValue(c.parameter) > c.value) {
+						conditionsOK = false;
+					}
+					break;
+					case r_equal:
+					if (this->parameters.getValue(c.parameter) != c.value) {
+						conditionsOK = false;
+					}
+					break;
+					case r_different:
+					if (this->parameters.getValue(c.parameter) == c.value) {
+						conditionsOK = false;
+					}
+					break;
+			}	
+		}
+		if (conditionsOK) {
+			//iterate through each action in subproduction
+			for (int i = 0; i < sp.actions.size(); i++) {
+#if CONV_DEBUG > 1
+				cout << "sp.actions.size(): " << sp.actions.size() << endl;
+#endif
+				Action *action = sp.actions[i].action;
+				vector<SString> strParams = sp.actions[i].params;
+				vector<double> params;
+				//replace parameter names with values
+				for (vector<SString>::iterator paramIter = strParams.begin();
+					 paramIter != strParams.end(); paramIter++) {
+					SString parameter;
+					SString element;
+					int pos = 0;
+					while ((*paramIter).getNextToken(pos, element, ';')) {
+						if (element[0] == 'n') {
+							double val = this->parameters.getValue(element);
+							parameter += SString::valueOf(val) + ";";
+						} else {
+							parameter += element + ";";
+						}
+					}
+					params.push_back(parseExpression(parameter));
+				}
+				
+				ActionP ap;
+				ap.action = action;
+				ap.params = params;
+				l.push_back(ap);
+			}
+		}
+	}
+	
+	return l;
+}
+
+const SString Production::getF8Representation() {
+	return this->name;
+}
+
+
+
+
+
+
+
+
+
+const char* GenoConv_F8ToF1::simpleprods="X[]^RrLlAaCcFfMmSsIiQqWw"; //Ee skipped
+
+
+#define FIELDSTRUCT GenoConv_F8ToF1
+
+static ParamEntry GENOCONVf8param_tab[]=
+{
+{"Genetics: f8: Converter",1,1,},
+{"f8conv_maxlen", 0, 0, "Maximal genotype length", "d 10 10000 500", FIELD(maxF1Length),"Maximal length of the resulting f1 genotype, in characters. If the f8 L-system produces longer f1 genotype, it will be considered incorrect.", },
+{0,},
+};
+
+#undef FIELDSTRUCT
+
+Param GenoConv_F8ToF1::staticpar; 
+
+
+GenoConv_F8ToF1::GenoConv_F8ToF1()
+{
+	name = "Generative encoding";
+	in_format = '8';
+	out_format = '1';
+	mapsupport = 0;
+	maxF1Length = 500;
+        par.setParamTab(GENOCONVf8param_tab);
+       	par.select(this);
+        par.setDefault();
+}
+
+
+vector<SString> GenoConv_F8ToF1::readProductionNames(const SString &in) {
+	vector<SString> names;
+	SString line;
+	int pos = 0;
+	bool afterFirstProd = false;
+	//ParsingStatus status = firstLine;
+	while (in.getNextToken(pos, line, '\n')) {
+#if CONV_DEBUG > 1
+		std::cout << "### Line: " << line << std::endl;
+#endif
+		if (line.startsWith("P") && line.indexOf('(', 0) == -1) {
+			afterFirstProd = true;
+			continue;
+		}
+		if (!afterFirstProd) {
+			continue;
+		}
+		int lParenIndex = line.indexOf('(', 0);
+		if (line.startsWith("P") && lParenIndex != -1) {
+			SString prodName = line.substr(0, lParenIndex);
+#if CONV_DEBUG > 1
+			std::cout << "###Production: " << prodName << std::endl;
+#endif
+			names.push_back(prodName);
+		}
+	}
+	return names;
+}
+
+bool GenoConv_F8ToF1::checkSyntax(const char *geno) {
+	return this->parseInput(geno, NULL);
+}
+
+SString GenoConv_F8ToF1::convert(SString &in, MultiMap *mmap) {
+#if CONV_DEBUG > 0
+	cout << "convert() start" << endl;
+#endif
+	SString dst = "";
+	const char* src = in;
+	
+	if (in.len() < 1 || !this->checkSyntax(src)) {
+		return SString();
+	}
+	
+	Lsystem *lsystem = this->createLsystem(in);
+	if (lsystem == NULL) {
+		return SString();
+	}
+	if (lsystem->firstProductionName.empty()) {
+                delete lsystem;
+		return SString();
+	}
+	
+#if CONV_DEBUG > 0
+	for (map<string, Production*>::iterator i1 = lsystem->productions.begin(); i1 != lsystem->productions.end(); i1++) {
+		Production *p = i1->second;
+		cout << "Production: " << p->name << endl;
+		for (vector<SubProduction>::iterator i2 = p->subproductions.begin(); i2 != p->subproductions.end(); i2++) {
+			SubProduction sp = *i2;
+			cout << "\tConditions" << endl;
+			for (vector<Condition>::iterator i3 = sp.conditions.begin(); i3 != sp.conditions.end(); i3++) {
+				cout << "\t\t" << *i3 << endl;
+			}
+			cout << "\tAction : params" << endl;
+			for (int i = 0; i < sp.actions.size(); i++) {
+				Action *a = sp.actions[i].action;
+				vector<SString> strParams = sp.actions[i].params;
+				cout << "\t\t" << a->name << " : ";
+				for (vector<SString>::iterator i4 = strParams.begin(); i4 != strParams.end(); i4++) {
+					cout << *i4 << ", ";
+				}
+				cout << endl;
+			}
+		}
+	}
+#endif
+#if CONV_DEBUG > 1
+	cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << endl;
+#endif
+	
+	//cout << "convert() 1" << endl;
+	//set parameters for start production
+	Production *firstProduction = lsystem->productions[lsystem->firstProductionName];
+        if (firstProduction==NULL) {
+                delete lsystem;
+                return SString(""); //should never happen because of syntax validation
+        }
+
+	vector<double> params;
+	params.assign(lsystem->startParams.size(), 0.0);
+	//cout << "startParams->size: " << lsystem->startParams.size() << endl;
+	for (map<string, double>::iterator iter = lsystem->startParams.begin();
+		 iter != lsystem->startParams.end(); iter++)
+        {
+		int position = firstProduction->parameters.getParameterPosition(stringToSString(iter->first));
+		//cout << "position of " << iter->first << ": " << position << endl;
+		//params.insert(params.begin() + (position - 1), iter->second); //no need because the vector has required length (assign above)
+                if (position>params.size()) {
+                        delete lsystem;
+                        return SString("");
+                }
+		params[position - 1] = iter->second;
+	}
+	
+	//cout << "convert() 2" << endl;
+	
+	ActionP ap;
+	ap.action = firstProduction;
+	ap.params = params;
+	
+	list<ActionP> actionList;
+	actionList.push_back(ap);
+	
+	//cout << "iterations: " << lsystem->iterations << endl;
+	for (int i = 0; i < lsystem->iterations; i++) {
+		//cout << "convert() 2.1" << endl;
+		list<ActionP> newList;
+		for (list<ActionP>::iterator iter = actionList.begin(); iter != actionList.end(); iter++) {
+			//cout << "convert() 2.1.1" << endl;
+			Action *a = (*iter).action;
+			vector<double> p = (*iter).params;
+			if (a != NULL) {
+				list<ActionP> tmpList = a->getActionList(p);
+				newList.insert(newList.end(), tmpList.begin(), tmpList.end());
+			}
+		}
+		actionList = newList;
+	}
+	
+#if CONV_DEBUG > 1
+	cout << "&&&&&&&&&&&&&&&&&&&&& ^ &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << endl;
+	for (list<ActionP>::iterator it = actionList.begin(); it != actionList.end(); it++) {
+		cout << (*it).action->name << "(";
+		for (vector<double>::iterator it2 = (*it).params.begin(); it2 != (*it).params.end(); it2++) {
+			cout << *it2 << ", ";
+		}
+		cout << ")" << endl;
+	}
+	cout << "&&&&&&&&&&&&&&&&&&&&& ^ &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << endl;
+#endif	
+	for (list<ActionP>::iterator iter = actionList.begin(); iter != actionList.end(); iter++) {
+		Action *a = (*iter).action;
+		vector<double> p = (*iter).params;
+		if (a != NULL) {
+			dst += a->getF1Genotype(p);
+			if (dst.len() > maxF1Length) {
+                                delete lsystem;
+				return SString(); //genotype becomes too long so we abort conversion
+			}
+		}
+	}
+	
+	delete lsystem;
+	
+#if CONV_DEBUG > 0
+	cout << "convert() end" << endl;
+#endif
+	return dst;
+}
+
+//Lsystem* GenoConv_F8ToF1::createLsystem(const SString &in) {
+Lsystem* GenoConv_F8ToF1::createLsystem(SString in) {
+#if CONV_DEBUG > 0
+	cout << "createLsystem() start" << endl;
+#endif
+	Lsystem *lsys = new Lsystem();
+
+	//read production names and create objects for them
+	vector<SString> names = this->readProductionNames(in);
+	for (vector<SString>::iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) {
+		Production *production = new Production();
+		production->name = *nameIter;
+		//lsystem->productions.insert(make_pair(*nameIter, production));
+		lsys->productions[sstringToString(*nameIter)] = production;
+	}
+	
+#if CONV_DEBUG > 1
+	cout << "lsystemprodsize " << lsys->productions.size() << endl;
+	for (map<string, Production*>::iterator iii = lsys->productions.begin(); iii != lsys->productions.end(); iii++) {
+		cout << "PPP '" << iii->first << "' adr " << (long) &(iii->second) << endl;
+	}
+#endif
+	
+	const char* src = in;
+	bool result = this->parseInput(src, lsys);
+	if (!result) {
+		delete lsys;
+		return NULL;
+	}
+	
+#if CONV_DEBUG > 1
+	
+	cout << "@@@@@ Parsed" << endl;
+	
+	cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << endl;
+#endif
+	//final check
+	for (map<string, Production*>::iterator prodIter = lsys->productions.begin();
+		 prodIter != lsys->productions.end(); prodIter++) {
+		for (vector<SubProduction>::iterator subProdIter = prodIter->second->subproductions.begin();
+			 subProdIter != prodIter->second->subproductions.end(); subProdIter++) {
+			SubProduction subProduction = *subProdIter;
+			for (vector<ActionStrP>::iterator i = subProduction.actions.begin();
+				 i != subProduction.actions.end(); /*nothing*/) {
+				if ((*i).action == NULL) {
+					i = subProduction.actions.erase(i);
+				} else {
+					i++;
+				}
+			}
+		}
+	}
+#if CONV_DEBUG > 0
+	cout << "createLsystem() end" << endl;
+#endif
+	return lsys;
+}
+
+bool GenoConv_F8ToF1::parseInput(const char* src, Lsystem* lsys) {
+	//initialize parser
+	int yv;
+	istringstream input;
+	input.str(string(src));
+	ostringstream output;
+	yyFlexLexer scanner(&input, &output);
+	bool syntaxOk = false;
+	void* pParser = prs::ParseAlloc(malloc, lsys, (lsys == NULL), &syntaxOk);
+	struct prs::Token t0;
+	//t0.strValue = "";
+	memset(t0.strArrValue, 0, 30);
+	extern YYSTYPE yylval;
+	
+	//parse input
+	// on EOF yylex will return 0
+	while((yv = scanner.yylex()) != 0) {
+#if CONV_DEBUG > 1
+		cout << " yylex() " << yv << " yylval.strVal " << yylval.strVal << endl;
+#endif
+		memset(t0.strArrValue, 0, 30);
+		sprintf(t0.strArrValue, yylval.strVal);
+		prs::Parse (pParser, yv, t0);
+	}
+	prs::Parse(pParser, 0, t0);
+	prs::ParseFree(pParser, free);
+	
+	return syntaxOk;	
+}
+#undef CONV_DEBUG
+
Index: /cpp/_old/f8-to-f1/conv_f8tof1.h
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1.h	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1.h	(revision 110)
@@ -0,0 +1,258 @@
+/*
+ *  conv_f8tof1.h
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-03-21.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef _CONV_F8_TO_F1_H
+#define _CONV_F8_TO_F1_H
+
+#include <map>
+#include <vector>
+#include <string>
+#include <list>
+#include <iostream>
+#include "genoconv.h"
+#include "model.h"
+
+using std::ostream;
+using std::vector;
+using std::list;
+using std::string;
+using std::map;
+
+enum RelationType {
+	r_greater,
+	r_greaterEqual,
+	r_less,
+	r_lessEqual,
+	r_equal,
+	r_different
+};
+
+class Condition {
+public:
+	RelationType relation;
+	SString parameter;
+	double value;
+	
+	friend ostream& operator<<(ostream& os, const Condition& c);
+};
+
+class ActionP; //only declaration
+
+/// superclass of all actions, e.g. Production, PrimitiveProduction etc.
+class Action {
+public:
+	/// action's name
+	SString name;
+	/// if true action should ignore params passed to it
+	bool ignoreParams;
+	/// gets string representaion of this action in f1 format
+	virtual const SString getF1Genotype(vector<double> params) = 0;
+	/// gets list of actions with double parameters to each of them
+	/// @param params parameters passed to this action
+	virtual const list<ActionP> getActionList(const vector<double> params) = 0;
+	/// gets string representaion of this action in f8 format
+	virtual const SString getF8Representation() = 0;
+	virtual ~Action() {}
+};
+
+/// this class consists of pointer to some action and a list of parameters to that action;
+/// parameters are kept as strings
+class ActionStrP {
+public:
+	Action *action;
+	vector<SString> params;
+};
+
+/// this class consists of pointer to some action and a list of parameters to that action;
+/// parameters are kept as doubles
+class ActionP {
+public:
+	Action *action;
+	vector<double> params;
+};
+
+/// part of production which is used in translation only if all the conditions are met
+class SubProduction {
+public:
+	/// list of conditions necessary to be met
+	vector<Condition> conditions;
+	/// actions with params (as strings)
+	vector<ActionStrP> actions;
+};
+
+/// primitive production; it's directly translated to its f1 equivalent
+/// e.g. X, r, R etc.
+class PrimitiveProduction : public Action {
+public:
+	PrimitiveProduction(const SString command);
+	const SString getF1Genotype(const vector<double> params);
+	const list<ActionP> getActionList(const vector<double> params);
+	const SString getF8Representation();
+protected:
+	SString f1command;
+	SString f8command;
+};
+
+/// param production; all param productions during translation are replaced with the current value of parameter
+/// pointed by this production
+class ParamProduction : public Action {
+public:
+	ParamProduction(const SString paramName);
+	const SString getF1Genotype(const vector<double> params);
+	const list<ActionP> getActionList(const vector<double> params);
+	const SString getF8Representation();
+protected:
+	SString paramName;
+};
+
+/// neuron production; it is directly translated to f1 without any change
+class NeuronProduction : public Action {
+public:
+	NeuronProduction(SString body);
+	const SString getF1Genotype(const vector<double> params);
+	const list<ActionP> getActionList(const vector<double> params);
+	const SString getF8Representation();
+protected:
+	SString body;
+};
+
+/// class which keeps all parameters of a production and enables to access them in convenient way
+/// IMPORTANT! All indices (positions) begins with 1 (not 0)!
+class ParameterCollection {
+public:
+	/// returns parameter's value
+	/// @param position parameter's position (first parameter has an index 1!)
+	const double getValue(int position);
+	/// returns parameter's value
+	/// @param name parameter's name
+	const double getValue(SString name);
+	/// returns parameter's name
+	/// @param position parameter's position (first parameter has an index 1!)
+	const SString getParameterName(int position);
+	/// returns parameter's position (first parameter has an index 1!)
+	/// @param name parameter's name
+	const int getParameterPosition(SString name);
+	/// sets parameter's value
+	/// @param position parameter's position
+	/// @param value parameter's new value
+	void setValue(int position, double value);
+	/// sets parameter's value
+	/// @param name parameter's name
+	/// @param value parameter's new value
+	void setValue(SString name, double value);
+	/// adds parameter
+	/// @param name parameter's name
+	/// @param position desired parameter's position; defualts to -1 which means it will have first available position
+	/// @param value parameter's value; defaults to 0.0
+	void addParameter(SString name, int position = -1, double value = 0.0);
+	/// returns the number of parameters kept in this class
+	const int size();
+	/// removes a parameter
+	/// @param position position of parameter to be deleted
+	void removeParameter(int position);
+	/// removes a parameter
+	/// @param name name of parameter to be deleted
+	void removeParameter(SString name);
+	/// returns true if parameter with given name exists
+	/// @param name parameter's name
+	bool paramExist(SString name);
+protected:
+	vector<string> parameters;
+	map<string, double> paramValues;
+};
+
+/// represents a general rule in L-systems
+/// only "calls" to Production in genotype are replaced in translation procedure
+class Production : public Action {
+public:
+	/// parameters of this production
+	ParameterCollection parameters;
+	/// list of subproductions
+	vector<SubProduction> subproductions;
+	
+	Production();
+	~Production() {};
+	const SString getF1Genotype(const vector<double> params);
+	const list<ActionP> getActionList(const vector<double> params);
+	const SString getF8Representation();
+};
+
+/// Main class that represents a genotype in f8 format
+class Lsystem {
+public:
+	/// number of iterations in f8->f1 translation procedure
+	int iterations;
+	/// map of parameters of start production; key - parameter's name, value - parameter's value
+	map<string, double> startParams;
+	/// map of productions of L-system; key - productions's name, value - pointer to production
+	map<string, Production*> productions;
+	/// collection of neuron productions held in L-system
+	vector<NeuronProduction*> neuronProductions;
+	/// first production's name
+	string firstProductionName;
+	
+	Lsystem();
+	~Lsystem();
+	/// returns a primitive production of a given name
+	/// @param name primitive production's name
+	PrimitiveProduction* getPrimitiveProduction(SString name);
+	/// returns a param production of a given name
+	/// @param name param production's name
+	ParamProduction* getParamProduction(SString name);
+	/// gets string representation of this L-system (f8 genotype)
+	SString toString();
+	/// returns all actions
+	/// @param normal if true all normal actions will be included
+	/// @param primitives if true all primitive actions will be included
+	/// @param params if true all param actions will be included
+	/// @param neurons if true all neuron actions will be included
+	vector<Action*> getAllActions(bool normal, bool primitives, bool params, bool neurons);
+protected:
+	map<string, PrimitiveProduction*> primitiveProductions;
+	map<string, ParamProduction*> paramProductions;
+
+	void removeEmptySubproductionsAndProductions();
+};
+
+
+
+
+
+/// Converter between f8 and f1 format
+class GenoConv_F8ToF1 : public GenoConverter {
+public:
+        Param par;
+        static Param staticpar; //needed to add 'par' to the list of simulator params (this field is initialized externally)
+  
+	GenoConv_F8ToF1();
+	~GenoConv_F8ToF1() {}
+
+	SString convert(SString &in, MultiMap *map);
+
+	/// check syntax of given f8 genotype
+	/// @param geno f8 genotype to be checked
+	bool checkSyntax(const char *geno);
+
+	/// returns names of productions in a given genotype
+	/// @param in f8 genotype
+	vector<SString> readProductionNames(const SString &in);
+	//Lsystem* createLsystem(const SString &in);
+
+	/// creates Lsystem object based on input genotype
+	/// @param f8 genotype
+	Lsystem* createLsystem(SString in);
+
+	int maxF1Length;
+        static const char* simpleprods; 
+
+protected:
+	bool parseInput(const char* src, Lsystem* lsys);
+};
+
+#endif
Index: /cpp/_old/f8-to-f1/conv_f8tof1_grammar.c
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1_grammar.c	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1_grammar.c	(revision 110)
@@ -0,0 +1,1767 @@
+/* Driver template for the LEMON parser generator.
+** The author disclaims copyright to this source code.
+*/
+/* First off, code is include which follows the "include" declaration
+** in the input file. */
+#include <stdio.h>
+#include <assert.h>
+#line 1 "conv_f8tof1_grammar.y"
+
+#include <iostream>
+#include <sstream>
+#include "lemonglobal.h"
+#include "conv_f8tof1.h"
+#include "conv_f8_utils.h"
+#define PARSER_DEBUG 0
+#line 18 "conv_f8tof1_grammar.c"
+/* Next is all token values, in a form suitable for use by makeheaders.
+** This section will be null unless lemon is run with the -m switch.
+*/
+/* 
+** These constants (all generated automatically by the parser generator)
+** specify the various kinds of tokens (terminals) that the parser
+** understands. 
+**
+** Each symbol here is a terminal symbol in the grammar.
+*/
+/* Make sure the INTERFACE macro is defined.
+*/
+#ifndef INTERFACE
+# define INTERFACE 1
+#endif
+/* The next thing included is series of defines which control
+** various aspects of the generated parser.
+**    YYCODETYPE         is the data type used for storing terminal
+**                       and nonterminal numbers.  "unsigned char" is
+**                       used if there are fewer than 250 terminals
+**                       and nonterminals.  "int" is used otherwise.
+**    YYNOCODE           is a number of type YYCODETYPE which corresponds
+**                       to no legal terminal or nonterminal number.  This
+**                       number is used to fill in empty slots of the hash 
+**                       table.
+**    YYFALLBACK         If defined, this indicates that one or more tokens
+**                       have fall-back values which should be used if the
+**                       original value of the token will not parse.
+**    YYACTIONTYPE       is the data type used for storing terminal
+**                       and nonterminal numbers.  "unsigned char" is
+**                       used if there are fewer than 250 rules and
+**                       states combined.  "int" is used otherwise.
+**    ParseTOKENTYPE     is the data type used for minor tokens given 
+**                       directly to the parser from the tokenizer.
+**    YYMINORTYPE        is the data type used for all minor tokens.
+**                       This is typically a union of many types, one of
+**                       which is ParseTOKENTYPE.  The entry in the union
+**                       for base tokens is called "yy0".
+**    YYSTACKDEPTH       is the maximum depth of the parser's stack.  If
+**                       zero the stack is dynamically sized using realloc()
+**    ParseARG_SDECL     A static variable declaration for the %extra_argument
+**    ParseARG_PDECL     A parameter declaration for the %extra_argument
+**    ParseARG_STORE     Code to store %extra_argument into yypParser
+**    ParseARG_FETCH     Code to extract %extra_argument from yypParser
+**    YYNSTATE           the combined number of states.
+**    YYNRULE            the number of rules in the grammar
+**    YYERRORSYMBOL      is the code number of the error symbol.  If not
+**                       defined, then do no error processing.
+*/
+#define YYCODETYPE unsigned char
+#define YYNOCODE 51
+#define YYACTIONTYPE unsigned char
+#define ParseTOKENTYPE Token
+typedef union {
+  ParseTOKENTYPE yy0;
+  ProductionTailToken yy11;
+  Token yy78;
+  ProdPieceToken yy89;
+} YYMINORTYPE;
+#ifndef YYSTACKDEPTH
+#define YYSTACKDEPTH 100
+#endif
+#define ParseARG_SDECL
+#define ParseARG_PDECL
+#define ParseARG_FETCH
+#define ParseARG_STORE
+#define YYNSTATE 91
+#define YYNRULE 47
+#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
+#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
+#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)
+
+/* Next are that tables used to determine what action to take based on the
+** current state and lookahead token.  These tables are used to implement
+** functions that take a state number and lookahead value and return an
+** action integer.  
+**
+** Suppose the action integer is N.  Then the action is determined as
+** follows
+**
+**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
+**                                      token onto the stack and goto state N.
+**
+**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
+**
+**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
+**
+**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
+**
+**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
+**                                      slots in the yy_action[] table.
+**
+** The action table is constructed as a single large table named yy_action[].
+** Given state S and lookahead X, the action is computed as
+**
+**      yy_action[ yy_shift_ofst[S] + X ]
+**
+** If the index value yy_shift_ofst[S]+X is out of range or if the value
+** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+** and that yy_default[S] should be used instead.  
+**
+** The formula above is for computing the action when the lookahead is
+** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
+** a reduce action) then the yy_reduce_ofst[] array is used in place of
+** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
+** YY_SHIFT_USE_DFLT.
+**
+** The following are the tables generated in this section:
+**
+**  yy_action[]        A single table containing all actions.
+**  yy_lookahead[]     A table containing the lookahead for each entry in
+**                     yy_action.  Used to detect hash collisions.
+**  yy_shift_ofst[]    For each state, the offset into yy_action for
+**                     shifting terminals.
+**  yy_reduce_ofst[]   For each state, the offset into yy_action for
+**                     shifting non-terminals after a reduce.
+**  yy_default[]       Default action for each state.
+*/
+static const YYACTIONTYPE yy_action[] = {
+ /*     0 */    46,    4,   23,   24,   26,   27,   22,   28,   85,   61,
+ /*    10 */    31,   62,   43,   56,    4,   40,   37,   83,   76,   66,
+ /*    20 */    63,   69,   71,   31,   72,   43,    9,    4,   40,   37,
+ /*    30 */    83,   76,   47,    4,   69,   71,   70,   14,   43,  139,
+ /*    40 */    17,    4,   70,   59,   43,   51,   66,   69,   71,   57,
+ /*    50 */    70,   52,   43,   69,   71,   38,    4,   58,   15,   11,
+ /*    60 */    84,   69,   71,   19,   61,   70,   62,   43,   12,   13,
+ /*    70 */    15,   11,   44,   89,   30,   34,   69,   71,   16,   48,
+ /*    80 */    75,    5,   76,   91,   66,   72,   73,   74,   12,   13,
+ /*    90 */    15,   11,   61,   20,   62,   65,   66,    6,    1,    2,
+ /*   100 */    65,    7,   42,   33,   35,   54,   10,   39,   41,   10,
+ /*   110 */    39,   41,   61,   49,   62,   68,   61,   61,   62,   62,
+ /*   120 */    61,   88,   62,   33,   67,   65,   66,   36,   32,   25,
+ /*   130 */     8,   64,   52,   18,   16,   48,   86,   55,   29,   53,
+ /*   140 */    60,   87,   90,   81,    3,   77,   78,   45,   21,   79,
+ /*   150 */   140,  140,   80,   82,   50,
+};
+static const YYCODETYPE yy_lookahead[] = {
+ /*     0 */    27,   28,   13,   14,   15,   16,   17,   18,   11,   35,
+ /*    10 */    37,   37,   39,   27,   28,   42,   43,   44,   45,   22,
+ /*    20 */    46,   48,   49,   37,   23,   39,   33,   28,   42,   43,
+ /*    30 */    44,   45,   39,   28,   48,   49,   37,   10,   39,   29,
+ /*    40 */    30,   28,   37,   44,   39,   35,   22,   48,   49,   44,
+ /*    50 */    37,   37,   39,   48,   49,   41,   28,   44,    4,    5,
+ /*    60 */    11,   48,   49,   10,   35,   37,   37,   39,    2,    3,
+ /*    70 */     4,    5,   44,   31,   37,   46,   48,   49,   36,   37,
+ /*    80 */    43,   19,   45,    0,   22,   23,   24,   25,    2,    3,
+ /*    90 */     4,    5,   35,    1,   37,   21,   22,   11,    9,    9,
+ /*   100 */    21,   10,   34,   46,   47,   34,   38,   39,   40,   38,
+ /*   110 */    39,   40,   35,   20,   37,   11,   35,   35,   37,   37,
+ /*   120 */    35,    6,   37,   46,   47,   21,   22,   46,   46,   31,
+ /*   130 */     1,   46,   37,    1,   36,   37,   41,    6,    8,    6,
+ /*   140 */    11,    6,    6,   35,   12,   35,   35,    7,   32,   35,
+ /*   150 */    50,   50,   35,   35,   35,
+};
+#define YY_SHIFT_USE_DFLT (-12)
+#define YY_SHIFT_MAX 52
+static const short yy_shift_ofst[] = {
+ /*     0 */    79,   62,   62,   62,   62,   62,   62,  104,   74,    1,
+ /*    10 */     1,   74,   74,   74,   74,   74,   24,   24,   24,   -3,
+ /*    20 */    24,    1,   79,   79,   79,  140,   79,   79,   79,   79,
+ /*    30 */   -11,  -11,   86,   66,   54,  129,   54,  132,   49,   53,
+ /*    40 */    89,   90,   83,   91,   93,  115,  131,  135,  130,   27,
+ /*    50 */   136,  133,   92,
+};
+#define YY_REDUCE_USE_DFLT (-28)
+#define YY_REDUCE_MAX 29
+static const signed char yy_reduce_ofst[] = {
+ /*     0 */    10,  -14,  -27,    5,   13,   28,   -1,   57,   77,   68,
+ /*    10 */    71,  -26,   29,   81,   82,   85,   42,   98,   37,   14,
+ /*    20 */    95,   -7,  108,  110,  111,  116,  114,  117,  118,  119,
+};
+static const YYACTIONTYPE yy_default[] = {
+ /*     0 */   138,  117,  117,  117,  117,  117,  117,  138,  138,   98,
+ /*    10 */    98,  138,  138,  138,  138,  138,   95,   95,  138,  138,
+ /*    20 */   138,  138,  138,  138,  138,  138,  138,  138,  138,  138,
+ /*    30 */   138,  123,  138,  125,  129,  138,  130,  138,  138,  138,
+ /*    40 */   106,  138,  138,  138,  138,  138,  138,  138,  138,  138,
+ /*    50 */   138,  138,  104,   92,   97,  100,  105,  107,  118,  119,
+ /*    60 */   120,  127,  128,  131,  132,  133,  134,  126,  121,  122,
+ /*    70 */   123,  124,  135,  136,  137,  109,  110,  111,  112,  113,
+ /*    80 */   114,  115,  116,  108,  101,  102,  103,   99,   93,   94,
+ /*    90 */    96,
+};
+#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
+
+/* The next table maps tokens into fallback tokens.  If a construct
+** like the following:
+** 
+**      %fallback ID X Y Z.
+**
+** appears in the grammer, then ID becomes a fallback token for X, Y,
+** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
+** but it does not parse, the type of the token is changed to ID and
+** the parse is retried before an error is thrown.
+*/
+#ifdef YYFALLBACK
+static const YYCODETYPE yyFallback[] = {
+};
+#endif /* YYFALLBACK */
+
+/* The following structure represents a single element of the
+** parser's stack.  Information stored includes:
+**
+**   +  The state number for the parser at this level of the stack.
+**
+**   +  The value of the token stored at this level of the stack.
+**      (In other words, the "major" token.)
+**
+**   +  The semantic value stored at this level of the stack.  This is
+**      the information used by the action routines in the grammar.
+**      It is sometimes called the "minor" token.
+*/
+struct yyStackEntry {
+  int stateno;       /* The state-number */
+  int major;         /* The major token value.  This is the code
+                     ** number for the token at this stack level */
+  YYMINORTYPE minor; /* The user-supplied minor token value.  This
+                     ** is the value of the token  */
+};
+typedef struct yyStackEntry yyStackEntry;
+
+/* The state of the parser is completely contained in an instance of
+** the following structure */
+struct yyParser {
+  int yyidx;                    /* Index of top element in stack */
+  int yyerrcnt;                 /* Shifts left before out of the error */
+  ParseARG_SDECL                /* A place to hold %extra_argument */
+#if YYSTACKDEPTH<=0
+  int yystksz;                  /* Current side of the stack */
+  yyStackEntry *yystack;        /* The parser's stack */
+#else
+  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
+#endif
+};
+typedef struct yyParser yyParser;
+
+#ifndef NDEBUG
+#include <stdio.h>
+static FILE *yyTraceFILE = 0;
+static char *yyTracePrompt = 0;
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* 
+** Turn parser tracing on by giving a stream to which to write the trace
+** and a prompt to preface each trace message.  Tracing is turned off
+** by making either argument NULL 
+**
+** Inputs:
+** <ul>
+** <li> A FILE* to which trace output should be written.
+**      If NULL, then tracing is turned off.
+** <li> A prefix string written at the beginning of every
+**      line of trace output.  If NULL, then tracing is
+**      turned off.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
+  yyTraceFILE = TraceFILE;
+  yyTracePrompt = zTracePrompt;
+  if( yyTraceFILE==0 ) yyTracePrompt = 0;
+  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
+}
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing shifts, the names of all terminals and nonterminals
+** are required.  The following table supplies these names */
+static const char *const yyTokenName[] = { 
+  "$",             "COMMA",         "PLUS",          "MINUS",       
+  "DIV",           "TIMES",         "NEWLINE",       "DELIMETER",   
+  "ASSIGN",        "SEMICOLON",     "LPAREN",        "RPAREN",      
+  "PIPE",          "LESS",          "LESS_EQUAL",    "NOT_EQUAL",   
+  "EQUAL",         "GREATER_EQUAL",  "GREATER",       "FORLOOP_BEGIN",
+  "FORLOOP_END",   "DOUBLE_VAL",    "PARAM_NAME",    "PROD_NAME",   
+  "COMMAND",       "NEURON",        "error",         "production_tail",
+  "prod_piece",    "program",       "counter",       "start_params",
+  "delim",         "first_prod",    "productions",   "double_val",  
+  "start_parameter",  "param_name",    "production",    "prod_name",   
+  "production_head",  "prod_params",   "subproduction",  "conditions",  
+  "real_prod",     "condition",     "single_val",    "multiple_val",
+  "command",       "neuron",      
+};
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing reduce actions, the names of all rules are required.
+*/
+static const char *const yyRuleName[] = {
+ /*   0 */ "program ::= counter start_params delim first_prod productions",
+ /*   1 */ "counter ::= double_val NEWLINE",
+ /*   2 */ "delim ::= DELIMETER NEWLINE",
+ /*   3 */ "start_params ::= start_parameter start_params",
+ /*   4 */ "start_params ::=",
+ /*   5 */ "start_parameter ::= param_name ASSIGN double_val NEWLINE",
+ /*   6 */ "productions ::= production productions",
+ /*   7 */ "productions ::=",
+ /*   8 */ "first_prod ::= prod_name NEWLINE",
+ /*   9 */ "production ::= production_head SEMICOLON production_tail NEWLINE",
+ /*  10 */ "production_head ::= prod_name LPAREN prod_params RPAREN",
+ /*  11 */ "production_head ::= prod_name LPAREN RPAREN",
+ /*  12 */ "prod_params ::= param_name COMMA prod_params",
+ /*  13 */ "prod_params ::= param_name",
+ /*  14 */ "production_tail ::= subproduction SEMICOLON production_tail",
+ /*  15 */ "production_tail ::= subproduction",
+ /*  16 */ "subproduction ::= conditions PIPE real_prod",
+ /*  17 */ "subproduction ::= real_prod",
+ /*  18 */ "conditions ::= conditions COMMA conditions",
+ /*  19 */ "conditions ::= condition",
+ /*  20 */ "condition ::= param_name LESS double_val",
+ /*  21 */ "condition ::= param_name LESS_EQUAL double_val",
+ /*  22 */ "condition ::= param_name NOT_EQUAL double_val",
+ /*  23 */ "condition ::= param_name EQUAL double_val",
+ /*  24 */ "condition ::= param_name GREATER_EQUAL double_val",
+ /*  25 */ "condition ::= param_name GREATER double_val",
+ /*  26 */ "real_prod ::=",
+ /*  27 */ "real_prod ::= prod_piece real_prod",
+ /*  28 */ "real_prod ::= FORLOOP_BEGIN real_prod FORLOOP_END LPAREN single_val RPAREN real_prod",
+ /*  29 */ "prod_piece ::= prod_name LPAREN multiple_val RPAREN",
+ /*  30 */ "prod_piece ::= prod_name LPAREN RPAREN",
+ /*  31 */ "prod_piece ::= command",
+ /*  32 */ "prod_piece ::= param_name",
+ /*  33 */ "prod_piece ::= neuron",
+ /*  34 */ "multiple_val ::= single_val",
+ /*  35 */ "multiple_val ::= multiple_val COMMA multiple_val",
+ /*  36 */ "single_val ::= double_val",
+ /*  37 */ "single_val ::= param_name",
+ /*  38 */ "single_val ::= single_val PLUS single_val",
+ /*  39 */ "single_val ::= single_val MINUS single_val",
+ /*  40 */ "single_val ::= single_val TIMES single_val",
+ /*  41 */ "single_val ::= single_val DIV single_val",
+ /*  42 */ "double_val ::= DOUBLE_VAL",
+ /*  43 */ "param_name ::= PARAM_NAME",
+ /*  44 */ "prod_name ::= PROD_NAME",
+ /*  45 */ "command ::= COMMAND",
+ /*  46 */ "neuron ::= NEURON",
+};
+#endif /* NDEBUG */
+
+
+#if YYSTACKDEPTH<=0
+/*
+** Try to increase the size of the parser stack.
+*/
+static void yyGrowStack(yyParser *p){
+  int newSize;
+  yyStackEntry *pNew;
+
+  newSize = p->yystksz*2 + 100;
+  pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
+  if( pNew ){
+    p->yystack = pNew;
+    p->yystksz = newSize;
+#ifndef NDEBUG
+    if( yyTraceFILE ){
+      fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
+              yyTracePrompt, p->yystksz);
+    }
+#endif
+  }
+}
+#endif
+
+/* MW */
+Lsystem *lsys;
+bool syntaxOnly;
+bool *syntaxOk;
+
+/* 
+** This function allocates a new parser.
+** The only argument is a pointer to a function which works like
+** malloc.
+**
+** Inputs:
+** A pointer to the function used to allocate memory.
+**
+** Outputs:
+** A pointer to a parser.  This pointer is used in subsequent calls
+** to Parse and ParseFree.
+*/
+void *ParseAlloc(void *(*mallocProc)(size_t), Lsystem *lsystem, bool checkSyntaxOnly = false, bool *isSyntaxOk = NULL){
+  yyParser *pParser;
+  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
+  if( pParser ){
+    pParser->yyidx = -1;
+#if YYSTACKDEPTH<=0
+    yyGrowStack(pParser);
+#endif
+	  //input = new Lsystem();
+	  lsys = lsystem;
+	  syntaxOnly = checkSyntaxOnly;
+	  syntaxOk = isSyntaxOk;
+  }
+  return pParser;
+}
+
+/* The following function deletes the value associated with a
+** symbol.  The symbol can be either a terminal or nonterminal.
+** "yymajor" is the symbol code, and "yypminor" is a pointer to
+** the value.
+*/
+static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
+  switch( yymajor ){
+    /* Here is inserted the actions which take place when a
+    ** terminal or non-terminal is destroyed.  This can happen
+    ** when the symbol is popped from the stack during a
+    ** reduce or during error processing or when a parser is 
+    ** being destroyed before it is finished parsing.
+    **
+    ** Note: during a reduce, the only symbols destroyed are those
+    ** which appear on the RHS of the rule, but which are not used
+    ** inside the C code.
+    */
+    default:  break;   /* If no destructor action specified: do nothing */
+  }
+}
+
+/*
+** Pop the parser's stack once.
+**
+** If there is a destructor routine associated with the token which
+** is popped from the stack, then call it.
+**
+** Return the major token number for the symbol popped.
+*/
+static int yy_pop_parser_stack(yyParser *pParser){
+  YYCODETYPE yymajor;
+  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
+
+  if( pParser->yyidx<0 ) return 0;
+#ifndef NDEBUG
+  if( yyTraceFILE && pParser->yyidx>=0 ){
+    fprintf(yyTraceFILE,"%sPopping %s\n",
+      yyTracePrompt,
+      yyTokenName[yytos->major]);
+  }
+#endif
+  yymajor = yytos->major;
+  yy_destructor( yymajor, &yytos->minor);
+  pParser->yyidx--;
+  return yymajor;
+}
+
+/* 
+** Deallocate and destroy a parser.  Destructors are all called for
+** all stack elements before shutting the parser down.
+**
+** Inputs:
+** <ul>
+** <li>  A pointer to the parser.  This should be a pointer
+**       obtained from ParseAlloc.
+** <li>  A pointer to a function used to reclaim memory obtained
+**       from malloc.
+** </ul>
+*/
+void ParseFree(
+  void *p,                    /* The parser to be deleted */
+  void (*freeProc)(void*)     /* Function used to reclaim memory */
+){
+  yyParser *pParser = (yyParser*)p;
+  if( pParser==0 ) return;
+  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
+#if YYSTACKDEPTH<=0
+  free(pParser->yystack);
+#endif
+  (*freeProc)((void*)pParser);
+	//delete lsys;
+}
+
+/*
+** Find the appropriate action for a parser given the terminal
+** look-ahead token iLookAhead.
+**
+** If the look-ahead token is YYNOCODE, then check to see if the action is
+** independent of the look-ahead.  If it is, return the action, otherwise
+** return YY_NO_ACTION.
+*/
+static int yy_find_shift_action(
+  yyParser *pParser,        /* The parser */
+  YYCODETYPE iLookAhead     /* The look-ahead token */
+){
+  int i;
+  int stateno = pParser->yystack[pParser->yyidx].stateno;
+ 
+  if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
+    return yy_default[stateno];
+  }
+  assert( iLookAhead!=YYNOCODE );
+  i += iLookAhead;
+  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
+    if( iLookAhead>0 ){
+#ifdef YYFALLBACK
+      int iFallback;            /* Fallback token */
+      if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
+             && (iFallback = yyFallback[iLookAhead])!=0 ){
+#ifndef NDEBUG
+        if( yyTraceFILE ){
+          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
+             yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+        }
+#endif
+        return yy_find_shift_action(pParser, iFallback);
+      }
+#endif
+#ifdef YYWILDCARD
+      {
+        int j = i - iLookAhead + YYWILDCARD;
+        if( j>=0 && j<YY_SZ_ACTTAB && yy_lookahead[j]==YYWILDCARD ){
+#ifndef NDEBUG
+          if( yyTraceFILE ){
+            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
+               yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
+          }
+#endif /* NDEBUG */
+          return yy_action[j];
+        }
+      }
+#endif /* YYWILDCARD */
+    }
+    return yy_default[stateno];
+  }else{
+    return yy_action[i];
+  }
+}
+
+/*
+** Find the appropriate action for a parser given the non-terminal
+** look-ahead token iLookAhead.
+**
+** If the look-ahead token is YYNOCODE, then check to see if the action is
+** independent of the look-ahead.  If it is, return the action, otherwise
+** return YY_NO_ACTION.
+*/
+static int yy_find_reduce_action(
+  int stateno,              /* Current state number */
+  YYCODETYPE iLookAhead     /* The look-ahead token */
+){
+  int i;
+  assert( stateno<=YY_REDUCE_MAX );
+  i = yy_reduce_ofst[stateno];
+  assert( i!=YY_REDUCE_USE_DFLT );
+  assert( iLookAhead!=YYNOCODE );
+  i += iLookAhead;
+  assert( i>=0 && i<YY_SZ_ACTTAB );
+  assert( yy_lookahead[i]==iLookAhead );
+  return yy_action[i];
+}
+
+/*
+** The following routine is called if the stack overflows.
+*/
+static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
+   ParseARG_FETCH;
+   yypParser->yyidx--;
+#ifndef NDEBUG
+   if( yyTraceFILE ){
+     fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
+   }
+#endif
+   while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+   /* Here code is inserted which will execute if the parser
+   ** stack every overflows */
+   ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
+}
+
+/*
+** Perform a shift action.
+*/
+static void yy_shift(
+  yyParser *yypParser,          /* The parser to be shifted */
+  int yyNewState,               /* The new state to shift in */
+  int yyMajor,                  /* The major token to shift in */
+  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */
+){
+  yyStackEntry *yytos;
+  yypParser->yyidx++;
+#if YYSTACKDEPTH>0 
+  if( yypParser->yyidx>=YYSTACKDEPTH ){
+    yyStackOverflow(yypParser, yypMinor);
+    return;
+  }
+#else
+  if( yypParser->yyidx>=yypParser->yystksz ){
+    yyGrowStack(yypParser);
+    if( yypParser->yyidx>=yypParser->yystksz ){
+      yyStackOverflow(yypParser, yypMinor);
+      return;
+    }
+  }
+#endif
+  yytos = &yypParser->yystack[yypParser->yyidx];
+  yytos->stateno = yyNewState;
+  yytos->major = yyMajor;
+  yytos->minor = *yypMinor;
+#ifndef NDEBUG
+  if( yyTraceFILE && yypParser->yyidx>0 ){
+    int i;
+    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
+    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
+    for(i=1; i<=yypParser->yyidx; i++)
+      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
+    fprintf(yyTraceFILE,"\n");
+  }
+#endif
+}
+
+/* The following table contains information about every rule that
+** is used during the reduce.
+*/
+static const struct {
+  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
+  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
+} yyRuleInfo[] = {
+  { 29, 5 },
+  { 30, 2 },
+  { 32, 2 },
+  { 31, 2 },
+  { 31, 0 },
+  { 36, 4 },
+  { 34, 2 },
+  { 34, 0 },
+  { 33, 2 },
+  { 38, 4 },
+  { 40, 4 },
+  { 40, 3 },
+  { 41, 3 },
+  { 41, 1 },
+  { 27, 3 },
+  { 27, 1 },
+  { 42, 3 },
+  { 42, 1 },
+  { 43, 3 },
+  { 43, 1 },
+  { 45, 3 },
+  { 45, 3 },
+  { 45, 3 },
+  { 45, 3 },
+  { 45, 3 },
+  { 45, 3 },
+  { 44, 0 },
+  { 44, 2 },
+  { 44, 7 },
+  { 28, 4 },
+  { 28, 3 },
+  { 28, 1 },
+  { 28, 1 },
+  { 28, 1 },
+  { 47, 1 },
+  { 47, 3 },
+  { 46, 1 },
+  { 46, 1 },
+  { 46, 3 },
+  { 46, 3 },
+  { 46, 3 },
+  { 46, 3 },
+  { 35, 1 },
+  { 37, 1 },
+  { 39, 1 },
+  { 48, 1 },
+  { 49, 1 },
+};
+
+static void yy_accept(yyParser*);  /* Forward Declaration */
+
+/*
+** Perform a reduce action and the shift that must immediately
+** follow the reduce.
+*/
+static void yy_reduce(
+  yyParser *yypParser,         /* The parser */
+  int yyruleno                 /* Number of the rule by which to reduce */
+){
+  int yygoto;                     /* The next state */
+  int yyact;                      /* The next action */
+  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
+  yyStackEntry *yymsp;            /* The top of the parser's stack */
+  int yysize;                     /* Amount to pop the stack */
+  ParseARG_FETCH;
+  yymsp = &yypParser->yystack[yypParser->yyidx];
+#ifndef NDEBUG
+  if( yyTraceFILE && yyruleno>=0 
+        && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
+    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
+      yyRuleName[yyruleno]);
+  }
+#endif /* NDEBUG */
+
+  /* Silence complaints from purify about yygotominor being uninitialized
+  ** in some cases when it is copied into the stack after the following
+  ** switch.  yygotominor is uninitialized when a rule reduces that does
+  ** not set the value of its left-hand side nonterminal.  Leaving the
+  ** value of the nonterminal uninitialized is utterly harmless as long
+  ** as the value is never used.  So really the only thing this code
+  ** accomplishes is to quieten purify.  
+  **
+  ** 2007-01-16:  The wireshark project (www.wireshark.org) reports that
+  ** without this code, their parser segfaults.  I'm not sure what there
+  ** parser is doing to make this happen.  This is the second bug report
+  ** from wireshark this week.  Clearly they are stressing Lemon in ways
+  ** that it has not been previously stressed...  (SQLite ticket #2172)
+  */
+  memset(&yygotominor, 0, sizeof(yygotominor));
+
+
+  switch( yyruleno ){
+  /* Beginning here are the reduction cases.  A typical example
+  ** follows:
+  **   case 0:
+  **  #line <lineno> <grammarfile>
+  **     { ... }           // User supplied code
+  **  #line <lineno> <thisfile>
+  **     break;
+  */
+      case 0: /* program ::= counter start_params delim first_prod productions */
+#line 18 "conv_f8tof1_grammar.y"
+{
+	*syntaxOk = true;	
+}
+#line 741 "conv_f8tof1_grammar.c"
+        break;
+      case 1: /* counter ::= double_val NEWLINE */
+#line 22 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "counter ::= double_val NEWLINE." << std::endl;
+#endif
+		}
+		lsys->iterations = (int) yymsp[-1].minor.yy78.dblValue; 
+	}
+}
+#line 755 "conv_f8tof1_grammar.c"
+        break;
+      case 2: /* delim ::= DELIMETER NEWLINE */
+      case 3: /* start_params ::= start_parameter start_params */
+      case 4: /* start_params ::= */
+      case 6: /* productions ::= production productions */
+      case 7: /* productions ::= */
+#line 33 "conv_f8tof1_grammar.y"
+{
+}
+#line 765 "conv_f8tof1_grammar.c"
+        break;
+      case 5: /* start_parameter ::= param_name ASSIGN double_val NEWLINE */
+#line 38 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{	
+#if PARSER_DEBUG > 0
+			std::cout << "start_parameter ::= param_name ASSIGN double_val NEWLINE." << std::endl;
+#endif
+		}
+		lsys->startParams[sstringToString(*(yymsp[-3].minor.yy78.strValue))] = yymsp[-1].minor.yy78.dblValue;
+#if PARSER_DEBUG > 0
+		cout << "**** " << lsys->startParams["n0"] << endl;
+		cout << "**** " << lsys->startParams["n1"] << endl;
+#endif
+		delete yymsp[-3].minor.yy78.strValue;
+	}
+}
+#line 784 "conv_f8tof1_grammar.c"
+        break;
+      case 8: /* first_prod ::= prod_name NEWLINE */
+#line 57 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "first_prod ::= prod_name NEWLINE." << std::endl;
+#endif
+		}
+		lsys->firstProductionName = sstringToString(*(yymsp[-1].minor.yy78.strValue));
+		delete yymsp[-1].minor.yy78.strValue;
+	}
+}
+#line 799 "conv_f8tof1_grammar.c"
+        break;
+      case 9: /* production ::= production_head SEMICOLON production_tail NEWLINE */
+#line 69 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production ::= production_head SEMICOLON production_tail NEWLINE." << std::endl;
+#endif
+		}
+		Production *p = lsys->productions[sstringToString(*(yymsp[-3].minor.yy78.strValue))];
+		for (vector<SString>::iterator paramIter = yymsp[-3].minor.yy78.vectorStr->begin(); paramIter != yymsp[-3].minor.yy78.vectorStr->end(); paramIter++) {
+#if PARSER_DEBUG > 0
+			std::cout << "1.1 " << *paramIter << std::endl;
+			std::cout << *(yymsp[-3].minor.yy78.strValue) << " # " << (p == NULL) << " # " << true << std::endl;
+#endif
+			p->parameters.addParameter(*paramIter);
+		}
+		p->subproductions = *(yymsp[-1].minor.yy11.subproductions);
+		delete yymsp[-3].minor.yy78.strValue;
+		delete yymsp[-3].minor.yy78.vectorStr;
+		delete yymsp[-1].minor.yy11.subproductions;
+	}
+}
+#line 824 "conv_f8tof1_grammar.c"
+        break;
+      case 10: /* production_head ::= prod_name LPAREN prod_params RPAREN */
+#line 91 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_head ::= prod_name LPAREN prod_params RPAREN." << std::endl;
+#endif
+		}
+#if PARSER_DEBUG > 0
+		std::cout << "---------" << *(yymsp[-3].minor.yy78.strValue) << std::endl;
+#endif
+		yygotominor.yy78.strValue = new SString(*(yymsp[-3].minor.yy78.strValue));
+		yygotominor.yy78.vectorStr = new vector<SString>(*(yymsp[-1].minor.yy78.vectorStr));
+		delete yymsp[-3].minor.yy78.strValue;
+		delete yymsp[-1].minor.yy78.vectorStr;
+	}
+}
+#line 844 "conv_f8tof1_grammar.c"
+        break;
+      case 11: /* production_head ::= prod_name LPAREN RPAREN */
+#line 107 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_head ::= prod_name LPAREN RPAREN." << std::endl;
+#endif
+		}
+#if PARSER_DEBUG > 0
+		std::cout << "---------" << *(yymsp[-2].minor.yy78.strValue) << std::endl;
+#endif
+		yygotominor.yy78.strValue = new SString(*(yymsp[-2].minor.yy78.strValue));
+		yygotominor.yy78.vectorStr = new vector<SString>();
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 863 "conv_f8tof1_grammar.c"
+        break;
+      case 12: /* prod_params ::= param_name COMMA prod_params */
+#line 123 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_params ::= param_name COMMA prod_params." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorStr = new vector<SString>();
+		yygotominor.yy78.vectorStr->push_back(*(yymsp[-2].minor.yy78.strValue));
+		for (vector<SString>::iterator iter = yymsp[0].minor.yy78.vectorStr->begin(); iter != yymsp[0].minor.yy78.vectorStr->end(); iter++) {
+			yygotominor.yy78.vectorStr->push_back(*iter);
+		}
+		delete yymsp[-2].minor.yy78.strValue;
+		delete yymsp[0].minor.yy78.vectorStr;
+	}
+}
+#line 883 "conv_f8tof1_grammar.c"
+        break;
+      case 13: /* prod_params ::= param_name */
+#line 139 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_params ::= param_name." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorStr = new vector<SString>();
+		yygotominor.yy78.vectorStr->push_back(*(yymsp[0].minor.yy78.strValue));
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 899 "conv_f8tof1_grammar.c"
+        break;
+      case 14: /* production_tail ::= subproduction SEMICOLON production_tail */
+#line 152 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_tail ::= subproduction SEMICOLON production_tail." << std::endl;
+#endif
+		}
+		SubProduction sp;
+		sp.conditions = *(yymsp[-2].minor.yy78.vectorConditions);
+		vector<ActionStrP> actions;
+		actions.reserve(yymsp[-2].minor.yy78.vectorActions->size());
+		for (int i = 0; i < yymsp[-2].minor.yy78.vectorActions->size() && i < yymsp[-2].minor.yy78.parameters->size(); i++) {
+			ActionStrP ap;
+			ap.action = (*(yymsp[-2].minor.yy78.vectorActions)).at(i);
+			ap.params = (*(yymsp[-2].minor.yy78.parameters)).at(i);
+			actions.push_back(ap);
+		}
+		sp.actions = actions;
+		yygotominor.yy11.subproductions = new vector<SubProduction>();
+		yygotominor.yy11.subproductions->push_back(sp);
+		for (vector<SubProduction>::iterator iter = yymsp[0].minor.yy11.subproductions->begin(); iter != yymsp[0].minor.yy11.subproductions->end(); iter++) {
+			yygotominor.yy11.subproductions->push_back(*iter);
+		}
+		delete yymsp[-2].minor.yy78.vectorConditions;
+		delete yymsp[-2].minor.yy78.vectorActions;
+		delete yymsp[-2].minor.yy78.parameters;
+		delete yymsp[0].minor.yy11.subproductions;
+	}
+}
+#line 932 "conv_f8tof1_grammar.c"
+        break;
+      case 15: /* production_tail ::= subproduction */
+#line 181 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_tail ::= subproduction." << std::endl;
+#endif
+		}
+		SubProduction sp;
+		sp.conditions = *(yymsp[0].minor.yy78.vectorConditions);
+		vector<ActionStrP> actions;
+		actions.reserve(yymsp[0].minor.yy78.vectorActions->size());
+		for (int i = 0; i < yymsp[0].minor.yy78.vectorActions->size() && i < yymsp[0].minor.yy78.parameters->size(); i++) {
+			ActionStrP ap;
+			ap.action = (*(yymsp[0].minor.yy78.vectorActions)).at(i);
+			ap.params = (*(yymsp[0].minor.yy78.parameters)).at(i);
+			actions.push_back(ap);
+		}
+		sp.actions = actions;
+		yygotominor.yy11.subproductions = new vector<SubProduction>();
+		yygotominor.yy11.subproductions->push_back(sp);
+		delete yymsp[0].minor.yy78.vectorConditions;
+		delete yymsp[0].minor.yy78.vectorActions;
+		delete yymsp[0].minor.yy78.parameters;
+	}
+}
+#line 961 "conv_f8tof1_grammar.c"
+        break;
+      case 16: /* subproduction ::= conditions PIPE real_prod */
+#line 207 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "subproduction ::= conditions PIPE real_prod." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorConditions = new vector<Condition>(*(yymsp[-2].minor.yy78.vectorConditions));
+		yygotominor.yy78.vectorActions = new vector<Action*>(*(yymsp[0].minor.yy78.vectorActions));
+		yygotominor.yy78.parameters = new vector<vector<SString> >(*(yymsp[0].minor.yy78.parameters));
+		delete yymsp[-2].minor.yy78.vectorConditions;
+		delete yymsp[0].minor.yy78.vectorActions;
+		delete yymsp[0].minor.yy78.parameters;
+	}
+}
+#line 980 "conv_f8tof1_grammar.c"
+        break;
+      case 17: /* subproduction ::= real_prod */
+#line 222 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "subproduction ::= real_prod." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorConditions = new vector<Condition>();
+		yygotominor.yy78.vectorActions = new vector<Action*>(*(yymsp[0].minor.yy78.vectorActions));
+		yygotominor.yy78.parameters = new vector<vector<SString> >(*(yymsp[0].minor.yy78.parameters));
+		delete yymsp[0].minor.yy78.vectorActions;
+		delete yymsp[0].minor.yy78.parameters;
+	}
+}
+#line 998 "conv_f8tof1_grammar.c"
+        break;
+      case 18: /* conditions ::= conditions COMMA conditions */
+#line 237 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "conditions ::= condition COMMA conditions." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorConditions = new vector<Condition>(*(yymsp[-2].minor.yy78.vectorConditions));
+		for (vector<Condition>::iterator iter = yymsp[0].minor.yy78.vectorConditions->begin(); 
+			 iter != yymsp[0].minor.yy78.vectorConditions->end(); iter++) {
+			yygotominor.yy78.vectorConditions->push_back(*iter);
+		}	
+		delete yymsp[-2].minor.yy78.vectorConditions;
+		delete yymsp[0].minor.yy78.vectorConditions;
+	}
+}
+#line 1018 "conv_f8tof1_grammar.c"
+        break;
+      case 19: /* conditions ::= condition */
+#line 253 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "conditions ::= condition." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorConditions = new vector<Condition>();
+		yygotominor.yy78.vectorConditions->push_back(*(yymsp[0].minor.yy78.cond));
+		delete yymsp[0].minor.yy78.cond;
+	}
+}
+#line 1034 "conv_f8tof1_grammar.c"
+        break;
+      case 20: /* condition ::= param_name LESS double_val */
+#line 266 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name LESS double_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.cond = new Condition();
+		yygotominor.yy78.cond->relation = r_less;
+		yygotominor.yy78.cond->parameter = *(yymsp[-2].minor.yy78.strValue);
+		yygotominor.yy78.cond->value = yymsp[0].minor.yy78.dblValue;
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 1052 "conv_f8tof1_grammar.c"
+        break;
+      case 21: /* condition ::= param_name LESS_EQUAL double_val */
+#line 280 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name LESS_EQUAL double_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.cond = new Condition();
+		yygotominor.yy78.cond->relation = r_lessEqual;
+		yygotominor.yy78.cond->parameter = *(yymsp[-2].minor.yy78.strValue);
+		yygotominor.yy78.cond->value = yymsp[0].minor.yy78.dblValue;
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 1070 "conv_f8tof1_grammar.c"
+        break;
+      case 22: /* condition ::= param_name NOT_EQUAL double_val */
+#line 294 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name NOT_EQUAL double_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.cond = new Condition();
+		yygotominor.yy78.cond->relation = r_different;
+		yygotominor.yy78.cond->parameter = *(yymsp[-2].minor.yy78.strValue);
+		yygotominor.yy78.cond->value = yymsp[0].minor.yy78.dblValue;
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 1088 "conv_f8tof1_grammar.c"
+        break;
+      case 23: /* condition ::= param_name EQUAL double_val */
+#line 308 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name EQUAL double_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.cond = new Condition();
+		yygotominor.yy78.cond->relation = r_equal;
+		yygotominor.yy78.cond->parameter = *(yymsp[-2].minor.yy78.strValue);
+		yygotominor.yy78.cond->value = yymsp[0].minor.yy78.dblValue;
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 1106 "conv_f8tof1_grammar.c"
+        break;
+      case 24: /* condition ::= param_name GREATER_EQUAL double_val */
+#line 322 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name GREATER_EQUAL double_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.cond = new Condition();
+		yygotominor.yy78.cond->relation = r_greaterEqual;
+		yygotominor.yy78.cond->parameter = *(yymsp[-2].minor.yy78.strValue);
+		yygotominor.yy78.cond->value = yymsp[0].minor.yy78.dblValue;
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 1124 "conv_f8tof1_grammar.c"
+        break;
+      case 25: /* condition ::= param_name GREATER double_val */
+#line 336 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name GREATER double_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.cond = new Condition();
+		yygotominor.yy78.cond->relation = r_greater;
+		yygotominor.yy78.cond->parameter = *(yymsp[-2].minor.yy78.strValue);
+		yygotominor.yy78.cond->value = yymsp[0].minor.yy78.dblValue;
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 1142 "conv_f8tof1_grammar.c"
+        break;
+      case 26: /* real_prod ::= */
+#line 351 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "real_prod ::= ." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorActions = new vector<Action*>();
+		yygotominor.yy78.parameters = new vector<vector<SString> >();
+	}
+}
+#line 1157 "conv_f8tof1_grammar.c"
+        break;
+      case 27: /* real_prod ::= prod_piece real_prod */
+#line 362 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "real_prod ::= prod_piece real_prod." << std::endl;
+			for (vector<Action*>::iterator actIter = yymsp[-1].minor.yy89.actions->begin(); actIter != yymsp[-1].minor.yy89.actions->end(); actIter++) {
+				cout << "\t" << (*actIter)->name << endl;
+			}
+#endif
+		}
+		//yygotominor.yy78 = yymsp[-1].minor.yy89.clone() && yygotominor.yy78.append(yymsp[0].minor.yy78)
+		yygotominor.yy78.vectorActions = new vector<Action*>(*(yymsp[-1].minor.yy89.actions));
+		yygotominor.yy78.parameters = new vector<vector<SString> >(*(yymsp[-1].minor.yy89.parameters));
+		if (yymsp[0].minor.yy78.vectorActions != NULL && yymsp[0].minor.yy78.parameters != NULL) {
+			for (vector<Action*>::iterator iter = yymsp[0].minor.yy78.vectorActions->begin(); iter != yymsp[0].minor.yy78.vectorActions->end(); iter++) {
+				yygotominor.yy78.vectorActions->push_back(*iter);
+			}
+			for(vector<vector<SString> >::iterator iter = yymsp[0].minor.yy78.parameters->begin(); iter != yymsp[0].minor.yy78.parameters->end(); iter++) {
+				yygotominor.yy78.parameters->push_back(*iter);
+			}
+			delete yymsp[0].minor.yy78.vectorActions;
+			delete yymsp[0].minor.yy78.parameters;
+		} else {
+#if PARSER_DEBUG > 0
+			cout << "\tNULL~~~~~~~~~~~~" << endl;
+#endif
+		}
+		delete yymsp[-1].minor.yy89.actions;
+		delete yymsp[-1].minor.yy89.parameters;
+	}
+}
+#line 1192 "conv_f8tof1_grammar.c"
+        break;
+      case 28: /* real_prod ::= FORLOOP_BEGIN real_prod FORLOOP_END LPAREN single_val RPAREN real_prod */
+#line 393 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "real_prod ::= FORLOOP_BEGIN real_prod FORLOOP_END LPAREN single_val RPAREN." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorActions = new vector<Action*>();
+		yygotominor.yy78.parameters = new vector<vector<SString> >();
+		int iterations = (int) parseExpression(*(yymsp[-2].minor.yy78.strValue));
+		for (int i = 0; i < iterations; i++) {
+			for (vector<Action*>::iterator iter = yymsp[-5].minor.yy78.vectorActions->begin(); iter != yymsp[-5].minor.yy78.vectorActions->end(); iter++) {
+				yygotominor.yy78.vectorActions->push_back(*iter);
+			}
+			for (vector<vector<SString> >::iterator iter = yymsp[-5].minor.yy78.parameters->begin(); iter != yymsp[-5].minor.yy78.parameters->end(); iter++) {
+				yygotominor.yy78.parameters->push_back(*iter);
+			}
+		}
+		for (vector<Action*>::iterator iter = yymsp[0].minor.yy78.vectorActions->begin(); iter != yymsp[0].minor.yy78.vectorActions->end(); iter++) {
+			yygotominor.yy78.vectorActions->push_back(*iter);
+		}
+		for (vector<vector<SString> >::iterator iter = yymsp[0].minor.yy78.parameters->begin(); iter != yymsp[0].minor.yy78.parameters->end(); iter++) {
+			yygotominor.yy78.parameters->push_back(*iter);
+		}
+		delete yymsp[-5].minor.yy78.vectorActions;
+		delete yymsp[-5].minor.yy78.parameters;
+		delete yymsp[-2].minor.yy78.strValue;
+		delete yymsp[0].minor.yy78.vectorActions;
+		delete yymsp[0].minor.yy78.parameters;
+	}
+}
+#line 1227 "conv_f8tof1_grammar.c"
+        break;
+      case 29: /* prod_piece ::= prod_name LPAREN multiple_val RPAREN */
+#line 425 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= prod_name LPAREN multiple_val RPAREN." << std::endl;
+#endif
+		}
+		yygotominor.yy89.actions = new vector<Action*>();
+		yygotominor.yy89.parameters = new vector<vector<SString> >();
+		
+		Production *p = lsys->productions.find(sstringToString(*(yymsp[-3].minor.yy78.strValue)))->second;
+		yygotominor.yy89.actions->push_back(p);
+		yygotominor.yy89.parameters->push_back(*(yymsp[-1].minor.yy78.vectorStr));
+		delete yymsp[-3].minor.yy78.strValue;
+		delete yymsp[-1].minor.yy78.vectorStr;
+	}
+}
+#line 1248 "conv_f8tof1_grammar.c"
+        break;
+      case 30: /* prod_piece ::= prod_name LPAREN RPAREN */
+#line 442 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= prod_name LPAREN RPAREN." << std::endl;
+#endif
+		}
+		yygotominor.yy89.actions = new vector<Action*>();
+		vector<SString> param;
+		yygotominor.yy89.parameters = new vector<vector<SString> >();
+		yygotominor.yy89.parameters->push_back(param);
+		
+		Production *p = lsys->productions.find(sstringToString(*(yymsp[-2].minor.yy78.strValue)))->second;
+		yygotominor.yy89.actions->push_back(p);
+		delete yymsp[-2].minor.yy78.strValue;
+	}
+}
+#line 1269 "conv_f8tof1_grammar.c"
+        break;
+      case 31: /* prod_piece ::= command */
+#line 459 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= command."  << std::endl;
+#endif
+		}
+		yygotominor.yy89.actions = new vector<Action*>();
+		yygotominor.yy89.parameters = new vector<vector<SString> >();
+		PrimitiveProduction *pp = lsys->getPrimitiveProduction(*(yymsp[0].minor.yy78.strValue));
+		yygotominor.yy89.actions->push_back(pp);
+		vector<SString> param;
+		yygotominor.yy89.parameters->push_back(param);
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1289 "conv_f8tof1_grammar.c"
+        break;
+      case 32: /* prod_piece ::= param_name */
+#line 475 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= paramName." << std::endl;
+#endif
+		}
+		yygotominor.yy89.actions = new vector<Action*>();
+		yygotominor.yy89.parameters = new vector<vector<SString> >();
+		ParamProduction *pp = lsys->getParamProduction(*(yymsp[0].minor.yy78.strValue));
+		yygotominor.yy89.actions->push_back(pp);
+		vector<SString> param;
+		param.push_back(*(yymsp[0].minor.yy78.strValue));
+		yygotominor.yy89.parameters->push_back(param);
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1310 "conv_f8tof1_grammar.c"
+        break;
+      case 33: /* prod_piece ::= neuron */
+#line 492 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= neuron." << std::endl;
+#endif
+		}
+		yygotominor.yy89.actions = new vector<Action*>();
+		yygotominor.yy89.parameters = new vector<vector<SString> >();
+		NeuronProduction *np = new NeuronProduction(*(yymsp[0].minor.yy78.strValue));
+		lsys->neuronProductions.push_back(np);
+		yygotominor.yy89.actions->push_back(np);
+		vector<SString> param;
+		yygotominor.yy89.parameters->push_back(param);
+		delete yymsp[0].minor.yy78.strValue;		
+	}
+}
+#line 1331 "conv_f8tof1_grammar.c"
+        break;
+      case 34: /* multiple_val ::= single_val */
+#line 510 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "multiple_val ::= single_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorStr = new vector<SString>();
+		yygotominor.yy78.vectorStr->push_back(SString(*(yymsp[0].minor.yy78.strValue)));
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1347 "conv_f8tof1_grammar.c"
+        break;
+      case 35: /* multiple_val ::= multiple_val COMMA multiple_val */
+#line 522 "conv_f8tof1_grammar.y"
+{
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "multiple_val ::= multiple_val COMMA multiple_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.vectorStr = new vector<SString>();
+		for (vector<SString>::iterator iter = yymsp[-2].minor.yy78.vectorStr->begin(); iter != yymsp[-2].minor.yy78.vectorStr->end(); iter++) {
+			yygotominor.yy78.vectorStr->push_back(*iter);
+		}
+		for (vector<SString>::iterator iter = yymsp[0].minor.yy78.vectorStr->begin(); iter != yymsp[0].minor.yy78.vectorStr->end(); iter++) {
+			yygotominor.yy78.vectorStr->push_back(*iter);
+		}
+		delete yymsp[-2].minor.yy78.vectorStr;
+		delete yymsp[0].minor.yy78.vectorStr;
+	}
+}
+#line 1369 "conv_f8tof1_grammar.c"
+        break;
+      case 36: /* single_val ::= double_val */
+#line 541 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= double_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(SString::valueOf(yymsp[0].minor.yy78.dblValue) + ";");
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1384 "conv_f8tof1_grammar.c"
+        break;
+      case 37: /* single_val ::= param_name */
+#line 552 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= param_name." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(*(yymsp[0].minor.yy78.strValue) + ";");
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1399 "conv_f8tof1_grammar.c"
+        break;
+      case 38: /* single_val ::= single_val PLUS single_val */
+#line 563 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val PLUS single_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(*(yymsp[-2].minor.yy78.strValue) + *(yymsp[0].minor.yy78.strValue) + "+;");
+		delete yymsp[-2].minor.yy78.strValue;
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1415 "conv_f8tof1_grammar.c"
+        break;
+      case 39: /* single_val ::= single_val MINUS single_val */
+#line 575 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val MINUS single_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(*(yymsp[-2].minor.yy78.strValue) + *(yymsp[0].minor.yy78.strValue) + "-;");
+		delete yymsp[-2].minor.yy78.strValue;
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1431 "conv_f8tof1_grammar.c"
+        break;
+      case 40: /* single_val ::= single_val TIMES single_val */
+#line 587 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val TIMES single_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(*(yymsp[-2].minor.yy78.strValue) + *(yymsp[0].minor.yy78.strValue) + "*;");
+		delete yymsp[-2].minor.yy78.strValue;
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1447 "conv_f8tof1_grammar.c"
+        break;
+      case 41: /* single_val ::= single_val DIV single_val */
+#line 599 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val DIV single_val." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(*(yymsp[-2].minor.yy78.strValue) + *(yymsp[0].minor.yy78.strValue) + "/;");
+		delete yymsp[-2].minor.yy78.strValue;
+		delete yymsp[0].minor.yy78.strValue;
+	}
+}
+#line 1463 "conv_f8tof1_grammar.c"
+        break;
+      case 42: /* double_val ::= DOUBLE_VAL */
+#line 612 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "double_val ::= DOUBLE_VAL. -> " << (string(yymsp[0].minor.yy0.strArrValue)).c_str() << std::endl;
+#endif
+		}
+		yygotominor.yy78.dblValue = atof((string(yymsp[0].minor.yy0.strArrValue)).c_str()); 
+	}
+}
+#line 1477 "conv_f8tof1_grammar.c"
+        break;
+      case 43: /* param_name ::= PARAM_NAME */
+#line 622 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "param_name ::= PARAM_NAME." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(string(yymsp[0].minor.yy0.strArrValue).c_str());
+	}
+}
+#line 1491 "conv_f8tof1_grammar.c"
+        break;
+      case 44: /* prod_name ::= PROD_NAME */
+#line 632 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_name ::= PROD_NAME." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(string(yymsp[0].minor.yy0.strArrValue).c_str());
+	}
+}
+#line 1505 "conv_f8tof1_grammar.c"
+        break;
+      case 45: /* command ::= COMMAND */
+#line 642 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "command ::= COMMAND." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(string(yymsp[0].minor.yy0.strArrValue).c_str()); 
+	}
+}
+#line 1519 "conv_f8tof1_grammar.c"
+        break;
+      case 46: /* neuron ::= NEURON */
+#line 652 "conv_f8tof1_grammar.y"
+{ 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "neuron ::= NEURON." << std::endl;
+#endif
+		}
+		yygotominor.yy78.strValue = new SString(string(yymsp[0].minor.yy0.strArrValue).c_str()); 
+	}
+}
+#line 1533 "conv_f8tof1_grammar.c"
+        break;
+  };
+  yygoto = yyRuleInfo[yyruleno].lhs;
+  yysize = yyRuleInfo[yyruleno].nrhs;
+  yypParser->yyidx -= yysize;
+  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto);
+  if( yyact < YYNSTATE ){
+#ifdef NDEBUG
+    /* If we are not debugging and the reduce action popped at least
+    ** one element off the stack, then we can push the new element back
+    ** onto the stack here, and skip the stack overflow test in yy_shift().
+    ** That gives a significant speed improvement. */
+    if( yysize ){
+      yypParser->yyidx++;
+      yymsp -= yysize-1;
+      yymsp->stateno = yyact;
+      yymsp->major = yygoto;
+      yymsp->minor = yygotominor;
+    }else
+#endif
+    {
+      yy_shift(yypParser,yyact,yygoto,&yygotominor);
+    }
+  }else{
+    assert( yyact == YYNSTATE + YYNRULE + 1 );
+    yy_accept(yypParser);
+  }
+}
+
+/*
+** The following code executes when the parse fails
+*/
+static void yy_parse_failed(
+  yyParser *yypParser           /* The parser */
+){
+  ParseARG_FETCH;
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
+  }
+#endif
+  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+  /* Here code is inserted which will be executed whenever the
+  ** parser fails */
+  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/*
+** The following code executes when a syntax error first occurs.
+*/
+static void yy_syntax_error(
+  yyParser *yypParser,           /* The parser */
+  int yymajor,                   /* The major type of the error token */
+  YYMINORTYPE yyminor            /* The minor type of the error token */
+){
+  ParseARG_FETCH;
+#define TOKEN (yyminor.yy0)
+  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/*
+** The following is executed when the parser accepts
+*/
+static void yy_accept(
+  yyParser *yypParser           /* The parser */
+){
+  ParseARG_FETCH;
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
+  }
+#endif
+  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+  /* Here code is inserted which will be executed whenever the
+  ** parser accepts */
+  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/* The main parser program.
+** The first argument is a pointer to a structure obtained from
+** "ParseAlloc" which describes the current state of the parser.
+** The second argument is the major token number.  The third is
+** the minor token.  The fourth optional argument is whatever the
+** user wants (and specified in the grammar) and is available for
+** use by the action routines.
+**
+** Inputs:
+** <ul>
+** <li> A pointer to the parser (an opaque structure.)
+** <li> The major token number.
+** <li> The minor token number.
+** <li> An option argument of a grammar-specified type.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void Parse(
+  void *yyp,                   /* The parser */
+  int yymajor,                 /* The major token code number */
+  ParseTOKENTYPE yyminor       /* The value for the token */
+  ParseARG_PDECL               /* Optional %extra_argument parameter */
+){
+  YYMINORTYPE yyminorunion;
+  int yyact;            /* The parser action. */
+  int yyendofinput;     /* True if we are at the end of input */
+#ifdef YYERRORSYMBOL
+  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
+#endif
+  yyParser *yypParser;  /* The parser */
+
+  /* (re)initialize the parser, if necessary */
+  yypParser = (yyParser*)yyp;
+  if( yypParser->yyidx<0 ){
+#if YYSTACKDEPTH<=0
+    if( yypParser->yystksz <=0 ){
+      memset(&yyminorunion, 0, sizeof(yyminorunion));
+      yyStackOverflow(yypParser, &yyminorunion);
+      return;
+    }
+#endif
+    yypParser->yyidx = 0;
+    yypParser->yyerrcnt = -1;
+    yypParser->yystack[0].stateno = 0;
+    yypParser->yystack[0].major = 0;
+  }
+  yyminorunion.yy0 = yyminor;
+  yyendofinput = (yymajor==0);
+  ParseARG_STORE;
+
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
+  }
+#endif
+
+  do{
+    yyact = yy_find_shift_action(yypParser,yymajor);
+    if( yyact<YYNSTATE ){
+      assert( !yyendofinput );  /* Impossible to shift the $ token */
+      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
+      yypParser->yyerrcnt--;
+      yymajor = YYNOCODE;
+    }else if( yyact < YYNSTATE + YYNRULE ){
+      yy_reduce(yypParser,yyact-YYNSTATE);
+    }else{
+      assert( yyact == YY_ERROR_ACTION );
+#ifdef YYERRORSYMBOL
+      int yymx;
+#endif
+#ifndef NDEBUG
+      if( yyTraceFILE ){
+        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
+      }
+#endif
+#ifdef YYERRORSYMBOL
+      /* A syntax error has occurred.
+      ** The response to an error depends upon whether or not the
+      ** grammar defines an error token "ERROR".  
+      **
+      ** This is what we do if the grammar does define ERROR:
+      **
+      **  * Call the %syntax_error function.
+      **
+      **  * Begin popping the stack until we enter a state where
+      **    it is legal to shift the error symbol, then shift
+      **    the error symbol.
+      **
+      **  * Set the error count to three.
+      **
+      **  * Begin accepting and shifting new tokens.  No new error
+      **    processing will occur until three tokens have been
+      **    shifted successfully.
+      **
+      */
+      if( yypParser->yyerrcnt<0 ){
+        yy_syntax_error(yypParser,yymajor,yyminorunion);
+      }
+      yymx = yypParser->yystack[yypParser->yyidx].major;
+      if( yymx==YYERRORSYMBOL || yyerrorhit ){
+#ifndef NDEBUG
+        if( yyTraceFILE ){
+          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
+             yyTracePrompt,yyTokenName[yymajor]);
+        }
+#endif
+        yy_destructor(yymajor,&yyminorunion);
+        yymajor = YYNOCODE;
+      }else{
+         while(
+          yypParser->yyidx >= 0 &&
+          yymx != YYERRORSYMBOL &&
+          (yyact = yy_find_reduce_action(
+                        yypParser->yystack[yypParser->yyidx].stateno,
+                        YYERRORSYMBOL)) >= YYNSTATE
+        ){
+          yy_pop_parser_stack(yypParser);
+        }
+        if( yypParser->yyidx < 0 || yymajor==0 ){
+          yy_destructor(yymajor,&yyminorunion);
+          yy_parse_failed(yypParser);
+          yymajor = YYNOCODE;
+        }else if( yymx!=YYERRORSYMBOL ){
+          YYMINORTYPE u2;
+          u2.YYERRSYMDT = 0;
+          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
+        }
+      }
+      yypParser->yyerrcnt = 3;
+      yyerrorhit = 1;
+#else  /* YYERRORSYMBOL is not defined */
+      /* This is what we do if the grammar does not define ERROR:
+      **
+      **  * Report an error message, and throw away the input token.
+      **
+      **  * If the input token is $, then fail the parse.
+      **
+      ** As before, subsequent error messages are suppressed until
+      ** three input tokens have been successfully shifted.
+      */
+      if( yypParser->yyerrcnt<=0 ){
+        yy_syntax_error(yypParser,yymajor,yyminorunion);
+      }
+      yypParser->yyerrcnt = 3;
+      yy_destructor(yymajor,&yyminorunion);
+      if( yyendofinput ){
+        yy_parse_failed(yypParser);
+      }
+      yymajor = YYNOCODE;
+#endif
+    }
+  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
+  return;
+}
+
+
Index: /cpp/_old/f8-to-f1/conv_f8tof1_grammar.h
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1_grammar.h	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1_grammar.h	(revision 110)
@@ -0,0 +1,25 @@
+#define COMMA                           1
+#define PLUS                            2
+#define MINUS                           3
+#define DIV                             4
+#define TIMES                           5
+#define NEWLINE                         6
+#define DELIMETER                       7
+#define ASSIGN                          8
+#define SEMICOLON                       9
+#define LPAREN                         10
+#define RPAREN                         11
+#define PIPE                           12
+#define LESS                           13
+#define LESS_EQUAL                     14
+#define NOT_EQUAL                      15
+#define EQUAL                          16
+#define GREATER_EQUAL                  17
+#define GREATER                        18
+#define FORLOOP_BEGIN                  19
+#define FORLOOP_END                    20
+#define DOUBLE_VAL                     21
+#define PARAM_NAME                     22
+#define PROD_NAME                      23
+#define COMMAND                        24
+#define NEURON                         25
Index: /cpp/_old/f8-to-f1/conv_f8tof1_grammar.y
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1_grammar.y	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1_grammar.y	(revision 110)
@@ -0,0 +1,662 @@
+%include {
+#include <iostream>
+#include <sstream>
+#include "lemonglobal.h"
+#include "conv_f8tof1.h"
+#include "conv_f8_utils.h"
+#define PARSER_DEBUG 0
+}
+%token_type {Token}
+%default_type {Token}
+%type production_tail {ProductionTailToken}
+%type prod_piece {ProdPieceToken}
+
+%left COMMA.
+%left PLUS MINUS.
+%left DIV TIMES.
+
+program ::= counter start_params delim first_prod productions. {
+	*syntaxOk = true;	
+}
+
+counter ::= double_val(A) NEWLINE. {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "counter ::= double_val NEWLINE." << std::endl;
+#endif
+		}
+		lsys->iterations = (int) A.dblValue; 
+	}
+}
+			
+delim ::= DELIMETER NEWLINE.
+
+start_params ::= start_parameter start_params.
+start_params ::= .
+
+start_parameter ::= param_name(A) ASSIGN double_val(B) NEWLINE. { 
+	if (!syntaxOnly) {
+		{	
+#if PARSER_DEBUG > 0
+			std::cout << "start_parameter ::= param_name ASSIGN double_val NEWLINE." << std::endl;
+#endif
+		}
+		lsys->startParams[sstringToString(*(A.strValue))] = B.dblValue;
+#if PARSER_DEBUG > 0
+		//cout << "**** " << lsys->startParams["n0"] << endl;
+		//cout << "**** " << lsys->startParams["n1"] << endl;
+#endif
+		delete A.strValue;
+	}
+}
+
+productions ::= production productions_others. 
+productions_others ::= production productions_others. 
+productions_others ::= .
+
+first_prod ::= prod_name(A) NEWLINE. { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "first_prod ::= prod_name NEWLINE." << std::endl;
+#endif
+		}
+		lsys->firstProductionName = sstringToString(*(A.strValue));
+		delete A.strValue;
+	}
+}
+
+production ::= production_head(A) SEMICOLON production_tail(B) NEWLINE. { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production ::= production_head SEMICOLON production_tail NEWLINE." << std::endl;
+#endif
+		}
+		Production *p = lsys->productions[sstringToString(*(A.strValue))];
+		for (vector<SString>::iterator paramIter = A.vectorStr->begin(); paramIter != A.vectorStr->end(); paramIter++) {
+#if PARSER_DEBUG > 0
+			std::cout << "1.1 " << *paramIter << std::endl;
+			std::cout << *(A.strValue) << " # " << (p == NULL) << " # " << true << std::endl;
+#endif
+			p->parameters.addParameter(*paramIter);
+		}
+		p->subproductions = *(B.subproductions);
+		delete A.strValue;
+		delete A.vectorStr;
+		delete B.subproductions;
+	}
+}
+
+production_head(A) ::= prod_name(B) LPAREN prod_params(C) RPAREN. {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_head ::= prod_name LPAREN prod_params RPAREN." << std::endl;
+#endif
+		}
+#if PARSER_DEBUG > 0
+		std::cout << "---------" << *(B.strValue) << std::endl;
+#endif
+		A.strValue = new SString(*(B.strValue));
+		A.vectorStr = new vector<SString>(*(C.vectorStr));
+		delete B.strValue;
+		delete C.vectorStr;
+	}
+}
+production_head(A) ::= prod_name(B) LPAREN RPAREN. {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_head ::= prod_name LPAREN RPAREN." << std::endl;
+#endif
+		}
+#if PARSER_DEBUG > 0
+		std::cout << "---------" << *(B.strValue) << std::endl;
+#endif
+		A.strValue = new SString(*(B.strValue));
+		A.vectorStr = new vector<SString>();
+		delete B.strValue;
+	}
+}
+
+prod_params(A) ::= param_name(B) COMMA prod_params(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_params ::= param_name COMMA prod_params." << std::endl;
+#endif
+		}
+		A.vectorStr = new vector<SString>();
+		A.vectorStr->push_back(*(B.strValue));
+		for (vector<SString>::iterator iter = C.vectorStr->begin(); iter != C.vectorStr->end(); iter++) {
+			A.vectorStr->push_back(*iter);
+		}
+		delete B.strValue;
+		delete C.vectorStr;
+	}
+}
+prod_params(A) ::= param_name(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_params ::= param_name." << std::endl;
+#endif
+		}
+		A.vectorStr = new vector<SString>();
+		A.vectorStr->push_back(*(B.strValue));
+		delete B.strValue;
+	}
+}
+
+production_tail(A) ::= subproduction(B) SEMICOLON production_tail(C). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_tail ::= subproduction SEMICOLON production_tail." << std::endl;
+#endif
+		}
+		SubProduction sp;
+		sp.conditions = *(B.vectorConditions);
+		vector<ActionStrP> actions;
+		actions.reserve(B.vectorActions->size());
+		for (int i = 0; i < B.vectorActions->size() && i < B.parameters->size(); i++) {
+			ActionStrP ap;
+			ap.action = (*(B.vectorActions)).at(i);
+			ap.params = (*(B.parameters)).at(i);
+			actions.push_back(ap);
+		}
+		sp.actions = actions;
+		A.subproductions = new vector<SubProduction>();
+		A.subproductions->push_back(sp);
+		for (vector<SubProduction>::iterator iter = C.subproductions->begin(); iter != C.subproductions->end(); iter++) {
+			A.subproductions->push_back(*iter);
+		}
+		delete B.vectorConditions;
+		delete B.vectorActions;
+		delete B.parameters;
+		delete C.subproductions;
+	}
+}
+production_tail(A) ::= subproduction(B). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "production_tail ::= subproduction." << std::endl;
+#endif
+		}
+		SubProduction sp;
+		sp.conditions = *(B.vectorConditions);
+		vector<ActionStrP> actions;
+		actions.reserve(B.vectorActions->size());
+		for (int i = 0; i < B.vectorActions->size() && i < B.parameters->size(); i++) {
+			ActionStrP ap;
+			ap.action = (*(B.vectorActions)).at(i);
+			ap.params = (*(B.parameters)).at(i);
+			actions.push_back(ap);
+		}
+		sp.actions = actions;
+		A.subproductions = new vector<SubProduction>();
+		A.subproductions->push_back(sp);
+		delete B.vectorConditions;
+		delete B.vectorActions;
+		delete B.parameters;
+	}
+}
+
+subproduction(A) ::= conditions(B) PIPE real_prod(C). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "subproduction ::= conditions PIPE real_prod." << std::endl;
+#endif
+		}
+		A.vectorConditions = new vector<Condition>(*(B.vectorConditions));
+		A.vectorActions = new vector<Action*>(*(C.vectorActions));
+		A.parameters = new vector<vector<SString> >(*(C.parameters));
+		delete B.vectorConditions;
+		delete C.vectorActions;
+		delete C.parameters;
+	}
+}
+subproduction(A) ::= real_prod(C). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "subproduction ::= real_prod." << std::endl;
+#endif
+		}
+		A.vectorConditions = new vector<Condition>();
+		A.vectorActions = new vector<Action*>(*(C.vectorActions));
+		A.parameters = new vector<vector<SString> >(*(C.parameters));
+		delete C.vectorActions;
+		delete C.parameters;
+	}
+}
+
+conditions(A) ::= conditions(B) COMMA conditions(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "conditions ::= condition COMMA conditions." << std::endl;
+#endif
+		}
+		A.vectorConditions = new vector<Condition>(*(B.vectorConditions));
+		for (vector<Condition>::iterator iter = C.vectorConditions->begin(); 
+			 iter != C.vectorConditions->end(); iter++) {
+			A.vectorConditions->push_back(*iter);
+		}	
+		delete B.vectorConditions;
+		delete C.vectorConditions;
+	}
+}
+conditions(A) ::= condition(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "conditions ::= condition." << std::endl;
+#endif
+		}
+		A.vectorConditions = new vector<Condition>();
+		A.vectorConditions->push_back(*(B.cond));
+		delete B.cond;
+	}
+}
+
+condition(A) ::= param_name(B) LESS double_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name LESS double_val." << std::endl;
+#endif
+		}
+		A.cond = new Condition();
+		A.cond->relation = r_less;
+		A.cond->parameter = *(B.strValue);
+		A.cond->value = C.dblValue;
+		delete B.strValue;
+	}
+}
+condition(A) ::= param_name(B) LESS_EQUAL double_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name LESS_EQUAL double_val." << std::endl;
+#endif
+		}
+		A.cond = new Condition();
+		A.cond->relation = r_lessEqual;
+		A.cond->parameter = *(B.strValue);
+		A.cond->value = C.dblValue;
+		delete B.strValue;
+	}
+}
+condition(A) ::= param_name(B) NOT_EQUAL double_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name NOT_EQUAL double_val." << std::endl;
+#endif
+		}
+		A.cond = new Condition();
+		A.cond->relation = r_different;
+		A.cond->parameter = *(B.strValue);
+		A.cond->value = C.dblValue;
+		delete B.strValue;
+	}
+}
+condition(A) ::= param_name(B) EQUAL double_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name EQUAL double_val." << std::endl;
+#endif
+		}
+		A.cond = new Condition();
+		A.cond->relation = r_equal;
+		A.cond->parameter = *(B.strValue);
+		A.cond->value = C.dblValue;
+		delete B.strValue;
+	}
+}
+condition(A) ::= param_name(B) GREATER_EQUAL double_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name GREATER_EQUAL double_val." << std::endl;
+#endif
+		}
+		A.cond = new Condition();
+		A.cond->relation = r_greaterEqual;
+		A.cond->parameter = *(B.strValue);
+		A.cond->value = C.dblValue;
+		delete B.strValue;
+	}
+}
+condition(A) ::= param_name(B) GREATER double_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "condition ::= param_name GREATER double_val." << std::endl;
+#endif
+		}
+		A.cond = new Condition();
+		A.cond->relation = r_greater;
+		A.cond->parameter = *(B.strValue);
+		A.cond->value = C.dblValue;
+		delete B.strValue;
+	}
+}
+
+real_prod(A) ::= . {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "real_prod ::= ." << std::endl;
+#endif
+		}
+		A.vectorActions = new vector<Action*>();
+		A.parameters = new vector<vector<SString> >();
+	}
+}
+real_prod(A) ::= prod_piece(B) real_prod(C). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "real_prod ::= prod_piece real_prod." << std::endl;
+			for (vector<Action*>::iterator actIter = B.actions->begin(); actIter != B.actions->end(); actIter++) {
+				cout << "\t" << (*actIter)->name << endl;
+			}
+#endif
+		}
+		//A = B.clone() && A.append(C)
+		A.vectorActions = new vector<Action*>(*(B.actions));
+		A.parameters = new vector<vector<SString> >(*(B.parameters));
+		if (C.vectorActions != NULL && C.parameters != NULL) {
+			for (vector<Action*>::iterator iter = C.vectorActions->begin(); iter != C.vectorActions->end(); iter++) {
+				A.vectorActions->push_back(*iter);
+			}
+			for(vector<vector<SString> >::iterator iter = C.parameters->begin(); iter != C.parameters->end(); iter++) {
+				A.parameters->push_back(*iter);
+			}
+			delete C.vectorActions;
+			delete C.parameters;
+		} else {
+#if PARSER_DEBUG > 0
+			cout << "\tNULL~~~~~~~~~~~~" << endl;
+#endif
+		}
+		delete B.actions;
+		delete B.parameters;
+	}
+}
+real_prod(A) ::= FORLOOP_BEGIN real_prod(B) FORLOOP_END LPAREN single_val(C) RPAREN real_prod(D). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "real_prod ::= FORLOOP_BEGIN real_prod FORLOOP_END LPAREN single_val RPAREN." << std::endl;
+#endif
+		}
+		A.vectorActions = new vector<Action*>();
+		A.parameters = new vector<vector<SString> >();
+		int iterations = (int) parseExpression(*(C.strValue));
+		for (int i = 0; i < iterations; i++) {
+			for (vector<Action*>::iterator iter = B.vectorActions->begin(); iter != B.vectorActions->end(); iter++) {
+				A.vectorActions->push_back(*iter);
+			}
+			for (vector<vector<SString> >::iterator iter = B.parameters->begin(); iter != B.parameters->end(); iter++) {
+				A.parameters->push_back(*iter);
+			}
+		}
+		for (vector<Action*>::iterator iter = D.vectorActions->begin(); iter != D.vectorActions->end(); iter++) {
+			A.vectorActions->push_back(*iter);
+		}
+		for (vector<vector<SString> >::iterator iter = D.parameters->begin(); iter != D.parameters->end(); iter++) {
+			A.parameters->push_back(*iter);
+		}
+		delete B.vectorActions;
+		delete B.parameters;
+		delete C.strValue;
+		delete D.vectorActions;
+		delete D.parameters;
+	}
+}
+
+prod_piece(A) ::= prod_name(B) LPAREN multiple_val(C) RPAREN. {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= prod_name LPAREN multiple_val RPAREN." << std::endl;
+#endif
+		}
+		A.actions = new vector<Action*>();
+		A.parameters = new vector<vector<SString> >();
+		
+		Production *p = lsys->productions.find(sstringToString(*(B.strValue)))->second;
+		A.actions->push_back(p);
+		A.parameters->push_back(*(C.vectorStr));
+		delete B.strValue;
+		delete C.vectorStr;
+	}
+}
+prod_piece(A) ::= prod_name(B) LPAREN RPAREN. {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= prod_name LPAREN RPAREN." << std::endl;
+#endif
+		}
+		A.actions = new vector<Action*>();
+		vector<SString> param;
+		A.parameters = new vector<vector<SString> >();
+		A.parameters->push_back(param);
+		
+		Production *p = lsys->productions.find(sstringToString(*(B.strValue)))->second;
+		A.actions->push_back(p);
+		delete B.strValue;
+	}
+}
+prod_piece(A) ::= command(B). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= command."  << std::endl;
+#endif
+		}
+		A.actions = new vector<Action*>();
+		A.parameters = new vector<vector<SString> >();
+		PrimitiveProduction *pp = lsys->getPrimitiveProduction(*(B.strValue));
+		A.actions->push_back(pp);
+		vector<SString> param;
+		A.parameters->push_back(param);
+		delete B.strValue;
+	}
+}
+prod_piece(A) ::= param_name(B). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= paramName." << std::endl;
+#endif
+		}
+		A.actions = new vector<Action*>();
+		A.parameters = new vector<vector<SString> >();
+		ParamProduction *pp = lsys->getParamProduction(*(B.strValue));
+		A.actions->push_back(pp);
+		vector<SString> param;
+		param.push_back(*(B.strValue));
+		A.parameters->push_back(param);
+		delete B.strValue;
+	}
+}
+prod_piece(A) ::= neuron(B). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_piece ::= neuron." << std::endl;
+#endif
+		}
+		A.actions = new vector<Action*>();
+		A.parameters = new vector<vector<SString> >();
+		NeuronProduction *np = new NeuronProduction(*(B.strValue));
+		lsys->neuronProductions.push_back(np);
+		A.actions->push_back(np);
+		vector<SString> param;
+		A.parameters->push_back(param);
+		delete B.strValue;		
+	}
+}
+
+multiple_val(A) ::= single_val(B). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "multiple_val ::= single_val." << std::endl;
+#endif
+		}
+		A.vectorStr = new vector<SString>();
+		A.vectorStr->push_back(SString(*(B.strValue)));
+		delete B.strValue;
+	}
+}
+multiple_val(A) ::= multiple_val(B) COMMA multiple_val(C). {
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "multiple_val ::= multiple_val COMMA multiple_val." << std::endl;
+#endif
+		}
+		A.vectorStr = new vector<SString>();
+		for (vector<SString>::iterator iter = B.vectorStr->begin(); iter != B.vectorStr->end(); iter++) {
+			A.vectorStr->push_back(*iter);
+		}
+		for (vector<SString>::iterator iter = C.vectorStr->begin(); iter != C.vectorStr->end(); iter++) {
+			A.vectorStr->push_back(*iter);
+		}
+		delete B.vectorStr;
+		delete C.vectorStr;
+	}
+}
+
+single_val(A) ::= double_val(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= double_val." << std::endl;
+#endif
+		}
+		A.strValue = new SString(SString::valueOf(B.dblValue) + ";");
+		delete B.strValue;
+	}
+}
+single_val(A) ::= param_name(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= param_name." << std::endl;
+#endif
+		}
+		A.strValue = new SString(*(B.strValue) + ";");
+		delete B.strValue;
+	}
+}
+single_val(A) ::= single_val(B) PLUS single_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val PLUS single_val." << std::endl;
+#endif
+		}
+		A.strValue = new SString(*(B.strValue) + *(C.strValue) + "+;");
+		delete B.strValue;
+		delete C.strValue;
+	}
+}
+single_val(A) ::= single_val(B) MINUS single_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val MINUS single_val." << std::endl;
+#endif
+		}
+		A.strValue = new SString(*(B.strValue) + *(C.strValue) + "-;");
+		delete B.strValue;
+		delete C.strValue;
+	}
+}
+single_val(A) ::= single_val(B) TIMES single_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val TIMES single_val." << std::endl;
+#endif
+		}
+		A.strValue = new SString(*(B.strValue) + *(C.strValue) + "*;");
+		delete B.strValue;
+		delete C.strValue;
+	}
+}
+single_val(A) ::= single_val(B) DIV single_val(C). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "single_val ::= single_val DIV single_val." << std::endl;
+#endif
+		}
+		A.strValue = new SString(*(B.strValue) + *(C.strValue) + "/;");
+		delete B.strValue;
+		delete C.strValue;
+	}
+}
+
+double_val(A) ::= DOUBLE_VAL(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "double_val ::= DOUBLE_VAL. -> " << (string(B.strArrValue)).c_str() << std::endl;
+#endif
+		}
+		A.dblValue = atof((string(B.strArrValue)).c_str()); 
+	}
+}
+param_name(A) ::= PARAM_NAME(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "param_name ::= PARAM_NAME. -> " << (string(B.strArrValue)).c_str() << std::endl;
+#endif
+		}
+		A.strValue = new SString(string(B.strArrValue).c_str());
+	}
+}
+prod_name(A) ::= PROD_NAME(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "prod_name ::= PROD_NAME." << std::endl;
+#endif
+		}
+		A.strValue = new SString(string(B.strArrValue).c_str());
+	}
+}
+command(A) ::= COMMAND(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "command ::= COMMAND." << std::endl;
+#endif
+		}
+		A.strValue = new SString(string(B.strArrValue).c_str()); 
+	}
+}
+neuron(A) ::= NEURON(B). { 
+	if (!syntaxOnly) {
+		{
+#if PARSER_DEBUG > 0
+			std::cout << "neuron ::= NEURON." << std::endl;
+#endif
+		}
+		A.strValue = new SString(string(B.strArrValue).c_str()); 
+	}
+}
Index: /cpp/_old/f8-to-f1/conv_f8tof1_scanner.cpp
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1_scanner.cpp	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1_scanner.cpp	(revision 110)
@@ -0,0 +1,1720 @@
+#line 2 "conv_f8tof1_scanner.cpp"
+
+#line 4 "conv_f8tof1_scanner.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+    /* The c++ scanner is a mess. The FlexLexer.h header file relies on the
+     * following macro. This is required in order to pass the c++-multiple-scanners
+     * test in the regression suite. We get reports that it breaks inheritance.
+     * We will address this in a future release of flex, or omit the C++ scanner
+     * altogether.
+     */
+    #define yyFlexLexer yyFlexLexer
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+#include <iostream> 
+#include <errno.h>
+#include <cstdlib>
+#include <cstring>
+/* end standard C++ headers. */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+
+	std::istream* yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+#define yytext_ptr yytext
+#define YY_INTERACTIVE
+
+#include <FlexLexer.h>
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 28
+#define YY_END_OF_BUFFER 29
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[44] =
+    {   0,
+        0,    0,   29,   27,    4,   26,   27,   16,   17,   24,
+       22,   21,   23,   25,    3,   19,    6,    5,   11,   12,
+       27,   27,   27,   14,   20,   15,    4,    9,    0,    0,
+        3,    7,    8,   10,    2,    0,    1,   18,    3,    0,
+        0,   13,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    1,    1,    1,    1,    1,    1,    5,
+        6,    7,    8,    9,   10,   11,   12,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   14,    1,   15,
+       16,   17,    1,    1,   18,    1,   18,    1,   18,   18,
+        1,    1,   18,    1,    1,   18,   18,    1,    1,   19,
+       18,   18,   18,    1,    1,    1,   18,   18,    1,    1,
+       20,   21,   22,   18,    1,    1,   18,    1,   18,    1,
+
+       18,   18,    1,    1,   18,    1,    1,   18,   18,   23,
+        1,    1,   18,   18,   18,    1,    1,    1,   18,    1,
+        1,    1,   24,   25,   26,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[27] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[45] =
+    {   0,
+        0,    0,   52,   53,   49,   53,   34,   53,   53,   53,
+       53,   53,   39,   53,   16,   53,   32,   31,   30,   53,
+       32,   24,   30,   53,   53,   53,   40,   53,   31,   27,
+       17,   53,   53,   53,   26,   17,   24,   53,   23,   14,
+       10,   13,   53,   32
+    } ;
+
+static yyconst flex_int16_t yy_def[45] =
+    {   0,
+       43,    1,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   44,   43,   43,   43,   44,
+       44,   44,    0,   43
+    } ;
+
+static yyconst flex_int16_t yy_nxt[80] =
+    {   0,
+        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
+        4,   14,   15,   16,   17,   18,   19,   20,   21,   20,
+       22,   20,   23,   24,   25,   26,   30,   30,   31,   31,
+       41,   42,   40,   41,   41,   39,   37,   41,   35,   39,
+       38,   27,   37,   36,   35,   34,   33,   32,   29,   28,
+       27,   43,    3,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43
+    } ;
+
+static yyconst flex_int16_t yy_chk[80] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,   15,   31,   15,   31,
+       41,   41,   44,   42,   40,   39,   37,   36,   35,   30,
+       29,   27,   23,   22,   21,   19,   18,   17,   13,    7,
+        5,    3,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   43
+    } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "conv_f8tof1_scanner.l"
+/*
+ *  conv_f8tof1_scanner.l
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-03-28.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+#line 10 "conv_f8tof1_scanner.l"
+#include "lexglobal.h"
+#include "conv_f8tof1_grammar.h"
+#include <string.h>
+#include <math.h>
+	
+	YYSTYPE yylval;
+	int line = 1, col = 1;
+	int yyFlexLexer::yywrap(void) {
+	//int yywrap(void) {
+		return 1;
+	}
+#line 453 "conv_f8tof1_scanner.cpp"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+#define ECHO LexerOutput( yytext, yyleng )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+\
+	if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \
+		YY_FATAL_ERROR( "input in flex scanner failed" );
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) LexerError( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+#define YY_DECL int yyFlexLexer::yylex()
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 22 "conv_f8tof1_scanner.l"
+
+
+#line 556 "conv_f8tof1_scanner.cpp"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = & std::cin;
+
+		if ( ! yyout )
+			yyout = & std::cout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state(  );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 44 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 53 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 24 "conv_f8tof1_scanner.l"
+{ col += yyleng; 
+					  yylval.strVal = yytext;
+					  return PARAM_NAME; 
+					}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 29 "conv_f8tof1_scanner.l"
+{ col += yyleng; 
+					  yylval.strVal = yytext;
+					  return PROD_NAME; 
+					}
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 34 "conv_f8tof1_scanner.l"
+{ col += yyleng;
+					  //yylval.dblVal = atof(yytext);
+					  yylval.strVal = yytext;
+					  return DOUBLE_VAL; 
+					}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 40 "conv_f8tof1_scanner.l"
+{ col += yyleng; }               /* ignore but count white space */
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 42 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return ASSIGN; }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 44 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return LESS; }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 45 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return LESS_EQUAL; }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 46 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return EQUAL; }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 47 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return NOT_EQUAL; }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 48 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return GREATER_EQUAL; }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 49 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return GREATER; }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 51 "conv_f8tof1_scanner.l"
+{ col += yyleng; 
+					  yylval.strVal = yytext;
+					  return COMMAND; 
+					}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 56 "conv_f8tof1_scanner.l"
+{ col += yyleng;
+					  yylval.strVal = yytext;
+					  return NEURON;
+					}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 61 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return FORLOOP_BEGIN; }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 62 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return FORLOOP_END; }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 64 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return LPAREN; }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 65 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return RPAREN; }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 67 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return DELIMETER; }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 69 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return SEMICOLON; }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 70 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return PIPE; }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 71 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return COMMA; }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 73 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return PLUS; }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 74 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return MINUS; }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 75 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return TIMES; }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 76 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return DIV; }
+	YY_BREAK
+case 26:
+/* rule 26 can match eol */
+YY_RULE_SETUP
+#line 78 "conv_f8tof1_scanner.l"
+{ col = 0; ++line; yylval.strVal = "\\n"; return NEWLINE; }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 80 "conv_f8tof1_scanner.l"
+{ col += yyleng; yylval.strVal = yytext; return -1; }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 82 "conv_f8tof1_scanner.l"
+ECHO;
+	YY_BREAK
+#line 796 "conv_f8tof1_scanner.cpp"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap(  ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* The contents of this function are C++ specific, so the () macro is not used.
+ */
+yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout )
+{
+	yyin = arg_yyin;
+	yyout = arg_yyout;
+	yy_c_buf_p = 0;
+	yy_init = 0;
+	yy_start = 0;
+	yy_flex_debug = 0;
+	yylineno = 1;	// this will only get updated if %option yylineno
+
+	yy_did_buffer_switch_on_eof = 0;
+
+	yy_looking_for_trail_begin = 0;
+	yy_more_flag = 0;
+	yy_more_len = 0;
+	yy_more_offset = yy_prev_more_offset = 0;
+
+	yy_start_stack_ptr = yy_start_stack_depth = 0;
+	yy_start_stack = NULL;
+
+	yy_buffer_stack = 0;
+	yy_buffer_stack_top = 0;
+	yy_buffer_stack_max = 0;
+
+	yy_state_buf = 0;
+
+}
+
+/* The contents of this function are C++ specific, so the () macro is not used.
+ */
+yyFlexLexer::~yyFlexLexer()
+{
+	delete [] yy_state_buf;
+	yyfree(yy_start_stack  );
+	yy_delete_buffer( YY_CURRENT_BUFFER );
+	yyfree(yy_buffer_stack  );
+}
+
+/* The contents of this function are C++ specific, so the () macro is not used.
+ */
+void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out )
+{
+	if ( new_in )
+		{
+		yy_delete_buffer( YY_CURRENT_BUFFER );
+		yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE  ) );
+		}
+
+	if ( new_out )
+		yyout = new_out;
+}
+
+#ifdef YY_INTERACTIVE
+int yyFlexLexer::LexerInput( char* buf, int /* max_size */ )
+#else
+int yyFlexLexer::LexerInput( char* buf, int max_size )
+#endif
+{
+	if ( yyin->eof() || yyin->fail() )
+		return 0;
+
+#ifdef YY_INTERACTIVE
+	yyin->get( buf[0] );
+
+	if ( yyin->eof() )
+		return 0;
+
+	if ( yyin->bad() )
+		return -1;
+
+	return 1;
+
+#else
+	(void) yyin->read( buf, max_size );
+
+	if ( yyin->bad() )
+		return -1;
+	else
+		return yyin->gcount();
+#endif
+}
+
+void yyFlexLexer::LexerOutput( const char* buf, int size )
+{
+	(void) yyout->write( buf, size );
+}
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+int yyFlexLexer::yy_get_next_buffer()
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    yy_state_type yyFlexLexer::yy_get_previous_state()
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 44 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 44 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 43);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    void yyFlexLexer::yyunput( int c, register char* yy_bp)
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up yytext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+    int yyFlexLexer::yyinput()
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap(  ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyFlexLexer::yyrestart( std::istream* input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer( yyin, YY_BUF_SIZE );
+	}
+
+	yy_init_buffer( YY_CURRENT_BUFFER, input_file );
+	yy_load_buffer_state(  );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state(  );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+    void yyFlexLexer::yy_load_buffer_state()
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+extern "C" int isatty (int );
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+	b->yy_is_interactive = 0;
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state(  );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer)
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state(  );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yyFlexLexer::yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state(  );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+void yyFlexLexer::yyensure_buffer_stack(void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+    void yyFlexLexer::yy_push_state( int new_state )
+{
+    	if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) )
+		{
+		yy_size_t new_size;
+
+		(yy_start_stack_depth) += YY_START_STACK_INCR;
+		new_size = (yy_start_stack_depth) * sizeof( int );
+
+		if ( ! (yy_start_stack) )
+			(yy_start_stack) = (int *) yyalloc(new_size  );
+
+		else
+			(yy_start_stack) = (int *) yyrealloc((void *) (yy_start_stack),new_size  );
+
+		if ( ! (yy_start_stack) )
+			YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+		}
+
+	(yy_start_stack)[(yy_start_stack_ptr)++] = YY_START;
+
+	BEGIN(new_state);
+}
+
+    void yyFlexLexer::yy_pop_state()
+{
+    	if ( --(yy_start_stack_ptr) < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN((yy_start_stack)[(yy_start_stack_ptr)]);
+}
+
+    int yyFlexLexer::yy_top_state()
+{
+    	return (yy_start_stack)[(yy_start_stack_ptr) - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+void yyFlexLexer::LexerError( yyconst char msg[] )
+{
+    	std::cerr << msg << std::endl;
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 82 "conv_f8tof1_scanner.l"
+
+
+/**
+  * reset the line and column count
+  */
+void reset_lexer(void)
+{
+	line = 1;
+	col  = 1;    
+}
+
+/**
+  * yyerror() is invoked when the lexer or the parser encounter
+  * an error. The error message is passed via *s
+  */
+void yyerror(char *s)
+{
+	printf("error: %s at line: %d col: %d\n",s,line,col);
+}
+
+/*int yywrap(void)
+{
+	return 1;
+}*/
+
Index: /cpp/_old/f8-to-f1/conv_f8tof1_scanner.h
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1_scanner.h	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1_scanner.h	(revision 110)
@@ -0,0 +1,273 @@
+#ifndef yyHEADER_H
+#define yyHEADER_H 1
+#define yyIN_HEADER 1
+
+#line 6 "conv_f8tof1_scanner.h"
+
+#line 8 "conv_f8tof1_scanner.h"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+    /* The c++ scanner is a mess. The FlexLexer.h header file relies on the
+     * following macro. This is required in order to pass the c++-multiple-scanners
+     * test in the regression suite. We get reports that it breaks inheritance.
+     * We will address this in a future release of flex, or omit the C++ scanner
+     * altogether.
+     */
+    #define yyFlexLexer yyFlexLexer
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+#include <iostream> 
+#include <errno.h>
+#include <cstdlib>
+#include <cstring>
+/* end standard C++ headers. */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+
+	std::istream* yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+/* Begin user sect3 */
+
+#define yytext_ptr yytext
+#define YY_INTERACTIVE
+
+#include <FlexLexer.h>
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+
+#endif
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+#define YY_DECL int yyFlexLexer::yylex()
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 82 "conv_f8tof1_scanner.l"
+
+
+#line 272 "conv_f8tof1_scanner.h"
+#undef yyIN_HEADER
+#endif /* yyHEADER_H */
Index: /cpp/_old/f8-to-f1/conv_f8tof1_scanner.l
===================================================================
--- /cpp/_old/f8-to-f1/conv_f8tof1_scanner.l	(revision 110)
+++ /cpp/_old/f8-to-f1/conv_f8tof1_scanner.l	(revision 110)
@@ -0,0 +1,104 @@
+/*
+ *  conv_f8tof1_scanner.l
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-03-28.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+%{
+#include "lexglobal.h"
+#include "conv_f8tof1_grammar.h"
+#include <string.h>
+#include <math.h>
+	
+	YYSTYPE yylval;
+	int line = 1, col = 1;
+	//int yyFlexLexer::yywrap(void) {
+	int yywrap(void) {
+		return 1;
+	}
+%}
+%%
+
+n[0-9]+			{ col += yyleng; 
+					  yylval.strVal = yytext;
+					  return PARAM_NAME; 
+					}
+
+P[0-9]+		{ col += yyleng; 
+					  yylval.strVal = yytext;
+					  return PROD_NAME; 
+					}
+
+-?[0-9]+(\.[0-9]+)?	{ col += yyleng;
+					  //yylval.dblVal = atof(yytext);
+					  yylval.strVal = yytext;
+					  return DOUBLE_VAL; 
+					}
+
+[ \t\r]+				{ col += yyleng; }               /* ignore but count white space */
+
+"="					{ col += yyleng; yylval.strVal = yytext; return ASSIGN; }
+
+"<"					{ col += yyleng; yylval.strVal = yytext; return LESS; }
+"<="				{ col += yyleng; yylval.strVal = yytext; return LESS_EQUAL; }
+"=="				{ col += yyleng; yylval.strVal = yytext; return EQUAL; }
+"!="				{ col += yyleng; yylval.strVal = yytext; return NOT_EQUAL; }
+">="				{ col += yyleng; yylval.strVal = yytext; return GREATER_EQUAL; }
+">"					{ col += yyleng; yylval.strVal = yytext; return GREATER; }
+
+[X\[\]\^RrLlAaCcFfMmSsIiQqWwEe]		{ col += yyleng; 
+					  yylval.strVal = yytext;
+					  return COMMAND; 
+					}
+
+\\\[.*\\\]			{ col += yyleng;
+					  yylval.strVal = yytext;
+					  return NEURON;
+					}
+
+"{"					{ col += yyleng; yylval.strVal = yytext; return FORLOOP_BEGIN; }
+"}"					{ col += yyleng; yylval.strVal = yytext; return FORLOOP_END; }
+
+"("					{ col += yyleng; yylval.strVal = yytext; return LPAREN; }
+")"					{ col += yyleng; yylval.strVal = yytext; return RPAREN; }
+
+"-"{3}				{ col += yyleng; yylval.strVal = yytext; return DELIMETER; }
+
+":"					{ col += yyleng; yylval.strVal = yytext; return SEMICOLON; }
+"|"					{ col += yyleng; yylval.strVal = yytext; return PIPE; }
+","					{ col += yyleng; yylval.strVal = yytext; return COMMA; }
+
+"+"					{ col += yyleng; yylval.strVal = yytext; return PLUS; }
+"-"					{ col += yyleng; yylval.strVal = yytext; return MINUS; }
+"*"					{ col += yyleng; yylval.strVal = yytext; return TIMES; }
+"/"					{ col += yyleng; yylval.strVal = yytext; return DIV; }
+
+\n					{ col = 0; ++line; yylval.strVal = "\\n"; return NEWLINE; }
+
+.					{ col += yyleng; yylval.strVal = yytext; return -1; }
+
+%%
+/**
+  * reset the line and column count
+  */
+void reset_lexer(void)
+{
+	line = 1;
+	col  = 1;    
+}
+
+/**
+  * yyerror() is invoked when the lexer or the parser encounter
+  * an error. The error message is passed via *s
+  */
+void yyerror(char *s)
+{
+	printf("error: %s at line: %d col: %d\n",s,line,col);
+}
+
+/*int yywrap(void)
+{
+	return 1;
+}*/
Index: /cpp/_old/f8-to-f1/geno_f8.cpp
===================================================================
--- /cpp/_old/f8-to-f1/geno_f8.cpp	(revision 110)
+++ /cpp/_old/f8-to-f1/geno_f8.cpp	(revision 110)
@@ -0,0 +1,1535 @@
+/*
+ *  geno_f8.cpp
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-06-07.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "geno_f8.h"
+#include <cstdlib>
+//#include <sys/time.h>
+#include "conv_f8tof1.h"
+#include "multimap.h"
+#include <iostream>
+#include <string>
+#include "sstringutils.h"
+#include "conv_f8_utils.h"
+
+#define GENO_F8_DEBUG 1 //0 - off, 1 - on
+
+#define FIELDSTRUCT Geno_f8
+
+static ParamEntry GENO8param_tab[]=
+{
+{"Genetics: f8",1,F8_OPERATION_COUNT,},
+{"f8_mut_chg_begin_arg", 0, 0, "Change beginning argument", "f 0 100 7", FIELD(operation[F8_CHANGE_BEGINNING_ARG]),"mutation: probability of changing a beginning argument", },
+{"f8_mut_chg_arg", 0, 0, "Change argument", "f 0 100 7", FIELD(operation[F8_CHANGE_ARG]),"mutation: probability of changing a production's argument", },
+{"f8_mut_del_comm", 0, 0, "Delete command", "f 0 100 8", FIELD(operation[F8_DELETE_COMMAND]),"mutation: probability of deleting a command", },
+{"f8_mut_insert_comm", 0, 0, "Insert commands", "f 0 100 8", FIELD(operation[F8_INSERT_COMMANDS]),"mutation: probability of inserting commands", },
+{"f8_mut_enc", 0, 0, "Encapsulate commands", "f 0 100 8",FIELD(operation[F8_ENCAPSULATE]),"mutation: probability of encapsulating commands", },
+{"f8_mut_chg_cond_sign", 0, 0, "Change condition sign", "f 0 100 7",FIELD(operation[F8_CHANGE_CONDITION_SIGN]),"mutation: probability of changing a condition sign", },
+{"f8_mut_add_param", 0, 0, "Add parameter", "f 0 100 8", FIELD(operation[F8_ADD_PARAMETER]),"mutation: probability of adding a parameter to the production", },
+{"f8_mut_add_cond", 0, 0, "Add condition", "f 0 100 8", FIELD(operation[F8_ADD_CONDITION]),"mutation: probability of adding a condition to the subproduction", },
+{"f8_mut_add_subprod", 0, 0, "Add subproduction", "f 0 100 8", FIELD(operation[F8_ADD_SUBPRODUCTION]),"mutation: probability of adding a subproduction", },
+{"f8_mut_chg_iter_number", 0, 0, "Change iteration number", "f 0 100 7", FIELD(operation[F8_CHANGE_ITERATIONS_NUMBER]),"mutation: probability of changing a number of iterations", },
+{"f8_mut_del_param", 0, 0, "Delete parameter", "f 0 100 8", FIELD(operation[F8_DELETE_PARAMETER]),"mutation: probability of deleting a parameter", },
+{"f8_mut_del_cond", 0, 0, "Delete condition", "f 0 100 8", FIELD(operation[F8_DELETE_CONDITION]),"mutation: probability of deleting a condition", },
+{"f8_mut_add_loop", 0, 0, "Add loop", "f 0 100 0", FIELD(operation[F8_ADD_LOOP]),"mutation: probability of adding a loop", },
+{"f8_mut_del_loop", 0, 0, "Delete loop", "f 0 100 0", FIELD(operation[F8_DELETE_LOOP]),"mutation: probability of deleting a loop", },
+{"f8_mut_del_prod", 0, 0, "Delete production", "f 0 100 8", FIELD(operation[F8_DELETE_PRODUCTION]),"mutation: probability of deleting a production", },
+{0,},
+};
+
+#undef FIELDSTRUCT
+
+ProductionInfo::ProductionInfo(SString name, int paramCount) {
+	this->name = name;
+	this->paramCount = paramCount;
+}
+
+Geno_f8::Geno_f8()
+{
+	supported_format = '8';
+
+        for(int i=0;i<strlen(GenoConv_F8ToF1::simpleprods);i++)
+	        this->simpleCommandLetters.push_back(GenoConv_F8ToF1::simpleprods[i]);
+                
+	this->converter = new GenoConv_F8ToF1();
+
+	par.setParamTab(GENO8param_tab);
+	par.select(this);
+	par.setDefault();
+
+	/*mutation_method_names = new char*[F8_OPERATION_COUNT - 1]; //FIXME
+	int index = 0;
+	mutation_method_names[index++]="changed beginning argument";
+	mutation_method_names[index++]="changed argument";
+	mutation_method_names[index++]="deleted command";
+	mutation_method_names[index++]="inserted command";
+	mutation_method_names[index++]="encapsulated command";
+	mutation_method_names[index++]="changed condition sign";
+	mutation_method_names[index++]="added parameter";
+	mutation_method_names[index++]="added condition";
+	mutation_method_names[index++]="added subproduction";
+	mutation_method_names[index++]="changed iterations number";
+	mutation_method_names[index++]="deleted parameter";
+	mutation_method_names[index++]="deleted condition";
+	mutation_method_names[index++]="added loop";
+	mutation_method_names[index++]="deleted loop";
+	*/
+	
+#ifdef GENO_F8_DEBUG > 0
+	for (int i = 0; i < F8_OPERATION_COUNT; i++) {
+		this->operation[i] = 1.0 / (double)F8_OPERATION_COUNT;
+	}
+#endif
+}
+
+Geno_f8::~Geno_f8() {
+	delete this->converter;
+}
+
+
+char* Geno_f8::getSimplest() {
+	return "1\n---\nP0\nP0():X\n";
+}
+
+int Geno_f8::checkValidity(const char * geno) {
+	SString ssgeno = SString(geno);
+	SString f1ssgeno = this->converter->convert(ssgeno, NULL);
+	const char* f1genosrc = f1ssgeno;
+	Geno f1geno(f1genosrc);
+	if (/*this->converter->checkSyntax(geno) &&*/ f1geno.isValid()) {
+		return GENOPER_OK;
+	} else {
+		return 1;
+	}
+}
+
+int Geno_f8::validate(char *& geno) {
+	SString in = geno;
+	SString validated = "";
+	SString line;
+	int pos = 0;
+	bool firstLine = true;
+	bool beforeDelim = true;
+	bool justAfterDelim = false;
+	while (in.getNextToken(pos, line, '\n')) {
+		if (firstLine) {
+			firstLine = false;
+			const char* str = geno;
+			std::istringstream i(str);
+			double x;
+			if (i >> x) {
+				validated += line + "\n";
+			} else {
+				validated += "10\n";
+			}
+		} else if (beforeDelim) {
+			if (line[0] == 'P' && line.indexOf('(') != -1 && line.indexOf(')') != -1 && line.indexOf(':') != -1) {
+				validated += "---\n";
+				validated += line + "\n";
+				beforeDelim = false;
+			}
+			int eqSignPos = line.indexOf('=');
+			if (line[0] == 'n' && eqSignPos != -1) {
+				validated += line + "\n";
+			} else if (line == SString("---")) {
+				validated += line + "\n";
+				beforeDelim = false;
+				justAfterDelim = true;
+			}
+		} else if (justAfterDelim && line[0] == 'P') {
+			const char* digits = "0123456789";
+			SString s = line.substr(1);
+			bool ok = true;
+			for (int i = 0; i < s.len(); i++) {
+				if (!strContainsOneOf(s(i), digits)) {
+					ok = false;
+					break;
+				}
+			}
+			if (ok) {
+				validated += line +"\n";
+			}
+			justAfterDelim = false;
+		} else if (line[0] == 'P' && line.indexOf('(') != -1 && line.indexOf(')') != -1 && line.indexOf(':') != -1) {
+			validated += line + "\n";
+		}
+	}
+	free(geno); //must take care of the original allocation
+	char* validatedTmp = (char*)malloc(strlen(validated) + 1); //allocate for mutated genotype
+	strcpy(validatedTmp, validated); //the rest is originalg = mutated;
+	geno = validatedTmp;
+
+	return GENOPER_OK;
+}
+
+unsigned long Geno_f8::style(const char *g, int pos)
+{
+   char ch=g[pos];
+   unsigned long style=GENSTYLE_CS(0,GENSTYLE_NONE); //default, should be changed below
+   if (strchr("^[]X",ch))          style=GENSTYLE_RGBS(0,0,0,GENSTYLE_BOLD); else
+   if (strchr(":",ch))             style=GENSTYLE_RGBS(220,0,0,GENSTYLE_BOLD); else
+   if (strchr("|",ch))             style=GENSTYLE_RGBS(220,0,0,GENSTYLE_NONE);
+   return style;
+}
+
+
+int Geno_f8::getProductionsCount(const SString &in) {
+	int pos = 0;
+	SString line;
+	int counter = 0;
+	bool beforeDelim = true;
+	while (in.getNextToken(pos, line, '\n')) {
+		if (line.startsWith("---")) {
+			beforeDelim = false;
+			//also skip the start production
+			in.getNextToken(pos, line, '\n');
+			continue;
+		} else if (beforeDelim) {
+			continue;
+		} else {
+			counter++;
+		}				
+	}
+	return counter;
+}
+
+vector<ProductionInfo> Geno_f8::getProductionsInfo(const SString &in) {
+	vector<ProductionInfo> productions;
+	SString line;
+	int pos = 0;
+	bool beforeFirstProd = true;
+	SString firstProdName;
+	while (in.getNextToken(pos, line, '\n')) {
+		if (line.startsWith("P") && line.indexOf('(', 0) == -1) {
+			firstProdName = line;
+			beforeFirstProd = false;
+			continue;
+		}
+		if (beforeFirstProd) {
+			continue;
+		}
+		int lParenIndex = line.indexOf('(', 0);
+		int rParenIndex = line.indexOf(')', 0);
+		if (line[0] == 'P' && lParenIndex != -1 && rParenIndex != -1) {
+			ProductionInfo info;
+			SString prodName = line.substr(0, lParenIndex);
+			info.name = prodName;
+			info.paramCount = 0;
+			//if (line[lParenIndex + 1] == 'n') {
+			SString strParams = line.substr(lParenIndex + 1, rParenIndex - lParenIndex - 1);
+			int pos2 = 0;
+			SString tok;
+			while (strParams.getNextToken(pos2, tok, ',')) {
+				info.paramCount++;
+				info.paramNames.push_back(tok);
+			}
+			//}
+			info.isFirstProduction = (prodName == firstProdName) ? true : false;
+			productions.push_back(info);
+		}
+	}
+	return productions;
+}
+
+SString Geno_f8::mutateChangeBeginningArg(SString &in, float& chg) {
+	SString mutated, line, before, mid, after, tmp;
+	int counter = 0;
+	int pos = 0;
+	bool afterDelim = false;
+	bool firstLine = true;
+	while (in.getNextToken(pos, line, '\n')) {
+		if (firstLine) {
+			firstLine = false;
+			before += line + "\n";
+			continue;
+		}
+		if (afterDelim) {
+			after += line + "\n";
+			continue;
+		} 
+		if (line.startsWith("---")) {
+			afterDelim = true;
+			after += line + "\n";					
+		} else {
+			mid += line + "\n";
+			counter++;
+		}				
+	}
+	if (counter == 0) {
+		chg = 0.0;
+		mutated = in;
+	} else {
+		int randNbr = randomN(counter);
+		pos = 0;
+		counter = 0;
+		while (mid.getNextToken(pos, line, '\n')) {
+			if (counter++ == randNbr) {
+				int pos2 = 0;
+				SString tok;
+				line.getNextToken(pos2, tok, '=');
+				tmp += tok + "=";
+				line.getNextToken(pos2, tok, '=');
+				double arg = parseDouble(tok);
+				arg += (double) (randomN(11) - 5); //-5..5
+				tmp += SString::valueOf(arg) + "\n";
+				chg = (float) (SString::valueOf(arg).len()) / (float) in.len();
+			} else {
+				tmp += line + "\n";
+			}
+		}
+		mid = tmp;
+		mutated += before;
+		mutated += mid;
+		mutated += after;
+	}
+	return mutated;
+}
+
+SString Geno_f8::mutateChangeArg(SString &in, float& chg) {
+	SString mutated;
+
+	Lsystem *newLsystem = this->converter->createLsystem(in);
+	if (newLsystem == NULL) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+	
+	vector<Production*> interestingProductions;
+	
+	for (map<string, Production*>::iterator prodIter = newLsystem->productions.begin();
+		 prodIter != newLsystem->productions.end(); prodIter++) {
+		if (prodIter->second->parameters.size() > 0) {
+			interestingProductions.push_back(prodIter->second);
+		}
+	}
+	
+	if (interestingProductions.size() > 0) {
+		int rnd = randomN(interestingProductions.size());
+		
+		Production *randomProduction = interestingProductions[rnd];
+		SString prodName = randomProduction->name;
+		
+		int paramIndex = randomN(randomProduction->parameters.size());
+		
+		for (map<string, Production*>::iterator prodIter = newLsystem->productions.begin();
+			 prodIter != newLsystem->productions.end(); prodIter++) {
+			vector<SubProduction> *subproductions = &(prodIter->second->subproductions);
+			for (vector<SubProduction>::iterator subProdIter = subproductions->begin();
+				 subProdIter != subproductions->end(); subProdIter++) {
+				SubProduction *sp = &(*subProdIter);
+				for (vector<ActionStrP>::iterator actionIter = sp->actions.begin();
+					 actionIter != sp->actions.end(); actionIter++) {
+					if ((*actionIter).action != NULL && (*actionIter).action->name == prodName && (*actionIter).params.size() > paramIndex) {
+						SString param = (*actionIter).params[paramIndex];
+						int counter = 0;
+						int pos = 0;
+						SString tok;
+						while (in.getNextToken(pos, tok, ',')) {
+							counter++;
+						}
+						int rnd = randomN(counter);
+						pos = 0;
+						counter = 0;
+						SString newParam = "";
+						if (randomN(2) == 0 || prodIter->second->parameters.size() == 0) {
+							int rnd2 = randomN(5) + 1;
+							newParam += param + SString::valueOf(rnd2) + ";";
+						} else {
+							SString paramName = prodIter->second->parameters.getParameterName(randomN(prodIter->second->parameters.size())+1);
+							newParam += param + paramName + ";";
+						}
+						newParam += (rnd == 0) ? SString("+;") : SString("-;");
+						(*actionIter).params[paramIndex] = newParam;
+						goto label;
+					}
+				}
+			}
+		}
+	label:
+		chg = 2.0 / (float) in.len();
+	}
+	
+	mutated = newLsystem->toString();
+	
+	delete newLsystem;
+	
+	return mutated;
+}
+
+SString Geno_f8::mutateDeleteCommand(SString &in, float& chg) {
+	SString mutated;
+	
+	Lsystem *lsystem = this->converter->createLsystem(in);
+	if (lsystem == NULL) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+	
+	map<string, Production*>::iterator prodIter = lsystem->productions.begin();
+	for (int i = 0; i < randomN(lsystem->productions.size()); i++) {
+		if (i != 0) {
+			prodIter++;
+		}
+	}
+	
+	Production *randomProduction = prodIter->second;
+	if (randomProduction->subproductions.size() > 0) {
+		vector<ActionStrP> *actions = &(randomProduction->subproductions.at(randomN(randomProduction->subproductions.size())).actions);
+		int rnd = randomN(actions->size());
+		if (actions->size() > 0) {
+			Action *a = actions->at(rnd).action;
+			if (a != NULL) {
+				chg = (float) (a->getF8Representation().len()) / (float) in.len();
+				actions->erase(actions->begin() + rnd);
+			}
+		}
+	}
+	
+	mutated = lsystem->toString();
+	
+	delete lsystem;
+	
+	return mutated;
+}
+
+SString Geno_f8::mutateInsertCommands(SString &in, float& chg) {
+	SString mutated;
+	
+	//cout << "insertCommands 1" << endl;
+	Lsystem *lsystem = this->converter->createLsystem(in);
+	if (lsystem == NULL) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+	
+	//cout << "insertCommands 2" << endl;
+	vector<Action*> actions = lsystem->getAllActions(true, true, false, false);
+	//cout << "insertCommands 3" << endl;
+	
+	int random1 = randomN(lsystem->productions.size());
+	
+	map<string, Production*>::iterator prodIter = lsystem->productions.begin();
+	for (int counter = 0; counter < random1; counter++) {
+		prodIter++;
+	}
+	//cout << "insertCommands 4" << endl;
+	
+	Production *p = prodIter->second;
+	SubProduction *sp;
+	if (p->subproductions.size() > 0) {
+		sp = &(p->subproductions.at(randomN(p->subproductions.size())));
+	} else {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+	
+	int commandsToInsert = /*randomN(3) +*/ 1;
+	int insertLen = 0;
+	for (int i = 0; i < commandsToInsert; i++) {
+		ActionStrP a;
+		if (actions.size() > 0) {
+			a.action = actions.at(randomN(actions.size()));
+		} else {
+			mutated += in;
+			chg = -1.0;
+			return mutated;
+		}
+		insertLen += a.action->getF8Representation().len();
+		if (a.action->ignoreParams == false && a.action->name[0] == 'P') {
+			Production *p = (Production*) a.action;
+			insertLen += 2;
+			for (int j = 0; j < p->parameters.size(); j++) {
+				int rnd = randomN(p->parameters.size() + 1);
+				if (rnd == 0) {
+					a.params.push_back(SString("0;"));
+					insertLen += 1;
+				} else {
+					SString s = p->parameters.getParameterName(randomN(p->parameters.size()) + 1);
+					a.params.push_back(s + ";");
+					insertLen += s.len();
+				}
+			}
+		}
+		sp->actions.push_back(a);
+	}
+	//cout << "insertCommands 5" << endl;
+	
+	mutated = lsystem->toString();
+	//cout << "insertCommands 6" << endl;
+	chg = (float) insertLen / (float) in.len();
+	
+	delete lsystem;	
+	//cout << "insertCommands 7" << endl;
+			
+	return mutated;
+}
+
+SString Geno_f8::mutateEncapsulate(SString &in, float& chg) {
+	SString mutated;
+	
+	Lsystem *lsystem = this->converter->createLsystem(in);
+	if (lsystem == NULL || lsystem->productions.size() == 0) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+	
+	int counter = 0;
+	int rnd = randomN(lsystem->productions.size());
+	int len = 0;
+	
+	Production *p = new Production();
+	p->subproductions.push_back(SubProduction());
+	SubProduction *newSubProd = &(p->subproductions.back());
+	
+	for (map<string, Production*>::iterator prodIter = lsystem->productions.begin();
+		 prodIter != lsystem->productions.end(); prodIter++) {
+		if (counter++ == rnd) {
+			ParameterCollection *params = &(prodIter->second->parameters);
+			//copy parameters to the encapsulated production
+			for (int i = 1; i <= params->size(); i++) {
+				p->parameters.addParameter(params->getParameterName(i));
+			}
+			
+			SubProduction *subproduction;
+			if (prodIter->second->subproductions.size() > 0) {
+				subproduction = &(prodIter->second->subproductions[randomN(prodIter->second->subproductions.size())]);
+			} else {
+				mutated += in;
+				chg = -1.0;
+				return mutated;
+			}
+			int firstActionIdx;
+			if (subproduction->actions.size() > 0) {
+				firstActionIdx = randomN(subproduction->actions.size());
+			} else {
+				mutated += in;
+				chg = -1.0;
+				return mutated;
+			}
+			int i;
+			vector<ActionStrP> newActions;
+			for (i = 0; i < firstActionIdx; i++) {
+				newActions.push_back(subproduction->actions[i]);
+			}
+			for (i = firstActionIdx; i <= firstActionIdx + randomN(4) + 1
+				 && i < subproduction->actions.size(); i++) { //1..4 actions
+				newSubProd->actions.push_back(subproduction->actions[i]);
+				if (subproduction->actions[i].action != NULL) {
+					len += subproduction->actions[i].action->getF8Representation().len();
+				}
+			}
+			ActionStrP a;
+			a.action = p;
+			a.params = vector<SString>();
+			for (int j = 0; j < params->size(); j++) {
+				//a.params.push_back(SString("0;"));
+				a.params.push_back(params->getParameterName(j + 1));
+			}
+			newActions.push_back(a);
+			while (i < subproduction->actions.size()) {
+				if (subproduction->actions[i].action != NULL) {
+					newActions.push_back(subproduction->actions[i]);
+				}
+				i++;
+			}
+			subproduction->actions = newActions;
+			break;
+		}		
+	}
+	
+	SString newName;
+	for (int i = 0; i < 100000; i++) {
+		newName = "P";
+		newName += SString::valueOf(i);
+		if (lsystem->productions[sstringToString(newName)] == NULL) {
+			break;
+		}
+	}	
+	p->name = newName;
+	lsystem->productions[sstringToString(newName)] = p;
+	
+	mutated = lsystem->toString();
+	
+	delete lsystem;
+
+	chg = (float) len / (float) in.len();
+	return mutated;
+}
+
+SString Geno_f8::mutateDeleteProduction(SString &in, float& chg) {
+	SString mutated;
+	
+	Lsystem *lsystem = this->converter->createLsystem(in);
+	if (lsystem == NULL || lsystem->productions.size() == 0) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+	
+	if (lsystem->productions.size() < 2) {
+		mutated += in;
+		chg = 0.0;
+                delete lsystem;
+		return mutated;
+	}
+
+	vector<SString> productionNamesSS = this->converter->readProductionNames(in);
+	vector<string> productionNames;
+	for (int ssI = 0; ssI < productionNamesSS.size(); ssI++) {
+		productionNames.push_back(sstringToString(productionNamesSS[ssI]));
+	}
+	vector<string>::iterator prodNameIter = productionNames.begin();
+	while (prodNameIter != productionNames.end()) {
+		//delete first production from candidate list
+		if ((*prodNameIter).compare(lsystem->firstProductionName) == 0) {
+			prodNameIter = productionNames.erase(prodNameIter);
+		} else {
+			prodNameIter++;
+		}
+	}
+	//choose production to delete
+	string prodNameToDelete = productionNames[randomN(productionNames.size())];
+	productionNames.push_back(lsystem->firstProductionName);
+	prodNameIter = productionNames.begin();
+	while (prodNameIter != productionNames.end()) {
+		//delete prodNameToDelete from candidate list
+		if ((*prodNameIter).compare(prodNameToDelete) == 0) {
+			prodNameIter = productionNames.erase(prodNameIter);
+		} else {
+			prodNameIter++;
+		}
+	}
+	//choose production to which we will append the contents of deleted production
+	string prodNameToAppendTo = productionNames[randomN(productionNames.size())];
+
+	int len = 0;
+
+	Production* deletedProd = lsystem->productions[prodNameToDelete];
+	Production* appendProd = lsystem->productions[prodNameToAppendTo];
+	//add missing parameters
+	for (int i = 1; i <= deletedProd->parameters.size(); i++) {
+		SString paramName = deletedProd->parameters.getParameterName(i);
+		if (appendProd->parameters.paramExist(paramName) == false) {
+			appendProd->parameters.addParameter(paramName);
+		}
+	}
+
+	//copy subproductions
+	for (vector<SubProduction>::iterator subprodIter = deletedProd->subproductions.begin();
+		 subprodIter != deletedProd->subproductions.end(); subprodIter++) {
+		SubProduction sp;
+		//copy conditions
+		for (vector<Condition>::iterator condIter = (*subprodIter).conditions.begin();
+			 condIter != (*subprodIter).conditions.end(); condIter++) {
+			Condition *cFrom = &(*condIter);
+			Condition cTo;
+			cTo.parameter = SString(cFrom->parameter);
+			cTo.relation = cFrom->relation;
+			cTo.value = cFrom->value;
+			sp.conditions.push_back(cTo);
+		}
+		for (vector<ActionStrP>::iterator actionIter = (*subprodIter).actions.begin();
+			 actionIter != (*subprodIter).actions.end(); actionIter++) {
+			ActionStrP aFrom = *actionIter;
+			ActionStrP aTo;
+			aTo.action = aFrom.action;
+			aTo.params = vector<SString>(aFrom.params);
+			sp.actions.push_back(aTo);
+		}
+		appendProd->subproductions.push_back(sp);
+	}
+	lsystem->productions.erase(string(prodNameToDelete));
+
+	int paramCount = appendProd->parameters.size();
+	for (map<string, Production*>::iterator prodIter = lsystem->productions.begin();
+		 prodIter != lsystem->productions.end(); prodIter++) {
+		for (vector<SubProduction>::iterator subprodIter = prodIter->second->subproductions.begin();
+			 subprodIter != prodIter->second->subproductions.end(); subprodIter++) {
+			for (vector<ActionStrP>::iterator actionIter = (*subprodIter).actions.begin();
+				 actionIter != (*subprodIter).actions.end(); actionIter++) {
+				if ((*actionIter).action != NULL && (*actionIter).action->name != NULL) {
+					if ((*actionIter).action->name == stringToSString(prodNameToDelete)) {
+						(*actionIter).action = appendProd;
+						(*actionIter).params = vector<SString>(paramCount, SString("0;"));
+					}
+					if ((*actionIter).action->name == stringToSString(prodNameToAppendTo)) {
+						(*actionIter).action = appendProd;
+						SString paramVal = "0;";
+						for (int i = (*actionIter).params.size(); i < paramCount; i++) {
+							(*actionIter).params.push_back("0;");
+						}
+					}
+
+				}
+			}
+		}
+	}
+	delete deletedProd;
+
+
+	mutated = lsystem->toString();
+
+	delete lsystem;
+
+	chg = (float) len / (float) in.len();
+	return mutated;
+}
+
+SString Geno_f8::mutateChangeConditionSign(SString &in, float& chg) {
+	SString mutated;
+
+	Lsystem *newLsystem = this->converter->createLsystem(in);
+	if (newLsystem == NULL) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+
+	map<int, SubProduction*> interestingSubproductions;
+	int counter = 0;
+
+	for (map<string, Production*>::iterator prodIter = newLsystem->productions.begin();
+		 prodIter != newLsystem->productions.end(); prodIter++) {
+		for (vector<SubProduction>::iterator subprodIter = prodIter->second->subproductions.begin();
+			 subprodIter != prodIter->second->subproductions.end(); subprodIter++) {
+			SubProduction *sp = &(*subprodIter);
+			if (sp->conditions.size() > 0) {
+				interestingSubproductions[counter++] =  sp;
+			}
+		}
+	}
+
+	if (interestingSubproductions.size() > 0) {
+		int random1 = randomN(interestingSubproductions.size());
+		SubProduction *randomSubproduction = interestingSubproductions[random1];
+		int random2 = randomN(randomSubproduction->conditions.size()); //all interesting conditions have conditions.size() > 0
+		Condition *c = &(randomSubproduction->conditions.at(random2));
+		c->relation = this->getDifferentCondition(c->relation);
+		chg = 2.0 / (float) in.len();
+	}
+
+	mutated = newLsystem->toString();
+
+	delete newLsystem;
+
+	return mutated;
+}
+
+SString Geno_f8::mutateAddParameter(SString &in, float& chg) {
+	SString mutated;
+
+	Lsystem *lsystem = this->converter->createLsystem(in);
+	if (lsystem == NULL || lsystem->productions.size() == 0) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+
+	//cout << "addParameter 1" << endl;
+	int rnd = randomN(lsystem->productions.size());
+	int chglen = 0;
+
+	SString prodName = "";
+
+	int counter = 0;
+	for (map<string, Production*>::iterator prodIter = lsystem->productions.begin();
+		 prodIter != lsystem->productions.end(); prodIter++) {
+		if (counter++ == rnd) {
+			prodName = prodIter->second->name;
+			SString newParam;
+			for (int i = 0; i < 10000; i++) {
+				newParam = "n";
+				newParam += SString::valueOf(i);
+				if (!prodIter->second->parameters.paramExist(newParam)) {
+					prodIter->second->parameters.addParameter(newParam);
+					chglen += newParam.len();
+					break;
+				}
+			}
+
+			if (prodName == stringToSString(lsystem->firstProductionName)) {
+				lsystem->startParams[sstringToString(newParam)] = 0.0;
+			}
+			break;
+		}
+	}
+	//cout << "addParameter 2" << endl;
+	for (map<string, Production*>::iterator prodIter = lsystem->productions.begin();
+		 prodIter != lsystem->productions.end(); prodIter++) {
+		for (vector<SubProduction>::iterator subprodIter = prodIter->second->subproductions.begin();
+			 subprodIter != prodIter->second->subproductions.end(); subprodIter++) {
+			for (vector<ActionStrP>::iterator actionIter = (*subprodIter).actions.begin();
+				 actionIter != (*subprodIter).actions.end(); actionIter++) {
+				if ((*actionIter).action != NULL && (*actionIter).action->name != NULL) { 
+					if ((*actionIter).action->name == prodName) {
+						int randParamVal = randomN(prodIter->second->parameters.size() + 1);
+						SString paramVal = NULL;
+						if (randParamVal == 0) {
+							paramVal = "0;";
+						} else {
+							paramVal = prodIter->second->parameters.getParameterName(randParamVal) + ";";
+						}
+						//(*actionIter).params.push_back(paramVal);
+						chglen += 2;
+					}
+				}
+			}
+		}
+	}
+	//cout << "addParameter 3" << endl;
+	
+	mutated = lsystem->toString();
+	//cout << "addParameter 4" << endl;
+	
+	delete lsystem;
+	
+	chg = (float) chglen / (float) in.len();
+	return mutated;
+}
+
+SString Geno_f8::mutateAddCondition(SString &in, float& chg) {
+	SString mutated, before, mid, after, line;
+	vector<ProductionInfo> prodInfo = this->getProductionsInfo(in);
+	vector<int> interestingProductions;
+	for (int i = 0; i < prodInfo.size(); i++) {
+		if (prodInfo[i].paramNames.size() > 0) {
+			interestingProductions.push_back(i);
+		}
+	}
+	if (interestingProductions.size() == 0) {
+		chg = -1.0;
+		mutated = in;
+		return mutated;
+	}
+	int rndProd = interestingProductions[randomN(interestingProductions.size())];
+	int pos = 0;
+	mutated = "";
+	while (in.getNextToken(pos, line, '\n')) {
+		if (line.startsWith(prodInfo[rndProd].name) && line.len() > prodInfo[rndProd].name.len()) {
+			int subproductionsCount = -1;
+			SString tok;
+			int pos2 = 0;
+			while (line.getNextToken(pos2, tok, ':')) {
+				subproductionsCount++;
+			}
+			if (subproductionsCount == 0) {
+				chg = -1.0;
+				mutated = in;
+				return mutated;
+			}
+			int rnd = randomN(subproductionsCount);
+			int counter = 0;
+			int colonIdx = line.indexOf(':', 0);
+			pos2 = colonIdx;
+			while (counter != rnd) {
+				colonIdx = line.indexOf(':', pos2 + 1);
+				counter++;
+			}
+			
+			int nextColonIdx = line.indexOf(':', colonIdx + 1);
+			if (nextColonIdx == -1) {
+				nextColonIdx = 2147483646;
+			}
+			int pipeIdx = line.indexOf('|', colonIdx + 1);
+			mid = "";
+			if (pipeIdx < nextColonIdx && pipeIdx != -1) {
+				//before += line.substr(colonIdx + 1, pipeIdx - colonIdx - 1);
+				before = line.substr(0, pipeIdx);
+				mid += ",";
+				after = line.substr(pipeIdx);				
+			} else {
+				before = line.substr(0, colonIdx + 1);
+				after = SString("|") + line.substr(colonIdx + 1);
+			}
+			int paramIdx = (int) randomN(prodInfo[rndProd].paramNames.size());
+			mid += prodInfo[rndProd].paramNames[paramIdx];
+			mid += (randomN(2) == 0) ? ">" : "<";
+			mid += SString::valueOf((int) randomN(21) - 10);
+			
+			mutated += before + mid + after + "\n";
+			chg = (float) mid.len() / (float)in.len();
+		} else {
+			mutated += line + "\n";
+		}
+	}
+	return mutated;
+}
+
+SString Geno_f8::mutateDeleteParameter(SString &in, float& chg) {
+	SString mutated;
+	
+	Lsystem *newLsystem = this->converter->createLsystem(in);
+	if (newLsystem == NULL) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+		
+	map<int, Production*> interestingProductions;
+	int counter = 0;
+	
+	for (map<string, Production*>::iterator prodIter = newLsystem->productions.begin();
+			prodIter != newLsystem->productions.end(); prodIter++) {
+		if (prodIter->second->parameters.size() > 0) {
+			interestingProductions[counter++] =  prodIter->second;
+		}
+	}
+	
+	if (interestingProductions.size() > 0) {
+		int rnd = randomN(interestingProductions.size());
+		
+		Production *randomProduction = interestingProductions[rnd];
+		SString prodName = randomProduction->name;
+		
+		int paramIndex = randomN(randomProduction->parameters.size()) + 1;
+		SString paramName = randomProduction->parameters.getParameterName(paramIndex);
+		string sparamName = sstringToString(paramName);
+		int change = paramName.len();
+		
+		randomProduction->parameters.removeParameter(paramName);
+		
+		if (prodName == stringToSString(newLsystem->firstProductionName)) {
+			newLsystem->startParams.erase(sstringToString(paramName));
+		}
+		
+		for (vector<SubProduction>::iterator subProdIter = randomProduction->subproductions.begin();
+				subProdIter != randomProduction->subproductions.end(); subProdIter++) {
+			for (vector<Condition>::iterator condIter = (*subProdIter).conditions.begin(); 
+				 condIter != (*subProdIter).conditions.end(); /*nothing*/) {
+				if ((*condIter).parameter == paramName) {
+					condIter = (*subProdIter).conditions.erase(condIter);
+				} else {
+					condIter++;
+				}
+			}
+			for (vector<ActionStrP>::iterator actionIter = (*subProdIter).actions.begin();
+					actionIter != (*subProdIter).actions.end(); actionIter++) {
+				for (vector<SString>::iterator paramIter = (*actionIter).params.begin();
+						paramIter != (*actionIter).params.end(); paramIter++) {
+					string s = sstringToString(*paramIter);
+					if (s.find(sparamName, 0) != string::npos) {
+						*paramIter = SString("0;");
+					}
+				}
+			}
+		}
+				
+		for (map<string, Production*>::iterator prodIter = newLsystem->productions.begin();
+				prodIter != newLsystem->productions.end(); prodIter++) {
+			vector<SubProduction> *subproductions = &(prodIter->second->subproductions);
+			for (vector<SubProduction>::iterator subProdIter = subproductions->begin();
+			    	subProdIter != subproductions->end(); subProdIter++) {
+				SubProduction *sp = &(*subProdIter);
+				for (vector<ActionStrP>::iterator actionIter = sp->actions.begin(); 
+					 actionIter != sp->actions.end(); actionIter++) {
+					if ((*actionIter).action != NULL) {
+						if ((*actionIter).action->name == prodName && (*actionIter).params.size() > paramIndex - 1) {
+							change += paramName.len(); //more less
+							(*actionIter).params.erase((*actionIter).params.begin() + (paramIndex - 1));
+						}
+					}
+				}
+			}
+		}
+		chg = (float) change / (float) in.len();
+	}
+	
+	mutated = newLsystem->toString();
+	
+	delete newLsystem;
+	
+	return mutated;
+}
+
+SString Geno_f8::mutateDeleteCondition(SString &in, float& chg) {
+	SString mutated;
+	
+	Lsystem *newLsystem = this->converter->createLsystem(in);
+	if (newLsystem == NULL) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+		
+	map<int, SubProduction*> interestingSubproductions;
+	int counter = 0;
+	
+	for (map<string, Production*>::iterator prodIter = newLsystem->productions.begin();
+		 prodIter != newLsystem->productions.end(); prodIter++) {
+		for (vector<SubProduction>::iterator subprodIter = prodIter->second->subproductions.begin();
+			 subprodIter != prodIter->second->subproductions.end(); subprodIter++) {
+			SubProduction *sp = &(*subprodIter);
+			if (sp->conditions.size() > 0) {
+				interestingSubproductions[counter++] =  sp;
+			}
+		}
+	}
+	
+	if (interestingSubproductions.size() > 0) {
+		int rnd = randomN(interestingSubproductions.size());
+		SubProduction *randomSubproduction = interestingSubproductions[rnd];
+		vector<Condition>::iterator condIter = randomSubproduction->conditions.begin();
+		condIter += randomN(randomSubproduction->conditions.size() - 1);
+		Condition c = *condIter;
+		chg = (float) (c.parameter.len() + 1 + SString::valueOf(c.value).len()) / (float) in.len();
+		randomSubproduction->conditions.erase(condIter);
+	}
+	
+	mutated = newLsystem->toString();
+	
+	delete newLsystem;
+	
+	return mutated;
+}
+
+SString Geno_f8::mutateAddLoop(SString &in, float& chg) {
+	/*
+	 * Podczas wczytania genotypu do obiektu typu Lsystem nastepuje rozwiniecie petli, wiec kolejne mutacje
+	 * zniweczyly by zysk ktory mozna uzyskac dzieki petlom. Dlatego nic nie zmieniamy.
+	 */
+	SString mutated, line;
+	int pos = 0;
+	while (in.getNextToken(pos, line, '\n')) {
+		mutated += line + "\n";
+	}
+	chg = 0.0;
+	return mutated;
+}
+
+SString Geno_f8::mutateDeleteLoop(SString &in, float& chg) {
+	/*
+	 * Podczas wczytania genotypu do obiektu typu Lsystem nastepuje rozwiniecie petli, wiec kolejne mutacje
+	 * zniweczyly by zysk ktory mozna uzyskac dzieki petlom. Dlatego nic nie zmieniamy.
+	 */
+	SString mutated, line;
+	int pos = 0;
+	while (in.getNextToken(pos, line, '\n')) {
+		mutated += line + "\n";
+	}
+	chg = 0.0;
+	return mutated;
+}
+
+SString Geno_f8::mutateAddSubproduction(SString &in, float& chg) {
+	SString mutated, line;
+	vector<ProductionInfo> prodInfo = this->getProductionsInfo(in);
+	int rndProd = randomN(prodInfo.size());
+	int pos = 0;
+	mutated = "";
+	while (in.getNextToken(pos, line, '\n')) {
+		if (line.startsWith(prodInfo[rndProd].name) && line.indexOf(':', 0) != -1) {
+			SString tmp = ":";
+			int paramCount = prodInfo[rndProd].paramNames.size();
+			if (paramCount > 0) {
+				tmp += prodInfo[rndProd].paramNames[(int) randomN(paramCount)];
+				tmp += (randomN(2) == 0) ? ">" : "<";
+				tmp += SString::valueOf((int) randomN(21) - 10);
+				tmp += "|";
+			}
+			tmp += "X\n";
+			chg = (float) tmp.len() / (float) in.len();
+			mutated += line + tmp;
+		} else {
+			mutated += line + "\n";
+		}
+	}
+	return mutated;
+}
+
+SString Geno_f8::mutateChangeIterationsNumber(SString &in, float& chg) {
+	SString mutated;	
+	Lsystem *newLsystem = this->converter->createLsystem(in);
+	if (newLsystem == NULL) {
+		mutated += in;
+		chg = -1.0;
+		return mutated;
+	}
+	
+	newLsystem->iterations += randomN(7) - 3; //-3..3
+	if (newLsystem->iterations < 1) {
+		newLsystem->iterations = 1;
+	}
+	mutated = newLsystem->toString();	
+	delete newLsystem;	
+	chg = 1.0 / (float) in.len();
+	return mutated;
+}
+
+int Geno_f8::mutate(char *&g,float& chg, int &method) {
+	SString in = g;
+
+	/*struct timeval tv;
+	gettimeofday(&tv, NULL);
+	srandom(tv.tv_sec + tv.tv_usec);
+	*/
+	method = roulette(this->operation, F8_OPERATION_COUNT);
+	if (method < 0) {
+		return GENOPER_OPFAIL;
+	}
+
+#if GENO_F8_DEBUG > 0
+	string mutationName = (method == 0) ? "F8_CHANGE_BEGINNING_ARG" : //TODO use mutation_method_names[] here
+	(method == 1) ? "F8_CHANGE_ARG" :
+	(method == 2) ? "F8_DELETE_COMMAND" :
+	(method == 3) ? "F8_INSERT_COMMANDS" :
+	(method == 4) ? "F8_ENCAPSULATE" :
+	(method == 5) ? "F8_CHANGE_CONDITION_SIGN" :
+	(method == 6) ? "F8_REPLACE_COMMAND" :
+	(method == 7) ? "F8_ADD_PARAMETER" :
+	(method == 8) ? "F8_ADD_CONDITION" :
+	(method == 9) ? "F8_ADD_SUBPRODUCTION" :
+	(method == 10) ? "F8_CHANGE_ITERATIONS_NUMBER" :
+	(method == 11) ? "F8_DELETE_PARAMETER" :
+	(method == 12) ? "F8_DELETE_CONDITION" :
+	(method == 13) ? "F8_ADD_LOOP" :
+	(method == 14) ? "F8_DELETE_LOOP" :
+	(method == 15) ? "F8_OPERATION_COUNT" : "*invalid*";
+	//cout << "-------------------- " << mutationName << " --------------------" << endl;
+#endif
+
+	const char* mutatedTmp;
+	SString ssMutatedTmp;
+
+	//cout << "mutate 1" << endl;
+	switch (method) {
+		case F8_CHANGE_BEGINNING_ARG:
+			ssMutatedTmp = this->mutateChangeBeginningArg(in, chg);
+			break;
+		case F8_CHANGE_ARG:
+			ssMutatedTmp = this->mutateChangeArg(in, chg);
+			break;
+		case F8_DELETE_COMMAND:
+			ssMutatedTmp = this->mutateDeleteCommand(in, chg);
+			break;
+		case F8_INSERT_COMMANDS:
+			ssMutatedTmp = this->mutateInsertCommands(in, chg);
+			break;
+		case F8_ENCAPSULATE:
+			ssMutatedTmp = this->mutateEncapsulate(in, chg);
+			break;
+		case F8_CHANGE_CONDITION_SIGN:
+			ssMutatedTmp = this->mutateChangeConditionSign(in, chg);
+			break;
+		/*case F8_REPLACE_COMMAND:
+			ssMutatedTmp = this->mutateReplaceCommand(in, chg);
+			break;*/
+		case F8_ADD_PARAMETER:
+			ssMutatedTmp = this->mutateAddParameter(in, chg);
+			break;
+		case F8_ADD_CONDITION:
+			ssMutatedTmp = this->mutateAddCondition(in, chg);
+			break;
+		case F8_ADD_SUBPRODUCTION:
+			ssMutatedTmp = this->mutateAddSubproduction(in, chg);
+			break;
+		case F8_CHANGE_ITERATIONS_NUMBER:
+			ssMutatedTmp = this->mutateChangeIterationsNumber(in, chg);
+			break;
+		case F8_DELETE_PARAMETER:
+			ssMutatedTmp = this->mutateDeleteParameter(in, chg);
+			break;
+		case F8_DELETE_CONDITION:
+			ssMutatedTmp = this->mutateDeleteCondition(in, chg);
+			break;
+		case F8_ADD_LOOP:
+			ssMutatedTmp = this->mutateAddLoop(in, chg);
+			break;
+		case F8_DELETE_LOOP:
+			ssMutatedTmp = this->mutateDeleteLoop(in, chg);
+			break;
+		case F8_DELETE_PRODUCTION:
+			ssMutatedTmp = this->mutateDeleteProduction(in, chg);
+			break;
+		default:
+			return GENOPER_OPFAIL;
+	}
+
+	//cout << "mutate 2" << endl;
+	if (ssMutatedTmp.len() < 16) {
+		return GENOPER_OPFAIL;
+	}
+	if (chg == -1.0) {
+		chg = 0.0;
+		return GENOPER_OPFAIL;
+	}
+	
+	mutatedTmp = ssMutatedTmp;
+	
+	if (this->checkValidity(mutatedTmp) == GENOPER_OK) { 
+		free(g); //must take care of the original allocation
+		g = (char*)malloc(strlen(mutatedTmp) + 1); //allocate for mutated genotype
+		strcpy(g, mutatedTmp); //the rest is originalg = mutated;
+		//cout << "mutate 3" << endl;
+		return GENOPER_OK;
+	} else {
+		return GENOPER_OPFAIL;
+	}
+}
+
+int Geno_f8::crossOver(char *&g1,char *&g2,float& chg1,float& chg2) {
+	/* wymiana niewielkiej (max. 25%) ilości odpowiadającej sobie informacji
+	 * ma to przypominać "celowaną" mutację, w której osobnik dostaje
+	 * niewiele wiedzy, która sprawdziła się u innego osobnika
+	 */
+	SString in1 = g1;
+	SString in2 = g2;
+	SString mutated;
+	//SString dst;
+	//const char* src = in;
+	//const char* t;
+	
+	Lsystem *newLsystem = this->converter->createLsystem(in1);
+	Lsystem *lsystem2 = this->converter->createLsystem(in2);
+	if (newLsystem == NULL || lsystem2 == NULL) {
+		chg1 = 0.0;
+		chg2 = 0.0;
+		return GENOPER_OPFAIL;
+	}
+	
+	//shuffle second parent's productions
+	vector<int> indices;
+	for (int i = 0; i < lsystem2->productions.size(); i++) {
+		indices.push_back(i);
+	}
+	map<string, Production*> shuffledProductions;
+	while (!indices.empty()) {
+		int rnd = randomN(indices.size());
+		int counter = 0;
+		//Production *p;
+		for (map<string, Production*>::iterator it = lsystem2->productions.begin();
+			 it != lsystem2->productions.end(); it++) {
+			if (counter == rnd) {
+				//p = it->second;
+				shuffledProductions[it->first] = it->second;
+				break;
+			}
+		}
+		//delete index number
+		indices.erase(indices.begin() + rnd);
+	}
+	
+	int productionCount = randomN(min(newLsystem->productions.size() / 4, lsystem2->productions.size())) + 1;
+	
+	int counter = 0;
+	for (map<string, Production*>::iterator it = shuffledProductions.begin(); 
+		 it != shuffledProductions.end() && counter < productionCount; it++) {
+		//if selected production's name exist in the first parent
+		if (newLsystem->productions.find(it->first) != newLsystem->productions.end()) {
+			newLsystem->productions[it->first]->subproductions = it->second->subproductions;
+			counter++;
+		} else {
+			/* This fragment is commented out because we are interested only in matching productions ///////
+			//search for first production, which name does not exist in one of the productions
+			//selected from second parent
+			//this is to avoid information loss when new subproductions will be overwritten
+			//just after adding to the child production
+			for (map<string, Production*>::iterator it2 = newLsystem->productions.begin();
+				 it2 != newLsystem->productions.end(); it2++) {
+				if (shuffledProductions.find(it2->first) == shuffledProductions.end()) { //not found
+					it2->second->subproductions = it->second->subproductions;
+					break;
+				}
+				//there are no "else" because there is at least twice as many productions
+				//in the first parent as selected productions from the second parent
+				//so always we will find "free" production name
+			}*/
+		}		
+	}
+	
+	//check validity of productions indicated in actions
+	for (map<string, Production*>::iterator prodIter = newLsystem->productions.begin();
+		 prodIter != newLsystem->productions.end(); prodIter++) {
+		vector<SString> paramNames;
+		for (int i = 1; i <= prodIter->second->parameters.size(); i++) {
+			paramNames.push_back(prodIter->second->parameters.getParameterName(i));
+		}
+		for (vector<SubProduction>::iterator subprodIter = prodIter->second->subproductions.begin();
+			 subprodIter != prodIter->second->subproductions.end(); subprodIter++) {
+			//conditions
+			if (paramNames.size() > 0) {
+				for (vector<Condition>::iterator condIter = (*subprodIter).conditions.begin();
+					 condIter != (*subprodIter).conditions.end(); condIter++) {
+					vector<SString>::iterator searchIter = find(paramNames.begin(), paramNames.end(), 
+																(*condIter).parameter);
+					if (searchIter == paramNames.end()) { //unknown parameter name!
+						//choose random existing parameter
+						(*condIter).parameter = paramNames[randomN(paramNames.size())];
+					}
+				}
+			} else { //no params, so delete all conditions
+				(*subprodIter).conditions.clear();
+			}
+			
+			//actions
+			for (vector<ActionStrP>::iterator i = (*subprodIter).actions.begin(); 
+				 i != (*subprodIter).actions.end(); /*nothing*/) {
+				bool deleted = false;
+				if ((*i).action == NULL) {
+					continue;
+				}
+				SString &actionName = (*i).action->name;
+				if (actionName[0] == 'n') {
+					if (paramNames.size() > 0) {
+						vector<SString>::iterator searchIter = find(paramNames.begin(), paramNames.end(), 
+																	actionName);
+						if (searchIter != paramNames.end()) { //valid name
+							//ensure it is linked to the correct production
+							(*i).action = newLsystem->getParamProduction(actionName);
+						} else {
+							//link to random parameter prodution
+							SString name = paramNames[randomN(paramNames.size())];
+							(*i).action = newLsystem->getParamProduction(name);
+						}
+					} else { //no params, so delete this param production
+						i = (*subprodIter).actions.erase(i);
+						deleted = true;
+					}
+				} else if (actionName[0] == 'P') {
+					if (newLsystem->productions.find(sstringToString(actionName)) != newLsystem->productions.end()) {
+						//ensure it is linked to the correct production
+						(*i).action = newLsystem->productions[sstringToString(actionName)];
+					} else {
+						//delete this action
+						i = (*subprodIter).actions.erase(i);
+						deleted = true;
+					}
+				}
+				if (!deleted) {
+					i++;
+				}
+			}
+			if ((*subprodIter).actions.size() == 0) { //we erased all the actions
+				ActionStrP a;
+				a.action = newLsystem->getPrimitiveProduction(SString("X"));
+				(*subprodIter).actions.push_back(a);
+			}
+		}
+	}
+	
+	mutated = newLsystem->toString();
+	
+	shuffledProductions.clear();
+	
+	delete newLsystem;
+	delete lsystem2;
+	
+	free(g1); //must take care of the original allocation
+	//free(g2);
+	const char* mutatedTmp = mutated;
+	char* mutatedTmp2 = (char*)malloc(strlen(mutatedTmp) + 1); //allocate for mutated genotype
+    strcpy(mutatedTmp2, mutatedTmp); //the rest is originalg = mutated;
+	g1 = mutatedTmp2;
+	chg1 = 0.5;
+	
+	return GENOPER_OK;	
+}
+
+
+bool Geno_f8::checkProdNameExist(vector<ProductionInfo> info, SString name) const {
+	for (vector<ProductionInfo>::iterator it = info.begin(); it != info.end(); it++) {
+		if ((*it).name == name) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool Geno_f8::checkParamNameExist(vector<SString> names, SString name) const {
+	for (vector<SString>::iterator it = names.begin(); it != names.end(); it++ ) {
+		if ((*it) == name) {
+			return true;
+		}
+	}
+	return false;
+}
+
+SString Geno_f8::getOppositeCondition(const SString &c) const {
+	if (c.equals("=="))
+		return "!=";
+	if (c.equals("!="))
+		return "==";
+	if (c.equals(">"))
+		return "<=";
+	if (c.equals("<"))
+		return ">=";
+	if (c.equals(">="))
+		return "<";
+	if (c.equals("<="))
+		return ">";
+	return "<"; //default
+}
+
+RelationType Geno_f8::getDifferentCondition(RelationType type) {
+	RelationType types[6];
+	types[0] = r_greater;
+	types[1] = r_greaterEqual;
+	types[2] = r_equal;
+	types[3] = r_different;
+	types[4] = r_lessEqual;
+	types[5] = r_less;
+	
+	for (int i = 0; i < 6; i++) {
+		if (types[i] == type) {
+			types[i] = types[5];
+			//types[5] = type;
+			break;
+		}
+	}
+	
+	int randomType = randomN(5);
+	return types[randomType];
+}
+
+SString Geno_f8::removeProductionCalls(const SString production) const {
+	SString line = trimSString(production);
+	SString result = "";
+	bool skip = false;
+	for (int i = 0; i < line.len(); i++) {
+		if (skip) {
+			if (line[i] == ')') {
+				skip = false;
+			} else {
+				//do nothing
+			}
+		} else {
+			if (line[i] == 'P') {
+				skip = true;
+			} else {
+				result += line[i];
+			}
+		}
+	}
+	return result;
+}
+
+SString Geno_f8::addParameterToCalls(const SString line, SString &prodName) {
+	SString newStr = "";
+	int colonIdx = line.indexOf(':', 0);
+	if (colonIdx != -1 && line.indexOf(prodName, colonIdx) != -1) {
+		int pos2 = colonIdx;
+		int beginIdx = 0;
+		int prodIdx;
+		while ((prodIdx = line.indexOf(prodName, pos2)) != -1) {
+			int indexRBrace = line.indexOf(')', prodIdx);
+			newStr += line.substr(beginIdx, indexRBrace);
+			if (newStr[newStr.len() - 1] != '(') {
+				newStr += SString(",");
+			}
+			newStr += "0.0";
+			beginIdx = indexRBrace;
+			pos2 = indexRBrace;
+		}
+		newStr += line.substr(pos2);
+	} else {
+		newStr = line;
+	}
+	return newStr;
+}
+
+SString Geno_f8::deleteParameterFromCalls(const SString line, SString &prodName, int paramIdx) {
+	SString newStr = "";
+	SString tmp, before, mid, midTmp;
+	mid = "";
+	int colonIdx = line.indexOf(':', 0);
+	if (colonIdx != -1 && line.indexOf(prodName, colonIdx) != -1) {
+		int pos2 = colonIdx;
+		int beginIdx = 0;
+		int prodIdx;
+		while ((prodIdx = line.indexOf(prodName, pos2)) != -1) {
+			int indexRBrace = line.indexOf(')', prodIdx);
+			before = line.substr(beginIdx, prodIdx + prodName.len() + 1);
+			midTmp = line.substr(prodIdx + prodName.len() + 1, indexRBrace - (prodIdx + prodName.len() + 1));
+			pos2 = 0;
+			SString tok;
+			int i = 0;
+			while (midTmp.getNextToken(pos2, tok, ',')) {
+				if (i++ == paramIdx) {
+					//do nothing
+				} else {
+					mid += tok + ",";
+				}
+			}
+			if (mid[mid.len() - 1] == ',') {
+				mid = mid.substr(0, mid.len() - 1);
+			}
+			
+			newStr += before + mid + ")";
+			beginIdx = indexRBrace;
+			pos2 = indexRBrace;
+		}
+		newStr += line.substr(pos2 + 1);
+	} else {
+		newStr = line;
+	}
+	return newStr;
+}
+
+SString Geno_f8::testMutate(SString &in, int method) {
+	/*struct timeval tv;
+	gettimeofday(&tv, NULL);
+	srandom(tv.tv_sec + tv.tv_usec);
+	*/
+	SString mutatedTmp;
+	float chg = 0.0;
+	switch (method) {
+		case F8_CHANGE_BEGINNING_ARG:
+			mutatedTmp = this->mutateChangeBeginningArg(in, chg);
+			break;
+		case F8_CHANGE_ARG:
+			mutatedTmp = this->mutateChangeArg(in, chg);
+			break;
+		case F8_DELETE_COMMAND:
+			mutatedTmp = this->mutateDeleteCommand(in, chg);
+			break;
+		case F8_INSERT_COMMANDS:
+			mutatedTmp = this->mutateInsertCommands(in, chg);
+			break;
+		case F8_ENCAPSULATE:
+			mutatedTmp = this->mutateEncapsulate(in, chg);
+			break;
+		case F8_CHANGE_CONDITION_SIGN:
+			mutatedTmp = this->mutateChangeConditionSign(in, chg);
+			break;
+		/*case F8_REPLACE_COMMAND:
+			mutatedTmp = this->mutateReplaceCommand(in, chg);
+			break;*/
+		case F8_ADD_PARAMETER:
+			mutatedTmp = this->mutateAddParameter(in, chg);
+			break;
+		case F8_ADD_CONDITION:
+			mutatedTmp = this->mutateAddCondition(in, chg);
+			break;
+		case F8_ADD_SUBPRODUCTION:
+			mutatedTmp = this->mutateAddSubproduction(in, chg);
+			break;
+		case F8_CHANGE_ITERATIONS_NUMBER:
+			mutatedTmp = this->mutateChangeIterationsNumber(in, chg);
+			break;
+		case F8_DELETE_PARAMETER:
+			mutatedTmp = this->mutateDeleteParameter(in, chg);
+			break;
+		case F8_DELETE_CONDITION:
+			mutatedTmp = this->mutateDeleteCondition(in, chg);
+			break;
+		case F8_ADD_LOOP:
+			mutatedTmp = this->mutateAddLoop(in, chg);
+			break;
+		case F8_DELETE_LOOP:
+			mutatedTmp = this->mutateDeleteLoop(in, chg);
+			break;
+		default:
+			mutatedTmp = "";
+	}
+	return mutatedTmp;
+	
+}
Index: /cpp/_old/f8-to-f1/geno_f8.h
===================================================================
--- /cpp/_old/f8-to-f1/geno_f8.h	(revision 110)
+++ /cpp/_old/f8-to-f1/geno_f8.h	(revision 110)
@@ -0,0 +1,101 @@
+/*
+ *  geno_f8.h
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-06-07.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef _GENO_F8_H_
+#define _GENO_F8_H_
+
+#include "param.h"
+#include "sstring.h"
+#include "geno_fx.h"
+#include <vector>
+#include "conv_f8tof1.h"
+
+using namespace std;
+
+//indices in array with probabilities of mutation operators
+#define F8_CHANGE_BEGINNING_ARG 0
+#define F8_CHANGE_ARG 1
+#define F8_DELETE_COMMAND 2
+#define F8_INSERT_COMMANDS 3
+#define F8_ENCAPSULATE 4
+#define F8_CHANGE_CONDITION_SIGN 5
+//#define F8_REPLACE_COMMAND 6
+#define F8_ADD_PARAMETER 6
+#define F8_ADD_CONDITION 7
+#define F8_ADD_SUBPRODUCTION 8
+#define F8_CHANGE_ITERATIONS_NUMBER 9
+#define F8_DELETE_PARAMETER 10
+#define F8_DELETE_CONDITION 11
+#define F8_ADD_LOOP 12
+#define F8_DELETE_LOOP 13
+#define F8_DELETE_PRODUCTION 14
+#define F8_OPERATION_COUNT 15
+
+class ProductionInfo {
+public:
+	ProductionInfo() {};
+	ProductionInfo(SString name, int paramCount);
+	SString name;
+	int paramCount;
+	vector<SString> paramNames;
+	bool isFirstProduction;
+};
+
+class Geno_f8 : public Geno_fx {
+public:
+	Geno_f8();
+	~Geno_f8();
+
+   	//probabilities of mutation operators
+	double operation[F8_OPERATION_COUNT];
+
+	int checkValidity(const char * geno);
+	int validate(char * &geno);
+	int mutate(char *&g,float& chg, int &method);
+	int crossOver(char *&g1,char *&g2,float& chg1,float& chg2);
+	unsigned long style(const char *g, int pos);
+	char* getSimplest();
+
+	SString testMutate(SString &in, int method);
+protected:
+	GenoConv_F8ToF1 *converter;
+	
+	vector<char> simpleCommandLetters;
+	
+	int getProductionsCount(const SString &in);
+	vector<ProductionInfo> getProductionsInfo(const SString &in);
+	bool checkProdNameExist(vector<ProductionInfo> info, SString name) const;
+	bool checkParamNameExist(vector<SString> names, SString name) const;
+	SString getOppositeCondition(const SString &c) const;
+	SString removeProductionCalls(const SString production) const;
+	SString mutateChangeBeginningArg(SString &in, float& chg);
+	SString mutateChangeArg(SString &in, float& chg);
+	SString mutateDeleteCommand(SString &in, float& chg);
+	SString mutateInsertCommands(SString &in, float& chg);
+	//SString mutateReplaceCommand(SString &in, float& chg);
+	//SString mutateInsertReplaceCommand(SString &in, float& chg, bool replace);
+	SString mutateEncapsulate(SString &in, float& chg);
+	SString mutateDeleteProduction(SString &in, float& chg);
+	SString mutateChangeConditionSign(SString &in, float& chg);
+	SString mutateAddParameter(SString &in, float& chg);
+	SString mutateAddCondition(SString &in, float& chg);
+	SString mutateDeleteParameter(SString &in, float& chg);
+	SString mutateDeleteCondition(SString &in, float& chg);
+	SString mutateAddLoop(SString &in, float& chg);
+	SString mutateDeleteLoop(SString &in, float& chg);
+	SString mutateAddSubproduction(SString &in, float& chg);
+	SString mutateChangeIterationsNumber(SString &in, float& chg);
+	SString addParameterToCalls(const SString line, SString &prodName);
+	SString deleteParameterFromCalls(const SString line, SString &prodName, int paramIdx);
+private:
+	RelationType getDifferentCondition(RelationType type);
+};
+
+#endif
+
Index: /cpp/_old/f8-to-f1/lemon.c
===================================================================
--- /cpp/_old/f8-to-f1/lemon.c	(revision 110)
+++ /cpp/_old/f8-to-f1/lemon.c	(revision 110)
@@ -0,0 +1,4822 @@
+/*
+** This file contains all sources (including headers) to the LEMON
+** LALR(1) parser generator.  The sources have been combined into a
+** single file to make it easy to include LEMON in the source tree
+** and Makefile of another program.
+**
+** The author of this program disclaims copyright.
+*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifndef __WIN32__
+#   if defined(_WIN32) || defined(WIN32)
+#	define __WIN32__
+#   endif
+#endif
+
+#ifdef __WIN32__
+extern int access();
+#else
+#include <unistd.h>
+#endif
+
+/* #define PRIVATE static */
+#define PRIVATE
+
+#ifdef TEST
+#define MAXRHS 5       /* Set low to exercise exception code */
+#else
+#define MAXRHS 1000
+#endif
+
+static char *msort(char*,char**,int(*)(const char*,const char*));
+
+static struct action *Action_new(void);
+static struct action *Action_sort(struct action *);
+
+/********** From the file "build.h" ************************************/
+void FindRulePrecedences();
+void FindFirstSets();
+void FindStates();
+void FindLinks();
+void FindFollowSets();
+void FindActions();
+
+/********* From the file "configlist.h" *********************************/
+void Configlist_init(/* void */);
+struct config *Configlist_add(/* struct rule *, int */);
+struct config *Configlist_addbasis(/* struct rule *, int */);
+void Configlist_closure(/* void */);
+void Configlist_sort(/* void */);
+void Configlist_sortbasis(/* void */);
+struct config *Configlist_return(/* void */);
+struct config *Configlist_basis(/* void */);
+void Configlist_eat(/* struct config * */);
+void Configlist_reset(/* void */);
+
+/********* From the file "error.h" ***************************************/
+void ErrorMsg(const char *, int,const char *, ...);
+
+/****** From the file "option.h" ******************************************/
+struct s_options {
+  enum { OPT_FLAG=1,  OPT_INT,  OPT_DBL,  OPT_STR,
+         OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
+  char *label;
+  char *arg;
+  char *message;
+};
+int    OptInit(/* char**,struct s_options*,FILE* */);
+int    OptNArgs(/* void */);
+char  *OptArg(/* int */);
+void   OptErr(/* int */);
+void   OptPrint(/* void */);
+
+/******** From the file "parse.h" *****************************************/
+void Parse(/* struct lemon *lemp */);
+
+/********* From the file "plink.h" ***************************************/
+struct plink *Plink_new(/* void */);
+void Plink_add(/* struct plink **, struct config * */);
+void Plink_copy(/* struct plink **, struct plink * */);
+void Plink_delete(/* struct plink * */);
+
+/********** From the file "report.h" *************************************/
+void Reprint(/* struct lemon * */);
+void ReportOutput(/* struct lemon * */);
+void ReportTable(/* struct lemon * */);
+void ReportHeader(/* struct lemon * */);
+void CompressTables(/* struct lemon * */);
+void ResortStates(/* struct lemon * */);
+
+/********** From the file "set.h" ****************************************/
+void  SetSize(/* int N */);             /* All sets will be of size N */
+char *SetNew(/* void */);               /* A new set for element 0..N */
+void  SetFree(/* char* */);             /* Deallocate a set */
+
+int SetAdd(/* char*,int */);            /* Add element to a set */
+int SetUnion(/* char *A,char *B */);    /* A <- A U B, thru element N */
+
+#define SetFind(X,Y) (X[Y])       /* True if Y is in set X */
+
+/********** From the file "struct.h" *************************************/
+/*
+** Principal data structures for the LEMON parser generator.
+*/
+
+typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean;
+
+/* Symbols (terminals and nonterminals) of the grammar are stored
+** in the following: */
+struct symbol {
+  char *name;              /* Name of the symbol */
+  int index;               /* Index number for this symbol */
+  enum {
+    TERMINAL,
+    NONTERMINAL,
+    MULTITERMINAL
+  } type;                  /* Symbols are all either TERMINALS or NTs */
+  struct rule *rule;       /* Linked list of rules of this (if an NT) */
+  struct symbol *fallback; /* fallback token in case this token doesn't parse */
+  int prec;                /* Precedence if defined (-1 otherwise) */
+  enum e_assoc {
+    LEFT,
+    RIGHT,
+    NONE,
+    UNK
+  } assoc;                 /* Associativity if predecence is defined */
+  char *firstset;          /* First-set for all rules of this symbol */
+  Boolean lambda;          /* True if NT and can generate an empty string */
+  int useCnt;              /* Number of times used */
+  char *destructor;        /* Code which executes whenever this symbol is
+                           ** popped from the stack during error processing */
+  int destructorln;        /* Line number of destructor code */
+  char *datatype;          /* The data type of information held by this
+                           ** object. Only used if type==NONTERMINAL */
+  int dtnum;               /* The data type number.  In the parser, the value
+                           ** stack is a union.  The .yy%d element of this
+                           ** union is the correct data type for this object */
+  /* The following fields are used by MULTITERMINALs only */
+  int nsubsym;             /* Number of constituent symbols in the MULTI */
+  struct symbol **subsym;  /* Array of constituent symbols */
+};
+
+/* Each production rule in the grammar is stored in the following
+** structure.  */
+struct rule {
+  struct symbol *lhs;      /* Left-hand side of the rule */
+  char *lhsalias;          /* Alias for the LHS (NULL if none) */
+  int lhsStart;            /* True if left-hand side is the start symbol */
+  int ruleline;            /* Line number for the rule */
+  int nrhs;                /* Number of RHS symbols */
+  struct symbol **rhs;     /* The RHS symbols */
+  char **rhsalias;         /* An alias for each RHS symbol (NULL if none) */
+  int line;                /* Line number at which code begins */
+  char *code;              /* The code executed when this rule is reduced */
+  struct symbol *precsym;  /* Precedence symbol for this rule */
+  int index;               /* An index number for this rule */
+  Boolean canReduce;       /* True if this rule is ever reduced */
+  struct rule *nextlhs;    /* Next rule with the same LHS */
+  struct rule *next;       /* Next rule in the global list */
+};
+
+/* A configuration is a production rule of the grammar together with
+** a mark (dot) showing how much of that rule has been processed so far.
+** Configurations also contain a follow-set which is a list of terminal
+** symbols which are allowed to immediately follow the end of the rule.
+** Every configuration is recorded as an instance of the following: */
+struct config {
+  struct rule *rp;         /* The rule upon which the configuration is based */
+  int dot;                 /* The parse point */
+  char *fws;               /* Follow-set for this configuration only */
+  struct plink *fplp;      /* Follow-set forward propagation links */
+  struct plink *bplp;      /* Follow-set backwards propagation links */
+  struct state *stp;       /* Pointer to state which contains this */
+  enum {
+    COMPLETE,              /* The status is used during followset and */
+    INCOMPLETE             /*    shift computations */
+  } status;
+  struct config *next;     /* Next configuration in the state */
+  struct config *bp;       /* The next basis configuration */
+};
+
+/* Every shift or reduce operation is stored as one of the following */
+struct action {
+  struct symbol *sp;       /* The look-ahead symbol */
+  enum e_action {
+    SHIFT,
+    ACCEPT,
+    REDUCE,
+    ERROR,
+    SSCONFLICT,              /* A shift/shift conflict */
+    SRCONFLICT,              /* Was a reduce, but part of a conflict */
+    RRCONFLICT,              /* Was a reduce, but part of a conflict */
+    SH_RESOLVED,             /* Was a shift.  Precedence resolved conflict */
+    RD_RESOLVED,             /* Was reduce.  Precedence resolved conflict */
+    NOT_USED                 /* Deleted by compression */
+  } type;
+  union {
+    struct state *stp;     /* The new state, if a shift */
+    struct rule *rp;       /* The rule, if a reduce */
+  } x;
+  struct action *next;     /* Next action for this state */
+  struct action *collide;  /* Next action with the same hash */
+};
+
+/* Each state of the generated parser's finite state machine
+** is encoded as an instance of the following structure. */
+struct state {
+  struct config *bp;       /* The basis configurations for this state */
+  struct config *cfp;      /* All configurations in this set */
+  int statenum;            /* Sequencial number for this state */
+  struct action *ap;       /* Array of actions for this state */
+  int nTknAct, nNtAct;     /* Number of actions on terminals and nonterminals */
+  int iTknOfst, iNtOfst;   /* yy_action[] offset for terminals and nonterms */
+  int iDflt;               /* Default action */
+};
+#define NO_OFFSET (-2147483647)
+
+/* A followset propagation link indicates that the contents of one
+** configuration followset should be propagated to another whenever
+** the first changes. */
+struct plink {
+  struct config *cfp;      /* The configuration to which linked */
+  struct plink *next;      /* The next propagate link */
+};
+
+/* The state vector for the entire parser generator is recorded as
+** follows.  (LEMON uses no global variables and makes little use of
+** static variables.  Fields in the following structure can be thought
+** of as begin global variables in the program.) */
+struct lemon {
+  struct state **sorted;   /* Table of states sorted by state number */
+  struct rule *rule;       /* List of all rules */
+  int nstate;              /* Number of states */
+  int nrule;               /* Number of rules */
+  int nsymbol;             /* Number of terminal and nonterminal symbols */
+  int nterminal;           /* Number of terminal symbols */
+  struct symbol **symbols; /* Sorted array of pointers to symbols */
+  int errorcnt;            /* Number of errors */
+  struct symbol *errsym;   /* The error symbol */
+  struct symbol *wildcard; /* Token that matches anything */
+  char *name;              /* Name of the generated parser */
+  char *arg;               /* Declaration of the 3th argument to parser */
+  char *tokentype;         /* Type of terminal symbols in the parser stack */
+  char *vartype;           /* The default type of non-terminal symbols */
+  char *start;             /* Name of the start symbol for the grammar */
+  char *stacksize;         /* Size of the parser stack */
+  char *include;           /* Code to put at the start of the C file */
+  int  includeln;          /* Line number for start of include code */
+  char *error;             /* Code to execute when an error is seen */
+  int  errorln;            /* Line number for start of error code */
+  char *overflow;          /* Code to execute on a stack overflow */
+  int  overflowln;         /* Line number for start of overflow code */
+  char *failure;           /* Code to execute on parser failure */
+  int  failureln;          /* Line number for start of failure code */
+  char *accept;            /* Code to execute when the parser excepts */
+  int  acceptln;           /* Line number for the start of accept code */
+  char *extracode;         /* Code appended to the generated file */
+  int  extracodeln;        /* Line number for the start of the extra code */
+  char *tokendest;         /* Code to execute to destroy token data */
+  int  tokendestln;        /* Line number for token destroyer code */
+  char *vardest;           /* Code for the default non-terminal destructor */
+  int  vardestln;          /* Line number for default non-term destructor code*/
+  char *filename;          /* Name of the input file */
+  char *outname;           /* Name of the current output file */
+  char *tokenprefix;       /* A prefix added to token names in the .h file */
+  int nconflict;           /* Number of parsing conflicts */
+  int tablesize;           /* Size of the parse tables */
+  int basisflag;           /* Print only basis configurations */
+  int has_fallback;        /* True if any %fallback is seen in the grammer */
+  char *argv0;             /* Name of the program */
+};
+
+#define MemoryCheck(X) if((X)==0){ \
+  extern void memory_error(); \
+  memory_error(); \
+}
+
+/**************** From the file "table.h" *********************************/
+/*
+** All code in this file has been automatically generated
+** from a specification in the file
+**              "table.q"
+** by the associative array code building program "aagen".
+** Do not edit this file!  Instead, edit the specification
+** file, then rerun aagen.
+*/
+/*
+** Code for processing tables in the LEMON parser generator.
+*/
+
+/* Routines for handling a strings */
+
+char *Strsafe();
+
+void Strsafe_init(/* void */);
+int Strsafe_insert(/* char * */);
+char *Strsafe_find(/* char * */);
+
+/* Routines for handling symbols of the grammar */
+
+struct symbol *Symbol_new();
+int Symbolcmpp(/* struct symbol **, struct symbol ** */);
+void Symbol_init(/* void */);
+int Symbol_insert(/* struct symbol *, char * */);
+struct symbol *Symbol_find(/* char * */);
+struct symbol *Symbol_Nth(/* int */);
+int Symbol_count(/*  */);
+struct symbol **Symbol_arrayof(/*  */);
+
+/* Routines to manage the state table */
+
+int Configcmp(/* struct config *, struct config * */);
+struct state *State_new();
+void State_init(/* void */);
+int State_insert(/* struct state *, struct config * */);
+struct state *State_find(/* struct config * */);
+struct state **State_arrayof(/*  */);
+
+/* Routines used for efficiency in Configlist_add */
+
+void Configtable_init(/* void */);
+int Configtable_insert(/* struct config * */);
+struct config *Configtable_find(/* struct config * */);
+void Configtable_clear(/* int(*)(struct config *) */);
+/****************** From the file "action.c" *******************************/
+/*
+** Routines processing parser actions in the LEMON parser generator.
+*/
+
+/* Allocate a new parser action */
+static struct action *Action_new(void){
+  static struct action *freelist = 0;
+  struct action *new;
+
+  if( freelist==0 ){
+    int i;
+    int amt = 100;
+    freelist = (struct action *)calloc(amt, sizeof(struct action));
+    if( freelist==0 ){
+      fprintf(stderr,"Unable to allocate memory for a new parser action.");
+      exit(1);
+    }
+    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
+    freelist[amt-1].next = 0;
+  }
+  new = freelist;
+  freelist = freelist->next;
+  return new;
+}
+
+/* Compare two actions for sorting purposes.  Return negative, zero, or
+** positive if the first action is less than, equal to, or greater than
+** the first
+*/
+static int actioncmp(
+  struct action *ap1,
+  struct action *ap2
+){
+  int rc;
+  rc = ap1->sp->index - ap2->sp->index;
+  if( rc==0 ){
+    rc = (int)ap1->type - (int)ap2->type;
+  }
+  if( rc==0 && ap1->type==REDUCE ){
+    rc = ap1->x.rp->index - ap2->x.rp->index;
+  }
+  return rc;
+}
+
+/* Sort parser actions */
+static struct action *Action_sort(
+  struct action *ap
+){
+  ap = (struct action *)msort((char *)ap,(char **)&ap->next,
+                              (int(*)(const char*,const char*))actioncmp);
+  return ap;
+}
+
+void Action_add(app,type,sp,arg)
+struct action **app;
+enum e_action type;
+struct symbol *sp;
+char *arg;
+{
+  struct action *new;
+  new = Action_new();
+  new->next = *app;
+  *app = new;
+  new->type = type;
+  new->sp = sp;
+  if( type==SHIFT ){
+    new->x.stp = (struct state *)arg;
+  }else{
+    new->x.rp = (struct rule *)arg;
+  }
+}
+/********************** New code to implement the "acttab" module ***********/
+/*
+** This module implements routines use to construct the yy_action[] table.
+*/
+
+/*
+** The state of the yy_action table under construction is an instance of
+** the following structure
+*/
+typedef struct acttab acttab;
+struct acttab {
+  int nAction;                 /* Number of used slots in aAction[] */
+  int nActionAlloc;            /* Slots allocated for aAction[] */
+  struct {
+    int lookahead;             /* Value of the lookahead token */
+    int action;                /* Action to take on the given lookahead */
+  } *aAction,                  /* The yy_action[] table under construction */
+    *aLookahead;               /* A single new transaction set */
+  int mnLookahead;             /* Minimum aLookahead[].lookahead */
+  int mnAction;                /* Action associated with mnLookahead */
+  int mxLookahead;             /* Maximum aLookahead[].lookahead */
+  int nLookahead;              /* Used slots in aLookahead[] */
+  int nLookaheadAlloc;         /* Slots allocated in aLookahead[] */
+};
+
+/* Return the number of entries in the yy_action table */
+#define acttab_size(X) ((X)->nAction)
+
+/* The value for the N-th entry in yy_action */
+#define acttab_yyaction(X,N)  ((X)->aAction[N].action)
+
+/* The value for the N-th entry in yy_lookahead */
+#define acttab_yylookahead(X,N)  ((X)->aAction[N].lookahead)
+
+/* Free all memory associated with the given acttab */
+void acttab_free(acttab *p){
+  free( p->aAction );
+  free( p->aLookahead );
+  free( p );
+}
+
+/* Allocate a new acttab structure */
+acttab *acttab_alloc(void){
+  acttab *p = calloc( 1, sizeof(*p) );
+  if( p==0 ){
+    fprintf(stderr,"Unable to allocate memory for a new acttab.");
+    exit(1);
+  }
+  memset(p, 0, sizeof(*p));
+  return p;
+}
+
+/* Add a new action to the current transaction set
+*/
+void acttab_action(acttab *p, int lookahead, int action){
+  if( p->nLookahead>=p->nLookaheadAlloc ){
+    p->nLookaheadAlloc += 25;
+    p->aLookahead = realloc( p->aLookahead,
+                             sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
+    if( p->aLookahead==0 ){
+      fprintf(stderr,"malloc failed\n");
+      exit(1);
+    }
+  }
+  if( p->nLookahead==0 ){
+    p->mxLookahead = lookahead;
+    p->mnLookahead = lookahead;
+    p->mnAction = action;
+  }else{
+    if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
+    if( p->mnLookahead>lookahead ){
+      p->mnLookahead = lookahead;
+      p->mnAction = action;
+    }
+  }
+  p->aLookahead[p->nLookahead].lookahead = lookahead;
+  p->aLookahead[p->nLookahead].action = action;
+  p->nLookahead++;
+}
+
+/*
+** Add the transaction set built up with prior calls to acttab_action()
+** into the current action table.  Then reset the transaction set back
+** to an empty set in preparation for a new round of acttab_action() calls.
+**
+** Return the offset into the action table of the new transaction.
+*/
+int acttab_insert(acttab *p){
+  int i, j, k, n;
+  assert( p->nLookahead>0 );
+
+  /* Make sure we have enough space to hold the expanded action table
+  ** in the worst case.  The worst case occurs if the transaction set
+  ** must be appended to the current action table
+  */
+  n = p->mxLookahead + 1;
+  if( p->nAction + n >= p->nActionAlloc ){
+    int oldAlloc = p->nActionAlloc;
+    p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
+    p->aAction = realloc( p->aAction,
+                          sizeof(p->aAction[0])*p->nActionAlloc);
+    if( p->aAction==0 ){
+      fprintf(stderr,"malloc failed\n");
+      exit(1);
+    }
+    for(i=oldAlloc; i<p->nActionAlloc; i++){
+      p->aAction[i].lookahead = -1;
+      p->aAction[i].action = -1;
+    }
+  }
+
+  /* Scan the existing action table looking for an offset where we can
+  ** insert the current transaction set.  Fall out of the loop when that
+  ** offset is found.  In the worst case, we fall out of the loop when
+  ** i reaches p->nAction, which means we append the new transaction set.
+  **
+  ** i is the index in p->aAction[] where p->mnLookahead is inserted.
+  */
+  for(i=0; i<p->nAction+p->mnLookahead; i++){
+    if( p->aAction[i].lookahead<0 ){
+      for(j=0; j<p->nLookahead; j++){
+        k = p->aLookahead[j].lookahead - p->mnLookahead + i;
+        if( k<0 ) break;
+        if( p->aAction[k].lookahead>=0 ) break;
+      }
+      if( j<p->nLookahead ) continue;
+      for(j=0; j<p->nAction; j++){
+        if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
+      }
+      if( j==p->nAction ){
+        break;  /* Fits in empty slots */
+      }
+    }else if( p->aAction[i].lookahead==p->mnLookahead ){
+      if( p->aAction[i].action!=p->mnAction ) continue;
+      for(j=0; j<p->nLookahead; j++){
+        k = p->aLookahead[j].lookahead - p->mnLookahead + i;
+        if( k<0 || k>=p->nAction ) break;
+        if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
+        if( p->aLookahead[j].action!=p->aAction[k].action ) break;
+      }
+      if( j<p->nLookahead ) continue;
+      n = 0;
+      for(j=0; j<p->nAction; j++){
+        if( p->aAction[j].lookahead<0 ) continue;
+        if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
+      }
+      if( n==p->nLookahead ){
+        break;  /* Same as a prior transaction set */
+      }
+    }
+  }
+  /* Insert transaction set at index i. */
+  for(j=0; j<p->nLookahead; j++){
+    k = p->aLookahead[j].lookahead - p->mnLookahead + i;
+    p->aAction[k] = p->aLookahead[j];
+    if( k>=p->nAction ) p->nAction = k+1;
+  }
+  p->nLookahead = 0;
+
+  /* Return the offset that is added to the lookahead in order to get the
+  ** index into yy_action of the action */
+  return i - p->mnLookahead;
+}
+
+/********************** From the file "build.c" *****************************/
+/*
+** Routines to construction the finite state machine for the LEMON
+** parser generator.
+*/
+
+/* Find a precedence symbol of every rule in the grammar.
+** 
+** Those rules which have a precedence symbol coded in the input
+** grammar using the "[symbol]" construct will already have the
+** rp->precsym field filled.  Other rules take as their precedence
+** symbol the first RHS symbol with a defined precedence.  If there
+** are not RHS symbols with a defined precedence, the precedence
+** symbol field is left blank.
+*/
+void FindRulePrecedences(xp)
+struct lemon *xp;
+{
+  struct rule *rp;
+  for(rp=xp->rule; rp; rp=rp->next){
+    if( rp->precsym==0 ){
+      int i, j;
+      for(i=0; i<rp->nrhs && rp->precsym==0; i++){
+        struct symbol *sp = rp->rhs[i];
+        if( sp->type==MULTITERMINAL ){
+          for(j=0; j<sp->nsubsym; j++){
+            if( sp->subsym[j]->prec>=0 ){
+              rp->precsym = sp->subsym[j];
+              break;
+            }
+          }
+        }else if( sp->prec>=0 ){
+          rp->precsym = rp->rhs[i];
+	}
+      }
+    }
+  }
+  return;
+}
+
+/* Find all nonterminals which will generate the empty string.
+** Then go back and compute the first sets of every nonterminal.
+** The first set is the set of all terminal symbols which can begin
+** a string generated by that nonterminal.
+*/
+void FindFirstSets(lemp)
+struct lemon *lemp;
+{
+  int i, j;
+  struct rule *rp;
+  int progress;
+
+  for(i=0; i<lemp->nsymbol; i++){
+    lemp->symbols[i]->lambda = LEMON_FALSE;
+  }
+  for(i=lemp->nterminal; i<lemp->nsymbol; i++){
+    lemp->symbols[i]->firstset = SetNew();
+  }
+
+  /* First compute all lambdas */
+  do{
+    progress = 0;
+    for(rp=lemp->rule; rp; rp=rp->next){
+      if( rp->lhs->lambda ) continue;
+      for(i=0; i<rp->nrhs; i++){
+         struct symbol *sp = rp->rhs[i];
+         if( sp->type!=TERMINAL || sp->lambda==LEMON_FALSE ) break;
+      }
+      if( i==rp->nrhs ){
+        rp->lhs->lambda = LEMON_TRUE;
+        progress = 1;
+      }
+    }
+  }while( progress );
+
+  /* Now compute all first sets */
+  do{
+    struct symbol *s1, *s2;
+    progress = 0;
+    for(rp=lemp->rule; rp; rp=rp->next){
+      s1 = rp->lhs;
+      for(i=0; i<rp->nrhs; i++){
+        s2 = rp->rhs[i];
+        if( s2->type==TERMINAL ){
+          progress += SetAdd(s1->firstset,s2->index);
+          break;
+        }else if( s2->type==MULTITERMINAL ){
+          for(j=0; j<s2->nsubsym; j++){
+            progress += SetAdd(s1->firstset,s2->subsym[j]->index);
+          }
+          break;
+	}else if( s1==s2 ){
+          if( s1->lambda==LEMON_FALSE ) break;
+	}else{
+          progress += SetUnion(s1->firstset,s2->firstset);
+          if( s2->lambda==LEMON_FALSE ) break;
+	}
+      }
+    }
+  }while( progress );
+  return;
+}
+
+/* Compute all LR(0) states for the grammar.  Links
+** are added to between some states so that the LR(1) follow sets
+** can be computed later.
+*/
+PRIVATE struct state *getstate(/* struct lemon * */);  /* forward reference */
+void FindStates(lemp)
+struct lemon *lemp;
+{
+  struct symbol *sp;
+  struct rule *rp;
+
+  Configlist_init();
+
+  /* Find the start symbol */
+  if( lemp->start ){
+    sp = Symbol_find(lemp->start);
+    if( sp==0 ){
+      ErrorMsg(lemp->filename,0,
+"The specified start symbol \"%s\" is not \
+in a nonterminal of the grammar.  \"%s\" will be used as the start \
+symbol instead.",lemp->start,lemp->rule->lhs->name);
+      lemp->errorcnt++;
+      sp = lemp->rule->lhs;
+    }
+  }else{
+    sp = lemp->rule->lhs;
+  }
+
+  /* Make sure the start symbol doesn't occur on the right-hand side of
+  ** any rule.  Report an error if it does.  (YACC would generate a new
+  ** start symbol in this case.) */
+  for(rp=lemp->rule; rp; rp=rp->next){
+    int i;
+    for(i=0; i<rp->nrhs; i++){
+      if( rp->rhs[i]==sp ){   /* FIX ME:  Deal with multiterminals */
+        ErrorMsg(lemp->filename,0,
+"The start symbol \"%s\" occurs on the \
+right-hand side of a rule. This will result in a parser which \
+does not work properly.",sp->name);
+        lemp->errorcnt++;
+      }
+    }
+  }
+
+  /* The basis configuration set for the first state
+  ** is all rules which have the start symbol as their
+  ** left-hand side */
+  for(rp=sp->rule; rp; rp=rp->nextlhs){
+    struct config *newcfp;
+    rp->lhsStart = 1;
+    newcfp = Configlist_addbasis(rp,0);
+    SetAdd(newcfp->fws,0);
+  }
+
+  /* Compute the first state.  All other states will be
+  ** computed automatically during the computation of the first one.
+  ** The returned pointer to the first state is not used. */
+  (void)getstate(lemp);
+  return;
+}
+
+/* Return a pointer to a state which is described by the configuration
+** list which has been built from calls to Configlist_add.
+*/
+PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */
+PRIVATE struct state *getstate(lemp)
+struct lemon *lemp;
+{
+  struct config *cfp, *bp;
+  struct state *stp;
+
+  /* Extract the sorted basis of the new state.  The basis was constructed
+  ** by prior calls to "Configlist_addbasis()". */
+  Configlist_sortbasis();
+  bp = Configlist_basis();
+
+  /* Get a state with the same basis */
+  stp = State_find(bp);
+  if( stp ){
+    /* A state with the same basis already exists!  Copy all the follow-set
+    ** propagation links from the state under construction into the
+    ** preexisting state, then return a pointer to the preexisting state */
+    struct config *x, *y;
+    for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
+      Plink_copy(&y->bplp,x->bplp);
+      Plink_delete(x->fplp);
+      x->fplp = x->bplp = 0;
+    }
+    cfp = Configlist_return();
+    Configlist_eat(cfp);
+  }else{
+    /* This really is a new state.  Construct all the details */
+    Configlist_closure(lemp);    /* Compute the configuration closure */
+    Configlist_sort();           /* Sort the configuration closure */
+    cfp = Configlist_return();   /* Get a pointer to the config list */
+    stp = State_new();           /* A new state structure */
+    MemoryCheck(stp);
+    stp->bp = bp;                /* Remember the configuration basis */
+    stp->cfp = cfp;              /* Remember the configuration closure */
+    stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
+    stp->ap = 0;                 /* No actions, yet. */
+    State_insert(stp,stp->bp);   /* Add to the state table */
+    buildshifts(lemp,stp);       /* Recursively compute successor states */
+  }
+  return stp;
+}
+
+/*
+** Return true if two symbols are the same.
+*/
+int same_symbol(a,b)
+struct symbol *a;
+struct symbol *b;
+{
+  int i;
+  if( a==b ) return 1;
+  if( a->type!=MULTITERMINAL ) return 0;
+  if( b->type!=MULTITERMINAL ) return 0;
+  if( a->nsubsym!=b->nsubsym ) return 0;
+  for(i=0; i<a->nsubsym; i++){
+    if( a->subsym[i]!=b->subsym[i] ) return 0;
+  }
+  return 1;
+}
+
+/* Construct all successor states to the given state.  A "successor"
+** state is any state which can be reached by a shift action.
+*/
+PRIVATE void buildshifts(lemp,stp)
+struct lemon *lemp;
+struct state *stp;     /* The state from which successors are computed */
+{
+  struct config *cfp;  /* For looping thru the config closure of "stp" */
+  struct config *bcfp; /* For the inner loop on config closure of "stp" */
+  struct config *new;  /* */
+  struct symbol *sp;   /* Symbol following the dot in configuration "cfp" */
+  struct symbol *bsp;  /* Symbol following the dot in configuration "bcfp" */
+  struct state *newstp; /* A pointer to a successor state */
+
+  /* Each configuration becomes complete after it contibutes to a successor
+  ** state.  Initially, all configurations are incomplete */
+  for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
+
+  /* Loop through all configurations of the state "stp" */
+  for(cfp=stp->cfp; cfp; cfp=cfp->next){
+    if( cfp->status==COMPLETE ) continue;    /* Already used by inner loop */
+    if( cfp->dot>=cfp->rp->nrhs ) continue;  /* Can't shift this config */
+    Configlist_reset();                      /* Reset the new config set */
+    sp = cfp->rp->rhs[cfp->dot];             /* Symbol after the dot */
+
+    /* For every configuration in the state "stp" which has the symbol "sp"
+    ** following its dot, add the same configuration to the basis set under
+    ** construction but with the dot shifted one symbol to the right. */
+    for(bcfp=cfp; bcfp; bcfp=bcfp->next){
+      if( bcfp->status==COMPLETE ) continue;    /* Already used */
+      if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
+      bsp = bcfp->rp->rhs[bcfp->dot];           /* Get symbol after dot */
+      if( !same_symbol(bsp,sp) ) continue;      /* Must be same as for "cfp" */
+      bcfp->status = COMPLETE;                  /* Mark this config as used */
+      new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
+      Plink_add(&new->bplp,bcfp);
+    }
+
+    /* Get a pointer to the state described by the basis configuration set
+    ** constructed in the preceding loop */
+    newstp = getstate(lemp);
+
+    /* The state "newstp" is reached from the state "stp" by a shift action
+    ** on the symbol "sp" */
+    if( sp->type==MULTITERMINAL ){
+      int i;
+      for(i=0; i<sp->nsubsym; i++){
+        Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp);
+      }
+    }else{
+      Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
+    }
+  }
+}
+
+/*
+** Construct the propagation links
+*/
+void FindLinks(lemp)
+struct lemon *lemp;
+{
+  int i;
+  struct config *cfp, *other;
+  struct state *stp;
+  struct plink *plp;
+
+  /* Housekeeping detail:
+  ** Add to every propagate link a pointer back to the state to
+  ** which the link is attached. */
+  for(i=0; i<lemp->nstate; i++){
+    stp = lemp->sorted[i];
+    for(cfp=stp->cfp; cfp; cfp=cfp->next){
+      cfp->stp = stp;
+    }
+  }
+
+  /* Convert all backlinks into forward links.  Only the forward
+  ** links are used in the follow-set computation. */
+  for(i=0; i<lemp->nstate; i++){
+    stp = lemp->sorted[i];
+    for(cfp=stp->cfp; cfp; cfp=cfp->next){
+      for(plp=cfp->bplp; plp; plp=plp->next){
+        other = plp->cfp;
+        Plink_add(&other->fplp,cfp);
+      }
+    }
+  }
+}
+
+/* Compute all followsets.
+**
+** A followset is the set of all symbols which can come immediately
+** after a configuration.
+*/
+void FindFollowSets(lemp)
+struct lemon *lemp;
+{
+  int i;
+  struct config *cfp;
+  struct plink *plp;
+  int progress;
+  int change;
+
+  for(i=0; i<lemp->nstate; i++){
+    for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
+      cfp->status = INCOMPLETE;
+    }
+  }
+  
+  do{
+    progress = 0;
+    for(i=0; i<lemp->nstate; i++){
+      for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
+        if( cfp->status==COMPLETE ) continue;
+        for(plp=cfp->fplp; plp; plp=plp->next){
+          change = SetUnion(plp->cfp->fws,cfp->fws);
+          if( change ){
+            plp->cfp->status = INCOMPLETE;
+            progress = 1;
+	  }
+	}
+        cfp->status = COMPLETE;
+      }
+    }
+  }while( progress );
+}
+
+static int resolve_conflict();
+
+/* Compute the reduce actions, and resolve conflicts.
+*/
+void FindActions(lemp)
+struct lemon *lemp;
+{
+  int i,j;
+  struct config *cfp;
+  struct state *stp;
+  struct symbol *sp;
+  struct rule *rp;
+
+  /* Add all of the reduce actions 
+  ** A reduce action is added for each element of the followset of
+  ** a configuration which has its dot at the extreme right.
+  */
+  for(i=0; i<lemp->nstate; i++){   /* Loop over all states */
+    stp = lemp->sorted[i];
+    for(cfp=stp->cfp; cfp; cfp=cfp->next){  /* Loop over all configurations */
+      if( cfp->rp->nrhs==cfp->dot ){        /* Is dot at extreme right? */
+        for(j=0; j<lemp->nterminal; j++){
+          if( SetFind(cfp->fws,j) ){
+            /* Add a reduce action to the state "stp" which will reduce by the
+            ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
+            Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
+          }
+	}
+      }
+    }
+  }
+
+  /* Add the accepting token */
+  if( lemp->start ){
+    sp = Symbol_find(lemp->start);
+    if( sp==0 ) sp = lemp->rule->lhs;
+  }else{
+    sp = lemp->rule->lhs;
+  }
+  /* Add to the first state (which is always the starting state of the
+  ** finite state machine) an action to ACCEPT if the lookahead is the
+  ** start nonterminal.  */
+  Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
+
+  /* Resolve conflicts */
+  for(i=0; i<lemp->nstate; i++){
+    struct action *ap, *nap;
+    struct state *stp;
+    stp = lemp->sorted[i];
+    /* assert( stp->ap ); */
+    stp->ap = Action_sort(stp->ap);
+    for(ap=stp->ap; ap && ap->next; ap=ap->next){
+      for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
+         /* The two actions "ap" and "nap" have the same lookahead.
+         ** Figure out which one should be used */
+         lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
+      }
+    }
+  }
+
+  /* Report an error for each rule that can never be reduced. */
+  for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE;
+  for(i=0; i<lemp->nstate; i++){
+    struct action *ap;
+    for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
+      if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE;
+    }
+  }
+  for(rp=lemp->rule; rp; rp=rp->next){
+    if( rp->canReduce ) continue;
+    ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
+    lemp->errorcnt++;
+  }
+}
+
+/* Resolve a conflict between the two given actions.  If the
+** conflict can't be resolve, return non-zero.
+**
+** NO LONGER TRUE:
+**   To resolve a conflict, first look to see if either action
+**   is on an error rule.  In that case, take the action which
+**   is not associated with the error rule.  If neither or both
+**   actions are associated with an error rule, then try to
+**   use precedence to resolve the conflict.
+**
+** If either action is a SHIFT, then it must be apx.  This
+** function won't work if apx->type==REDUCE and apy->type==SHIFT.
+*/
+static int resolve_conflict(apx,apy,errsym)
+struct action *apx;
+struct action *apy;
+struct symbol *errsym;   /* The error symbol (if defined.  NULL otherwise) */
+{
+  struct symbol *spx, *spy;
+  int errcnt = 0;
+  assert( apx->sp==apy->sp );  /* Otherwise there would be no conflict */
+  if( apx->type==SHIFT && apy->type==SHIFT ){
+    apy->type = SSCONFLICT;
+    errcnt++;
+  }
+  if( apx->type==SHIFT && apy->type==REDUCE ){
+    spx = apx->sp;
+    spy = apy->x.rp->precsym;
+    if( spy==0 || spx->prec<0 || spy->prec<0 ){
+      /* Not enough precedence information. */
+      apy->type = SRCONFLICT;
+      errcnt++;
+    }else if( spx->prec>spy->prec ){    /* Lower precedence wins */
+      apy->type = RD_RESOLVED;
+    }else if( spx->prec<spy->prec ){
+      apx->type = SH_RESOLVED;
+    }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
+      apy->type = RD_RESOLVED;                             /* associativity */
+    }else if( spx->prec==spy->prec && spx->assoc==LEFT ){  /* to break tie */
+      apx->type = SH_RESOLVED;
+    }else{
+      assert( spx->prec==spy->prec && spx->assoc==NONE );
+      apy->type = SRCONFLICT;
+      errcnt++;
+    }
+  }else if( apx->type==REDUCE && apy->type==REDUCE ){
+    spx = apx->x.rp->precsym;
+    spy = apy->x.rp->precsym;
+    if( spx==0 || spy==0 || spx->prec<0 ||
+    spy->prec<0 || spx->prec==spy->prec ){
+      apy->type = RRCONFLICT;
+      errcnt++;
+    }else if( spx->prec>spy->prec ){
+      apy->type = RD_RESOLVED;
+    }else if( spx->prec<spy->prec ){
+      apx->type = RD_RESOLVED;
+    }
+  }else{
+    assert( 
+      apx->type==SH_RESOLVED ||
+      apx->type==RD_RESOLVED ||
+      apx->type==SSCONFLICT ||
+      apx->type==SRCONFLICT ||
+      apx->type==RRCONFLICT ||
+      apy->type==SH_RESOLVED ||
+      apy->type==RD_RESOLVED ||
+      apy->type==SSCONFLICT ||
+      apy->type==SRCONFLICT ||
+      apy->type==RRCONFLICT
+    );
+    /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
+    ** REDUCEs on the list.  If we reach this point it must be because
+    ** the parser conflict had already been resolved. */
+  }
+  return errcnt;
+}
+/********************* From the file "configlist.c" *************************/
+/*
+** Routines to processing a configuration list and building a state
+** in the LEMON parser generator.
+*/
+
+static struct config *freelist = 0;      /* List of free configurations */
+static struct config *current = 0;       /* Top of list of configurations */
+static struct config **currentend = 0;   /* Last on list of configs */
+static struct config *basis = 0;         /* Top of list of basis configs */
+static struct config **basisend = 0;     /* End of list of basis configs */
+
+/* Return a pointer to a new configuration */
+PRIVATE struct config *newconfig(){
+  struct config *new;
+  if( freelist==0 ){
+    int i;
+    int amt = 3;
+    freelist = (struct config *)calloc( amt, sizeof(struct config) );
+    if( freelist==0 ){
+      fprintf(stderr,"Unable to allocate memory for a new configuration.");
+      exit(1);
+    }
+    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
+    freelist[amt-1].next = 0;
+  }
+  new = freelist;
+  freelist = freelist->next;
+  return new;
+}
+
+/* The configuration "old" is no longer used */
+PRIVATE void deleteconfig(old)
+struct config *old;
+{
+  old->next = freelist;
+  freelist = old;
+}
+
+/* Initialized the configuration list builder */
+void Configlist_init(){
+  current = 0;
+  currentend = &current;
+  basis = 0;
+  basisend = &basis;
+  Configtable_init();
+  return;
+}
+
+/* Initialized the configuration list builder */
+void Configlist_reset(){
+  current = 0;
+  currentend = &current;
+  basis = 0;
+  basisend = &basis;
+  Configtable_clear(0);
+  return;
+}
+
+/* Add another configuration to the configuration list */
+struct config *Configlist_add(rp,dot)
+struct rule *rp;    /* The rule */
+int dot;            /* Index into the RHS of the rule where the dot goes */
+{
+  struct config *cfp, model;
+
+  assert( currentend!=0 );
+  model.rp = rp;
+  model.dot = dot;
+  cfp = Configtable_find(&model);
+  if( cfp==0 ){
+    cfp = newconfig();
+    cfp->rp = rp;
+    cfp->dot = dot;
+    cfp->fws = SetNew();
+    cfp->stp = 0;
+    cfp->fplp = cfp->bplp = 0;
+    cfp->next = 0;
+    cfp->bp = 0;
+    *currentend = cfp;
+    currentend = &cfp->next;
+    Configtable_insert(cfp);
+  }
+  return cfp;
+}
+
+/* Add a basis configuration to the configuration list */
+struct config *Configlist_addbasis(rp,dot)
+struct rule *rp;
+int dot;
+{
+  struct config *cfp, model;
+
+  assert( basisend!=0 );
+  assert( currentend!=0 );
+  model.rp = rp;
+  model.dot = dot;
+  cfp = Configtable_find(&model);
+  if( cfp==0 ){
+    cfp = newconfig();
+    cfp->rp = rp;
+    cfp->dot = dot;
+    cfp->fws = SetNew();
+    cfp->stp = 0;
+    cfp->fplp = cfp->bplp = 0;
+    cfp->next = 0;
+    cfp->bp = 0;
+    *currentend = cfp;
+    currentend = &cfp->next;
+    *basisend = cfp;
+    basisend = &cfp->bp;
+    Configtable_insert(cfp);
+  }
+  return cfp;
+}
+
+/* Compute the closure of the configuration list */
+void Configlist_closure(lemp)
+struct lemon *lemp;
+{
+  struct config *cfp, *newcfp;
+  struct rule *rp, *newrp;
+  struct symbol *sp, *xsp;
+  int i, dot;
+
+  assert( currentend!=0 );
+  for(cfp=current; cfp; cfp=cfp->next){
+    rp = cfp->rp;
+    dot = cfp->dot;
+    if( dot>=rp->nrhs ) continue;
+    sp = rp->rhs[dot];
+    if( sp->type==NONTERMINAL ){
+      if( sp->rule==0 && sp!=lemp->errsym ){
+        ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
+          sp->name);
+        lemp->errorcnt++;
+      }
+      for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
+        newcfp = Configlist_add(newrp,0);
+        for(i=dot+1; i<rp->nrhs; i++){
+          xsp = rp->rhs[i];
+          if( xsp->type==TERMINAL ){
+            SetAdd(newcfp->fws,xsp->index);
+            break;
+          }else if( xsp->type==MULTITERMINAL ){
+            int k;
+            for(k=0; k<xsp->nsubsym; k++){
+              SetAdd(newcfp->fws, xsp->subsym[k]->index);
+            }
+            break;
+	  }else{
+            SetUnion(newcfp->fws,xsp->firstset);
+            if( xsp->lambda==LEMON_FALSE ) break;
+	  }
+	}
+        if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
+      }
+    }
+  }
+  return;
+}
+
+/* Sort the configuration list */
+void Configlist_sort(){
+  current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp);
+  currentend = 0;
+  return;
+}
+
+/* Sort the basis configuration list */
+void Configlist_sortbasis(){
+  basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp);
+  basisend = 0;
+  return;
+}
+
+/* Return a pointer to the head of the configuration list and
+** reset the list */
+struct config *Configlist_return(){
+  struct config *old;
+  old = current;
+  current = 0;
+  currentend = 0;
+  return old;
+}
+
+/* Return a pointer to the head of the configuration list and
+** reset the list */
+struct config *Configlist_basis(){
+  struct config *old;
+  old = basis;
+  basis = 0;
+  basisend = 0;
+  return old;
+}
+
+/* Free all elements of the given configuration list */
+void Configlist_eat(cfp)
+struct config *cfp;
+{
+  struct config *nextcfp;
+  for(; cfp; cfp=nextcfp){
+    nextcfp = cfp->next;
+    assert( cfp->fplp==0 );
+    assert( cfp->bplp==0 );
+    if( cfp->fws ) SetFree(cfp->fws);
+    deleteconfig(cfp);
+  }
+  return;
+}
+/***************** From the file "error.c" *********************************/
+/*
+** Code for printing error message.
+*/
+
+/* Find a good place to break "msg" so that its length is at least "min"
+** but no more than "max".  Make the point as close to max as possible.
+*/
+static int findbreak(msg,min,max)
+char *msg;
+int min;
+int max;
+{
+  int i,spot;
+  char c;
+  for(i=spot=min; i<=max; i++){
+    c = msg[i];
+    if( c=='\t' ) msg[i] = ' ';
+    if( c=='\n' ){ msg[i] = ' '; spot = i; break; }
+    if( c==0 ){ spot = i; break; }
+    if( c=='-' && i<max-1 ) spot = i+1;
+    if( c==' ' ) spot = i;
+  }
+  return spot;
+}
+
+/*
+** The error message is split across multiple lines if necessary.  The
+** splits occur at a space, if there is a space available near the end
+** of the line.
+*/
+#define ERRMSGSIZE  10000 /* Hope this is big enough.  No way to error check */
+#define LINEWIDTH      79 /* Max width of any output line */
+#define PREFIXLIMIT    30 /* Max width of the prefix on each line */
+void ErrorMsg(const char *filename, int lineno, const char *format, ...){
+  char errmsg[ERRMSGSIZE];
+  char prefix[PREFIXLIMIT+10];
+  int errmsgsize;
+  int prefixsize;
+  int availablewidth;
+  va_list ap;
+  int end, restart, base;
+
+  va_start(ap, format);
+  /* Prepare a prefix to be prepended to every output line */
+  if( lineno>0 ){
+    sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
+  }else{
+    sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
+  }
+  prefixsize = strlen(prefix);
+  availablewidth = LINEWIDTH - prefixsize;
+
+  /* Generate the error message */
+  vsprintf(errmsg,format,ap);
+  va_end(ap);
+  errmsgsize = strlen(errmsg);
+  /* Remove trailing '\n's from the error message. */
+  while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
+     errmsg[--errmsgsize] = 0;
+  }
+
+  /* Print the error message */
+  base = 0;
+  while( errmsg[base]!=0 ){
+    end = restart = findbreak(&errmsg[base],0,availablewidth);
+    restart += base;
+    while( errmsg[restart]==' ' ) restart++;
+    fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
+    base = restart;
+  }
+}
+/**************** From the file "main.c" ************************************/
+/*
+** Main program file for the LEMON parser generator.
+*/
+
+/* Report an out-of-memory condition and abort.  This function
+** is used mostly by the "MemoryCheck" macro in struct.h
+*/
+void memory_error(){
+  fprintf(stderr,"Out of memory.  Aborting...\n");
+  exit(1);
+}
+
+static int nDefine = 0;      /* Number of -D options on the command line */
+static char **azDefine = 0;  /* Name of the -D macros */
+
+/* This routine is called with the argument to each -D command-line option.
+** Add the macro defined to the azDefine array.
+*/
+static void handle_D_option(char *z){
+  char **paz;
+  nDefine++;
+  azDefine = realloc(azDefine, sizeof(azDefine[0])*nDefine);
+  if( azDefine==0 ){
+    fprintf(stderr,"out of memory\n");
+    exit(1);
+  }
+  paz = &azDefine[nDefine-1];
+  *paz = malloc( strlen(z)+1 );
+  if( *paz==0 ){
+    fprintf(stderr,"out of memory\n");
+    exit(1);
+  }
+  strcpy(*paz, z);
+  for(z=*paz; *z && *z!='='; z++){}
+  *z = 0;
+}
+
+
+/* The main program.  Parse the command line and do it... */
+int main(argc,argv)
+int argc;
+char **argv;
+{
+  static int version = 0;
+  static int rpflag = 0;
+  static int basisflag = 0;
+  static int compress = 0;
+  static int quiet = 0;
+  static int statistics = 0;
+  static int mhflag = 0;
+  static struct s_options options[] = {
+    {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
+    {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
+    {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
+    {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
+    {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
+    {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
+    {OPT_FLAG, "s", (char*)&statistics,
+                                   "Print parser stats to standard output."},
+    {OPT_FLAG, "x", (char*)&version, "Print the version number."},
+    {OPT_FLAG,0,0,0}
+  };
+  int i;
+  struct lemon lem;
+
+  OptInit(argv,options,stderr);
+  if( version ){
+     printf("Lemon version 1.0\n");
+     exit(0); 
+  }
+  if( OptNArgs()!=1 ){
+    fprintf(stderr,"Exactly one filename argument is required.\n");
+    exit(1);
+  }
+  memset(&lem, 0, sizeof(lem));
+  lem.errorcnt = 0;
+
+  /* Initialize the machine */
+  Strsafe_init();
+  Symbol_init();
+  State_init();
+  lem.argv0 = argv[0];
+  lem.filename = OptArg(0);
+  lem.basisflag = basisflag;
+  Symbol_new("$");
+  lem.errsym = Symbol_new("error");
+  lem.errsym->useCnt = 0;
+
+  /* Parse the input file */
+  Parse(&lem);
+  if( lem.errorcnt ) exit(lem.errorcnt);
+  if( lem.nrule==0 ){
+    fprintf(stderr,"Empty grammar.\n");
+    exit(1);
+  }
+
+  /* Count and index the symbols of the grammar */
+  lem.nsymbol = Symbol_count();
+  Symbol_new("{default}");
+  lem.symbols = Symbol_arrayof();
+  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
+  qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
+        (int(*)())Symbolcmpp);
+  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
+  for(i=1; isupper(lem.symbols[i]->name[0]); i++);
+  lem.nterminal = i;
+
+  /* Generate a reprint of the grammar, if requested on the command line */
+  if( rpflag ){
+    Reprint(&lem);
+  }else{
+    /* Initialize the size for all follow and first sets */
+    SetSize(lem.nterminal+1);
+
+    /* Find the precedence for every production rule (that has one) */
+    FindRulePrecedences(&lem);
+
+    /* Compute the lambda-nonterminals and the first-sets for every
+    ** nonterminal */
+    FindFirstSets(&lem);
+
+    /* Compute all LR(0) states.  Also record follow-set propagation
+    ** links so that the follow-set can be computed later */
+    lem.nstate = 0;
+    FindStates(&lem);
+    lem.sorted = State_arrayof();
+
+    /* Tie up loose ends on the propagation links */
+    FindLinks(&lem);
+
+    /* Compute the follow set of every reducible configuration */
+    FindFollowSets(&lem);
+
+    /* Compute the action tables */
+    FindActions(&lem);
+
+    /* Compress the action tables */
+    if( compress==0 ) CompressTables(&lem);
+
+    /* Reorder and renumber the states so that states with fewer choices
+    ** occur at the end. */
+    ResortStates(&lem);
+
+    /* Generate a report of the parser generated.  (the "y.output" file) */
+    if( !quiet ) ReportOutput(&lem);
+
+    /* Generate the source code for the parser */
+    ReportTable(&lem, mhflag);
+
+    /* Produce a header file for use by the scanner.  (This step is
+    ** omitted if the "-m" option is used because makeheaders will
+    ** generate the file for us.) */
+    if( !mhflag ) ReportHeader(&lem);
+  }
+  if( statistics ){
+    printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
+      lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
+    printf("                   %d states, %d parser table entries, %d conflicts\n",
+      lem.nstate, lem.tablesize, lem.nconflict);
+  }
+  if( lem.nconflict ){
+    fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
+  }
+  exit(lem.errorcnt + lem.nconflict);
+  return (lem.errorcnt + lem.nconflict);
+}
+/******************** From the file "msort.c" *******************************/
+/*
+** A generic merge-sort program.
+**
+** USAGE:
+** Let "ptr" be a pointer to some structure which is at the head of
+** a null-terminated list.  Then to sort the list call:
+**
+**     ptr = msort(ptr,&(ptr->next),cmpfnc);
+**
+** In the above, "cmpfnc" is a pointer to a function which compares
+** two instances of the structure and returns an integer, as in
+** strcmp.  The second argument is a pointer to the pointer to the
+** second element of the linked list.  This address is used to compute
+** the offset to the "next" field within the structure.  The offset to
+** the "next" field must be constant for all structures in the list.
+**
+** The function returns a new pointer which is the head of the list
+** after sorting.
+**
+** ALGORITHM:
+** Merge-sort.
+*/
+
+/*
+** Return a pointer to the next structure in the linked list.
+*/
+#define NEXT(A) (*(char**)(((unsigned long)A)+offset))
+
+/*
+** Inputs:
+**   a:       A sorted, null-terminated linked list.  (May be null).
+**   b:       A sorted, null-terminated linked list.  (May be null).
+**   cmp:     A pointer to the comparison function.
+**   offset:  Offset in the structure to the "next" field.
+**
+** Return Value:
+**   A pointer to the head of a sorted list containing the elements
+**   of both a and b.
+**
+** Side effects:
+**   The "next" pointers for elements in the lists a and b are
+**   changed.
+*/
+static char *merge(
+  char *a,
+  char *b,
+  int (*cmp)(const char*,const char*),
+  int offset
+){
+  char *ptr, *head;
+
+  if( a==0 ){
+    head = b;
+  }else if( b==0 ){
+    head = a;
+  }else{
+    if( (*cmp)(a,b)<0 ){
+      ptr = a;
+      a = NEXT(a);
+    }else{
+      ptr = b;
+      b = NEXT(b);
+    }
+    head = ptr;
+    while( a && b ){
+      if( (*cmp)(a,b)<0 ){
+        NEXT(ptr) = a;
+        ptr = a;
+        a = NEXT(a);
+      }else{
+        NEXT(ptr) = b;
+        ptr = b;
+        b = NEXT(b);
+      }
+    }
+    if( a ) NEXT(ptr) = a;
+    else    NEXT(ptr) = b;
+  }
+  return head;
+}
+
+/*
+** Inputs:
+**   list:      Pointer to a singly-linked list of structures.
+**   next:      Pointer to pointer to the second element of the list.
+**   cmp:       A comparison function.
+**
+** Return Value:
+**   A pointer to the head of a sorted list containing the elements
+**   orginally in list.
+**
+** Side effects:
+**   The "next" pointers for elements in list are changed.
+*/
+#define LISTSIZE 30
+static char *msort(
+  char *list,
+  char **next,
+  int (*cmp)(const char*,const char*)
+){
+  unsigned long offset;
+  char *ep;
+  char *set[LISTSIZE];
+  int i;
+  offset = (unsigned long)next - (unsigned long)list;
+  for(i=0; i<LISTSIZE; i++) set[i] = 0;
+  while( list ){
+    ep = list;
+    list = NEXT(list);
+    NEXT(ep) = 0;
+    for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
+      ep = merge(ep,set[i],cmp,offset);
+      set[i] = 0;
+    }
+    set[i] = ep;
+  }
+  ep = 0;
+  for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
+  return ep;
+}
+/************************ From the file "option.c" **************************/
+static char **argv;
+static struct s_options *op;
+static FILE *errstream;
+
+#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
+
+/*
+** Print the command line with a carrot pointing to the k-th character
+** of the n-th field.
+*/
+static void errline(n,k,err)
+int n;
+int k;
+FILE *err;
+{
+  int spcnt, i;
+  if( argv[0] ) fprintf(err,"%s",argv[0]);
+  spcnt = strlen(argv[0]) + 1;
+  for(i=1; i<n && argv[i]; i++){
+    fprintf(err," %s",argv[i]);
+    spcnt += strlen(argv[i])+1;
+  }
+  spcnt += k;
+  for(; argv[i]; i++) fprintf(err," %s",argv[i]);
+  if( spcnt<20 ){
+    fprintf(err,"\n%*s^-- here\n",spcnt,"");
+  }else{
+    fprintf(err,"\n%*shere --^\n",spcnt-7,"");
+  }
+}
+
+/*
+** Return the index of the N-th non-switch argument.  Return -1
+** if N is out of range.
+*/
+static int argindex(n)
+int n;
+{
+  int i;
+  int dashdash = 0;
+  if( argv!=0 && *argv!=0 ){
+    for(i=1; argv[i]; i++){
+      if( dashdash || !ISOPT(argv[i]) ){
+        if( n==0 ) return i;
+        n--;
+      }
+      if( strcmp(argv[i],"--")==0 ) dashdash = 1;
+    }
+  }
+  return -1;
+}
+
+static char emsg[] = "Command line syntax error: ";
+
+/*
+** Process a flag command line argument.
+*/
+static int handleflags(i,err)
+int i;
+FILE *err;
+{
+  int v;
+  int errcnt = 0;
+  int j;
+  for(j=0; op[j].label; j++){
+    if( strncmp(&argv[i][1],op[j].label,strlen(op[j].label))==0 ) break;
+  }
+  v = argv[i][0]=='-' ? 1 : 0;
+  if( op[j].label==0 ){
+    if( err ){
+      fprintf(err,"%sundefined option.\n",emsg);
+      errline(i,1,err);
+    }
+    errcnt++;
+  }else if( op[j].type==OPT_FLAG ){
+    *((int*)op[j].arg) = v;
+  }else if( op[j].type==OPT_FFLAG ){
+    (*(void(*)())(op[j].arg))(v);
+  }else if( op[j].type==OPT_FSTR ){
+    (*(void(*)())(op[j].arg))(&argv[i][2]);
+  }else{
+    if( err ){
+      fprintf(err,"%smissing argument on switch.\n",emsg);
+      errline(i,1,err);
+    }
+    errcnt++;
+  }
+  return errcnt;
+}
+
+/*
+** Process a command line switch which has an argument.
+*/
+static int handleswitch(i,err)
+int i;
+FILE *err;
+{
+  int lv = 0;
+  double dv = 0.0;
+  char *sv = 0, *end;
+  char *cp;
+  int j;
+  int errcnt = 0;
+  cp = strchr(argv[i],'=');
+  assert( cp!=0 );
+  *cp = 0;
+  for(j=0; op[j].label; j++){
+    if( strcmp(argv[i],op[j].label)==0 ) break;
+  }
+  *cp = '=';
+  if( op[j].label==0 ){
+    if( err ){
+      fprintf(err,"%sundefined option.\n",emsg);
+      errline(i,0,err);
+    }
+    errcnt++;
+  }else{
+    cp++;
+    switch( op[j].type ){
+      case OPT_FLAG:
+      case OPT_FFLAG:
+        if( err ){
+          fprintf(err,"%soption requires an argument.\n",emsg);
+          errline(i,0,err);
+        }
+        errcnt++;
+        break;
+      case OPT_DBL:
+      case OPT_FDBL:
+        dv = strtod(cp,&end);
+        if( *end ){
+          if( err ){
+            fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
+            errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
+          }
+          errcnt++;
+        }
+        break;
+      case OPT_INT:
+      case OPT_FINT:
+        lv = strtol(cp,&end,0);
+        if( *end ){
+          if( err ){
+            fprintf(err,"%sillegal character in integer argument.\n",emsg);
+            errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
+          }
+          errcnt++;
+        }
+        break;
+      case OPT_STR:
+      case OPT_FSTR:
+        sv = cp;
+        break;
+    }
+    switch( op[j].type ){
+      case OPT_FLAG:
+      case OPT_FFLAG:
+        break;
+      case OPT_DBL:
+        *(double*)(op[j].arg) = dv;
+        break;
+      case OPT_FDBL:
+        (*(void(*)())(op[j].arg))(dv);
+        break;
+      case OPT_INT:
+        *(int*)(op[j].arg) = lv;
+        break;
+      case OPT_FINT:
+        (*(void(*)())(op[j].arg))((int)lv);
+        break;
+      case OPT_STR:
+        *(char**)(op[j].arg) = sv;
+        break;
+      case OPT_FSTR:
+        (*(void(*)())(op[j].arg))(sv);
+        break;
+    }
+  }
+  return errcnt;
+}
+
+int OptInit(a,o,err)
+char **a;
+struct s_options *o;
+FILE *err;
+{
+  int errcnt = 0;
+  argv = a;
+  op = o;
+  errstream = err;
+  if( argv && *argv && op ){
+    int i;
+    for(i=1; argv[i]; i++){
+      if( argv[i][0]=='+' || argv[i][0]=='-' ){
+        errcnt += handleflags(i,err);
+      }else if( strchr(argv[i],'=') ){
+        errcnt += handleswitch(i,err);
+      }
+    }
+  }
+  if( errcnt>0 ){
+    fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
+    OptPrint();
+    exit(1);
+  }
+  return 0;
+}
+
+int OptNArgs(){
+  int cnt = 0;
+  int dashdash = 0;
+  int i;
+  if( argv!=0 && argv[0]!=0 ){
+    for(i=1; argv[i]; i++){
+      if( dashdash || !ISOPT(argv[i]) ) cnt++;
+      if( strcmp(argv[i],"--")==0 ) dashdash = 1;
+    }
+  }
+  return cnt;
+}
+
+char *OptArg(n)
+int n;
+{
+  int i;
+  i = argindex(n);
+  return i>=0 ? argv[i] : 0;
+}
+
+void OptErr(n)
+int n;
+{
+  int i;
+  i = argindex(n);
+  if( i>=0 ) errline(i,0,errstream);
+}
+
+void OptPrint(){
+  int i;
+  int max, len;
+  max = 0;
+  for(i=0; op[i].label; i++){
+    len = strlen(op[i].label) + 1;
+    switch( op[i].type ){
+      case OPT_FLAG:
+      case OPT_FFLAG:
+        break;
+      case OPT_INT:
+      case OPT_FINT:
+        len += 9;       /* length of "<integer>" */
+        break;
+      case OPT_DBL:
+      case OPT_FDBL:
+        len += 6;       /* length of "<real>" */
+        break;
+      case OPT_STR:
+      case OPT_FSTR:
+        len += 8;       /* length of "<string>" */
+        break;
+    }
+    if( len>max ) max = len;
+  }
+  for(i=0; op[i].label; i++){
+    switch( op[i].type ){
+      case OPT_FLAG:
+      case OPT_FFLAG:
+        fprintf(errstream,"  -%-*s  %s\n",max,op[i].label,op[i].message);
+        break;
+      case OPT_INT:
+      case OPT_FINT:
+        fprintf(errstream,"  %s=<integer>%*s  %s\n",op[i].label,
+          (int)(max-strlen(op[i].label)-9),"",op[i].message);
+        break;
+      case OPT_DBL:
+      case OPT_FDBL:
+        fprintf(errstream,"  %s=<real>%*s  %s\n",op[i].label,
+          (int)(max-strlen(op[i].label)-6),"",op[i].message);
+        break;
+      case OPT_STR:
+      case OPT_FSTR:
+        fprintf(errstream,"  %s=<string>%*s  %s\n",op[i].label,
+          (int)(max-strlen(op[i].label)-8),"",op[i].message);
+        break;
+    }
+  }
+}
+/*********************** From the file "parse.c" ****************************/
+/*
+** Input file parser for the LEMON parser generator.
+*/
+
+/* The state of the parser */
+struct pstate {
+  char *filename;       /* Name of the input file */
+  int tokenlineno;      /* Linenumber at which current token starts */
+  int errorcnt;         /* Number of errors so far */
+  char *tokenstart;     /* Text of current token */
+  struct lemon *gp;     /* Global state vector */
+  enum e_state {
+    INITIALIZE,
+    WAITING_FOR_DECL_OR_RULE,
+    WAITING_FOR_DECL_KEYWORD,
+    WAITING_FOR_DECL_ARG,
+    WAITING_FOR_PRECEDENCE_SYMBOL,
+    WAITING_FOR_ARROW,
+    IN_RHS,
+    LHS_ALIAS_1,
+    LHS_ALIAS_2,
+    LHS_ALIAS_3,
+    RHS_ALIAS_1,
+    RHS_ALIAS_2,
+    PRECEDENCE_MARK_1,
+    PRECEDENCE_MARK_2,
+    RESYNC_AFTER_RULE_ERROR,
+    RESYNC_AFTER_DECL_ERROR,
+    WAITING_FOR_DESTRUCTOR_SYMBOL,
+    WAITING_FOR_DATATYPE_SYMBOL,
+    WAITING_FOR_FALLBACK_ID,
+    WAITING_FOR_WILDCARD_ID
+  } state;                   /* The state of the parser */
+  struct symbol *fallback;   /* The fallback token */
+  struct symbol *lhs;        /* Left-hand side of current rule */
+  char *lhsalias;            /* Alias for the LHS */
+  int nrhs;                  /* Number of right-hand side symbols seen */
+  struct symbol *rhs[MAXRHS];  /* RHS symbols */
+  char *alias[MAXRHS];       /* Aliases for each RHS symbol (or NULL) */
+  struct rule *prevrule;     /* Previous rule parsed */
+  char *declkeyword;         /* Keyword of a declaration */
+  char **declargslot;        /* Where the declaration argument should be put */
+  int *decllnslot;           /* Where the declaration linenumber is put */
+  enum e_assoc declassoc;    /* Assign this association to decl arguments */
+  int preccounter;           /* Assign this precedence to decl arguments */
+  struct rule *firstrule;    /* Pointer to first rule in the grammar */
+  struct rule *lastrule;     /* Pointer to the most recently parsed rule */
+};
+
+/* Parse a single token */
+static void parseonetoken(psp)
+struct pstate *psp;
+{
+  char *x;
+  x = Strsafe(psp->tokenstart);     /* Save the token permanently */
+#if 0
+  printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
+    x,psp->state);
+#endif
+  switch( psp->state ){
+    case INITIALIZE:
+      psp->prevrule = 0;
+      psp->preccounter = 0;
+      psp->firstrule = psp->lastrule = 0;
+      psp->gp->nrule = 0;
+      /* Fall thru to next case */
+    case WAITING_FOR_DECL_OR_RULE:
+      if( x[0]=='%' ){
+        psp->state = WAITING_FOR_DECL_KEYWORD;
+      }else if( islower(x[0]) ){
+        psp->lhs = Symbol_new(x);
+        psp->nrhs = 0;
+        psp->lhsalias = 0;
+        psp->state = WAITING_FOR_ARROW;
+      }else if( x[0]=='{' ){
+        if( psp->prevrule==0 ){
+          ErrorMsg(psp->filename,psp->tokenlineno,
+"There is not prior rule opon which to attach the code \
+fragment which begins on this line.");
+          psp->errorcnt++;
+	}else if( psp->prevrule->code!=0 ){
+          ErrorMsg(psp->filename,psp->tokenlineno,
+"Code fragment beginning on this line is not the first \
+to follow the previous rule.");
+          psp->errorcnt++;
+        }else{
+          psp->prevrule->line = psp->tokenlineno;
+          psp->prevrule->code = &x[1];
+	}
+      }else if( x[0]=='[' ){
+        psp->state = PRECEDENCE_MARK_1;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Token \"%s\" should be either \"%%\" or a nonterminal name.",
+          x);
+        psp->errorcnt++;
+      }
+      break;
+    case PRECEDENCE_MARK_1:
+      if( !isupper(x[0]) ){
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "The precedence symbol must be a terminal.");
+        psp->errorcnt++;
+      }else if( psp->prevrule==0 ){
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "There is no prior rule to assign precedence \"[%s]\".",x);
+        psp->errorcnt++;
+      }else if( psp->prevrule->precsym!=0 ){
+        ErrorMsg(psp->filename,psp->tokenlineno,
+"Precedence mark on this line is not the first \
+to follow the previous rule.");
+        psp->errorcnt++;
+      }else{
+        psp->prevrule->precsym = Symbol_new(x);
+      }
+      psp->state = PRECEDENCE_MARK_2;
+      break;
+    case PRECEDENCE_MARK_2:
+      if( x[0]!=']' ){
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Missing \"]\" on precedence mark.");
+        psp->errorcnt++;
+      }
+      psp->state = WAITING_FOR_DECL_OR_RULE;
+      break;
+    case WAITING_FOR_ARROW:
+      if( x[0]==':' && x[1]==':' && x[2]=='=' ){
+        psp->state = IN_RHS;
+      }else if( x[0]=='(' ){
+        psp->state = LHS_ALIAS_1;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Expected to see a \":\" following the LHS symbol \"%s\".",
+          psp->lhs->name);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_RULE_ERROR;
+      }
+      break;
+    case LHS_ALIAS_1:
+      if( isalpha(x[0]) ){
+        psp->lhsalias = x;
+        psp->state = LHS_ALIAS_2;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "\"%s\" is not a valid alias for the LHS \"%s\"\n",
+          x,psp->lhs->name);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_RULE_ERROR;
+      }
+      break;
+    case LHS_ALIAS_2:
+      if( x[0]==')' ){
+        psp->state = LHS_ALIAS_3;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_RULE_ERROR;
+      }
+      break;
+    case LHS_ALIAS_3:
+      if( x[0]==':' && x[1]==':' && x[2]=='=' ){
+        psp->state = IN_RHS;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Missing \"->\" following: \"%s(%s)\".",
+           psp->lhs->name,psp->lhsalias);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_RULE_ERROR;
+      }
+      break;
+    case IN_RHS:
+      if( x[0]=='.' ){
+        struct rule *rp;
+        rp = (struct rule *)calloc( sizeof(struct rule) + 
+             sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
+        if( rp==0 ){
+          ErrorMsg(psp->filename,psp->tokenlineno,
+            "Can't allocate enough memory for this rule.");
+          psp->errorcnt++;
+          psp->prevrule = 0;
+	}else{
+          int i;
+          rp->ruleline = psp->tokenlineno;
+          rp->rhs = (struct symbol**)&rp[1];
+          rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
+          for(i=0; i<psp->nrhs; i++){
+            rp->rhs[i] = psp->rhs[i];
+            rp->rhsalias[i] = psp->alias[i];
+	  }
+          rp->lhs = psp->lhs;
+          rp->lhsalias = psp->lhsalias;
+          rp->nrhs = psp->nrhs;
+          rp->code = 0;
+          rp->precsym = 0;
+          rp->index = psp->gp->nrule++;
+          rp->nextlhs = rp->lhs->rule;
+          rp->lhs->rule = rp;
+          rp->next = 0;
+          if( psp->firstrule==0 ){
+            psp->firstrule = psp->lastrule = rp;
+	  }else{
+            psp->lastrule->next = rp;
+            psp->lastrule = rp;
+	  }
+          psp->prevrule = rp;
+	}
+        psp->state = WAITING_FOR_DECL_OR_RULE;
+      }else if( isalpha(x[0]) ){
+        if( psp->nrhs>=MAXRHS ){
+          ErrorMsg(psp->filename,psp->tokenlineno,
+            "Too many symbols on RHS of rule beginning at \"%s\".",
+            x);
+          psp->errorcnt++;
+          psp->state = RESYNC_AFTER_RULE_ERROR;
+	}else{
+          psp->rhs[psp->nrhs] = Symbol_new(x);
+          psp->alias[psp->nrhs] = 0;
+          psp->nrhs++;
+	}
+      }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
+        struct symbol *msp = psp->rhs[psp->nrhs-1];
+        if( msp->type!=MULTITERMINAL ){
+          struct symbol *origsp = msp;
+          msp = calloc(1,sizeof(*msp));
+          memset(msp, 0, sizeof(*msp));
+          msp->type = MULTITERMINAL;
+          msp->nsubsym = 1;
+          msp->subsym = calloc(1,sizeof(struct symbol*));
+          msp->subsym[0] = origsp;
+          msp->name = origsp->name;
+          psp->rhs[psp->nrhs-1] = msp;
+        }
+        msp->nsubsym++;
+        msp->subsym = realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym);
+        msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
+        if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){
+          ErrorMsg(psp->filename,psp->tokenlineno,
+            "Cannot form a compound containing a non-terminal");
+          psp->errorcnt++;
+        }
+      }else if( x[0]=='(' && psp->nrhs>0 ){
+        psp->state = RHS_ALIAS_1;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Illegal character on RHS of rule: \"%s\".",x);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_RULE_ERROR;
+      }
+      break;
+    case RHS_ALIAS_1:
+      if( isalpha(x[0]) ){
+        psp->alias[psp->nrhs-1] = x;
+        psp->state = RHS_ALIAS_2;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
+          x,psp->rhs[psp->nrhs-1]->name);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_RULE_ERROR;
+      }
+      break;
+    case RHS_ALIAS_2:
+      if( x[0]==')' ){
+        psp->state = IN_RHS;
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_RULE_ERROR;
+      }
+      break;
+    case WAITING_FOR_DECL_KEYWORD:
+      if( isalpha(x[0]) ){
+        psp->declkeyword = x;
+        psp->declargslot = 0;
+        psp->decllnslot = 0;
+        psp->state = WAITING_FOR_DECL_ARG;
+        if( strcmp(x,"name")==0 ){
+          psp->declargslot = &(psp->gp->name);
+	}else if( strcmp(x,"include")==0 ){
+          psp->declargslot = &(psp->gp->include);
+          psp->decllnslot = &psp->gp->includeln;
+	}else if( strcmp(x,"code")==0 ){
+          psp->declargslot = &(psp->gp->extracode);
+          psp->decllnslot = &psp->gp->extracodeln;
+	}else if( strcmp(x,"token_destructor")==0 ){
+          psp->declargslot = &psp->gp->tokendest;
+          psp->decllnslot = &psp->gp->tokendestln;
+	}else if( strcmp(x,"default_destructor")==0 ){
+          psp->declargslot = &psp->gp->vardest;
+          psp->decllnslot = &psp->gp->vardestln;
+	}else if( strcmp(x,"token_prefix")==0 ){
+          psp->declargslot = &psp->gp->tokenprefix;
+	}else if( strcmp(x,"syntax_error")==0 ){
+          psp->declargslot = &(psp->gp->error);
+          psp->decllnslot = &psp->gp->errorln;
+	}else if( strcmp(x,"parse_accept")==0 ){
+          psp->declargslot = &(psp->gp->accept);
+          psp->decllnslot = &psp->gp->acceptln;
+	}else if( strcmp(x,"parse_failure")==0 ){
+          psp->declargslot = &(psp->gp->failure);
+          psp->decllnslot = &psp->gp->failureln;
+	}else if( strcmp(x,"stack_overflow")==0 ){
+          psp->declargslot = &(psp->gp->overflow);
+          psp->decllnslot = &psp->gp->overflowln;
+        }else if( strcmp(x,"extra_argument")==0 ){
+          psp->declargslot = &(psp->gp->arg);
+        }else if( strcmp(x,"token_type")==0 ){
+          psp->declargslot = &(psp->gp->tokentype);
+        }else if( strcmp(x,"default_type")==0 ){
+          psp->declargslot = &(psp->gp->vartype);
+        }else if( strcmp(x,"stack_size")==0 ){
+          psp->declargslot = &(psp->gp->stacksize);
+        }else if( strcmp(x,"start_symbol")==0 ){
+          psp->declargslot = &(psp->gp->start);
+        }else if( strcmp(x,"left")==0 ){
+          psp->preccounter++;
+          psp->declassoc = LEFT;
+          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
+        }else if( strcmp(x,"right")==0 ){
+          psp->preccounter++;
+          psp->declassoc = RIGHT;
+          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
+        }else if( strcmp(x,"nonassoc")==0 ){
+          psp->preccounter++;
+          psp->declassoc = NONE;
+          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
+	}else if( strcmp(x,"destructor")==0 ){
+          psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
+	}else if( strcmp(x,"type")==0 ){
+          psp->state = WAITING_FOR_DATATYPE_SYMBOL;
+        }else if( strcmp(x,"fallback")==0 ){
+          psp->fallback = 0;
+          psp->state = WAITING_FOR_FALLBACK_ID;
+        }else if( strcmp(x,"wildcard")==0 ){
+          psp->state = WAITING_FOR_WILDCARD_ID;
+        }else{
+          ErrorMsg(psp->filename,psp->tokenlineno,
+            "Unknown declaration keyword: \"%%%s\".",x);
+          psp->errorcnt++;
+          psp->state = RESYNC_AFTER_DECL_ERROR;
+	}
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Illegal declaration keyword: \"%s\".",x);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_DECL_ERROR;
+      }
+      break;
+    case WAITING_FOR_DESTRUCTOR_SYMBOL:
+      if( !isalpha(x[0]) ){
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Symbol name missing after %destructor keyword");
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_DECL_ERROR;
+      }else{
+        struct symbol *sp = Symbol_new(x);
+        psp->declargslot = &sp->destructor;
+        psp->decllnslot = &sp->destructorln;
+        psp->state = WAITING_FOR_DECL_ARG;
+      }
+      break;
+    case WAITING_FOR_DATATYPE_SYMBOL:
+      if( !isalpha(x[0]) ){
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Symbol name missing after %destructor keyword");
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_DECL_ERROR;
+      }else{
+        struct symbol *sp = Symbol_new(x);
+        psp->declargslot = &sp->datatype;
+        psp->decllnslot = 0;
+        psp->state = WAITING_FOR_DECL_ARG;
+      }
+      break;
+    case WAITING_FOR_PRECEDENCE_SYMBOL:
+      if( x[0]=='.' ){
+        psp->state = WAITING_FOR_DECL_OR_RULE;
+      }else if( isupper(x[0]) ){
+        struct symbol *sp;
+        sp = Symbol_new(x);
+        if( sp->prec>=0 ){
+          ErrorMsg(psp->filename,psp->tokenlineno,
+            "Symbol \"%s\" has already be given a precedence.",x);
+          psp->errorcnt++;
+	}else{
+          sp->prec = psp->preccounter;
+          sp->assoc = psp->declassoc;
+	}
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Can't assign a precedence to \"%s\".",x);
+        psp->errorcnt++;
+      }
+      break;
+    case WAITING_FOR_DECL_ARG:
+      if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){
+        if( *(psp->declargslot)!=0 ){
+          ErrorMsg(psp->filename,psp->tokenlineno,
+            "The argument \"%s\" to declaration \"%%%s\" is not the first.",
+            x[0]=='\"' ? &x[1] : x,psp->declkeyword);
+          psp->errorcnt++;
+          psp->state = RESYNC_AFTER_DECL_ERROR;
+	}else{
+          *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x;
+          if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno;
+          psp->state = WAITING_FOR_DECL_OR_RULE;
+	}
+      }else{
+        ErrorMsg(psp->filename,psp->tokenlineno,
+          "Illegal argument to %%%s: %s",psp->declkeyword,x);
+        psp->errorcnt++;
+        psp->state = RESYNC_AFTER_DECL_ERROR;
+      }
+      break;
+    case WAITING_FOR_FALLBACK_ID:
+      if( x[0]=='.' ){
+        psp->state = WAITING_FOR_DECL_OR_RULE;
+      }else if( !isupper(x[0]) ){
+        ErrorMsg(psp->filename, psp->tokenlineno,
+          "%%fallback argument \"%s\" should be a token", x);
+        psp->errorcnt++;
+      }else{
+        struct symbol *sp = Symbol_new(x);
+        if( psp->fallback==0 ){
+          psp->fallback = sp;
+        }else if( sp->fallback ){
+          ErrorMsg(psp->filename, psp->tokenlineno,
+            "More than one fallback assigned to token %s", x);
+          psp->errorcnt++;
+        }else{
+          sp->fallback = psp->fallback;
+          psp->gp->has_fallback = 1;
+        }
+      }
+      break;
+    case WAITING_FOR_WILDCARD_ID:
+      if( x[0]=='.' ){
+        psp->state = WAITING_FOR_DECL_OR_RULE;
+      }else if( !isupper(x[0]) ){
+        ErrorMsg(psp->filename, psp->tokenlineno,
+          "%%wildcard argument \"%s\" should be a token", x);
+        psp->errorcnt++;
+      }else{
+        struct symbol *sp = Symbol_new(x);
+        if( psp->gp->wildcard==0 ){
+          psp->gp->wildcard = sp;
+        }else{
+          ErrorMsg(psp->filename, psp->tokenlineno,
+            "Extra wildcard to token: %s", x);
+          psp->errorcnt++;
+        }
+      }
+      break;
+    case RESYNC_AFTER_RULE_ERROR:
+/*      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
+**      break; */
+    case RESYNC_AFTER_DECL_ERROR:
+      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
+      if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
+      break;
+  }
+}
+
+/* Run the proprocessor over the input file text.  The global variables
+** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
+** macros.  This routine looks for "%ifdef" and "%ifndef" and "%endif" and
+** comments them out.  Text in between is also commented out as appropriate.
+*/
+static void preprocess_input(char *z){
+  int i, j, k, n;
+  int exclude = 0;
+  int start = 0;
+  int lineno = 1;
+  int start_lineno = 1;
+  for(i=0; z[i]; i++){
+    if( z[i]=='\n' ) lineno++;
+    if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue;
+    if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){
+      if( exclude ){
+        exclude--;
+        if( exclude==0 ){
+          for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
+        }
+      }
+      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
+    }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace(z[i+6]))
+          || (strncmp(&z[i],"%ifndef",7)==0 && isspace(z[i+7])) ){
+      if( exclude ){
+        exclude++;
+      }else{
+        for(j=i+7; isspace(z[j]); j++){}
+        for(n=0; z[j+n] && !isspace(z[j+n]); n++){}
+        exclude = 1;
+        for(k=0; k<nDefine; k++){
+          if( strncmp(azDefine[k],&z[j],n)==0 && strlen(azDefine[k])==n ){
+            exclude = 0;
+            break;
+          }
+        }
+        if( z[i+3]=='n' ) exclude = !exclude;
+        if( exclude ){
+          start = i;
+          start_lineno = lineno;
+        }
+      }
+      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
+    }
+  }
+  if( exclude ){
+    fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno);
+    exit(1);
+  }
+}
+
+/* In spite of its name, this function is really a scanner.  It read
+** in the entire input file (all at once) then tokenizes it.  Each
+** token is passed to the function "parseonetoken" which builds all
+** the appropriate data structures in the global state vector "gp".
+*/
+void Parse(gp)
+struct lemon *gp;
+{
+  struct pstate ps;
+  FILE *fp;
+  char *filebuf;
+  int filesize;
+  int lineno;
+  int c;
+  char *cp, *nextcp;
+  int startline = 0;
+
+  memset(&ps, '\0', sizeof(ps));
+  ps.gp = gp;
+  ps.filename = gp->filename;
+  ps.errorcnt = 0;
+  ps.state = INITIALIZE;
+
+  /* Begin by reading the input file */
+  fp = fopen(ps.filename,"rb");
+  if( fp==0 ){
+    ErrorMsg(ps.filename,0,"Can't open this file for reading.");
+    gp->errorcnt++;
+    return;
+  }
+  fseek(fp,0,2);
+  filesize = ftell(fp);
+  rewind(fp);
+  filebuf = (char *)malloc( filesize+1 );
+  if( filebuf==0 ){
+    ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
+      filesize+1);
+    gp->errorcnt++;
+    return;
+  }
+  if( fread(filebuf,1,filesize,fp)!=filesize ){
+    ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
+      filesize);
+    free(filebuf);
+    gp->errorcnt++;
+    return;
+  }
+  fclose(fp);
+  filebuf[filesize] = 0;
+
+  /* Make an initial pass through the file to handle %ifdef and %ifndef */
+  preprocess_input(filebuf);
+
+  /* Now scan the text of the input file */
+  lineno = 1;
+  for(cp=filebuf; (c= *cp)!=0; ){
+    if( c=='\n' ) lineno++;              /* Keep track of the line number */
+    if( isspace(c) ){ cp++; continue; }  /* Skip all white space */
+    if( c=='/' && cp[1]=='/' ){          /* Skip C++ style comments */
+      cp+=2;
+      while( (c= *cp)!=0 && c!='\n' ) cp++;
+      continue;
+    }
+    if( c=='/' && cp[1]=='*' ){          /* Skip C style comments */
+      cp+=2;
+      while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
+        if( c=='\n' ) lineno++;
+        cp++;
+      }
+      if( c ) cp++;
+      continue;
+    }
+    ps.tokenstart = cp;                /* Mark the beginning of the token */
+    ps.tokenlineno = lineno;           /* Linenumber on which token begins */
+    if( c=='\"' ){                     /* String literals */
+      cp++;
+      while( (c= *cp)!=0 && c!='\"' ){
+        if( c=='\n' ) lineno++;
+        cp++;
+      }
+      if( c==0 ){
+        ErrorMsg(ps.filename,startline,
+"String starting on this line is not terminated before the end of the file.");
+        ps.errorcnt++;
+        nextcp = cp;
+      }else{
+        nextcp = cp+1;
+      }
+    }else if( c=='{' ){               /* A block of C code */
+      int level;
+      cp++;
+      for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
+        if( c=='\n' ) lineno++;
+        else if( c=='{' ) level++;
+        else if( c=='}' ) level--;
+        else if( c=='/' && cp[1]=='*' ){  /* Skip comments */
+          int prevc;
+          cp = &cp[2];
+          prevc = 0;
+          while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
+            if( c=='\n' ) lineno++;
+            prevc = c;
+            cp++;
+	  }
+	}else if( c=='/' && cp[1]=='/' ){  /* Skip C++ style comments too */
+          cp = &cp[2];
+          while( (c= *cp)!=0 && c!='\n' ) cp++;
+          if( c ) lineno++;
+	}else if( c=='\'' || c=='\"' ){    /* String a character literals */
+          int startchar, prevc;
+          startchar = c;
+          prevc = 0;
+          for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
+            if( c=='\n' ) lineno++;
+            if( prevc=='\\' ) prevc = 0;
+            else              prevc = c;
+	  }
+	}
+      }
+      if( c==0 ){
+        ErrorMsg(ps.filename,ps.tokenlineno,
+"C code starting on this line is not terminated before the end of the file.");
+        ps.errorcnt++;
+        nextcp = cp;
+      }else{
+        nextcp = cp+1;
+      }
+    }else if( isalnum(c) ){          /* Identifiers */
+      while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
+      nextcp = cp;
+    }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
+      cp += 3;
+      nextcp = cp;
+    }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){
+      cp += 2;
+      while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
+      nextcp = cp;
+    }else{                          /* All other (one character) operators */
+      cp++;
+      nextcp = cp;
+    }
+    c = *cp;
+    *cp = 0;                        /* Null terminate the token */
+    parseonetoken(&ps);             /* Parse the token */
+    *cp = c;                        /* Restore the buffer */
+    cp = nextcp;
+  }
+  free(filebuf);                    /* Release the buffer after parsing */
+  gp->rule = ps.firstrule;
+  gp->errorcnt = ps.errorcnt;
+}
+/*************************** From the file "plink.c" *********************/
+/*
+** Routines processing configuration follow-set propagation links
+** in the LEMON parser generator.
+*/
+static struct plink *plink_freelist = 0;
+
+/* Allocate a new plink */
+struct plink *Plink_new(){
+  struct plink *new;
+
+  if( plink_freelist==0 ){
+    int i;
+    int amt = 100;
+    plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
+    if( plink_freelist==0 ){
+      fprintf(stderr,
+      "Unable to allocate memory for a new follow-set propagation link.\n");
+      exit(1);
+    }
+    for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
+    plink_freelist[amt-1].next = 0;
+  }
+  new = plink_freelist;
+  plink_freelist = plink_freelist->next;
+  return new;
+}
+
+/* Add a plink to a plink list */
+void Plink_add(plpp,cfp)
+struct plink **plpp;
+struct config *cfp;
+{
+  struct plink *new;
+  new = Plink_new();
+  new->next = *plpp;
+  *plpp = new;
+  new->cfp = cfp;
+}
+
+/* Transfer every plink on the list "from" to the list "to" */
+void Plink_copy(to,from)
+struct plink **to;
+struct plink *from;
+{
+  struct plink *nextpl;
+  while( from ){
+    nextpl = from->next;
+    from->next = *to;
+    *to = from;
+    from = nextpl;
+  }
+}
+
+/* Delete every plink on the list */
+void Plink_delete(plp)
+struct plink *plp;
+{
+  struct plink *nextpl;
+
+  while( plp ){
+    nextpl = plp->next;
+    plp->next = plink_freelist;
+    plink_freelist = plp;
+    plp = nextpl;
+  }
+}
+/*********************** From the file "report.c" **************************/
+/*
+** Procedures for generating reports and tables in the LEMON parser generator.
+*/
+
+/* Generate a filename with the given suffix.  Space to hold the
+** name comes from malloc() and must be freed by the calling
+** function.
+*/
+PRIVATE char *file_makename(lemp,suffix)
+struct lemon *lemp;
+char *suffix;
+{
+  char *name;
+  char *cp;
+
+  name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 );
+  if( name==0 ){
+    fprintf(stderr,"Can't allocate space for a filename.\n");
+    exit(1);
+  }
+  strcpy(name,lemp->filename);
+  cp = strrchr(name,'.');
+  if( cp ) *cp = 0;
+  strcat(name,suffix);
+  return name;
+}
+
+/* Open a file with a name based on the name of the input file,
+** but with a different (specified) suffix, and return a pointer
+** to the stream */
+PRIVATE FILE *file_open(lemp,suffix,mode)
+struct lemon *lemp;
+char *suffix;
+char *mode;
+{
+  FILE *fp;
+
+  if( lemp->outname ) free(lemp->outname);
+  lemp->outname = file_makename(lemp, suffix);
+  fp = fopen(lemp->outname,mode);
+  if( fp==0 && *mode=='w' ){
+    fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
+    lemp->errorcnt++;
+    return 0;
+  }
+  return fp;
+}
+
+/* Duplicate the input file without comments and without actions 
+** on rules */
+void Reprint(lemp)
+struct lemon *lemp;
+{
+  struct rule *rp;
+  struct symbol *sp;
+  int i, j, maxlen, len, ncolumns, skip;
+  printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
+  maxlen = 10;
+  for(i=0; i<lemp->nsymbol; i++){
+    sp = lemp->symbols[i];
+    len = strlen(sp->name);
+    if( len>maxlen ) maxlen = len;
+  }
+  ncolumns = 76/(maxlen+5);
+  if( ncolumns<1 ) ncolumns = 1;
+  skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
+  for(i=0; i<skip; i++){
+    printf("//");
+    for(j=i; j<lemp->nsymbol; j+=skip){
+      sp = lemp->symbols[j];
+      assert( sp->index==j );
+      printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
+    }
+    printf("\n");
+  }
+  for(rp=lemp->rule; rp; rp=rp->next){
+    printf("%s",rp->lhs->name);
+    /*    if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
+    printf(" ::=");
+    for(i=0; i<rp->nrhs; i++){
+      sp = rp->rhs[i];
+      printf(" %s", sp->name);
+      if( sp->type==MULTITERMINAL ){
+        for(j=1; j<sp->nsubsym; j++){
+          printf("|%s", sp->subsym[j]->name);
+        }
+      }
+      /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
+    }
+    printf(".");
+    if( rp->precsym ) printf(" [%s]",rp->precsym->name);
+    /* if( rp->code ) printf("\n    %s",rp->code); */
+    printf("\n");
+  }
+}
+
+void ConfigPrint(fp,cfp)
+FILE *fp;
+struct config *cfp;
+{
+  struct rule *rp;
+  struct symbol *sp;
+  int i, j;
+  rp = cfp->rp;
+  fprintf(fp,"%s ::=",rp->lhs->name);
+  for(i=0; i<=rp->nrhs; i++){
+    if( i==cfp->dot ) fprintf(fp," *");
+    if( i==rp->nrhs ) break;
+    sp = rp->rhs[i];
+    fprintf(fp," %s", sp->name);
+    if( sp->type==MULTITERMINAL ){
+      for(j=1; j<sp->nsubsym; j++){
+        fprintf(fp,"|%s",sp->subsym[j]->name);
+      }
+    }
+  }
+}
+
+/* #define TEST */
+#if 0
+/* Print a set */
+PRIVATE void SetPrint(out,set,lemp)
+FILE *out;
+char *set;
+struct lemon *lemp;
+{
+  int i;
+  char *spacer;
+  spacer = "";
+  fprintf(out,"%12s[","");
+  for(i=0; i<lemp->nterminal; i++){
+    if( SetFind(set,i) ){
+      fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
+      spacer = " ";
+    }
+  }
+  fprintf(out,"]\n");
+}
+
+/* Print a plink chain */
+PRIVATE void PlinkPrint(out,plp,tag)
+FILE *out;
+struct plink *plp;
+char *tag;
+{
+  while( plp ){
+    fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum);
+    ConfigPrint(out,plp->cfp);
+    fprintf(out,"\n");
+    plp = plp->next;
+  }
+}
+#endif
+
+/* Print an action to the given file descriptor.  Return FALSE if
+** nothing was actually printed.
+*/
+int PrintAction(struct action *ap, FILE *fp, int indent){
+  int result = 1;
+  switch( ap->type ){
+    case SHIFT:
+      fprintf(fp,"%*s shift  %d",indent,ap->sp->name,ap->x.stp->statenum);
+      break;
+    case REDUCE:
+      fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
+      break;
+    case ACCEPT:
+      fprintf(fp,"%*s accept",indent,ap->sp->name);
+      break;
+    case ERROR:
+      fprintf(fp,"%*s error",indent,ap->sp->name);
+      break;
+    case SRCONFLICT:
+    case RRCONFLICT:
+      fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
+        indent,ap->sp->name,ap->x.rp->index);
+      break;
+    case SSCONFLICT:
+      fprintf(fp,"%*s shift  %d ** Parsing conflict **", 
+        indent,ap->sp->name,ap->x.stp->statenum);
+      break;
+    case SH_RESOLVED:
+    case RD_RESOLVED:
+    case NOT_USED:
+      result = 0;
+      break;
+  }
+  return result;
+}
+
+/* Generate the "y.output" log file */
+void ReportOutput(lemp)
+struct lemon *lemp;
+{
+  int i;
+  struct state *stp;
+  struct config *cfp;
+  struct action *ap;
+  FILE *fp;
+
+  fp = file_open(lemp,".out","wb");
+  if( fp==0 ) return;
+  for(i=0; i<lemp->nstate; i++){
+    stp = lemp->sorted[i];
+    fprintf(fp,"State %d:\n",stp->statenum);
+    if( lemp->basisflag ) cfp=stp->bp;
+    else                  cfp=stp->cfp;
+    while( cfp ){
+      char buf[20];
+      if( cfp->dot==cfp->rp->nrhs ){
+        sprintf(buf,"(%d)",cfp->rp->index);
+        fprintf(fp,"    %5s ",buf);
+      }else{
+        fprintf(fp,"          ");
+      }
+      ConfigPrint(fp,cfp);
+      fprintf(fp,"\n");
+#if 0
+      SetPrint(fp,cfp->fws,lemp);
+      PlinkPrint(fp,cfp->fplp,"To  ");
+      PlinkPrint(fp,cfp->bplp,"From");
+#endif
+      if( lemp->basisflag ) cfp=cfp->bp;
+      else                  cfp=cfp->next;
+    }
+    fprintf(fp,"\n");
+    for(ap=stp->ap; ap; ap=ap->next){
+      if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
+    }
+    fprintf(fp,"\n");
+  }
+  fprintf(fp, "----------------------------------------------------\n");
+  fprintf(fp, "Symbols:\n");
+  for(i=0; i<lemp->nsymbol; i++){
+    int j;
+    struct symbol *sp;
+
+    sp = lemp->symbols[i];
+    fprintf(fp, "  %3d: %s", i, sp->name);
+    if( sp->type==NONTERMINAL ){
+      fprintf(fp, ":");
+      if( sp->lambda ){
+        fprintf(fp, " <lambda>");
+      }
+      for(j=0; j<lemp->nterminal; j++){
+        if( sp->firstset && SetFind(sp->firstset, j) ){
+          fprintf(fp, " %s", lemp->symbols[j]->name);
+        }
+      }
+    }
+    fprintf(fp, "\n");
+  }
+  fclose(fp);
+  return;
+}
+
+/* Search for the file "name" which is in the same directory as
+** the exacutable */
+PRIVATE char *pathsearch(argv0,name,modemask)
+char *argv0;
+char *name;
+int modemask;
+{
+  char *pathlist;
+  char *path,*cp;
+  char c;
+
+#ifdef __WIN32__
+  cp = strrchr(argv0,'\\');
+#else
+  cp = strrchr(argv0,'/');
+#endif
+  if( cp ){
+    c = *cp;
+    *cp = 0;
+    path = (char *)malloc( strlen(argv0) + strlen(name) + 2 );
+    if( path ) sprintf(path,"%s/%s",argv0,name);
+    *cp = c;
+  }else{
+    extern char *getenv();
+    pathlist = getenv("PATH");
+    if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
+    path = (char *)malloc( strlen(pathlist)+strlen(name)+2 );
+    if( path!=0 ){
+      while( *pathlist ){
+        cp = strchr(pathlist,':');
+        if( cp==0 ) cp = &pathlist[strlen(pathlist)];
+        c = *cp;
+        *cp = 0;
+        sprintf(path,"%s/%s",pathlist,name);
+        *cp = c;
+        if( c==0 ) pathlist = "";
+        else pathlist = &cp[1];
+        if( access(path,modemask)==0 ) break;
+      }
+    }
+  }
+  return path;
+}
+
+/* Given an action, compute the integer value for that action
+** which is to be put in the action table of the generated machine.
+** Return negative if no action should be generated.
+*/
+PRIVATE int compute_action(lemp,ap)
+struct lemon *lemp;
+struct action *ap;
+{
+  int act;
+  switch( ap->type ){
+    case SHIFT:  act = ap->x.stp->statenum;            break;
+    case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
+    case ERROR:  act = lemp->nstate + lemp->nrule;     break;
+    case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
+    default:     act = -1; break;
+  }
+  return act;
+}
+
+#define LINESIZE 1000
+/* The next cluster of routines are for reading the template file
+** and writing the results to the generated parser */
+/* The first function transfers data from "in" to "out" until
+** a line is seen which begins with "%%".  The line number is
+** tracked.
+**
+** if name!=0, then any word that begin with "Parse" is changed to
+** begin with *name instead.
+*/
+PRIVATE void tplt_xfer(name,in,out,lineno)
+char *name;
+FILE *in;
+FILE *out;
+int *lineno;
+{
+  int i, iStart;
+  char line[LINESIZE];
+  while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
+    (*lineno)++;
+    iStart = 0;
+    if( name ){
+      for(i=0; line[i]; i++){
+        if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
+          && (i==0 || !isalpha(line[i-1]))
+        ){
+          if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
+          fprintf(out,"%s",name);
+          i += 4;
+          iStart = i+1;
+        }
+      }
+    }
+    fprintf(out,"%s",&line[iStart]);
+  }
+}
+
+/* The next function finds the template file and opens it, returning
+** a pointer to the opened file. */
+PRIVATE FILE *tplt_open(lemp)
+struct lemon *lemp;
+{
+  static char templatename[] = "lempar.c";
+  char buf[1000];
+  FILE *in;
+  char *tpltname;
+  char *cp;
+
+  cp = strrchr(lemp->filename,'.');
+  if( cp ){
+    sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
+  }else{
+    sprintf(buf,"%s.lt",lemp->filename);
+  }
+  if( access(buf,004)==0 ){
+    tpltname = buf;
+  }else if( access(templatename,004)==0 ){
+    tpltname = templatename;
+  }else{
+    tpltname = pathsearch(lemp->argv0,templatename,0);
+  }
+  if( tpltname==0 ){
+    fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
+    templatename);
+    lemp->errorcnt++;
+    return 0;
+  }
+  in = fopen(tpltname,"rb");
+  if( in==0 ){
+    fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
+    lemp->errorcnt++;
+    return 0;
+  }
+  return in;
+}
+
+/* Print a #line directive line to the output file. */
+PRIVATE void tplt_linedir(out,lineno,filename)
+FILE *out;
+int lineno;
+char *filename;
+{
+  fprintf(out,"#line %d \"",lineno);
+  while( *filename ){
+    if( *filename == '\\' ) putc('\\',out);
+    putc(*filename,out);
+    filename++;
+  }
+  fprintf(out,"\"\n");
+}
+
+/* Print a string to the file and keep the linenumber up to date */
+PRIVATE void tplt_print(out,lemp,str,strln,lineno)
+FILE *out;
+struct lemon *lemp;
+char *str;
+int strln;
+int *lineno;
+{
+  if( str==0 ) return;
+  tplt_linedir(out,strln,lemp->filename);
+  (*lineno)++;
+  while( *str ){
+    if( *str=='\n' ) (*lineno)++;
+    putc(*str,out);
+    str++;
+  }
+  if( str[-1]!='\n' ){
+    putc('\n',out);
+    (*lineno)++;
+  }
+  tplt_linedir(out,*lineno+2,lemp->outname); 
+  (*lineno)+=2;
+  return;
+}
+
+/*
+** The following routine emits code for the destructor for the
+** symbol sp
+*/
+void emit_destructor_code(out,sp,lemp,lineno)
+FILE *out;
+struct symbol *sp;
+struct lemon *lemp;
+int *lineno;
+{
+ char *cp = 0;
+
+ int linecnt = 0;
+ if( sp->type==TERMINAL ){
+   cp = lemp->tokendest;
+   if( cp==0 ) return;
+   tplt_linedir(out,lemp->tokendestln,lemp->filename);
+   fprintf(out,"{");
+ }else if( sp->destructor ){
+   cp = sp->destructor;
+   tplt_linedir(out,sp->destructorln,lemp->filename);
+   fprintf(out,"{");
+ }else if( lemp->vardest ){
+   cp = lemp->vardest;
+   if( cp==0 ) return;
+   tplt_linedir(out,lemp->vardestln,lemp->filename);
+   fprintf(out,"{");
+ }else{
+   assert( 0 );  /* Cannot happen */
+ }
+ for(; *cp; cp++){
+   if( *cp=='$' && cp[1]=='$' ){
+     fprintf(out,"(yypminor->yy%d)",sp->dtnum);
+     cp++;
+     continue;
+   }
+   if( *cp=='\n' ) linecnt++;
+   fputc(*cp,out);
+ }
+ (*lineno) += 3 + linecnt;
+ fprintf(out,"}\n");
+ tplt_linedir(out,*lineno,lemp->outname);
+ return;
+}
+
+/*
+** Return TRUE (non-zero) if the given symbol has a destructor.
+*/
+int has_destructor(sp, lemp)
+struct symbol *sp;
+struct lemon *lemp;
+{
+  int ret;
+  if( sp->type==TERMINAL ){
+    ret = lemp->tokendest!=0;
+  }else{
+    ret = lemp->vardest!=0 || sp->destructor!=0;
+  }
+  return ret;
+}
+
+/*
+** Append text to a dynamically allocated string.  If zText is 0 then
+** reset the string to be empty again.  Always return the complete text
+** of the string (which is overwritten with each call).
+**
+** n bytes of zText are stored.  If n==0 then all of zText up to the first
+** \000 terminator is stored.  zText can contain up to two instances of
+** %d.  The values of p1 and p2 are written into the first and second
+** %d.
+**
+** If n==-1, then the previous character is overwritten.
+*/
+PRIVATE char *append_str(char *zText, int n, int p1, int p2){
+  static char *z = 0;
+  static int alloced = 0;
+  static int used = 0;
+  int c;
+  char zInt[40];
+
+  if( zText==0 ){
+    used = 0;
+    return z;
+  }
+  if( n<=0 ){
+    if( n<0 ){
+      used += n;
+      assert( used>=0 );
+    }
+    n = strlen(zText);
+  }
+  if( n+sizeof(zInt)*2+used >= alloced ){
+    alloced = n + sizeof(zInt)*2 + used + 200;
+    z = realloc(z,  alloced);
+  }
+  if( z==0 ) return "";
+  while( n-- > 0 ){
+    c = *(zText++);
+    if( c=='%' && n>0 && zText[0]=='d' ){
+      sprintf(zInt, "%d", p1);
+      p1 = p2;
+      strcpy(&z[used], zInt);
+      used += strlen(&z[used]);
+      zText++;
+      n--;
+    }else{
+      z[used++] = c;
+    }
+  }
+  z[used] = 0;
+  return z;
+}
+
+/*
+** zCode is a string that is the action associated with a rule.  Expand
+** the symbols in this string so that the refer to elements of the parser
+** stack.
+*/
+PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
+  char *cp, *xp;
+  int i;
+  char lhsused = 0;    /* True if the LHS element has been used */
+  char used[MAXRHS];   /* True for each RHS element which is used */
+
+  for(i=0; i<rp->nrhs; i++) used[i] = 0;
+  lhsused = 0;
+
+  if( rp->code==0 ){
+    rp->code = "\n";
+    rp->line = rp->ruleline;
+  }
+
+  append_str(0,0,0,0);
+  for(cp=rp->code; *cp; cp++){
+    if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
+      char saved;
+      for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
+      saved = *xp;
+      *xp = 0;
+      if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
+        append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0);
+        cp = xp;
+        lhsused = 1;
+      }else{
+        for(i=0; i<rp->nrhs; i++){
+          if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
+            if( cp!=rp->code && cp[-1]=='@' ){
+              /* If the argument is of the form @X then substituted
+              ** the token number of X, not the value of X */
+              append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
+            }else{
+              struct symbol *sp = rp->rhs[i];
+              int dtnum;
+              if( sp->type==MULTITERMINAL ){
+                dtnum = sp->subsym[0]->dtnum;
+              }else{
+                dtnum = sp->dtnum;
+              }
+              append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum);
+            }
+            cp = xp;
+            used[i] = 1;
+            break;
+          }
+        }
+      }
+      *xp = saved;
+    }
+    append_str(cp, 1, 0, 0);
+  } /* End loop */
+
+  /* Check to make sure the LHS has been used */
+  if( rp->lhsalias && !lhsused ){
+    ErrorMsg(lemp->filename,rp->ruleline,
+      "Label \"%s\" for \"%s(%s)\" is never used.",
+        rp->lhsalias,rp->lhs->name,rp->lhsalias);
+    lemp->errorcnt++;
+  }
+
+  /* Generate destructor code for RHS symbols which are not used in the
+  ** reduce code */
+  for(i=0; i<rp->nrhs; i++){
+    if( rp->rhsalias[i] && !used[i] ){
+      ErrorMsg(lemp->filename,rp->ruleline,
+        "Label %s for \"%s(%s)\" is never used.",
+        rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
+      lemp->errorcnt++;
+    }else if( rp->rhsalias[i]==0 ){
+      if( has_destructor(rp->rhs[i],lemp) ){
+        append_str("  yy_destructor(%d,&yymsp[%d].minor);\n", 0,
+           rp->rhs[i]->index,i-rp->nrhs+1);
+      }else{
+        /* No destructor defined for this term */
+      }
+    }
+  }
+  if( rp->code ){
+    cp = append_str(0,0,0,0);
+    rp->code = Strsafe(cp?cp:"");
+  }
+}
+
+/* 
+** Generate code which executes when the rule "rp" is reduced.  Write
+** the code to "out".  Make sure lineno stays up-to-date.
+*/
+PRIVATE void emit_code(out,rp,lemp,lineno)
+FILE *out;
+struct rule *rp;
+struct lemon *lemp;
+int *lineno;
+{
+ char *cp;
+ int linecnt = 0;
+
+ /* Generate code to do the reduce action */
+ if( rp->code ){
+   tplt_linedir(out,rp->line,lemp->filename);
+   fprintf(out,"{%s",rp->code);
+   for(cp=rp->code; *cp; cp++){
+     if( *cp=='\n' ) linecnt++;
+   } /* End loop */
+   (*lineno) += 3 + linecnt;
+   fprintf(out,"}\n");
+   tplt_linedir(out,*lineno,lemp->outname);
+ } /* End if( rp->code ) */
+
+ return;
+}
+
+/*
+** Print the definition of the union used for the parser's data stack.
+** This union contains fields for every possible data type for tokens
+** and nonterminals.  In the process of computing and printing this
+** union, also set the ".dtnum" field of every terminal and nonterminal
+** symbol.
+*/
+void print_stack_union(out,lemp,plineno,mhflag)
+FILE *out;                  /* The output stream */
+struct lemon *lemp;         /* The main info structure for this parser */
+int *plineno;               /* Pointer to the line number */
+int mhflag;                 /* True if generating makeheaders output */
+{
+  int lineno = *plineno;    /* The line number of the output */
+  char **types;             /* A hash table of datatypes */
+  int arraysize;            /* Size of the "types" array */
+  int maxdtlength;          /* Maximum length of any ".datatype" field. */
+  char *stddt;              /* Standardized name for a datatype */
+  int i,j;                  /* Loop counters */
+  int hash;                 /* For hashing the name of a type */
+  char *name;               /* Name of the parser */
+
+  /* Allocate and initialize types[] and allocate stddt[] */
+  arraysize = lemp->nsymbol * 2;
+  types = (char**)calloc( arraysize, sizeof(char*) );
+  for(i=0; i<arraysize; i++) types[i] = 0;
+  maxdtlength = 0;
+  if( lemp->vartype ){
+    maxdtlength = strlen(lemp->vartype);
+  }
+  for(i=0; i<lemp->nsymbol; i++){
+    int len;
+    struct symbol *sp = lemp->symbols[i];
+    if( sp->datatype==0 ) continue;
+    len = strlen(sp->datatype);
+    if( len>maxdtlength ) maxdtlength = len;
+  }
+  stddt = (char*)malloc( maxdtlength*2 + 1 );
+  if( types==0 || stddt==0 ){
+    fprintf(stderr,"Out of memory.\n");
+    exit(1);
+  }
+
+  /* Build a hash table of datatypes. The ".dtnum" field of each symbol
+  ** is filled in with the hash index plus 1.  A ".dtnum" value of 0 is
+  ** used for terminal symbols.  If there is no %default_type defined then
+  ** 0 is also used as the .dtnum value for nonterminals which do not specify
+  ** a datatype using the %type directive.
+  */
+  for(i=0; i<lemp->nsymbol; i++){
+    struct symbol *sp = lemp->symbols[i];
+    char *cp;
+    if( sp==lemp->errsym ){
+      sp->dtnum = arraysize+1;
+      continue;
+    }
+    if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
+      sp->dtnum = 0;
+      continue;
+    }
+    cp = sp->datatype;
+    if( cp==0 ) cp = lemp->vartype;
+    j = 0;
+    while( isspace(*cp) ) cp++;
+    while( *cp ) stddt[j++] = *cp++;
+    while( j>0 && isspace(stddt[j-1]) ) j--;
+    stddt[j] = 0;
+    hash = 0;
+    for(j=0; stddt[j]; j++){
+      hash = hash*53 + stddt[j];
+    }
+    hash = (hash & 0x7fffffff)%arraysize;
+    while( types[hash] ){
+      if( strcmp(types[hash],stddt)==0 ){
+        sp->dtnum = hash + 1;
+        break;
+      }
+      hash++;
+      if( hash>=arraysize ) hash = 0;
+    }
+    if( types[hash]==0 ){
+      sp->dtnum = hash + 1;
+      types[hash] = (char*)malloc( strlen(stddt)+1 );
+      if( types[hash]==0 ){
+        fprintf(stderr,"Out of memory.\n");
+        exit(1);
+      }
+      strcpy(types[hash],stddt);
+    }
+  }
+
+  /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
+  name = lemp->name ? lemp->name : "Parse";
+  lineno = *plineno;
+  if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
+  fprintf(out,"#define %sTOKENTYPE %s\n",name,
+    lemp->tokentype?lemp->tokentype:"void*");  lineno++;
+  if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
+  fprintf(out,"typedef union {\n"); lineno++;
+  fprintf(out,"  %sTOKENTYPE yy0;\n",name); lineno++;
+  for(i=0; i<arraysize; i++){
+    if( types[i]==0 ) continue;
+    fprintf(out,"  %s yy%d;\n",types[i],i+1); lineno++;
+    free(types[i]);
+  }
+  if( lemp->errsym->useCnt ){
+    fprintf(out,"  int yy%d;\n",lemp->errsym->dtnum); lineno++;
+  }
+  free(stddt);
+  free(types);
+  fprintf(out,"} YYMINORTYPE;\n"); lineno++;
+  *plineno = lineno;
+}
+
+/*
+** Return the name of a C datatype able to represent values between
+** lwr and upr, inclusive.
+*/
+static const char *minimum_size_type(int lwr, int upr){
+  if( lwr>=0 ){
+    if( upr<=255 ){
+      return "unsigned char";
+    }else if( upr<65535 ){
+      return "unsigned short int";
+    }else{
+      return "unsigned int";
+    }
+  }else if( lwr>=-127 && upr<=127 ){
+    return "signed char";
+  }else if( lwr>=-32767 && upr<32767 ){
+    return "short";
+  }else{
+    return "int";
+  }
+}
+
+/*
+** Each state contains a set of token transaction and a set of
+** nonterminal transactions.  Each of these sets makes an instance
+** of the following structure.  An array of these structures is used
+** to order the creation of entries in the yy_action[] table.
+*/
+struct axset {
+  struct state *stp;   /* A pointer to a state */
+  int isTkn;           /* True to use tokens.  False for non-terminals */
+  int nAction;         /* Number of actions */
+};
+
+/*
+** Compare to axset structures for sorting purposes
+*/
+static int axset_compare(const void *a, const void *b){
+  struct axset *p1 = (struct axset*)a;
+  struct axset *p2 = (struct axset*)b;
+  return p2->nAction - p1->nAction;
+}
+
+/*
+** Write text on "out" that describes the rule "rp".
+*/
+static void writeRuleText(FILE *out, struct rule *rp){
+  int j;
+  fprintf(out,"%s ::=", rp->lhs->name);
+  for(j=0; j<rp->nrhs; j++){
+    struct symbol *sp = rp->rhs[j];
+    fprintf(out," %s", sp->name);
+    if( sp->type==MULTITERMINAL ){
+      int k;
+      for(k=1; k<sp->nsubsym; k++){
+        fprintf(out,"|%s",sp->subsym[k]->name);
+      }
+    }
+  }
+}
+
+
+/* Generate C source code for the parser */
+void ReportTable(lemp, mhflag)
+struct lemon *lemp;
+int mhflag;     /* Output in makeheaders format if true */
+{
+  FILE *out, *in;
+  char line[LINESIZE];
+  int  lineno;
+  struct state *stp;
+  struct action *ap;
+  struct rule *rp;
+  struct acttab *pActtab;
+  int i, j, n;
+  char *name;
+  int mnTknOfst, mxTknOfst;
+  int mnNtOfst, mxNtOfst;
+  struct axset *ax;
+
+  in = tplt_open(lemp);
+  if( in==0 ) return;
+  out = file_open(lemp,".c","wb");
+  if( out==0 ){
+    fclose(in);
+    return;
+  }
+  lineno = 1;
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate the include code, if any */
+  tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
+  if( mhflag ){
+    char *name = file_makename(lemp, ".h");
+    fprintf(out,"#include \"%s\"\n", name); lineno++;
+    free(name);
+  }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate #defines for all tokens */
+  if( mhflag ){
+    char *prefix;
+    fprintf(out,"#if INTERFACE\n"); lineno++;
+    if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
+    else                    prefix = "";
+    for(i=1; i<lemp->nterminal; i++){
+      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
+      lineno++;
+    }
+    fprintf(out,"#endif\n"); lineno++;
+  }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate the defines */
+  fprintf(out,"#define YYCODETYPE %s\n",
+    minimum_size_type(0, lemp->nsymbol+5)); lineno++;
+  fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1);  lineno++;
+  fprintf(out,"#define YYACTIONTYPE %s\n",
+    minimum_size_type(0, lemp->nstate+lemp->nrule+5));  lineno++;
+  if( lemp->wildcard ){
+    fprintf(out,"#define YYWILDCARD %d\n",
+       lemp->wildcard->index); lineno++;
+  }
+  print_stack_union(out,lemp,&lineno,mhflag);
+  fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++;
+  if( lemp->stacksize ){
+    fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize);  lineno++;
+  }else{
+    fprintf(out,"#define YYSTACKDEPTH 100\n");  lineno++;
+  }
+  fprintf(out, "#endif\n"); lineno++;
+  if( mhflag ){
+    fprintf(out,"#if INTERFACE\n"); lineno++;
+  }
+  name = lemp->name ? lemp->name : "Parse";
+  if( lemp->arg && lemp->arg[0] ){
+    int i;
+    i = strlen(lemp->arg);
+    while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
+    while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
+    fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg);  lineno++;
+    fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg);  lineno++;
+    fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
+                 name,lemp->arg,&lemp->arg[i]);  lineno++;
+    fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
+                 name,&lemp->arg[i],&lemp->arg[i]);  lineno++;
+  }else{
+    fprintf(out,"#define %sARG_SDECL\n",name);  lineno++;
+    fprintf(out,"#define %sARG_PDECL\n",name);  lineno++;
+    fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
+    fprintf(out,"#define %sARG_STORE\n",name); lineno++;
+  }
+  if( mhflag ){
+    fprintf(out,"#endif\n"); lineno++;
+  }
+  fprintf(out,"#define YYNSTATE %d\n",lemp->nstate);  lineno++;
+  fprintf(out,"#define YYNRULE %d\n",lemp->nrule);  lineno++;
+  if( lemp->errsym->useCnt ){
+    fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index);  lineno++;
+    fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum);  lineno++;
+  }
+  if( lemp->has_fallback ){
+    fprintf(out,"#define YYFALLBACK 1\n");  lineno++;
+  }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate the action table and its associates:
+  **
+  **  yy_action[]        A single table containing all actions.
+  **  yy_lookahead[]     A table containing the lookahead for each entry in
+  **                     yy_action.  Used to detect hash collisions.
+  **  yy_shift_ofst[]    For each state, the offset into yy_action for
+  **                     shifting terminals.
+  **  yy_reduce_ofst[]   For each state, the offset into yy_action for
+  **                     shifting non-terminals after a reduce.
+  **  yy_default[]       Default action for each state.
+  */
+
+  /* Compute the actions on all states and count them up */
+  ax = calloc(lemp->nstate*2, sizeof(ax[0]));
+  if( ax==0 ){
+    fprintf(stderr,"malloc failed\n");
+    exit(1);
+  }
+  for(i=0; i<lemp->nstate; i++){
+    stp = lemp->sorted[i];
+    ax[i*2].stp = stp;
+    ax[i*2].isTkn = 1;
+    ax[i*2].nAction = stp->nTknAct;
+    ax[i*2+1].stp = stp;
+    ax[i*2+1].isTkn = 0;
+    ax[i*2+1].nAction = stp->nNtAct;
+  }
+  mxTknOfst = mnTknOfst = 0;
+  mxNtOfst = mnNtOfst = 0;
+
+  /* Compute the action table.  In order to try to keep the size of the
+  ** action table to a minimum, the heuristic of placing the largest action
+  ** sets first is used.
+  */
+  qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
+  pActtab = acttab_alloc();
+  for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
+    stp = ax[i].stp;
+    if( ax[i].isTkn ){
+      for(ap=stp->ap; ap; ap=ap->next){
+        int action;
+        if( ap->sp->index>=lemp->nterminal ) continue;
+        action = compute_action(lemp, ap);
+        if( action<0 ) continue;
+        acttab_action(pActtab, ap->sp->index, action);
+      }
+      stp->iTknOfst = acttab_insert(pActtab);
+      if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
+      if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
+    }else{
+      for(ap=stp->ap; ap; ap=ap->next){
+        int action;
+        if( ap->sp->index<lemp->nterminal ) continue;
+        if( ap->sp->index==lemp->nsymbol ) continue;
+        action = compute_action(lemp, ap);
+        if( action<0 ) continue;
+        acttab_action(pActtab, ap->sp->index, action);
+      }
+      stp->iNtOfst = acttab_insert(pActtab);
+      if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
+      if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
+    }
+  }
+  free(ax);
+
+  /* Output the yy_action table */
+  fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
+  n = acttab_size(pActtab);
+  for(i=j=0; i<n; i++){
+    int action = acttab_yyaction(pActtab, i);
+    if( action<0 ) action = lemp->nstate + lemp->nrule + 2;
+    if( j==0 ) fprintf(out," /* %5d */ ", i);
+    fprintf(out, " %4d,", action);
+    if( j==9 || i==n-1 ){
+      fprintf(out, "\n"); lineno++;
+      j = 0;
+    }else{
+      j++;
+    }
+  }
+  fprintf(out, "};\n"); lineno++;
+
+  /* Output the yy_lookahead table */
+  fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
+  for(i=j=0; i<n; i++){
+    int la = acttab_yylookahead(pActtab, i);
+    if( la<0 ) la = lemp->nsymbol;
+    if( j==0 ) fprintf(out," /* %5d */ ", i);
+    fprintf(out, " %4d,", la);
+    if( j==9 || i==n-1 ){
+      fprintf(out, "\n"); lineno++;
+      j = 0;
+    }else{
+      j++;
+    }
+  }
+  fprintf(out, "};\n"); lineno++;
+
+  /* Output the yy_shift_ofst[] table */
+  fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
+  n = lemp->nstate;
+  while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
+  fprintf(out, "#define YY_SHIFT_MAX %d\n", n-1); lineno++;
+  fprintf(out, "static const %s yy_shift_ofst[] = {\n", 
+          minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
+  for(i=j=0; i<n; i++){
+    int ofst;
+    stp = lemp->sorted[i];
+    ofst = stp->iTknOfst;
+    if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
+    if( j==0 ) fprintf(out," /* %5d */ ", i);
+    fprintf(out, " %4d,", ofst);
+    if( j==9 || i==n-1 ){
+      fprintf(out, "\n"); lineno++;
+      j = 0;
+    }else{
+      j++;
+    }
+  }
+  fprintf(out, "};\n"); lineno++;
+
+  /* Output the yy_reduce_ofst[] table */
+  fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
+  n = lemp->nstate;
+  while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
+  fprintf(out, "#define YY_REDUCE_MAX %d\n", n-1); lineno++;
+  fprintf(out, "static const %s yy_reduce_ofst[] = {\n", 
+          minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
+  for(i=j=0; i<n; i++){
+    int ofst;
+    stp = lemp->sorted[i];
+    ofst = stp->iNtOfst;
+    if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
+    if( j==0 ) fprintf(out," /* %5d */ ", i);
+    fprintf(out, " %4d,", ofst);
+    if( j==9 || i==n-1 ){
+      fprintf(out, "\n"); lineno++;
+      j = 0;
+    }else{
+      j++;
+    }
+  }
+  fprintf(out, "};\n"); lineno++;
+
+  /* Output the default action table */
+  fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
+  n = lemp->nstate;
+  for(i=j=0; i<n; i++){
+    stp = lemp->sorted[i];
+    if( j==0 ) fprintf(out," /* %5d */ ", i);
+    fprintf(out, " %4d,", stp->iDflt);
+    if( j==9 || i==n-1 ){
+      fprintf(out, "\n"); lineno++;
+      j = 0;
+    }else{
+      j++;
+    }
+  }
+  fprintf(out, "};\n"); lineno++;
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate the table of fallback tokens.
+  */
+  if( lemp->has_fallback ){
+    for(i=0; i<lemp->nterminal; i++){
+      struct symbol *p = lemp->symbols[i];
+      if( p->fallback==0 ){
+        fprintf(out, "    0,  /* %10s => nothing */\n", p->name);
+      }else{
+        fprintf(out, "  %3d,  /* %10s => %s */\n", p->fallback->index,
+          p->name, p->fallback->name);
+      }
+      lineno++;
+    }
+  }
+  tplt_xfer(lemp->name, in, out, &lineno);
+
+  /* Generate a table containing the symbolic name of every symbol
+  */
+  for(i=0; i<lemp->nsymbol; i++){
+    sprintf(line,"\"%s\",",lemp->symbols[i]->name);
+    fprintf(out,"  %-15s",line);
+    if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
+  }
+  if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate a table containing a text string that describes every
+  ** rule in the rule set of the grammer.  This information is used
+  ** when tracing REDUCE actions.
+  */
+  for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
+    assert( rp->index==i );
+    fprintf(out," /* %3d */ \"", i);
+    writeRuleText(out, rp);
+    fprintf(out,"\",\n"); lineno++;
+  }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate code which executes every time a symbol is popped from
+  ** the stack while processing errors or while destroying the parser. 
+  ** (In other words, generate the %destructor actions)
+  */
+  if( lemp->tokendest ){
+    for(i=0; i<lemp->nsymbol; i++){
+      struct symbol *sp = lemp->symbols[i];
+      if( sp==0 || sp->type!=TERMINAL ) continue;
+      fprintf(out,"    case %d: /* %s */\n",
+              sp->index, sp->name); lineno++;
+    }
+    for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
+    if( i<lemp->nsymbol ){
+      emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
+      fprintf(out,"      break;\n"); lineno++;
+    }
+  }
+  if( lemp->vardest ){
+    struct symbol *dflt_sp = 0;
+    for(i=0; i<lemp->nsymbol; i++){
+      struct symbol *sp = lemp->symbols[i];
+      if( sp==0 || sp->type==TERMINAL ||
+          sp->index<=0 || sp->destructor!=0 ) continue;
+      fprintf(out,"    case %d: /* %s */\n",
+              sp->index, sp->name); lineno++;
+      dflt_sp = sp;
+    }
+    if( dflt_sp!=0 ){
+      emit_destructor_code(out,dflt_sp,lemp,&lineno);
+      fprintf(out,"      break;\n"); lineno++;
+    }
+  }
+  for(i=0; i<lemp->nsymbol; i++){
+    struct symbol *sp = lemp->symbols[i];
+    if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
+    fprintf(out,"    case %d: /* %s */\n",
+            sp->index, sp->name); lineno++;
+
+    /* Combine duplicate destructors into a single case */
+    for(j=i+1; j<lemp->nsymbol; j++){
+      struct symbol *sp2 = lemp->symbols[j];
+      if( sp2 && sp2->type!=TERMINAL && sp2->destructor
+          && sp2->dtnum==sp->dtnum
+          && strcmp(sp->destructor,sp2->destructor)==0 ){
+         fprintf(out,"    case %d: /* %s */\n",
+                 sp2->index, sp2->name); lineno++;
+         sp2->destructor = 0;
+      }
+    }
+
+    emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
+    fprintf(out,"      break;\n"); lineno++;
+  }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate code which executes whenever the parser stack overflows */
+  tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate the table of rule information 
+  **
+  ** Note: This code depends on the fact that rules are number
+  ** sequentually beginning with 0.
+  */
+  for(rp=lemp->rule; rp; rp=rp->next){
+    fprintf(out,"  { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
+  }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate code which execution during each REDUCE action */
+  for(rp=lemp->rule; rp; rp=rp->next){
+    translate_code(lemp, rp);
+  }
+  for(rp=lemp->rule; rp; rp=rp->next){
+    struct rule *rp2;
+    if( rp->code==0 ) continue;
+    fprintf(out,"      case %d: /* ", rp->index);
+    writeRuleText(out, rp);
+    fprintf(out, " */\n"); lineno++;
+    for(rp2=rp->next; rp2; rp2=rp2->next){
+      if( rp2->code==rp->code ){
+        fprintf(out,"      case %d: /* ", rp2->index);
+        writeRuleText(out, rp2);
+        fprintf(out," */\n"); lineno++;
+        rp2->code = 0;
+      }
+    }
+    emit_code(out,rp,lemp,&lineno);
+    fprintf(out,"        break;\n"); lineno++;
+  }
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate code which executes if a parse fails */
+  tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate code which executes when a syntax error occurs */
+  tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Generate code which executes when the parser accepts its input */
+  tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
+  tplt_xfer(lemp->name,in,out,&lineno);
+
+  /* Append any addition code the user desires */
+  tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
+
+  fclose(in);
+  fclose(out);
+  return;
+}
+
+/* Generate a header file for the parser */
+void ReportHeader(lemp)
+struct lemon *lemp;
+{
+  FILE *out, *in;
+  char *prefix;
+  char line[LINESIZE];
+  char pattern[LINESIZE];
+  int i;
+
+  if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
+  else                    prefix = "";
+  in = file_open(lemp,".h","rb");
+  if( in ){
+    for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
+      sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
+      if( strcmp(line,pattern) ) break;
+    }
+    fclose(in);
+    if( i==lemp->nterminal ){
+      /* No change in the file.  Don't rewrite it. */
+      return;
+    }
+  }
+  out = file_open(lemp,".h","wb");
+  if( out ){
+    for(i=1; i<lemp->nterminal; i++){
+      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
+    }
+    fclose(out);  
+  }
+  return;
+}
+
+/* Reduce the size of the action tables, if possible, by making use
+** of defaults.
+**
+** In this version, we take the most frequent REDUCE action and make
+** it the default.  Except, there is no default if the wildcard token
+** is a possible look-ahead.
+*/
+void CompressTables(lemp)
+struct lemon *lemp;
+{
+  struct state *stp;
+  struct action *ap, *ap2;
+  struct rule *rp, *rp2, *rbest;
+  int nbest, n;
+  int i;
+  int usesWildcard;
+
+  for(i=0; i<lemp->nstate; i++){
+    stp = lemp->sorted[i];
+    nbest = 0;
+    rbest = 0;
+    usesWildcard = 0;
+
+    for(ap=stp->ap; ap; ap=ap->next){
+      if( ap->type==SHIFT && ap->sp==lemp->wildcard ){
+        usesWildcard = 1;
+      }
+      if( ap->type!=REDUCE ) continue;
+      rp = ap->x.rp;
+      if( rp->lhsStart ) continue;
+      if( rp==rbest ) continue;
+      n = 1;
+      for(ap2=ap->next; ap2; ap2=ap2->next){
+        if( ap2->type!=REDUCE ) continue;
+        rp2 = ap2->x.rp;
+        if( rp2==rbest ) continue;
+        if( rp2==rp ) n++;
+      }
+      if( n>nbest ){
+        nbest = n;
+        rbest = rp;
+      }
+    }
+ 
+    /* Do not make a default if the number of rules to default
+    ** is not at least 1 or if the wildcard token is a possible
+    ** lookahead.
+    */
+    if( nbest<1 || usesWildcard ) continue;
+
+
+    /* Combine matching REDUCE actions into a single default */
+    for(ap=stp->ap; ap; ap=ap->next){
+      if( ap->type==REDUCE && ap->x.rp==rbest ) break;
+    }
+    assert( ap );
+    ap->sp = Symbol_new("{default}");
+    for(ap=ap->next; ap; ap=ap->next){
+      if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
+    }
+    stp->ap = Action_sort(stp->ap);
+  }
+}
+
+
+/*
+** Compare two states for sorting purposes.  The smaller state is the
+** one with the most non-terminal actions.  If they have the same number
+** of non-terminal actions, then the smaller is the one with the most
+** token actions.
+*/
+static int stateResortCompare(const void *a, const void *b){
+  const struct state *pA = *(const struct state**)a;
+  const struct state *pB = *(const struct state**)b;
+  int n;
+
+  n = pB->nNtAct - pA->nNtAct;
+  if( n==0 ){
+    n = pB->nTknAct - pA->nTknAct;
+  }
+  return n;
+}
+
+
+/*
+** Renumber and resort states so that states with fewer choices
+** occur at the end.  Except, keep state 0 as the first state.
+*/
+void ResortStates(lemp)
+struct lemon *lemp;
+{
+  int i;
+  struct state *stp;
+  struct action *ap;
+
+  for(i=0; i<lemp->nstate; i++){
+    stp = lemp->sorted[i];
+    stp->nTknAct = stp->nNtAct = 0;
+    stp->iDflt = lemp->nstate + lemp->nrule;
+    stp->iTknOfst = NO_OFFSET;
+    stp->iNtOfst = NO_OFFSET;
+    for(ap=stp->ap; ap; ap=ap->next){
+      if( compute_action(lemp,ap)>=0 ){
+        if( ap->sp->index<lemp->nterminal ){
+          stp->nTknAct++;
+        }else if( ap->sp->index<lemp->nsymbol ){
+          stp->nNtAct++;
+        }else{
+          stp->iDflt = compute_action(lemp, ap);
+        }
+      }
+    }
+  }
+  qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]),
+        stateResortCompare);
+  for(i=0; i<lemp->nstate; i++){
+    lemp->sorted[i]->statenum = i;
+  }
+}
+
+
+/***************** From the file "set.c" ************************************/
+/*
+** Set manipulation routines for the LEMON parser generator.
+*/
+
+static int size = 0;
+
+/* Set the set size */
+void SetSize(n)
+int n;
+{
+  size = n+1;
+}
+
+/* Allocate a new set */
+char *SetNew(){
+  char *s;
+  s = (char*)calloc( size, 1);
+  if( s==0 ){
+    extern void memory_error();
+    memory_error();
+  }
+  return s;
+}
+
+/* Deallocate a set */
+void SetFree(s)
+char *s;
+{
+  free(s);
+}
+
+/* Add a new element to the set.  Return TRUE if the element was added
+** and FALSE if it was already there. */
+int SetAdd(s,e)
+char *s;
+int e;
+{
+  int rv;
+  assert( e>=0 && e<size );
+  rv = s[e];
+  s[e] = 1;
+  return !rv;
+}
+
+/* Add every element of s2 to s1.  Return TRUE if s1 changes. */
+int SetUnion(s1,s2)
+char *s1;
+char *s2;
+{
+  int i, progress;
+  progress = 0;
+  for(i=0; i<size; i++){
+    if( s2[i]==0 ) continue;
+    if( s1[i]==0 ){
+      progress = 1;
+      s1[i] = 1;
+    }
+  }
+  return progress;
+}
+/********************** From the file "table.c" ****************************/
+/*
+** All code in this file has been automatically generated
+** from a specification in the file
+**              "table.q"
+** by the associative array code building program "aagen".
+** Do not edit this file!  Instead, edit the specification
+** file, then rerun aagen.
+*/
+/*
+** Code for processing tables in the LEMON parser generator.
+*/
+
+PRIVATE int strhash(x)
+char *x;
+{
+  int h = 0;
+  while( *x) h = h*13 + *(x++);
+  return h;
+}
+
+/* Works like strdup, sort of.  Save a string in malloced memory, but
+** keep strings in a table so that the same string is not in more
+** than one place.
+*/
+char *Strsafe(y)
+char *y;
+{
+  char *z;
+
+  if( y==0 ) return 0;
+  z = Strsafe_find(y);
+  if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
+    strcpy(z,y);
+    Strsafe_insert(z);
+  }
+  MemoryCheck(z);
+  return z;
+}
+
+/* There is one instance of the following structure for each
+** associative array of type "x1".
+*/
+struct s_x1 {
+  int size;               /* The number of available slots. */
+                          /*   Must be a power of 2 greater than or */
+                          /*   equal to 1 */
+  int count;              /* Number of currently slots filled */
+  struct s_x1node *tbl;  /* The data stored here */
+  struct s_x1node **ht;  /* Hash table for lookups */
+};
+
+/* There is one instance of this structure for every data element
+** in an associative array of type "x1".
+*/
+typedef struct s_x1node {
+  char *data;                  /* The data */
+  struct s_x1node *next;   /* Next entry with the same hash */
+  struct s_x1node **from;  /* Previous link */
+} x1node;
+
+/* There is only one instance of the array, which is the following */
+static struct s_x1 *x1a;
+
+/* Allocate a new associative array */
+void Strsafe_init(){
+  if( x1a ) return;
+  x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
+  if( x1a ){
+    x1a->size = 1024;
+    x1a->count = 0;
+    x1a->tbl = (x1node*)malloc( 
+      (sizeof(x1node) + sizeof(x1node*))*1024 );
+    if( x1a->tbl==0 ){
+      free(x1a);
+      x1a = 0;
+    }else{
+      int i;
+      x1a->ht = (x1node**)&(x1a->tbl[1024]);
+      for(i=0; i<1024; i++) x1a->ht[i] = 0;
+    }
+  }
+}
+/* Insert a new record into the array.  Return TRUE if successful.
+** Prior data with the same key is NOT overwritten */
+int Strsafe_insert(data)
+char *data;
+{
+  x1node *np;
+  int h;
+  int ph;
+
+  if( x1a==0 ) return 0;
+  ph = strhash(data);
+  h = ph & (x1a->size-1);
+  np = x1a->ht[h];
+  while( np ){
+    if( strcmp(np->data,data)==0 ){
+      /* An existing entry with the same key is found. */
+      /* Fail because overwrite is not allows. */
+      return 0;
+    }
+    np = np->next;
+  }
+  if( x1a->count>=x1a->size ){
+    /* Need to make the hash table bigger */
+    int i,size;
+    struct s_x1 array;
+    array.size = size = x1a->size*2;
+    array.count = x1a->count;
+    array.tbl = (x1node*)malloc(
+      (sizeof(x1node) + sizeof(x1node*))*size );
+    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
+    array.ht = (x1node**)&(array.tbl[size]);
+    for(i=0; i<size; i++) array.ht[i] = 0;
+    for(i=0; i<x1a->count; i++){
+      x1node *oldnp, *newnp;
+      oldnp = &(x1a->tbl[i]);
+      h = strhash(oldnp->data) & (size-1);
+      newnp = &(array.tbl[i]);
+      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
+      newnp->next = array.ht[h];
+      newnp->data = oldnp->data;
+      newnp->from = &(array.ht[h]);
+      array.ht[h] = newnp;
+    }
+    free(x1a->tbl);
+    *x1a = array;
+  }
+  /* Insert the new data */
+  h = ph & (x1a->size-1);
+  np = &(x1a->tbl[x1a->count++]);
+  np->data = data;
+  if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
+  np->next = x1a->ht[h];
+  x1a->ht[h] = np;
+  np->from = &(x1a->ht[h]);
+  return 1;
+}
+
+/* Return a pointer to data assigned to the given key.  Return NULL
+** if no such key. */
+char *Strsafe_find(key)
+char *key;
+{
+  int h;
+  x1node *np;
+
+  if( x1a==0 ) return 0;
+  h = strhash(key) & (x1a->size-1);
+  np = x1a->ht[h];
+  while( np ){
+    if( strcmp(np->data,key)==0 ) break;
+    np = np->next;
+  }
+  return np ? np->data : 0;
+}
+
+/* Return a pointer to the (terminal or nonterminal) symbol "x".
+** Create a new symbol if this is the first time "x" has been seen.
+*/
+struct symbol *Symbol_new(x)
+char *x;
+{
+  struct symbol *sp;
+
+  sp = Symbol_find(x);
+  if( sp==0 ){
+    sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
+    MemoryCheck(sp);
+    sp->name = Strsafe(x);
+    sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
+    sp->rule = 0;
+    sp->fallback = 0;
+    sp->prec = -1;
+    sp->assoc = UNK;
+    sp->firstset = 0;
+    sp->lambda = LEMON_FALSE;
+    sp->destructor = 0;
+    sp->datatype = 0;
+    sp->useCnt = 0;
+    Symbol_insert(sp,sp->name);
+  }
+  sp->useCnt++;
+  return sp;
+}
+
+/* Compare two symbols for working purposes
+**
+** Symbols that begin with upper case letters (terminals or tokens)
+** must sort before symbols that begin with lower case letters
+** (non-terminals).  Other than that, the order does not matter.
+**
+** We find experimentally that leaving the symbols in their original
+** order (the order they appeared in the grammar file) gives the
+** smallest parser tables in SQLite.
+*/
+int Symbolcmpp(struct symbol **a, struct symbol **b){
+  int i1 = (**a).index + 10000000*((**a).name[0]>'Z');
+  int i2 = (**b).index + 10000000*((**b).name[0]>'Z');
+  return i1-i2;
+}
+
+/* There is one instance of the following structure for each
+** associative array of type "x2".
+*/
+struct s_x2 {
+  int size;               /* The number of available slots. */
+                          /*   Must be a power of 2 greater than or */
+                          /*   equal to 1 */
+  int count;              /* Number of currently slots filled */
+  struct s_x2node *tbl;  /* The data stored here */
+  struct s_x2node **ht;  /* Hash table for lookups */
+};
+
+/* There is one instance of this structure for every data element
+** in an associative array of type "x2".
+*/
+typedef struct s_x2node {
+  struct symbol *data;                  /* The data */
+  char *key;                   /* The key */
+  struct s_x2node *next;   /* Next entry with the same hash */
+  struct s_x2node **from;  /* Previous link */
+} x2node;
+
+/* There is only one instance of the array, which is the following */
+static struct s_x2 *x2a;
+
+/* Allocate a new associative array */
+void Symbol_init(){
+  if( x2a ) return;
+  x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
+  if( x2a ){
+    x2a->size = 128;
+    x2a->count = 0;
+    x2a->tbl = (x2node*)malloc( 
+      (sizeof(x2node) + sizeof(x2node*))*128 );
+    if( x2a->tbl==0 ){
+      free(x2a);
+      x2a = 0;
+    }else{
+      int i;
+      x2a->ht = (x2node**)&(x2a->tbl[128]);
+      for(i=0; i<128; i++) x2a->ht[i] = 0;
+    }
+  }
+}
+/* Insert a new record into the array.  Return TRUE if successful.
+** Prior data with the same key is NOT overwritten */
+int Symbol_insert(data,key)
+struct symbol *data;
+char *key;
+{
+  x2node *np;
+  int h;
+  int ph;
+
+  if( x2a==0 ) return 0;
+  ph = strhash(key);
+  h = ph & (x2a->size-1);
+  np = x2a->ht[h];
+  while( np ){
+    if( strcmp(np->key,key)==0 ){
+      /* An existing entry with the same key is found. */
+      /* Fail because overwrite is not allows. */
+      return 0;
+    }
+    np = np->next;
+  }
+  if( x2a->count>=x2a->size ){
+    /* Need to make the hash table bigger */
+    int i,size;
+    struct s_x2 array;
+    array.size = size = x2a->size*2;
+    array.count = x2a->count;
+    array.tbl = (x2node*)malloc(
+      (sizeof(x2node) + sizeof(x2node*))*size );
+    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
+    array.ht = (x2node**)&(array.tbl[size]);
+    for(i=0; i<size; i++) array.ht[i] = 0;
+    for(i=0; i<x2a->count; i++){
+      x2node *oldnp, *newnp;
+      oldnp = &(x2a->tbl[i]);
+      h = strhash(oldnp->key) & (size-1);
+      newnp = &(array.tbl[i]);
+      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
+      newnp->next = array.ht[h];
+      newnp->key = oldnp->key;
+      newnp->data = oldnp->data;
+      newnp->from = &(array.ht[h]);
+      array.ht[h] = newnp;
+    }
+    free(x2a->tbl);
+    *x2a = array;
+  }
+  /* Insert the new data */
+  h = ph & (x2a->size-1);
+  np = &(x2a->tbl[x2a->count++]);
+  np->key = key;
+  np->data = data;
+  if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
+  np->next = x2a->ht[h];
+  x2a->ht[h] = np;
+  np->from = &(x2a->ht[h]);
+  return 1;
+}
+
+/* Return a pointer to data assigned to the given key.  Return NULL
+** if no such key. */
+struct symbol *Symbol_find(key)
+char *key;
+{
+  int h;
+  x2node *np;
+
+  if( x2a==0 ) return 0;
+  h = strhash(key) & (x2a->size-1);
+  np = x2a->ht[h];
+  while( np ){
+    if( strcmp(np->key,key)==0 ) break;
+    np = np->next;
+  }
+  return np ? np->data : 0;
+}
+
+/* Return the n-th data.  Return NULL if n is out of range. */
+struct symbol *Symbol_Nth(n)
+int n;
+{
+  struct symbol *data;
+  if( x2a && n>0 && n<=x2a->count ){
+    data = x2a->tbl[n-1].data;
+  }else{
+    data = 0;
+  }
+  return data;
+}
+
+/* Return the size of the array */
+int Symbol_count()
+{
+  return x2a ? x2a->count : 0;
+}
+
+/* Return an array of pointers to all data in the table.
+** The array is obtained from malloc.  Return NULL if memory allocation
+** problems, or if the array is empty. */
+struct symbol **Symbol_arrayof()
+{
+  struct symbol **array;
+  int i,size;
+  if( x2a==0 ) return 0;
+  size = x2a->count;
+  array = (struct symbol **)calloc(size, sizeof(struct symbol *));
+  if( array ){
+    for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
+  }
+  return array;
+}
+
+/* Compare two configurations */
+int Configcmp(a,b)
+struct config *a;
+struct config *b;
+{
+  int x;
+  x = a->rp->index - b->rp->index;
+  if( x==0 ) x = a->dot - b->dot;
+  return x;
+}
+
+/* Compare two states */
+PRIVATE int statecmp(a,b)
+struct config *a;
+struct config *b;
+{
+  int rc;
+  for(rc=0; rc==0 && a && b;  a=a->bp, b=b->bp){
+    rc = a->rp->index - b->rp->index;
+    if( rc==0 ) rc = a->dot - b->dot;
+  }
+  if( rc==0 ){
+    if( a ) rc = 1;
+    if( b ) rc = -1;
+  }
+  return rc;
+}
+
+/* Hash a state */
+PRIVATE int statehash(a)
+struct config *a;
+{
+  int h=0;
+  while( a ){
+    h = h*571 + a->rp->index*37 + a->dot;
+    a = a->bp;
+  }
+  return h;
+}
+
+/* Allocate a new state structure */
+struct state *State_new()
+{
+  struct state *new;
+  new = (struct state *)calloc(1, sizeof(struct state) );
+  MemoryCheck(new);
+  return new;
+}
+
+/* There is one instance of the following structure for each
+** associative array of type "x3".
+*/
+struct s_x3 {
+  int size;               /* The number of available slots. */
+                          /*   Must be a power of 2 greater than or */
+                          /*   equal to 1 */
+  int count;              /* Number of currently slots filled */
+  struct s_x3node *tbl;  /* The data stored here */
+  struct s_x3node **ht;  /* Hash table for lookups */
+};
+
+/* There is one instance of this structure for every data element
+** in an associative array of type "x3".
+*/
+typedef struct s_x3node {
+  struct state *data;                  /* The data */
+  struct config *key;                   /* The key */
+  struct s_x3node *next;   /* Next entry with the same hash */
+  struct s_x3node **from;  /* Previous link */
+} x3node;
+
+/* There is only one instance of the array, which is the following */
+static struct s_x3 *x3a;
+
+/* Allocate a new associative array */
+void State_init(){
+  if( x3a ) return;
+  x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
+  if( x3a ){
+    x3a->size = 128;
+    x3a->count = 0;
+    x3a->tbl = (x3node*)malloc( 
+      (sizeof(x3node) + sizeof(x3node*))*128 );
+    if( x3a->tbl==0 ){
+      free(x3a);
+      x3a = 0;
+    }else{
+      int i;
+      x3a->ht = (x3node**)&(x3a->tbl[128]);
+      for(i=0; i<128; i++) x3a->ht[i] = 0;
+    }
+  }
+}
+/* Insert a new record into the array.  Return TRUE if successful.
+** Prior data with the same key is NOT overwritten */
+int State_insert(data,key)
+struct state *data;
+struct config *key;
+{
+  x3node *np;
+  int h;
+  int ph;
+
+  if( x3a==0 ) return 0;
+  ph = statehash(key);
+  h = ph & (x3a->size-1);
+  np = x3a->ht[h];
+  while( np ){
+    if( statecmp(np->key,key)==0 ){
+      /* An existing entry with the same key is found. */
+      /* Fail because overwrite is not allows. */
+      return 0;
+    }
+    np = np->next;
+  }
+  if( x3a->count>=x3a->size ){
+    /* Need to make the hash table bigger */
+    int i,size;
+    struct s_x3 array;
+    array.size = size = x3a->size*2;
+    array.count = x3a->count;
+    array.tbl = (x3node*)malloc(
+      (sizeof(x3node) + sizeof(x3node*))*size );
+    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
+    array.ht = (x3node**)&(array.tbl[size]);
+    for(i=0; i<size; i++) array.ht[i] = 0;
+    for(i=0; i<x3a->count; i++){
+      x3node *oldnp, *newnp;
+      oldnp = &(x3a->tbl[i]);
+      h = statehash(oldnp->key) & (size-1);
+      newnp = &(array.tbl[i]);
+      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
+      newnp->next = array.ht[h];
+      newnp->key = oldnp->key;
+      newnp->data = oldnp->data;
+      newnp->from = &(array.ht[h]);
+      array.ht[h] = newnp;
+    }
+    free(x3a->tbl);
+    *x3a = array;
+  }
+  /* Insert the new data */
+  h = ph & (x3a->size-1);
+  np = &(x3a->tbl[x3a->count++]);
+  np->key = key;
+  np->data = data;
+  if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
+  np->next = x3a->ht[h];
+  x3a->ht[h] = np;
+  np->from = &(x3a->ht[h]);
+  return 1;
+}
+
+/* Return a pointer to data assigned to the given key.  Return NULL
+** if no such key. */
+struct state *State_find(key)
+struct config *key;
+{
+  int h;
+  x3node *np;
+
+  if( x3a==0 ) return 0;
+  h = statehash(key) & (x3a->size-1);
+  np = x3a->ht[h];
+  while( np ){
+    if( statecmp(np->key,key)==0 ) break;
+    np = np->next;
+  }
+  return np ? np->data : 0;
+}
+
+/* Return an array of pointers to all data in the table.
+** The array is obtained from malloc.  Return NULL if memory allocation
+** problems, or if the array is empty. */
+struct state **State_arrayof()
+{
+  struct state **array;
+  int i,size;
+  if( x3a==0 ) return 0;
+  size = x3a->count;
+  array = (struct state **)malloc( sizeof(struct state *)*size );
+  if( array ){
+    for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
+  }
+  return array;
+}
+
+/* Hash a configuration */
+PRIVATE int confighash(a)
+struct config *a;
+{
+  int h=0;
+  h = h*571 + a->rp->index*37 + a->dot;
+  return h;
+}
+
+/* There is one instance of the following structure for each
+** associative array of type "x4".
+*/
+struct s_x4 {
+  int size;               /* The number of available slots. */
+                          /*   Must be a power of 2 greater than or */
+                          /*   equal to 1 */
+  int count;              /* Number of currently slots filled */
+  struct s_x4node *tbl;  /* The data stored here */
+  struct s_x4node **ht;  /* Hash table for lookups */
+};
+
+/* There is one instance of this structure for every data element
+** in an associative array of type "x4".
+*/
+typedef struct s_x4node {
+  struct config *data;                  /* The data */
+  struct s_x4node *next;   /* Next entry with the same hash */
+  struct s_x4node **from;  /* Previous link */
+} x4node;
+
+/* There is only one instance of the array, which is the following */
+static struct s_x4 *x4a;
+
+/* Allocate a new associative array */
+void Configtable_init(){
+  if( x4a ) return;
+  x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
+  if( x4a ){
+    x4a->size = 64;
+    x4a->count = 0;
+    x4a->tbl = (x4node*)malloc( 
+      (sizeof(x4node) + sizeof(x4node*))*64 );
+    if( x4a->tbl==0 ){
+      free(x4a);
+      x4a = 0;
+    }else{
+      int i;
+      x4a->ht = (x4node**)&(x4a->tbl[64]);
+      for(i=0; i<64; i++) x4a->ht[i] = 0;
+    }
+  }
+}
+/* Insert a new record into the array.  Return TRUE if successful.
+** Prior data with the same key is NOT overwritten */
+int Configtable_insert(data)
+struct config *data;
+{
+  x4node *np;
+  int h;
+  int ph;
+
+  if( x4a==0 ) return 0;
+  ph = confighash(data);
+  h = ph & (x4a->size-1);
+  np = x4a->ht[h];
+  while( np ){
+    if( Configcmp(np->data,data)==0 ){
+      /* An existing entry with the same key is found. */
+      /* Fail because overwrite is not allows. */
+      return 0;
+    }
+    np = np->next;
+  }
+  if( x4a->count>=x4a->size ){
+    /* Need to make the hash table bigger */
+    int i,size;
+    struct s_x4 array;
+    array.size = size = x4a->size*2;
+    array.count = x4a->count;
+    array.tbl = (x4node*)malloc(
+      (sizeof(x4node) + sizeof(x4node*))*size );
+    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
+    array.ht = (x4node**)&(array.tbl[size]);
+    for(i=0; i<size; i++) array.ht[i] = 0;
+    for(i=0; i<x4a->count; i++){
+      x4node *oldnp, *newnp;
+      oldnp = &(x4a->tbl[i]);
+      h = confighash(oldnp->data) & (size-1);
+      newnp = &(array.tbl[i]);
+      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
+      newnp->next = array.ht[h];
+      newnp->data = oldnp->data;
+      newnp->from = &(array.ht[h]);
+      array.ht[h] = newnp;
+    }
+    free(x4a->tbl);
+    *x4a = array;
+  }
+  /* Insert the new data */
+  h = ph & (x4a->size-1);
+  np = &(x4a->tbl[x4a->count++]);
+  np->data = data;
+  if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
+  np->next = x4a->ht[h];
+  x4a->ht[h] = np;
+  np->from = &(x4a->ht[h]);
+  return 1;
+}
+
+/* Return a pointer to data assigned to the given key.  Return NULL
+** if no such key. */
+struct config *Configtable_find(key)
+struct config *key;
+{
+  int h;
+  x4node *np;
+
+  if( x4a==0 ) return 0;
+  h = confighash(key) & (x4a->size-1);
+  np = x4a->ht[h];
+  while( np ){
+    if( Configcmp(np->data,key)==0 ) break;
+    np = np->next;
+  }
+  return np ? np->data : 0;
+}
+
+/* Remove all data from the table.  Pass each data to the function "f"
+** as it is removed.  ("f" may be null to avoid this step.) */
+void Configtable_clear(f)
+int(*f)(/* struct config * */);
+{
+  int i;
+  if( x4a==0 || x4a->count==0 ) return;
+  if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
+  for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
+  x4a->count = 0;
+  return;
+}
Index: /cpp/_old/f8-to-f1/lemonglobal.h
===================================================================
--- /cpp/_old/f8-to-f1/lemonglobal.h	(revision 110)
+++ /cpp/_old/f8-to-f1/lemonglobal.h	(revision 110)
@@ -0,0 +1,31 @@
+/*
+ *  lemonglobal.h
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-04-04.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+#include "conv_f8tof1.h"
+#include "sstring.h"
+
+struct Token {
+	double dblValue;
+	//int intValue;
+	SString *strValue;
+	char strArrValue[30];
+	vector<SString> *vectorStr;
+	vector<Condition> *vectorConditions;
+	vector<Action*> *vectorActions;
+	vector<vector<SString> > *parameters;
+	Condition *cond;
+};
+
+struct ProductionTailToken {
+	vector<SubProduction> *subproductions;
+};
+
+struct ProdPieceToken {
+	vector<vector<SString> > *parameters;
+	vector<Action*> *actions;
+};
Index: /cpp/_old/f8-to-f1/lempar.c
===================================================================
--- /cpp/_old/f8-to-f1/lempar.c	(revision 110)
+++ /cpp/_old/f8-to-f1/lempar.c	(revision 110)
@@ -0,0 +1,782 @@
+/* Driver template for the LEMON parser generator.
+** The author disclaims copyright to this source code.
+*/
+/* First off, code is include which follows the "include" declaration
+** in the input file. */
+#include <stdio.h>
+#include <assert.h>
+%%
+/* Next is all token values, in a form suitable for use by makeheaders.
+** This section will be null unless lemon is run with the -m switch.
+*/
+/* 
+** These constants (all generated automatically by the parser generator)
+** specify the various kinds of tokens (terminals) that the parser
+** understands. 
+**
+** Each symbol here is a terminal symbol in the grammar.
+*/
+%%
+/* Make sure the INTERFACE macro is defined.
+*/
+#ifndef INTERFACE
+# define INTERFACE 1
+#endif
+/* The next thing included is series of defines which control
+** various aspects of the generated parser.
+**    YYCODETYPE         is the data type used for storing terminal
+**                       and nonterminal numbers.  "unsigned char" is
+**                       used if there are fewer than 250 terminals
+**                       and nonterminals.  "int" is used otherwise.
+**    YYNOCODE           is a number of type YYCODETYPE which corresponds
+**                       to no legal terminal or nonterminal number.  This
+**                       number is used to fill in empty slots of the hash 
+**                       table.
+**    YYFALLBACK         If defined, this indicates that one or more tokens
+**                       have fall-back values which should be used if the
+**                       original value of the token will not parse.
+**    YYACTIONTYPE       is the data type used for storing terminal
+**                       and nonterminal numbers.  "unsigned char" is
+**                       used if there are fewer than 250 rules and
+**                       states combined.  "int" is used otherwise.
+**    ParseTOKENTYPE     is the data type used for minor tokens given 
+**                       directly to the parser from the tokenizer.
+**    YYMINORTYPE        is the data type used for all minor tokens.
+**                       This is typically a union of many types, one of
+**                       which is ParseTOKENTYPE.  The entry in the union
+**                       for base tokens is called "yy0".
+**    YYSTACKDEPTH       is the maximum depth of the parser's stack.  If
+**                       zero the stack is dynamically sized using realloc()
+**    ParseARG_SDECL     A static variable declaration for the %extra_argument
+**    ParseARG_PDECL     A parameter declaration for the %extra_argument
+**    ParseARG_STORE     Code to store %extra_argument into yypParser
+**    ParseARG_FETCH     Code to extract %extra_argument from yypParser
+**    YYNSTATE           the combined number of states.
+**    YYNRULE            the number of rules in the grammar
+**    YYERRORSYMBOL      is the code number of the error symbol.  If not
+**                       defined, then do no error processing.
+*/
+%%
+#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
+#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
+#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)
+
+/* Next are that tables used to determine what action to take based on the
+** current state and lookahead token.  These tables are used to implement
+** functions that take a state number and lookahead value and return an
+** action integer.  
+**
+** Suppose the action integer is N.  Then the action is determined as
+** follows
+**
+**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
+**                                      token onto the stack and goto state N.
+**
+**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
+**
+**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
+**
+**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
+**
+**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
+**                                      slots in the yy_action[] table.
+**
+** The action table is constructed as a single large table named yy_action[].
+** Given state S and lookahead X, the action is computed as
+**
+**      yy_action[ yy_shift_ofst[S] + X ]
+**
+** If the index value yy_shift_ofst[S]+X is out of range or if the value
+** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+** and that yy_default[S] should be used instead.  
+**
+** The formula above is for computing the action when the lookahead is
+** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
+** a reduce action) then the yy_reduce_ofst[] array is used in place of
+** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
+** YY_SHIFT_USE_DFLT.
+**
+** The following are the tables generated in this section:
+**
+**  yy_action[]        A single table containing all actions.
+**  yy_lookahead[]     A table containing the lookahead for each entry in
+**                     yy_action.  Used to detect hash collisions.
+**  yy_shift_ofst[]    For each state, the offset into yy_action for
+**                     shifting terminals.
+**  yy_reduce_ofst[]   For each state, the offset into yy_action for
+**                     shifting non-terminals after a reduce.
+**  yy_default[]       Default action for each state.
+*/
+%%
+#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
+
+/* The next table maps tokens into fallback tokens.  If a construct
+** like the following:
+** 
+**      %fallback ID X Y Z.
+**
+** appears in the grammer, then ID becomes a fallback token for X, Y,
+** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
+** but it does not parse, the type of the token is changed to ID and
+** the parse is retried before an error is thrown.
+*/
+#ifdef YYFALLBACK
+static const YYCODETYPE yyFallback[] = {
+%%
+};
+#endif /* YYFALLBACK */
+
+/* The following structure represents a single element of the
+** parser's stack.  Information stored includes:
+**
+**   +  The state number for the parser at this level of the stack.
+**
+**   +  The value of the token stored at this level of the stack.
+**      (In other words, the "major" token.)
+**
+**   +  The semantic value stored at this level of the stack.  This is
+**      the information used by the action routines in the grammar.
+**      It is sometimes called the "minor" token.
+*/
+struct yyStackEntry {
+  int stateno;       /* The state-number */
+  int major;         /* The major token value.  This is the code
+                     ** number for the token at this stack level */
+  YYMINORTYPE minor; /* The user-supplied minor token value.  This
+                     ** is the value of the token  */
+};
+typedef struct yyStackEntry yyStackEntry;
+
+/* The state of the parser is completely contained in an instance of
+** the following structure */
+struct yyParser {
+  int yyidx;                    /* Index of top element in stack */
+  int yyerrcnt;                 /* Shifts left before out of the error */
+  ParseARG_SDECL                /* A place to hold %extra_argument */
+#if YYSTACKDEPTH<=0
+  int yystksz;                  /* Current side of the stack */
+  yyStackEntry *yystack;        /* The parser's stack */
+#else
+  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
+#endif
+};
+typedef struct yyParser yyParser;
+
+#ifndef NDEBUG
+#include <stdio.h>
+static FILE *yyTraceFILE = 0;
+static char *yyTracePrompt = 0;
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* 
+** Turn parser tracing on by giving a stream to which to write the trace
+** and a prompt to preface each trace message.  Tracing is turned off
+** by making either argument NULL 
+**
+** Inputs:
+** <ul>
+** <li> A FILE* to which trace output should be written.
+**      If NULL, then tracing is turned off.
+** <li> A prefix string written at the beginning of every
+**      line of trace output.  If NULL, then tracing is
+**      turned off.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
+  yyTraceFILE = TraceFILE;
+  yyTracePrompt = zTracePrompt;
+  if( yyTraceFILE==0 ) yyTracePrompt = 0;
+  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
+}
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing shifts, the names of all terminals and nonterminals
+** are required.  The following table supplies these names */
+static const char *const yyTokenName[] = { 
+%%
+};
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing reduce actions, the names of all rules are required.
+*/
+static const char *const yyRuleName[] = {
+%%
+};
+#endif /* NDEBUG */
+
+
+#if YYSTACKDEPTH<=0
+/*
+** Try to increase the size of the parser stack.
+*/
+static void yyGrowStack(yyParser *p){
+  int newSize;
+  yyStackEntry *pNew;
+
+  newSize = p->yystksz*2 + 100;
+  pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
+  if( pNew ){
+    p->yystack = pNew;
+    p->yystksz = newSize;
+#ifndef NDEBUG
+    if( yyTraceFILE ){
+      fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
+              yyTracePrompt, p->yystksz);
+    }
+#endif
+  }
+}
+#endif
+
+/* MW */
+Lsystem *lsys;
+bool syntaxOnly;
+bool *syntaxOk;
+
+/* 
+** This function allocates a new parser.
+** The only argument is a pointer to a function which works like
+** malloc.
+**
+** Inputs:
+** A pointer to the function used to allocate memory.
+**
+** Outputs:
+** A pointer to a parser.  This pointer is used in subsequent calls
+** to Parse and ParseFree.
+*/
+void *ParseAlloc(void *(*mallocProc)(size_t), Lsystem *lsystem, bool checkSyntaxOnly = false, bool *isSyntaxOk = NULL){
+  yyParser *pParser;
+  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
+  if( pParser ){
+    pParser->yyidx = -1;
+#if YYSTACKDEPTH<=0
+    yyGrowStack(pParser);
+#endif
+	  //input = new Lsystem();
+	  lsys = lsystem;
+	  syntaxOnly = checkSyntaxOnly;
+	  syntaxOk = isSyntaxOk;
+  }
+  return pParser;
+}
+
+/* The following function deletes the value associated with a
+** symbol.  The symbol can be either a terminal or nonterminal.
+** "yymajor" is the symbol code, and "yypminor" is a pointer to
+** the value.
+*/
+static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
+  switch( yymajor ){
+    /* Here is inserted the actions which take place when a
+    ** terminal or non-terminal is destroyed.  This can happen
+    ** when the symbol is popped from the stack during a
+    ** reduce or during error processing or when a parser is 
+    ** being destroyed before it is finished parsing.
+    **
+    ** Note: during a reduce, the only symbols destroyed are those
+    ** which appear on the RHS of the rule, but which are not used
+    ** inside the C code.
+    */
+%%
+    default:  break;   /* If no destructor action specified: do nothing */
+  }
+}
+
+/*
+** Pop the parser's stack once.
+**
+** If there is a destructor routine associated with the token which
+** is popped from the stack, then call it.
+**
+** Return the major token number for the symbol popped.
+*/
+static int yy_pop_parser_stack(yyParser *pParser){
+  YYCODETYPE yymajor;
+  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
+
+  if( pParser->yyidx<0 ) return 0;
+#ifndef NDEBUG
+  if( yyTraceFILE && pParser->yyidx>=0 ){
+    fprintf(yyTraceFILE,"%sPopping %s\n",
+      yyTracePrompt,
+      yyTokenName[yytos->major]);
+  }
+#endif
+  yymajor = yytos->major;
+  yy_destructor( yymajor, &yytos->minor);
+  pParser->yyidx--;
+  return yymajor;
+}
+
+/* 
+** Deallocate and destroy a parser.  Destructors are all called for
+** all stack elements before shutting the parser down.
+**
+** Inputs:
+** <ul>
+** <li>  A pointer to the parser.  This should be a pointer
+**       obtained from ParseAlloc.
+** <li>  A pointer to a function used to reclaim memory obtained
+**       from malloc.
+** </ul>
+*/
+void ParseFree(
+  void *p,                    /* The parser to be deleted */
+  void (*freeProc)(void*)     /* Function used to reclaim memory */
+){
+  yyParser *pParser = (yyParser*)p;
+  if( pParser==0 ) return;
+  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
+#if YYSTACKDEPTH<=0
+  free(pParser->yystack);
+#endif
+  (*freeProc)((void*)pParser);
+	//delete lsys;
+}
+
+/*
+** Find the appropriate action for a parser given the terminal
+** look-ahead token iLookAhead.
+**
+** If the look-ahead token is YYNOCODE, then check to see if the action is
+** independent of the look-ahead.  If it is, return the action, otherwise
+** return YY_NO_ACTION.
+*/
+static int yy_find_shift_action(
+  yyParser *pParser,        /* The parser */
+  YYCODETYPE iLookAhead     /* The look-ahead token */
+){
+  int i;
+  int stateno = pParser->yystack[pParser->yyidx].stateno;
+ 
+  if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
+    return yy_default[stateno];
+  }
+  assert( iLookAhead!=YYNOCODE );
+  i += iLookAhead;
+  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
+    if( iLookAhead>0 ){
+#ifdef YYFALLBACK
+      int iFallback;            /* Fallback token */
+      if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
+             && (iFallback = yyFallback[iLookAhead])!=0 ){
+#ifndef NDEBUG
+        if( yyTraceFILE ){
+          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
+             yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+        }
+#endif
+        return yy_find_shift_action(pParser, iFallback);
+      }
+#endif
+#ifdef YYWILDCARD
+      {
+        int j = i - iLookAhead + YYWILDCARD;
+        if( j>=0 && j<YY_SZ_ACTTAB && yy_lookahead[j]==YYWILDCARD ){
+#ifndef NDEBUG
+          if( yyTraceFILE ){
+            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
+               yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
+          }
+#endif /* NDEBUG */
+          return yy_action[j];
+        }
+      }
+#endif /* YYWILDCARD */
+    }
+    return yy_default[stateno];
+  }else{
+    return yy_action[i];
+  }
+}
+
+/*
+** Find the appropriate action for a parser given the non-terminal
+** look-ahead token iLookAhead.
+**
+** If the look-ahead token is YYNOCODE, then check to see if the action is
+** independent of the look-ahead.  If it is, return the action, otherwise
+** return YY_NO_ACTION.
+*/
+static int yy_find_reduce_action(
+  int stateno,              /* Current state number */
+  YYCODETYPE iLookAhead     /* The look-ahead token */
+){
+  int i;
+  assert( stateno<=YY_REDUCE_MAX );
+  i = yy_reduce_ofst[stateno];
+  assert( i!=YY_REDUCE_USE_DFLT );
+  assert( iLookAhead!=YYNOCODE );
+  i += iLookAhead;
+  assert( i>=0 && i<YY_SZ_ACTTAB );
+  assert( yy_lookahead[i]==iLookAhead );
+  return yy_action[i];
+}
+
+/*
+** The following routine is called if the stack overflows.
+*/
+static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
+   ParseARG_FETCH;
+   yypParser->yyidx--;
+#ifndef NDEBUG
+   if( yyTraceFILE ){
+     fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
+   }
+#endif
+   while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+   /* Here code is inserted which will execute if the parser
+   ** stack every overflows */
+%%
+   ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
+}
+
+/*
+** Perform a shift action.
+*/
+static void yy_shift(
+  yyParser *yypParser,          /* The parser to be shifted */
+  int yyNewState,               /* The new state to shift in */
+  int yyMajor,                  /* The major token to shift in */
+  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */
+){
+  yyStackEntry *yytos;
+  yypParser->yyidx++;
+#if YYSTACKDEPTH>0 
+  if( yypParser->yyidx>=YYSTACKDEPTH ){
+    yyStackOverflow(yypParser, yypMinor);
+    return;
+  }
+#else
+  if( yypParser->yyidx>=yypParser->yystksz ){
+    yyGrowStack(yypParser);
+    if( yypParser->yyidx>=yypParser->yystksz ){
+      yyStackOverflow(yypParser, yypMinor);
+      return;
+    }
+  }
+#endif
+  yytos = &yypParser->yystack[yypParser->yyidx];
+  yytos->stateno = yyNewState;
+  yytos->major = yyMajor;
+  yytos->minor = *yypMinor;
+#ifndef NDEBUG
+  if( yyTraceFILE && yypParser->yyidx>0 ){
+    int i;
+    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
+    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
+    for(i=1; i<=yypParser->yyidx; i++)
+      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
+    fprintf(yyTraceFILE,"\n");
+  }
+#endif
+}
+
+/* The following table contains information about every rule that
+** is used during the reduce.
+*/
+static const struct {
+  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
+  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
+} yyRuleInfo[] = {
+%%
+};
+
+static void yy_accept(yyParser*);  /* Forward Declaration */
+
+/*
+** Perform a reduce action and the shift that must immediately
+** follow the reduce.
+*/
+static void yy_reduce(
+  yyParser *yypParser,         /* The parser */
+  int yyruleno                 /* Number of the rule by which to reduce */
+){
+  int yygoto;                     /* The next state */
+  int yyact;                      /* The next action */
+  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
+  yyStackEntry *yymsp;            /* The top of the parser's stack */
+  int yysize;                     /* Amount to pop the stack */
+  ParseARG_FETCH;
+  yymsp = &yypParser->yystack[yypParser->yyidx];
+#ifndef NDEBUG
+  if( yyTraceFILE && yyruleno>=0 
+        && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
+    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
+      yyRuleName[yyruleno]);
+  }
+#endif /* NDEBUG */
+
+  /* Silence complaints from purify about yygotominor being uninitialized
+  ** in some cases when it is copied into the stack after the following
+  ** switch.  yygotominor is uninitialized when a rule reduces that does
+  ** not set the value of its left-hand side nonterminal.  Leaving the
+  ** value of the nonterminal uninitialized is utterly harmless as long
+  ** as the value is never used.  So really the only thing this code
+  ** accomplishes is to quieten purify.  
+  **
+  ** 2007-01-16:  The wireshark project (www.wireshark.org) reports that
+  ** without this code, their parser segfaults.  I'm not sure what there
+  ** parser is doing to make this happen.  This is the second bug report
+  ** from wireshark this week.  Clearly they are stressing Lemon in ways
+  ** that it has not been previously stressed...  (SQLite ticket #2172)
+  */
+  memset(&yygotominor, 0, sizeof(yygotominor));
+
+
+  switch( yyruleno ){
+  /* Beginning here are the reduction cases.  A typical example
+  ** follows:
+  **   case 0:
+  **  #line <lineno> <grammarfile>
+  **     { ... }           // User supplied code
+  **  #line <lineno> <thisfile>
+  **     break;
+  */
+%%
+  };
+  yygoto = yyRuleInfo[yyruleno].lhs;
+  yysize = yyRuleInfo[yyruleno].nrhs;
+  yypParser->yyidx -= yysize;
+  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto);
+  if( yyact < YYNSTATE ){
+#ifdef NDEBUG
+    /* If we are not debugging and the reduce action popped at least
+    ** one element off the stack, then we can push the new element back
+    ** onto the stack here, and skip the stack overflow test in yy_shift().
+    ** That gives a significant speed improvement. */
+    if( yysize ){
+      yypParser->yyidx++;
+      yymsp -= yysize-1;
+      yymsp->stateno = yyact;
+      yymsp->major = yygoto;
+      yymsp->minor = yygotominor;
+    }else
+#endif
+    {
+      yy_shift(yypParser,yyact,yygoto,&yygotominor);
+    }
+  }else{
+    assert( yyact == YYNSTATE + YYNRULE + 1 );
+    yy_accept(yypParser);
+  }
+}
+
+/*
+** The following code executes when the parse fails
+*/
+static void yy_parse_failed(
+  yyParser *yypParser           /* The parser */
+){
+  ParseARG_FETCH;
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
+  }
+#endif
+  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+  /* Here code is inserted which will be executed whenever the
+  ** parser fails */
+%%
+  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/*
+** The following code executes when a syntax error first occurs.
+*/
+static void yy_syntax_error(
+  yyParser *yypParser,           /* The parser */
+  int yymajor,                   /* The major type of the error token */
+  YYMINORTYPE yyminor            /* The minor type of the error token */
+){
+  ParseARG_FETCH;
+#define TOKEN (yyminor.yy0)
+%%
+  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/*
+** The following is executed when the parser accepts
+*/
+static void yy_accept(
+  yyParser *yypParser           /* The parser */
+){
+  ParseARG_FETCH;
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
+  }
+#endif
+  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+  /* Here code is inserted which will be executed whenever the
+  ** parser accepts */
+%%
+  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/* The main parser program.
+** The first argument is a pointer to a structure obtained from
+** "ParseAlloc" which describes the current state of the parser.
+** The second argument is the major token number.  The third is
+** the minor token.  The fourth optional argument is whatever the
+** user wants (and specified in the grammar) and is available for
+** use by the action routines.
+**
+** Inputs:
+** <ul>
+** <li> A pointer to the parser (an opaque structure.)
+** <li> The major token number.
+** <li> The minor token number.
+** <li> An option argument of a grammar-specified type.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void Parse(
+  void *yyp,                   /* The parser */
+  int yymajor,                 /* The major token code number */
+  ParseTOKENTYPE yyminor       /* The value for the token */
+  ParseARG_PDECL               /* Optional %extra_argument parameter */
+){
+  YYMINORTYPE yyminorunion;
+  int yyact;            /* The parser action. */
+  int yyendofinput;     /* True if we are at the end of input */
+#ifdef YYERRORSYMBOL
+  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
+#endif
+  yyParser *yypParser;  /* The parser */
+
+  /* (re)initialize the parser, if necessary */
+  yypParser = (yyParser*)yyp;
+  if( yypParser->yyidx<0 ){
+#if YYSTACKDEPTH<=0
+    if( yypParser->yystksz <=0 ){
+      memset(&yyminorunion, 0, sizeof(yyminorunion));
+      yyStackOverflow(yypParser, &yyminorunion);
+      return;
+    }
+#endif
+    yypParser->yyidx = 0;
+    yypParser->yyerrcnt = -1;
+    yypParser->yystack[0].stateno = 0;
+    yypParser->yystack[0].major = 0;
+  }
+  yyminorunion.yy0 = yyminor;
+  yyendofinput = (yymajor==0);
+  ParseARG_STORE;
+
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
+  }
+#endif
+
+  do{
+    yyact = yy_find_shift_action(yypParser,yymajor);
+    if( yyact<YYNSTATE ){
+      assert( !yyendofinput );  /* Impossible to shift the $ token */
+      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
+      yypParser->yyerrcnt--;
+      yymajor = YYNOCODE;
+    }else if( yyact < YYNSTATE + YYNRULE ){
+      yy_reduce(yypParser,yyact-YYNSTATE);
+    }else{
+      assert( yyact == YY_ERROR_ACTION );
+#ifdef YYERRORSYMBOL
+      int yymx;
+#endif
+#ifndef NDEBUG
+      if( yyTraceFILE ){
+        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
+      }
+#endif
+#ifdef YYERRORSYMBOL
+      /* A syntax error has occurred.
+      ** The response to an error depends upon whether or not the
+      ** grammar defines an error token "ERROR".  
+      **
+      ** This is what we do if the grammar does define ERROR:
+      **
+      **  * Call the %syntax_error function.
+      **
+      **  * Begin popping the stack until we enter a state where
+      **    it is legal to shift the error symbol, then shift
+      **    the error symbol.
+      **
+      **  * Set the error count to three.
+      **
+      **  * Begin accepting and shifting new tokens.  No new error
+      **    processing will occur until three tokens have been
+      **    shifted successfully.
+      **
+      */
+      if( yypParser->yyerrcnt<0 ){
+        yy_syntax_error(yypParser,yymajor,yyminorunion);
+      }
+      yymx = yypParser->yystack[yypParser->yyidx].major;
+      if( yymx==YYERRORSYMBOL || yyerrorhit ){
+#ifndef NDEBUG
+        if( yyTraceFILE ){
+          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
+             yyTracePrompt,yyTokenName[yymajor]);
+        }
+#endif
+        yy_destructor(yymajor,&yyminorunion);
+        yymajor = YYNOCODE;
+      }else{
+         while(
+          yypParser->yyidx >= 0 &&
+          yymx != YYERRORSYMBOL &&
+          (yyact = yy_find_reduce_action(
+                        yypParser->yystack[yypParser->yyidx].stateno,
+                        YYERRORSYMBOL)) >= YYNSTATE
+        ){
+          yy_pop_parser_stack(yypParser);
+        }
+        if( yypParser->yyidx < 0 || yymajor==0 ){
+          yy_destructor(yymajor,&yyminorunion);
+          yy_parse_failed(yypParser);
+          yymajor = YYNOCODE;
+        }else if( yymx!=YYERRORSYMBOL ){
+          YYMINORTYPE u2;
+          u2.YYERRSYMDT = 0;
+          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
+        }
+      }
+      yypParser->yyerrcnt = 3;
+      yyerrorhit = 1;
+#else  /* YYERRORSYMBOL is not defined */
+      /* This is what we do if the grammar does not define ERROR:
+      **
+      **  * Report an error message, and throw away the input token.
+      **
+      **  * If the input token is $, then fail the parse.
+      **
+      ** As before, subsequent error messages are suppressed until
+      ** three input tokens have been successfully shifted.
+      */
+      if( yypParser->yyerrcnt<=0 ){
+        yy_syntax_error(yypParser,yymajor,yyminorunion);
+      }
+      yypParser->yyerrcnt = 3;
+      yy_destructor(yymajor,&yyminorunion);
+      if( yyendofinput ){
+        yy_parse_failed(yypParser);
+      }
+      yymajor = YYNOCODE;
+#endif
+    }
+  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
+  return;
+}
+
+
Index: /cpp/_old/f8-to-f1/lexglobal.h
===================================================================
--- /cpp/_old/f8-to-f1/lexglobal.h	(revision 110)
+++ /cpp/_old/f8-to-f1/lexglobal.h	(revision 110)
@@ -0,0 +1,24 @@
+/*
+ *  lexglobal.h
+ *  L-systemToF1
+ *
+ *  Created by Maciej Wajcht on 08-03-28.
+ *  Copyright 2008 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef YYSTYPE
+#include "sstring.h"
+
+typedef struct {
+	double dblVal;
+	SString strVal;
+	struct symtab *symp;
+} yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+
+#endif
+
+/* extern YYSTYPE yylval; */
+//YYSTYPE yylval;
Index: p/geno_fx/LICENSE.txt
===================================================================
--- /cpp/geno_fx/LICENSE.txt	(revision 109)
+++ 	(revision )
@@ -1,452 +1,0 @@
-If you are using  any  part  of  Framsticks  GenoFX  for  a  project
-which is not  a  part  of  Framsticks  software,  please  explicitly
-acknowledge GenoFX and make a link to Framsticks, www.framsticks.com
-
----
-
-
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 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.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, 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 library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, 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 companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
-
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the 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.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
