summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2009-03-06 03:32:41 +0000
committerAdrian Thurston <thurston@complang.org>2009-03-06 03:32:41 +0000
commit43710153be28444536f527a05db2df81b9a1a095 (patch)
tree3b234e400fc1e2cf98e5db5f4aadbd5ea20cc34a
parent99bad941034ba014cdae7eae6ddd3f11121c67ae (diff)
parenta56c3a5d4b9b2139fb203b6adf93b93c88b75f52 (diff)
downloadcolm-43710153be28444536f527a05db2df81b9a1a095.tar.gz
Redid the branch for the pull scanner, this time at the root of the project and
not the colm subdir.
-rw-r--r--COPYING340
-rw-r--r--Makefile.in144
-rw-r--r--README43
-rw-r--r--aapl/COPYING502
-rw-r--r--aapl/README6
-rw-r--r--aapl/astring.h809
-rw-r--r--aapl/avlbasic.h65
-rw-r--r--aapl/avlcommon.h1630
-rw-r--r--aapl/avlibasic.h67
-rw-r--r--aapl/avlikeyless.h64
-rw-r--r--aapl/avlimap.h77
-rw-r--r--aapl/avlimel.h79
-rw-r--r--aapl/avlimelkey.h76
-rw-r--r--aapl/avliset.h75
-rw-r--r--aapl/avlitree.h78
-rw-r--r--aapl/avlkeyless.h58
-rw-r--r--aapl/avlmap.h74
-rw-r--r--aapl/avlmel.h74
-rw-r--r--aapl/avlmelkey.h71
-rw-r--r--aapl/avlset.h70
-rw-r--r--aapl/avltree.h73
-rw-r--r--aapl/bstcommon.h814
-rw-r--r--aapl/bstmap.h113
-rw-r--r--aapl/bstset.h86
-rw-r--r--aapl/bsttable.h84
-rw-r--r--aapl/bubblesort.h94
-rw-r--r--aapl/compare.h273
-rw-r--r--aapl/dlcommon.h790
-rw-r--r--aapl/dlist.h64
-rw-r--r--aapl/dlistmel.h71
-rw-r--r--aapl/dlistval.h71
-rw-r--r--aapl/insertsort.h94
-rw-r--r--aapl/mergesort.h140
-rw-r--r--aapl/quicksort.h185
-rw-r--r--aapl/resize.h344
-rw-r--r--aapl/sbstmap.h121
-rw-r--r--aapl/sbstset.h94
-rw-r--r--aapl/sbsttable.h93
-rw-r--r--aapl/svector.h1350
-rw-r--r--aapl/table.h252
-rw-r--r--aapl/vector.h1189
-rw-r--r--colm.vim91
-rw-r--r--colm/Makefile.in161
-rw-r--r--colm/buffer.h (renamed from buffer.h)0
-rw-r--r--colm/bytecode.cpp (renamed from bytecode.cpp)0
-rw-r--r--colm/bytecode.h (renamed from bytecode.h)0
-rw-r--r--colm/closure.cpp (renamed from closure.cpp)0
-rw-r--r--colm/colm.h (renamed from colm.h)0
-rw-r--r--colm/compile.cpp (renamed from compile.cpp)0
-rw-r--r--colm/config.h.in (renamed from config.h.in)0
-rw-r--r--colm/dotgen.cpp (renamed from dotgen.cpp)0
-rw-r--r--colm/dotgen.h (renamed from dotgen.h)0
-rw-r--r--colm/fsmap.cpp (renamed from fsmap.cpp)0
-rw-r--r--colm/fsmattach.cpp (renamed from fsmattach.cpp)0
-rw-r--r--colm/fsmbase.cpp (renamed from fsmbase.cpp)0
-rw-r--r--colm/fsmcodegen.cpp (renamed from fsmcodegen.cpp)8
-rw-r--r--colm/fsmcodegen.h (renamed from fsmcodegen.h)0
-rw-r--r--colm/fsmexec.cpp (renamed from fsmexec.cpp)22
-rw-r--r--colm/fsmgraph.cpp (renamed from fsmgraph.cpp)0
-rw-r--r--colm/fsmgraph.h (renamed from fsmgraph.h)0
-rw-r--r--colm/fsmmin.cpp (renamed from fsmmin.cpp)0
-rw-r--r--colm/fsmrun.cpp (renamed from fsmrun.cpp)0
-rw-r--r--colm/fsmrun.h (renamed from fsmrun.h)2
-rw-r--r--colm/fsmstate.cpp (renamed from fsmstate.cpp)0
-rw-r--r--colm/input.cpp (renamed from input.cpp)0
-rw-r--r--colm/input.h (renamed from input.h)0
-rw-r--r--colm/keyops.h (renamed from keyops.h)0
-rw-r--r--colm/list.cpp (renamed from list.cpp)0
-rw-r--r--colm/lmparse.kh (renamed from lmparse.kh)0
-rw-r--r--colm/lmparse.kl (renamed from lmparse.kl)0
-rw-r--r--colm/lmscan.h (renamed from lmscan.h)0
-rw-r--r--colm/lmscan.rl (renamed from lmscan.rl)0
-rw-r--r--colm/main.cpp (renamed from main.cpp)0
-rw-r--r--colm/map.cpp (renamed from map.cpp)0
-rw-r--r--colm/parsedata.cpp (renamed from parsedata.cpp)0
-rw-r--r--colm/parsedata.h (renamed from parsedata.h)0
-rw-r--r--colm/parsetree.cpp (renamed from parsetree.cpp)0
-rw-r--r--colm/parsetree.h (renamed from parsetree.h)0
-rw-r--r--colm/pcheck.cpp (renamed from pcheck.cpp)0
-rw-r--r--colm/pcheck.h (renamed from pcheck.h)0
-rw-r--r--colm/pdabuild.cpp (renamed from pdabuild.cpp)0
-rw-r--r--colm/pdacodegen.cpp (renamed from pdacodegen.cpp)0
-rw-r--r--colm/pdacodegen.h (renamed from pdacodegen.h)0
-rw-r--r--colm/pdagraph.cpp (renamed from pdagraph.cpp)0
-rw-r--r--colm/pdagraph.h (renamed from pdagraph.h)0
-rw-r--r--colm/pdarun.cpp (renamed from pdarun.cpp)0
-rw-r--r--colm/pdarun.h (renamed from pdarun.h)0
-rw-r--r--colm/redbuild.cpp (renamed from redbuild.cpp)0
-rw-r--r--colm/redbuild.h (renamed from redbuild.h)0
-rw-r--r--colm/redfsm.cpp (renamed from redfsm.cpp)0
-rw-r--r--colm/redfsm.h (renamed from redfsm.h)0
-rw-r--r--colm/string.cpp (renamed from string.cpp)0
-rw-r--r--colm/tree.cpp (renamed from tree.cpp)0
-rwxr-xr-xconfigure4177
-rw-r--r--configure.in75
-rw-r--r--test/Makefile46
-rw-r--r--test/backtrack1.lm24
-rw-r--r--test/backtrack2.lm24
-rw-r--r--test/backtrack3.lm27
-rw-r--r--test/btscan.in2
-rw-r--r--test/btscan.lm34
-rw-r--r--test/commitbt.in1
-rw-r--r--test/commitbt.lm110
-rw-r--r--test/constructex.in3
-rw-r--r--test/constructex.lm37
-rw-r--r--test/counting1.in1
-rw-r--r--test/counting1.lm91
-rw-r--r--test/counting2.lm82
-rw-r--r--test/counting3.lm92
-rw-r--r--test/counting4.lm89
-rw-r--r--test/cxx/Makefile34
-rw-r--r--test/cxx/cxx.lm2168
-rw-r--r--test/cxx/input01.cpp17
-rw-r--r--test/cxx/input02.cpp16
-rw-r--r--test/cxx/input03.cpp19
-rw-r--r--test/cxx/input04.cpp17
-rw-r--r--test/cxx/input05.cpp8
-rw-r--r--test/cxx/input06.cpp7
-rw-r--r--test/cxx/input07.cpp18
-rw-r--r--test/cxx/input08.cpp13
-rw-r--r--test/cxx/input09.cpp7
-rw-r--r--test/cxx/input10.cpp11
-rw-r--r--test/cxx/input11.cpp2
-rw-r--r--test/cxx/input12.cpp8
-rw-r--r--test/cxx/input13.cpp14
-rwxr-xr-xtest/cxx/preproc5
-rw-r--r--test/diff/Makefile34
-rw-r--r--test/diff/diff.lm84
-rw-r--r--test/diff/input1.diff86
-rw-r--r--test/dns/Makefile20
-rw-r--r--test/dns/dns.lm488
-rw-r--r--test/dns/dumpdns11
-rw-r--r--test/dns/extract.c48
-rw-r--r--test/heredoc.in3
-rw-r--r--test/heredoc.lm45
-rw-r--r--test/html/Makefile34
-rw-r--r--test/html/html-lextag.lm324
-rw-r--r--test/html/html.lm307
-rw-r--r--test/html/input01.html8
-rw-r--r--test/http/Makefile34
-rw-r--r--test/http/http.lm68
-rw-r--r--test/http/input12
-rw-r--r--test/http/input213
-rw-r--r--test/http/input38
-rw-r--r--test/http/xinetd.conf10
-rw-r--r--test/island.in19
-rw-r--r--test/island.lm57
-rw-r--r--test/liftattrs.in3
-rw-r--r--test/liftattrs.lm74
-rw-r--r--test/mailbox.in29
-rw-r--r--test/mailbox.lm44
-rw-r--r--test/matchex.in3
-rw-r--r--test/matchex.lm34
-rw-r--r--test/maxlen.lm44
-rw-r--r--test/mediawiki/Makefile43
-rw-r--r--test/mediawiki/garticle.rl135
-rw-r--r--test/mediawiki/mediawiki.lm196
-rw-r--r--test/mediawiki/pdump.rl115
-rw-r--r--test/nestedcomm.in1
-rw-r--r--test/nestedcomm.lm41
-rw-r--r--test/python/Makefile33
-rw-r--r--test/python/input1.py18
-rw-r--r--test/python/input2.py20
-rw-r--r--test/python/input3.py1
-rw-r--r--test/python/input4.py10
-rw-r--r--test/python/python.lm727
-rw-r--r--test/ragelambig.in1
-rw-r--r--test/ragelambig1.lm65
-rw-r--r--test/ragelambig2.lm65
-rw-r--r--test/ragelambig3.lm64
-rw-r--r--test/ragelambig4.lm69
-rw-r--r--test/rediv.in1
-rw-r--r--test/rediv.lm92
-rw-r--r--test/ruby/Makefile34
-rw-r--r--test/ruby/ruby.lm606
-rw-r--r--test/rubyhere.in8
-rw-r--r--test/rubyhere.lm89
-rw-r--r--test/string.in2
-rw-r--r--test/string.lm54
-rw-r--r--test/superid.in1
-rw-r--r--test/superid.lm59
-rw-r--r--test/tags.in1
-rw-r--r--test/tags.lm82
-rw-r--r--test/til.in14
-rw-r--r--test/til.lm168
-rw-r--r--test/travs1.in1
-rw-r--r--test/travs1.lm144
-rw-r--r--test/travs2.in1
-rw-r--r--test/travs2.lm93
-rw-r--r--test/xml/Makefile34
-rw-r--r--test/xml/xml.in3962
-rw-r--r--test/xml/xml.lm168
-rw-r--r--version.mk2
193 files changed, 27383 insertions, 131 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..ec0507be
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile.in b/Makefile.in
index 9b247eae..c16f4e8d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -19,143 +19,57 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-# Logging:
-# colm: rt on/off
-# rt_prd: off
-# rt_db: on
-# rt_clm: rt on/off
-
-INCS += -I../aapl
-
-DEFS_COLM += -DCOLM_LOG -DPREFIX='"$(prefix)"'
-DEFS_RT_P +=
-DEFS_RT_D += -DCOLM_LOG
-
-CFLAGS += -g -Wall -Wwrite-strings
-LDFLAGS +=
-
-# Frequently changed ones first.
-COLM_SRC = \
- compile.cpp \
- lmparse.cpp \
- lmscan.cpp \
- parsetree.cpp \
- parsedata.cpp \
- fsmstate.cpp \
- fsmbase.cpp \
- fsmattach.cpp \
- fsmmin.cpp \
- fsmgraph.cpp \
- pdagraph.cpp \
- pdabuild.cpp \
- pdacodegen.cpp \
- fsmcodegen.cpp \
- redfsm.cpp \
- fsmexec.cpp \
- main.cpp \
- redbuild.cpp \
- closure.cpp \
- fsmap.cpp \
- dotgen.cpp \
- pcheck.cpp
-
-RUNTIME_SRC = fsmrun.cpp pdarun.cpp bytecode.cpp list.cpp \
- map.cpp string.cpp input.cpp tree.cpp
-
-ALL_SRC = $(COLM_SRC) $(RUNTIME_SRC)
-
-# Files in ALL_SRC that are generated.
-GEN_SRC = version.h lmscan.cpp lmparse.h lmparse.cpp
-
-RUNTIME_P = libcolmp.a
-RUNTIME_D = libcolmd.a
-
-LIBS =
+BUILD_SUBDIRS = colm
+ALL_SUBDIRS = $(BUILD_SUBDIRS) test
#*************************************
-# Get the version info.
-include ../version.mk
-
-prefix = @prefix@
-
-BUILD_PARSERS = @BUILD_PARSERS@
-
# Programs
CXX = @CXX@
-# Get objects and dependencies from sources.
-COLM_OBJ = $(COLM_SRC:%.cpp=%.o)
-RUNTIME_OBJ_P = $(RUNTIME_SRC:%.cpp=%_p.o)
-RUNTIME_OBJ_D = $(RUNTIME_SRC:%.cpp=%_d.o)
-
-DEPS = $(COLM_SRC:%.cpp=.%.d) $(RUNTIME_SRC:%.cpp=.%_p.d) $(RUNTIME_SRC:%.cpp=.%_d.d)
-
-# Rules.
-all: colm $(RUNTIME_P) $(RUNTIME_D)
+# Get the version info.
+include version.mk
-colm: $(GEN_SRC) $(COLM_OBJ) $(RUNTIME_OBJ_D) $(LIBS)
- $(CXX) $(LDFLAGS) -o $@ $(COLM_OBJ) $(RUNTIME_OBJ_D) $(LIBS)
+# build targets
+all: $(BUILD_SUBDIRS)
-$(RUNTIME_P): $(RUNTIME_OBJ_P)
- ar -cr $@ $^
+.PHONY: $(BUILD_SUBDIRS)
-$(RUNTIME_D): $(RUNTIME_OBJ_D)
- ar -cr $@ $^
+$(BUILD_SUBDIRS):
+ @cd $@ && $(MAKE)
-version.h: ../version.mk
- echo '#define VERSION "$(VERSION)"' > version.h
- echo '#define PUBDATE "$(PUBDATE)"' >> version.h
+# clean targets.
-ifeq ($(BUILD_PARSERS),true)
+CLEAN_SUBDIRS = $(ALL_SUBDIRS:%=%-clean)
-lmparse.h: lmparse.kh
- kelbt -o $@ $<
+.PHONY: $(CLEAN_SUBDIRS)
-lmparse.cpp: lmparse.kl lmparse.kh
- kelbt -o $@ $<
+$(CLEAN_SUBDIRS):
+ @cd $(@:%-clean=%) && $(MAKE) clean
-lmscan.cpp: lmparse.h
+clean: $(CLEAN_SUBDIRS)
+ rm -f tags
-lmscan.cpp: lmscan.rl
- ragel -G2 -o $@ $<
+# distcleaan targets
-endif
+DISTCLEAN_SUBDIRS = $(ALL_SUBDIRS:%=%-distclean)
-$(COLM_OBJ): %.o: %.cpp
- @$(CXX) -M $(DEFS_COLM) $(INCS) $< > .$*.d
- $(CXX) -c $(CFLAGS) $(DEFS_COLM) $(INCS) -o $@ $<
+.PHONY: $(DISTCLEAN_SUBDIRS)
-$(RUNTIME_OBJ_P): %_p.o: %.cpp
- @$(CXX) -M -MT $@ $(DEFS_RT_P) $(INCS) $< > .$*_p.d
- $(CXX) -c $(CFLAGS) $(DEFS_RT_P) $(INCS) -o $@ $<
+$(DISTCLEAN_SUBDIRS):
+ @cd $(@:%-distclean=%) && $(MAKE) clean
-$(RUNTIME_OBJ_D): %_d.o: %.cpp
- @$(CXX) -M -MT $@ $(DEFS_RT_D) $(INCS) $< > .$*_d.d
- $(CXX) -c $(CFLAGS) $(DEFS_RT_D) $(INCS) -o $@ $<
+distclean: $(DISTCLEAN_SUBDIRS)
+ rm -f Makefile config.cache config.status config.log
+#install targets
-distclean: clean
- rm -f Makefile config.h
+INSTALL_SUBDIRS = $(BUILD_SUBDIRS:%=%-install)
-ifeq ($(BUILD_PARSERS),true)
-EXTRA_CLEAN = $(GEN_SRC)
-endif
+.PHONY: $(INSTALL_SUBDIRS)
-clean:
- rm -f tags .*.d *.o colm $(EXTRA_CLEAN) $(RUNTIME_P) $(RUNTIME_D)
+$(INSTALL_SUBDIRS):
+ @cd $(@:%-install=%) && $(MAKE) install
-install: all
- install -d $(prefix)/bin
- install -d $(prefix)/include
- install -d $(prefix)/include/colm
- install -d $(prefix)/lib
- install -s colm $(prefix)/bin/colm
- install libcolmp.a libcolmd.a $(prefix)/lib
- install ../aapl/astring.h ../aapl/avlcommon.h ../aapl/avlmap.h \
- ../aapl/compare.h ../aapl/dlcommon.h ../aapl/dlist.h \
- ../aapl/dlistval.h ../aapl/resize.h ../aapl/table.h \
- ../aapl/vector.h bytecode.h config.h fsmrun.h input.h \
- pdarun.h $(prefix)/include/colm
+install: $(INSTALL_SUBDIRS)
--include $(DEPS)
diff --git a/README b/README
new file mode 100644
index 00000000..a4119acc
--- /dev/null
+++ b/README
@@ -0,0 +1,43 @@
+BUILDING
+========
+
+Colm is currently supported only on Unix-like systems. It depends on the mmap
+function and it must be able to find g++ on the path.
+
+Building Colm from the source repository requires that you have ragel and kelbt
+installed. Building these two packages is straightforward. The usual
+./configure && make should be all that's needed. Alternatively, you may find
+packages for your system.
+
+http://www.complang.org/ragel/
+http://www.complang.org/kelbt/
+
+SYNTAX HIGHLIGHTING
+===================
+
+There is a vim syntax definition file colm.vim
+
+RUNNING
+=======
+
+The colm executable takes a Colm program and generates a .cpp file from it. It
+then compiles this program using g++. The g++ compile phase depends on include
+directories in the colm distribution, as well as a runtime library. Colm finds
+these using argv[0]:
+
+ -I dirname(argv[0])"../aapl"
+ -I dirname(argv[0])"../colm"
+ dirname(argv[0])"../colm/runtime.a"
+
+Therefore it is easiest to just run colm from the place it was built. This is
+temporary. In the future a proper install scheme will be provided.
+
+$ ./colm prog.lm
+
+Will produce:
+ prog.cpp
+ prog.bin
+
+The prog.bin program can then be run on some input:
+
+$ ./prog.bin < inputfile
diff --git a/aapl/COPYING b/aapl/COPYING
new file mode 100644
index 00000000..c6ed510b
--- /dev/null
+++ b/aapl/COPYING
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ 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 combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 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
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/aapl/README b/aapl/README
new file mode 100644
index 00000000..a2fa5e65
--- /dev/null
+++ b/aapl/README
@@ -0,0 +1,6 @@
+This directory contains the Aapl source distribution. For the
+documentation, build scripts, test programs, ChangeLog, etc. get the
+aapldev package.
+
+AaplDev and other information about Aapl is available from
+http://www.elude.ca/aapl/
diff --git a/aapl/astring.h b/aapl/astring.h
new file mode 100644
index 00000000..59343726
--- /dev/null
+++ b/aapl/astring.h
@@ -0,0 +1,809 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_ASTRING_H
+#define _AAPL_ASTRING_H
+
+#include <new>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <assert.h>
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+#ifdef AAPL_DOCUMENTATION
+
+/**
+ * \defgroup astring String
+ * \brief Implicitly shared copy-on-write string.
+ *
+ * @{
+ */
+
+/**
+ * \class String
+ * \brief Implicitly shared copy-on-write string.
+ */
+
+/*@}*/
+
+class String
+{
+public:
+ /**
+ * \brief Create a null string. Data points to NULL.
+ */
+ String();
+
+ /**
+ * \brief Construct a string from a c-style string.
+ *
+ * A new buffer is allocated for the c string. Initially, this string will
+ * be the only String class referencing the data.
+ */
+ String( const char *s );
+
+ /**
+ * \brief Construct a string from a c-style string of specific length.
+ *
+ * A new buffer is allocated for the c string. Initially, this string will
+ * be the only String class referencing the data.
+ */
+ String( const char *s, long len );
+
+ /**
+ * \brief Construct a string from another String.
+ *
+ * A refernce to the buffer allocated for s is taken. A new buffer is
+ * not allocated.
+ */
+ String( const String &s );
+
+ /**
+ * \brief Construct a string using snprintf.
+ *
+ * Requires a maximum length for the resulting string. If the formatting
+ * (not including trailing null) requires more space than maxLen, the
+ * result will be truncated to maxLen long. Only the length actually
+ * written will be used by the new string. This string will be the only
+ * String class referencing the data.
+ */
+ String( long maxLen, const char *format, ... )
+
+ /**
+ * \brief Clean up the string.
+ *
+ * If the string is not null, the referenced data is detached. If no other
+ * string refernces the detached data, it is deleted.
+ */
+ ~String();
+
+ /**
+ * \brief Set the string from a c-style string.
+ *
+ * If this string is not null, the current buffer is dereferenced and
+ * possibly deleted. A new buffer is allocated (or possibly the old buffer
+ * reused) for the string. Initially, this string will be the only String
+ * class referencing the data.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns A reference to this.
+ */
+ String &operator=( const char *s );
+
+ /**
+ * \brief Set the string from a c-style of specific length.
+ *
+ * If this string is not null, the current buffer is dereferenced and
+ * possibly deleted. A new buffer is allocated (or possibly the old buffer
+ * reused) for the string. Initially, this string will be the only String
+ * class referencing the data.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns A reference to this.
+ */
+ void setAs( const char *s, long len );
+
+ /**
+ * \brief Set the string from a single char.
+ *
+ * The current buffer is dereferenced and possibly deleted. A new buffer
+ * is allocated (or possibly the old buffer reused) for the string.
+ * Initially, this string will be the only String class referencing the
+ * data.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns A reference to this.
+ */
+ String &operator=( const char c );
+
+
+ /**
+ * \brief Set the string from another String.
+ *
+ * If this string is not null, the current buffer is dereferenced and
+ * possibly deleted. A reference to the buffer allocated for s is taken.
+ * A new buffer is not allocated.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns a reference to this.
+ */
+ String &operator=( const String &s );
+
+ /**
+ * \brief Append a c string to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and s is appended to the
+ * end.
+ *
+ * If s is null nothing happens.
+ *
+ * \returns a reference to this.
+ */
+ String &operator+=( const char *s );
+
+ /**
+ * \brief Append a c string of specific length to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and s is appended to the
+ * end.
+ *
+ * If s is null nothing happens.
+ *
+ * \returns a reference to this.
+ */
+ void append( const char *s, long len );
+
+ /**
+ * \brief Append a single char to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and s is appended to the
+ * end.
+ *
+ * \returns a reference to this.
+ */
+ String &operator+=( const char c );
+
+ /**
+ * \brief Append a String to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and the data of s is
+ * appeneded to the end.
+ *
+ * If s is null nothing happens.
+ *
+ * returns a reference to this.
+ */
+ String &operator+=( const String &s );
+
+ /**
+ * \brief Cast to a char star.
+ *
+ * \returns the string data. A null string returns 0.
+ */
+ operator char*() const;
+
+ /**
+ * \brief Get a pointer to the data.
+ *
+ * \returns the string Data
+ */
+ char *get() const;
+
+ /**
+ * \brief Get the length of the string
+ *
+ * If the string is null, then undefined behaviour results.
+ *
+ * \returns the length of the string.
+ */
+ long length() const;
+
+ /**
+ * \brief Pointer to the data.
+ *
+ * Publically accessible pointer to the data. Immediately in front of the
+ * string data block is the string header which stores the refcount and
+ * length. Consequently, care should be taken if modifying this pointer.
+ */
+ char *data;
+};
+
+/**
+ * \relates String
+ * \brief Concatenate a c-style string and a String.
+ *
+ * \returns The concatenation of the two strings in a String.
+ */
+String operator+( const String &s1, const char *s2 );
+
+/**
+ * \relates String
+ * \brief Concatenate a String and a c-style string.
+ *
+ * \returns The concatenation of the two strings in a String.
+ */
+String operator+( const char *s1, const String &s2 );
+
+/**
+ * \relates String
+ * \brief Concatenate two String classes.
+ *
+ * \returns The concatenation of the two strings in a String.
+ */
+String operator+( const String &s1, const String &s2 );
+
+#endif
+
+template<class T> class StrTmpl
+{
+public:
+ class Fresh {};
+
+ /* Header located just before string data. Keeps the length and a refcount on
+ * the data. */
+ struct Head
+ {
+ long refCount;
+ long length;
+ };
+
+ /**
+ * \brief Create a null string.
+ */
+ StrTmpl() : data(0) { }
+
+ /* Clean up the string. */
+ ~StrTmpl();
+
+ /* Construct a string from a c-style string. */
+ StrTmpl( const char *s );
+
+ /* Construct a string from a c-style string of specific len. */
+ StrTmpl( const char *s, long len );
+
+ /* Allocate len spaces. */
+ StrTmpl( const Fresh &, long len );
+
+ /* Construct a string from another StrTmpl. */
+ StrTmpl( const StrTmpl &s );
+
+ /* Construct a string from with, sprintf. */
+ StrTmpl( long lenGuess, const char *format, ... );
+
+ /* Set the string from a c-style string. */
+ StrTmpl &operator=( const char *s );
+
+ /* Set the string from a c-style string of specific len. */
+ void setAs( const char *s, long len );
+
+ /* Allocate len spaces. */
+ void setAs( const Fresh &, long len );
+
+ void chop( long len );
+
+ /* Construct a string from with, sprintf. */
+ void setAs( long lenGuess, const char *format, ... );
+
+ /* Set the string from a single char. */
+ StrTmpl &operator=( const char c );
+
+ /* Set the string from another StrTmpl. */
+ StrTmpl &operator=( const StrTmpl &s );
+
+ /* Append a c string to the end of this string. */
+ StrTmpl &operator+=( const char *s );
+
+ /* Append a c string to the end of this string of specifi len. */
+ void append( const char *s, long len );
+
+ /* Append a single char to the end of this string. */
+ StrTmpl &operator+=( const char c );
+
+ /* Append an StrTmpl to the end of this string. */
+ StrTmpl &operator+=( const StrTmpl &s );
+
+ /* Cast to a char star. */
+ operator char*() const { return data; }
+
+ /* Get a pointer to the data. */
+ char *get() const { return data; }
+
+ /* Return the length of the string. Must check for null data pointer. */
+ long length() const { return data ? (((Head*)data)-1)->length : 0; }
+
+ /**
+ * \brief Pointer to the data.
+ */
+ char *data;
+
+protected:
+ /* Make space for a string of length len to be appended. */
+ char *appendSpace( long len );
+ void initSpace( long length );
+ void setSpace( long length );
+
+ template <class FT> friend StrTmpl<FT> operator+(
+ const StrTmpl<FT> &s1, const char *s2 );
+ template <class FT> friend StrTmpl<FT> operator+(
+ const char *s1, const StrTmpl<FT> &s2 );
+ template <class FT> friend StrTmpl<FT> operator+(
+ const StrTmpl<FT> &s1, const StrTmpl<FT> &s2 );
+
+private:
+ /* A dummy struct solely to make a constructor that will never be
+ * ambiguous with the public constructors. */
+ struct DisAmbig { };
+ StrTmpl( char *data, const DisAmbig & ) : data(data) { }
+};
+
+/* Free all mem used by the string. */
+template<class T> StrTmpl<T>::~StrTmpl()
+{
+ if ( data != 0 ) {
+ /* If we are the only ones referencing the string, then delete it. */
+ Head *head = ((Head*) data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free( head );
+ }
+}
+
+/* Create from a c-style string. */
+template<class T> StrTmpl<T>::StrTmpl( const char *s )
+{
+ if ( s == 0 )
+ data = 0;
+ else {
+ /* Find the length and allocate the space for the shared string. */
+ long length = strlen( s );
+
+ /* Init space for the data. */
+ initSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length+1 );
+ }
+}
+
+/* Create from a c-style string. */
+template<class T> StrTmpl<T>::StrTmpl( const char *s, long length )
+{
+ if ( s == 0 )
+ data = 0;
+ else {
+ /* Init space for the data. */
+ initSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length );
+ data[length] = 0;
+ }
+}
+
+/* Create from a c-style string. */
+template<class T> StrTmpl<T>::StrTmpl( const Fresh &, long length )
+{
+ /* Init space for the data. */
+ initSpace( length );
+ data[length] = 0;
+}
+
+/* Create from another string class. */
+template<class T> StrTmpl<T>::StrTmpl( const StrTmpl &s )
+{
+ if ( s.data == 0 )
+ data = 0;
+ else {
+ /* Take a reference to the string. */
+ Head *strHead = ((Head*)s.data) - 1;
+ strHead->refCount += 1;
+ data = (char*) (strHead+1);
+ }
+}
+
+/* Construct a string from with, sprintf. */
+template<class T> StrTmpl<T>::StrTmpl( long lenGuess, const char *format, ... )
+{
+ /* Set the string for len. */
+ initSpace( lenGuess );
+
+ va_list args;
+
+ /* Write to the temporary buffer. */
+ va_start( args, format );
+
+ long written = vsnprintf( data, lenGuess+1, format, args );
+ if ( written > lenGuess ) {
+ setSpace( written );
+ written = vsnprintf( data, written+1, format, args );
+ }
+ chop( written );
+
+ va_end( args );
+}
+
+/* Construct a string from with, sprintf. */
+template<class T> void StrTmpl<T>::setAs( long lenGuess, const char *format, ... )
+{
+ /* Set the string for len. */
+ setSpace( lenGuess );
+
+ va_list args;
+
+ /* Write to the temporary buffer. */
+ va_start( args, format );
+
+ long written = vsnprintf( data, lenGuess+1, format, args );
+ if ( written > lenGuess ) {
+ setSpace( written );
+ written = vsnprintf( data, written+1, format, args );
+ }
+ chop( written );
+
+ va_end( args );
+}
+
+template<class T> void StrTmpl<T>::initSpace( long length )
+{
+ /* Find the length and allocate the space for the shared string. */
+ Head *head = (Head*) malloc( sizeof(Head) + length+1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Init the header. */
+ head->refCount = 1;
+ head->length = length;
+
+ /* Save the pointer to the data. */
+ data = (char*) (head+1);
+}
+
+
+/* Set this string to be the c string exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator=( const char *s )
+{
+ if ( s == 0 ) {
+ /* Just free the data, we are being set to null. */
+ if ( data != 0 ) {
+ Head *head = ((Head*)data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free(head);
+ data = 0;
+ }
+ }
+ else {
+ /* Find the length of the string we are setting. */
+ long length = strlen( s );
+
+ /* Set the string for len. */
+ setSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length+1 );
+ }
+ return *this;
+}
+
+/* Set this string to be the c string exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> void StrTmpl<T>::setAs( const char *s, long length )
+{
+ if ( s == 0 ) {
+ /* Just free the data, we are being set to null. */
+ if ( data != 0 ) {
+ Head *head = ((Head*)data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free(head);
+ data = 0;
+ }
+ }
+ else {
+ /* Set the string for len. */
+ setSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length );
+ data[length] = 0;
+ }
+}
+
+template<class T> void StrTmpl<T>::chop( long length )
+{
+ /* Detach from the existing string. */
+ Head *head = ((Head*)data) - 1;
+ assert( head->refCount == 1 );
+ assert( length <= head->length );
+ head->length = length;
+ data[length] = 0;
+}
+
+/* Set this string to be the c string exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> void StrTmpl<T>::setAs( const Fresh &, long length )
+{
+ setSpace( length );
+ data[length] = 0;
+}
+
+/* Set this string to be the single char exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator=( const char c )
+{
+ /* Set to length 1. */
+ setSpace( 1 );
+
+ /* Copy in the data. */
+ data[0] = c;
+ data[1] = 0;
+
+ /* Return ourselves. */
+ return *this;
+}
+
+/* Set this string to be the StrTmpl s exactly. The old string is
+ * discarded. */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator=( const StrTmpl &s )
+{
+ /* Detach from the existing string. */
+ if ( data != 0 ) {
+ Head *head = ((Head*)data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free( head );
+ }
+
+ if ( s.data != 0 ) {
+ /* Take a reference to the string. */
+ Head *strHead = ((Head*)s.data) - 1;
+ strHead->refCount += 1;
+ data = (char*)(strHead+1);
+ }
+ else {
+ /* Setting from a null string, just null our pointer. */
+ data = 0;
+ }
+ return *this;
+}
+
+/* Prepare the string to be set to something else of the given length. */
+template<class T> void StrTmpl<T>::setSpace( long length )
+{
+ /* Detach from the existing string. */
+ Head *head = ((Head*)data) - 1;
+ if ( data != 0 && --head->refCount == 0 ) {
+ /* Resuse the space. */
+ head = (Head*) realloc( head, sizeof(Head) + length+1 );
+ }
+ else {
+ /* Need to make new space, there is no usable old space. */
+ head = (Head*) malloc( sizeof(Head) + length+1 );
+ }
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Init the header. */
+ head->refCount = 1;
+ head->length = length;
+
+ /* Copy in the data and save the pointer to it. */
+ data = (char*) (head+1);
+}
+
+
+/* Append a c-style string to the end of this string. Returns a reference to
+ * this */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator+=( const char *s )
+{
+ /* Find the length of the string appended. */
+ if ( s != 0 ) {
+ /* Get the string length and make space on the end. */
+ long addedLen = strlen( s );
+ char *dest = appendSpace( addedLen );
+
+ /* Copy the data in. Plus one for the null. */
+ memcpy( dest, s, addedLen+1 );
+ }
+ return *this;
+}
+
+/* Append a c-style string of specific length to the end of this string.
+ * Returns a reference to this */
+template<class T> void StrTmpl<T>::append( const char *s, long length )
+{
+ /* Find the length of the string appended. */
+ if ( s != 0 ) {
+ /* Make space on the end. */
+ char *dest = appendSpace( length );
+
+ /* Copy the data in. Plus one for the null. */
+ memcpy( dest, s, length );
+ dest[length] = 0;
+ }
+}
+
+/* Append a single char to the end of this string. Returns a reference to
+ * this */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator+=( const char c )
+{
+ /* Grow on the end. */
+ char *dst = appendSpace( 1 );
+
+ /* Append a single charachter. */
+ dst[0] = c;
+ dst[1] = 0;
+ return *this;
+}
+
+
+/* Append an StrTmpl string to the end of this string. Returns a reference
+ * to this */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator+=( const StrTmpl &s )
+{
+ /* Find the length of the string appended. */
+ if ( s.data != 0 ) {
+ /* Find the length to append. */
+ long addedLen = (((Head*)s.data) - 1)->length;
+
+ /* Make space on the end to put the string. */
+ char *dest = appendSpace( addedLen );
+
+ /* Append the data, add one for the null. */
+ memcpy( dest, s.data, addedLen+1 );
+ }
+ return *this;
+}
+
+/* Make space for a string of length len to be appended. */
+template<class T> char *StrTmpl<T>::appendSpace( long len )
+{
+ /* Find the length of this and the string appended. */
+ Head *head = (((Head*)data) - 1);
+ long thisLen = head->length;
+
+ if ( head->refCount == 1 ) {
+ /* No other string is using the space, grow this space. */
+ head = (Head*) realloc( head,
+ sizeof(Head) + thisLen + len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+ data = (char*) (head+1);
+
+ /* Adjust the length. */
+ head->length += len;
+ }
+ else {
+ /* Another string is using this space, make new space. */
+ head->refCount -= 1;
+ Head *newHead = (Head*) malloc(
+ sizeof(Head) + thisLen + len + 1 );
+ if ( newHead == 0 )
+ throw std::bad_alloc();
+ data = (char*) (newHead+1);
+
+ /* Set the new header and data from this. */
+ newHead->refCount = 1;
+ newHead->length = thisLen + len;
+ memcpy( data, head+1, thisLen );
+ }
+
+ /* Return writing position. */
+ return data + thisLen;
+}
+
+/* Concatenate a String and a c-style string. */
+template<class T> StrTmpl<T> operator+( const StrTmpl<T> &s1, const char *s2 )
+{
+ /* Find s2 length and alloc the space for the result. */
+ long str1Len = (((typename StrTmpl<T>::Head*)(s1.data)) - 1)->length;
+ long str2Len = strlen( s2 );
+
+ typename StrTmpl<T>::Head *head = (typename StrTmpl<T>::Head*)
+ malloc( sizeof(typename StrTmpl<T>::Head) + str1Len + str2Len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header. */
+ head->refCount = 1;
+ head->length = str1Len + str2Len;
+
+ /* Save the pointer to data and copy the data in. */
+ char *data = (char*) (head+1);
+ memcpy( data, s1.data, str1Len );
+ memcpy( data + str1Len, s2, str2Len + 1 );
+ return StrTmpl<T>( data, typename StrTmpl<T>::DisAmbig() );
+}
+
+/* Concatenate a c-style string and a String. */
+template<class T> StrTmpl<T> operator+( const char *s1, const StrTmpl<T> &s2 )
+{
+ /* Find s2 length and alloc the space for the result. */
+ long str1Len = strlen( s1 );
+ long str2Len = (((typename StrTmpl<T>::Head*)(s2.data)) - 1)->length;
+
+ typename StrTmpl<T>::Head *head = (typename StrTmpl<T>::Head*)
+ malloc( sizeof(typename StrTmpl<T>::Head) + str1Len + str2Len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header. */
+ head->refCount = 1;
+ head->length = str1Len + str2Len;
+
+ /* Save the pointer to data and copy the data in. */
+ char *data = (char*) (head+1);
+ memcpy( data, s1, str1Len );
+ memcpy( data + str1Len, s2.data, str2Len + 1 );
+ return StrTmpl<T>( data, typename StrTmpl<T>::DisAmbig() );
+}
+
+/* Add two StrTmpl strings. */
+template<class T> StrTmpl<T> operator+( const StrTmpl<T> &s1, const StrTmpl<T> &s2 )
+{
+ /* Find s2 length and alloc the space for the result. */
+ long str1Len = (((typename StrTmpl<T>::Head*)(s1.data)) - 1)->length;
+ long str2Len = (((typename StrTmpl<T>::Head*)(s2.data)) - 1)->length;
+ typename StrTmpl<T>::Head *head = (typename StrTmpl<T>::Head*)
+ malloc( sizeof(typename StrTmpl<T>::Head) + str1Len + str2Len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header. */
+ head->refCount = 1;
+ head->length = str1Len + str2Len;
+
+ /* Save the pointer to data and copy the data in. */
+ char *data = (char*) (head+1);
+ memcpy( data, s1.data, str1Len );
+ memcpy( data + str1Len, s2.data, str2Len + 1 );
+ return StrTmpl<T>( data, typename StrTmpl<T>::DisAmbig() );
+}
+
+/* Operator used in case the compiler does not support the conversion. */
+template <class T> inline std::ostream &operator<<( std::ostream &o, const StrTmpl<T> &s )
+{
+ return o.write( s.data, s.length() );
+}
+
+typedef StrTmpl<char> String;
+
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_ASTRING_H */
diff --git a/aapl/avlbasic.h b/aapl/avlbasic.h
new file mode 100644
index 00000000..ed826f38
--- /dev/null
+++ b/aapl/avlbasic.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLBASIC_H
+#define _AAPL_AVLBASIC_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlBasic
+ * \brief AVL Tree in which the entire element structure is the key.
+ *
+ * AvlBasic is an AVL tree that does not distinguish between the element that
+ * it contains and the key. The entire element structure is the key that is
+ * used to compare the relative ordering of elements. This is similar to the
+ * BstSet structure.
+ *
+ * AvlBasic does not assume ownership of elements in the tree. Items must be
+ * explicitly de-allocated.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Compare
+#define AVLMEL_TEMPDEF class Element, class Compare
+#define AVLMEL_TEMPUSE Element, Compare
+#define AvlTree AvlBasic
+#define AVL_BASIC
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef AVL_BASIC
+
+#endif /* _AAPL_AVLBASIC_H */
diff --git a/aapl/avlcommon.h b/aapl/avlcommon.h
new file mode 100644
index 00000000..6cb0b89a
--- /dev/null
+++ b/aapl/avlcommon.h
@@ -0,0 +1,1630 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This header is not wrapped in ifndef becuase it is not intended to
+ * be included by the user. */
+
+#include <assert.h>
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+#ifdef WALKABLE
+/* This is used by AvlTree, AvlMel and AvlMelKey so it
+ * must be protected by global ifdefs. */
+#ifndef __AAPL_AVLI_EL__
+#define __AAPL_AVLI_EL__
+
+/**
+ * \brief Tree element properties for linked AVL trees.
+ *
+ * AvliTreeEl needs to be inherited by classes that intend to be element in an
+ * AvliTree.
+ */
+template<class SubClassEl> struct AvliTreeEl
+{
+ /**
+ * \brief Tree pointers connecting element in a tree.
+ */
+ SubClassEl *left, *right, *parent;
+
+ /**
+ * \brief Linked list pointers.
+ */
+ SubClassEl *prev, *next;
+
+ /**
+ * \brief Height of the tree rooted at this element.
+ *
+ * Height is required by the AVL balancing algorithm.
+ */
+ long height;
+};
+#endif /* __AAPL_AVLI_EL__ */
+
+#else /* not WALKABLE */
+
+/* This is used by All the non walkable trees so it must be
+ * protected by a global ifdef. */
+#ifndef __AAPL_AVL_EL__
+#define __AAPL_AVL_EL__
+/**
+ * \brief Tree element properties for linked AVL trees.
+ *
+ * AvlTreeEl needs to be inherited by classes that intend to be element in an
+ * AvlTree.
+ */
+template<class SubClassEl> struct AvlTreeEl
+{
+ /**
+ * \brief Tree pointers connecting element in a tree.
+ */
+ SubClassEl *left, *right, *parent;
+
+ /**
+ * \brief Height of the tree rooted at this element.
+ *
+ * Height is required by the AVL balancing algorithm.
+ */
+ long height;
+};
+#endif /* __AAPL_AVL_EL__ */
+#endif /* def WALKABLE */
+
+
+#if defined( AVLTREE_MAP )
+
+#ifdef WALKABLE
+
+/**
+ * \brief Tree element for AvliMap
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct AvliMapEl :
+ public AvliTreeEl< AvliMapEl<Key, Value> >
+{
+ AvliMapEl(const Key &key)
+ : key(key) { }
+ AvliMapEl(const Key &key, const Value &value)
+ : key(key), value(value) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+#else /* not WALKABLE */
+
+/**
+ * \brief Tree element for AvlMap
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct AvlMapEl :
+ public AvlTreeEl< AvlMapEl<Key, Value> >
+{
+ AvlMapEl(const Key &key)
+ : key(key) { }
+ AvlMapEl(const Key &key, const Value &value)
+ : key(key), value(value) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+#endif /* def WALKABLE */
+
+#elif defined( AVLTREE_SET )
+
+#ifdef WALKABLE
+/**
+ * \brief Tree element for AvliSet
+ *
+ * Stores the key.
+ */
+template <class Key> struct AvliSetEl :
+ public AvliTreeEl< AvliSetEl<Key> >
+{
+ AvliSetEl(const Key &key) : key(key) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+};
+#else /* not WALKABLE */
+/**
+ * \brief Tree element for AvlSet
+ *
+ * Stores the key.
+ */
+template <class Key> struct AvlSetEl :
+ public AvlTreeEl< AvlSetEl<Key> >
+{
+ AvlSetEl(const Key &key) : key(key) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+};
+#endif /* def WALKABLE */
+
+#endif /* AVLTREE_SET */
+
+/* Common AvlTree Class */
+template < AVLMEL_CLASSDEF > class AvlTree
+#if !defined( AVL_KEYLESS ) && defined ( WALKABLE )
+ : public Compare, public BASELIST
+#elif !defined( AVL_KEYLESS )
+ : public Compare
+#elif defined( WALKABLE )
+ : public BASELIST
+#endif
+{
+public:
+ /**
+ * \brief Create an empty tree.
+ */
+#ifdef WALKABLE
+ AvlTree() : root(0), treeSize(0) { }
+#else
+ AvlTree() : root(0), head(0), tail(0), treeSize(0) { }
+#endif
+
+ /**
+ * \brief Perform a deep copy of the tree.
+ *
+ * Each element is duplicated for the new tree. Copy constructors are used
+ * to create the new elements.
+ */
+ AvlTree(const AvlTree &other);
+
+#if defined( AVLTREE_MAP ) || defined( AVLTREE_SET )
+ /**
+ * \brief Clear the contents of the tree.
+ *
+ * All element are deleted.
+ */
+ ~AvlTree() { empty(); }
+
+ /**
+ * \brief Perform a deep copy of the tree.
+ *
+ * Each element is duplicated for the new tree. Copy constructors are used
+ * to create the new element. If this tree contains items, they are first
+ * deleted.
+ *
+ * \returns A reference to this.
+ */
+ AvlTree &operator=( const AvlTree &tree );
+
+ /**
+ * \brief Transfer the elements of another tree into this.
+ *
+ * First deletes all elements in this tree.
+ */
+ void transfer( AvlTree &tree );
+#else
+ /**
+ * \brief Abandon all elements in the tree.
+ *
+ * Tree elements are not deleted.
+ */
+ ~AvlTree() {}
+
+ /**
+ * \brief Perform a deep copy of the tree.
+ *
+ * Each element is duplicated for the new tree. Copy constructors are used
+ * to create the new element. If this tree contains items, they are
+ * abandoned.
+ *
+ * \returns A reference to this.
+ */
+ AvlTree &operator=( const AvlTree &tree );
+
+ /**
+ * \brief Transfer the elements of another tree into this.
+ *
+ * All elements in this tree are abandoned first.
+ */
+ void transfer( AvlTree &tree );
+#endif
+
+#ifndef AVL_KEYLESS
+ /* Insert a element into the tree. */
+ Element *insert( Element *element, Element **lastFound = 0 );
+
+#ifdef AVL_BASIC
+ /* Find a element in the tree. Returns the element if
+ * element exists, false otherwise. */
+ Element *find( const Element *element ) const;
+
+#else
+ Element *insert( const Key &key, Element **lastFound = 0 );
+
+#ifdef AVLTREE_MAP
+ Element *insert( const Key &key, const Value &val,
+ Element **lastFound = 0 );
+#endif
+
+ /* Find a element in the tree. Returns the element if
+ * key exists, false otherwise. */
+ Element *find( const Key &key ) const;
+
+ /* Detach a element from the tree. */
+ Element *detach( const Key &key );
+
+ /* Detach and delete a element from the tree. */
+ bool remove( const Key &key );
+#endif /* AVL_BASIC */
+#endif /* AVL_KEYLESS */
+
+ /* Detach a element from the tree. */
+ Element *detach( Element *element );
+
+ /* Detach and delete a element from the tree. */
+ void remove( Element *element );
+
+ /* Free all memory used by tree. */
+ void empty();
+
+ /* Abandon all element in the tree. Does not delete element. */
+ void abandon();
+
+ /** Root element of the tree. */
+ Element *root;
+
+#ifndef WALKABLE
+ Element *head, *tail;
+#endif
+
+ /** The number of element in the tree. */
+ long treeSize;
+
+ /** \brief Return the number of elements in the tree. */
+ long length() const { return treeSize; }
+
+ /** \brief Return the number of elements in the tree. */
+ long size() const { return treeSize; }
+
+ /* Various classes for setting the iterator */
+ struct Iter;
+ struct IterFirst { IterFirst( const AvlTree &t ) : t(t) { } const AvlTree &t; };
+ struct IterLast { IterLast( const AvlTree &t ) : t(t) { } const AvlTree &t; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+#ifdef WALKABLE
+ /**
+ * \brief Avl Tree Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Default construct. */
+ Iter() : ptr(0) { }
+
+ /* Construct from an avl tree and iterator-setting classes. */
+ Iter( const AvlTree &t ) : ptr(t.head) { }
+ Iter( const IterFirst &af ) : ptr(af.t.head) { }
+ Iter( const IterLast &al ) : ptr(al.t.tail) { }
+ Iter( const IterNext &an ) : ptr(findNext(an.i.ptr)) { }
+ Iter( const IterPrev &ap ) : ptr(findPrev(ap.i.ptr)) { }
+
+ /* Assign from a tree and iterator-setting classes. */
+ Iter &operator=( const AvlTree &tree ) { ptr = tree.head; return *this; }
+ Iter &operator=( const IterFirst &af ) { ptr = af.t.head; return *this; }
+ Iter &operator=( const IterLast &al ) { ptr = al.t.tail; return *this; }
+ Iter &operator=( const IterNext &an ) { ptr = findNext(an.i.ptr); return *this; }
+ Iter &operator=( const IterPrev &ap ) { ptr = findPrev(ap.i.ptr); return *this; }
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != 0; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == 0; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != 0; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == 0; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr && ptr->BASE_EL(prev) == 0; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr && ptr->BASE_EL(next) == 0; }
+
+ /** \brief Implicit cast to Element*. */
+ operator Element*() const { return ptr; }
+
+ /** \brief Dereference operator returns Element&. */
+ Element &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns Element*. */
+ Element *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ inline Element *operator++();
+
+ /** \brief Move to next item. */
+ inline Element *operator++(int);
+
+ /** \brief Move to next item. */
+ inline Element *increment();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--(int);
+
+ /** \brief Move to previous item. */
+ inline Element *decrement();
+
+ /** \brief Return the next item. Does not modify this. */
+ IterNext next() const { return IterNext( *this ); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ IterPrev prev() const { return IterPrev( *this ); }
+
+ private:
+ static Element *findPrev( Element *element ) { return element->BASE_EL(prev); }
+ static Element *findNext( Element *element ) { return element->BASE_EL(next); }
+
+ public:
+
+ /** \brief The iterator is simply a pointer. */
+ Element *ptr;
+ };
+
+#else
+
+ /**
+ * \brief Avl Tree Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Default construct. */
+ Iter() : ptr(0), tree(0) { }
+
+ /* Construct from a tree and iterator-setting classes. */
+ Iter( const AvlTree &t ) : ptr(t.head), tree(&t) { }
+ Iter( const IterFirst &af ) : ptr(af.t.head), tree(&af.t) { }
+ Iter( const IterLast &al ) : ptr(al.t.tail), tree(&al.t) { }
+ Iter( const IterNext &an ) : ptr(findNext(an.i.ptr)), tree(an.i.tree) { }
+ Iter( const IterPrev &ap ) : ptr(findPrev(ap.i.ptr)), tree(ap.i.tree) { }
+
+ /* Assign from a tree and iterator-setting classes. */
+ Iter &operator=( const AvlTree &t )
+ { ptr = t.head; tree = &t; return *this; }
+ Iter &operator=( const IterFirst &af )
+ { ptr = af.t.head; tree = &af.t; return *this; }
+ Iter &operator=( const IterLast &al )
+ { ptr = al.t.tail; tree = &al.t; return *this; }
+ Iter &operator=( const IterNext &an )
+ { ptr = findNext(an.i.ptr); tree = an.i.tree; return *this; }
+ Iter &operator=( const IterPrev &ap )
+ { ptr = findPrev(ap.i.ptr); tree = ap.i.tree; return *this; }
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != 0; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == 0; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != 0; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == 0; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr && ptr == tree->head; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr && ptr == tree->tail; }
+
+ /** \brief Implicit cast to Element*. */
+ operator Element*() const { return ptr; }
+
+ /** \brief Dereference operator returns Element&. */
+ Element &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns Element*. */
+ Element *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ inline Element *operator++();
+
+ /** \brief Move to next item. */
+ inline Element *operator++(int);
+
+ /** \brief Move to next item. */
+ inline Element *increment();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--(int);
+
+ /** \brief Move to previous item. */
+ inline Element *decrement();
+
+ /** \brief Return the next item. Does not modify this. */
+ IterNext next() const { return IterNext( *this ); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ IterPrev prev() const { return IterPrev( *this ); }
+
+ private:
+ static Element *findPrev( Element *element );
+ static Element *findNext( Element *element );
+
+ public:
+ /** \brief The iterator is simply a pointer. */
+ Element *ptr;
+
+ /* The list is not walkable so we need to keep a pointerto the tree
+ * so we can test against head and tail in O(1) time. */
+ const AvlTree *tree;
+ };
+#endif
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst( *this ); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast( *this ); }
+
+protected:
+ /* Recursive worker for the copy constructor. */
+ Element *copyBranch( Element *element );
+
+ /* Recursively delete element in the tree. */
+ void deleteChildrenOf(Element *n);
+
+ /* rebalance the tree beginning at the leaf whose
+ * grandparent is unbalanced. */
+ Element *rebalance(Element *start);
+
+ /* Move up the tree from a given element, recalculating the heights. */
+ void recalcHeights(Element *start);
+
+ /* Move up the tree and find the first element whose
+ * grand-parent is unbalanced. */
+ Element *findFirstUnbalGP(Element *start);
+
+ /* Move up the tree and find the first element which is unbalanced. */
+ Element *findFirstUnbalEl(Element *start);
+
+ /* Replace a element in the tree with another element not in the tree. */
+ void replaceEl(Element *element, Element *replacement);
+
+ /* Remove a element from the tree and put another (normally a child of element)
+ * in its place. */
+ void removeEl(Element *element, Element *filler);
+
+ /* Once an insertion point is found at a leaf then do the insert. */
+ void attachRebal( Element *element, Element *parentEl, Element *lastLess );
+};
+
+/* Copy constructor. New up each item. */
+template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE>::
+ AvlTree(const AvlTree<AVLMEL_TEMPUSE> &other)
+#if !defined( AVL_KEYLESS ) && defined ( WALKABLE )
+ /* BASELIST should be made empty. The copyBranch function
+ * will fill in the details for us. */
+ : Compare( other ), BASELIST()
+#elif !defined( AVL_KEYLESS )
+ : Compare( other )
+#elif defined( WALKABLE )
+ : BASELIST( )
+#endif
+{
+ treeSize = other.treeSize;
+ root = other.root;
+
+#ifndef WALKABLE
+ head = 0;
+ tail = 0;
+#endif
+
+ /* If there is a root, copy the tree. */
+ if ( other.root != 0 )
+ root = copyBranch( other.root );
+}
+
+#if defined( AVLTREE_MAP ) || defined( AVLTREE_SET )
+
+/* Assignment does deep copy. */
+template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE> &AvlTree<AVLMEL_TEMPUSE>::
+ operator=( const AvlTree &other )
+{
+ /* Clear the tree first. */
+ empty();
+
+ /* Reset the list pointers, the tree copy will fill in the list for us. */
+#ifdef WALKABLE
+ BASELIST::abandon();
+#else
+ head = 0;
+ tail = 0;
+#endif
+
+ /* Copy the entire tree. */
+ treeSize = other.treeSize;
+ root = other.root;
+ if ( other.root != 0 )
+ root = copyBranch( other.root );
+ return *this;
+}
+
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ transfer(AvlTree<AVLMEL_TEMPUSE> &other)
+{
+ /* Clear the tree first. */
+ empty();
+
+ treeSize = other.treeSize;
+ root = other.root;
+
+#ifdef WALKABLE
+ BASELIST::head = other.BASELIST::head;
+ BASELIST::tail = other.BASELIST::tail;
+ BASELIST::listLen = other.BASELIST::listLen;
+#else
+ head = other.head;
+ tail = other.tail;
+#endif
+
+ other.abandon();
+}
+
+#else /* ! AVLTREE_MAP && ! AVLTREE_SET */
+
+/* Assignment does deep copy. This version does not clear the tree first. */
+template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE> &AvlTree<AVLMEL_TEMPUSE>::
+ operator=( const AvlTree &other )
+{
+ /* Reset the list pointers, the tree copy will fill in the list for us. */
+#ifdef WALKABLE
+ BASELIST::abandon();
+#else
+ head = 0;
+ tail = 0;
+#endif
+
+ /* Copy the entire tree. */
+ treeSize = other.treeSize;
+ root = other.root;
+ if ( other.root != 0 )
+ root = copyBranch( other.root );
+ return *this;
+}
+
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ transfer(AvlTree<AVLMEL_TEMPUSE> &other)
+{
+ treeSize = other.treeSize;
+ root = other.root;
+
+#ifdef WALKABLE
+ BASELIST::head = other.BASELIST::head;
+ BASELIST::tail = other.BASELIST::tail;
+ BASELIST::listLen = other.BASELIST::listLen;
+#else
+ head = other.head;
+ tail = other.tail;
+#endif
+
+ other.abandon();
+}
+
+#endif
+
+/*
+ * Iterator operators.
+ */
+
+/* Prefix ++ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator++()
+{
+ return ptr = findNext( ptr );
+}
+
+/* Postfix ++ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator++(int)
+{
+ Element *rtn = ptr;
+ ptr = findNext( ptr );
+ return rtn;
+}
+
+/* increment */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ increment()
+{
+ return ptr = findNext( ptr );
+}
+
+/* Prefix -- */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator--()
+{
+ return ptr = findPrev( ptr );
+}
+
+/* Postfix -- */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator--(int)
+{
+ Element *rtn = ptr;
+ ptr = findPrev( ptr );
+ return rtn;
+}
+
+/* decrement */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ decrement()
+{
+ return ptr = findPrev( ptr );
+}
+
+#ifndef WALKABLE
+
+/* Move ahead one. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ findNext( Element *element )
+{
+ /* Try to go right once then infinite left. */
+ if ( element->BASE_EL(right) != 0 ) {
+ element = element->BASE_EL(right);
+ while ( element->BASE_EL(left) != 0 )
+ element = element->BASE_EL(left);
+ }
+ else {
+ /* Go up to parent until we were just a left child. */
+ while ( true ) {
+ Element *last = element;
+ element = element->BASE_EL(parent);
+ if ( element == 0 || element->BASE_EL(left) == last )
+ break;
+ }
+ }
+ return element;
+}
+
+/* Move back one. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ findPrev( Element *element )
+{
+ /* Try to go left once then infinite right. */
+ if ( element->BASE_EL(left) != 0 ) {
+ element = element->BASE_EL(left);
+ while ( element->BASE_EL(right) != 0 )
+ element = element->BASE_EL(right);
+ }
+ else {
+ /* Go up to parent until we were just a left child. */
+ while ( true ) {
+ Element *last = element;
+ element = element->BASE_EL(parent);
+ if ( element == 0 || element->BASE_EL(right) == last )
+ break;
+ }
+ }
+ return element;
+}
+
+#endif
+
+
+/* Recursive worker for tree copying. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ copyBranch( Element *element )
+{
+ /* Duplicate element. Either the base element's copy constructor or defaul
+ * constructor will get called. Both will suffice for initting the
+ * pointers to null when they need to be. */
+ Element *retVal = new Element(*element);
+
+ /* If the left tree is there, copy it. */
+ if ( retVal->BASE_EL(left) ) {
+ retVal->BASE_EL(left) = copyBranch(retVal->BASE_EL(left));
+ retVal->BASE_EL(left)->BASE_EL(parent) = retVal;
+ }
+
+#ifdef WALKABLE
+ BASELIST::addAfter( BASELIST::tail, retVal );
+#else
+ if ( head == 0 )
+ head = retVal;
+ tail = retVal;
+#endif
+
+ /* If the right tree is there, copy it. */
+ if ( retVal->BASE_EL(right) ) {
+ retVal->BASE_EL(right) = copyBranch(retVal->BASE_EL(right));
+ retVal->BASE_EL(right)->BASE_EL(parent) = retVal;
+ }
+ return retVal;
+}
+
+/* Once an insertion position is found, attach a element to the tree. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ attachRebal( Element *element, Element *parentEl, Element *lastLess )
+{
+ /* Increment the number of element in the tree. */
+ treeSize += 1;
+
+ /* Set element's parent. */
+ element->BASE_EL(parent) = parentEl;
+
+ /* New element always starts as a leaf with height 1. */
+ element->BASE_EL(left) = 0;
+ element->BASE_EL(right) = 0;
+ element->BASE_EL(height) = 1;
+
+ /* Are we inserting in the tree somewhere? */
+ if ( parentEl != 0 ) {
+ /* We have a parent so we are somewhere in the tree. If the parent
+ * equals lastLess, then the last traversal in the insertion went
+ * left, otherwise it went right. */
+ if ( lastLess == parentEl ) {
+ parentEl->BASE_EL(left) = element;
+#ifdef WALKABLE
+ BASELIST::addBefore( parentEl, element );
+#endif
+ }
+ else {
+ parentEl->BASE_EL(right) = element;
+#ifdef WALKABLE
+ BASELIST::addAfter( parentEl, element );
+#endif
+ }
+
+#ifndef WALKABLE
+ /* Maintain the first and last pointers. */
+ if ( head->BASE_EL(left) == element )
+ head = element;
+
+ /* Maintain the first and last pointers. */
+ if ( tail->BASE_EL(right) == element )
+ tail = element;
+#endif
+ }
+ else {
+ /* No parent element so we are inserting the root. */
+ root = element;
+#ifdef WALKABLE
+ BASELIST::addAfter( BASELIST::tail, element );
+#else
+ head = tail = element;
+#endif
+ }
+
+
+ /* Recalculate the heights. */
+ recalcHeights(parentEl);
+
+ /* Find the first unbalance. */
+ Element *ub = findFirstUnbalGP(element);
+
+ /* rebalance. */
+ if ( ub != 0 )
+ {
+ /* We assert that after this single rotation the
+ * tree is now properly balanced. */
+ rebalance(ub);
+ }
+}
+
+#ifndef AVL_KEYLESS
+
+/**
+ * \brief Insert an existing element into the tree.
+ *
+ * If the insert succeeds and lastFound is given then it is set to the element
+ * inserted. If the insert fails then lastFound is set to the existing element in
+ * the tree that has the same key as element. If the element's avl pointers are
+ * already in use then undefined behaviour results.
+ *
+ * \returns The element inserted upon success, null upon failure.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ insert( Element *element, Element **lastFound )
+{
+ long keyRelation;
+ Element *curEl = root, *parentEl = 0;
+ Element *lastLess = 0;
+
+ while (true) {
+ if ( curEl == 0 ) {
+ /* We are at an external element and did not find the key we were
+ * looking for. Attach underneath the leaf and rebalance. */
+ attachRebal( element, parentEl, lastLess );
+
+ if ( lastFound != 0 )
+ *lastFound = element;
+ return element;
+ }
+
+#ifdef AVL_BASIC
+ keyRelation = compare( *element, *curEl );
+#else
+ keyRelation = compare( element->BASEKEY(getKey()),
+ curEl->BASEKEY(getKey()) );
+#endif
+
+ /* Do we go left? */
+ if ( keyRelation < 0 ) {
+ parentEl = lastLess = curEl;
+ curEl = curEl->BASE_EL(left);
+ }
+ /* Do we go right? */
+ else if ( keyRelation > 0 ) {
+ parentEl = curEl;
+ curEl = curEl->BASE_EL(right);
+ }
+ /* We have hit the target. */
+ else {
+ if ( lastFound != 0 )
+ *lastFound = curEl;
+ return 0;
+ }
+ }
+}
+
+#ifdef AVL_BASIC
+
+/**
+ * \brief Find a element in the tree with the given key.
+ *
+ * \returns The element if key exists, null if the key does not exist.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ find( const Element *element ) const
+{
+ Element *curEl = root;
+ long keyRelation;
+
+ while (curEl) {
+ keyRelation = compare( *element, *curEl );
+
+ /* Do we go left? */
+ if ( keyRelation < 0 )
+ curEl = curEl->BASE_EL(left);
+ /* Do we go right? */
+ else if ( keyRelation > 0 )
+ curEl = curEl->BASE_EL(right);
+ /* We have hit the target. */
+ else {
+ return curEl;
+ }
+ }
+ return 0;
+}
+
+#else
+
+/**
+ * \brief Insert a new element into the tree with given key.
+ *
+ * If the key is not already in the tree then a new element is made using the
+ * Element(const Key &key) constructor and the insert succeeds. If lastFound is
+ * given then it is set to the element inserted. If the insert fails then
+ * lastFound is set to the existing element in the tree that has the same key as
+ * element.
+ *
+ * \returns The new element upon success, null upon failure.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ insert( const Key &key, Element **lastFound )
+{
+ long keyRelation;
+ Element *curEl = root, *parentEl = 0;
+ Element *lastLess = 0;
+
+ while (true) {
+ if ( curEl == 0 ) {
+ /* We are at an external element and did not find the key we were
+ * looking for. Create the new element, attach it underneath the leaf
+ * and rebalance. */
+ Element *element = new Element( key );
+ attachRebal( element, parentEl, lastLess );
+
+ if ( lastFound != 0 )
+ *lastFound = element;
+ return element;
+ }
+
+ keyRelation = compare( key, curEl->BASEKEY(getKey()) );
+
+ /* Do we go left? */
+ if ( keyRelation < 0 ) {
+ parentEl = lastLess = curEl;
+ curEl = curEl->BASE_EL(left);
+ }
+ /* Do we go right? */
+ else if ( keyRelation > 0 ) {
+ parentEl = curEl;
+ curEl = curEl->BASE_EL(right);
+ }
+ /* We have hit the target. */
+ else {
+ if ( lastFound != 0 )
+ *lastFound = curEl;
+ return 0;
+ }
+ }
+}
+
+#ifdef AVLTREE_MAP
+/**
+ * \brief Insert a new element into the tree with key and value.
+ *
+ * If the key is not already in the tree then a new element is constructed and
+ * the insert succeeds. If lastFound is given then it is set to the element
+ * inserted. If the insert fails then lastFound is set to the existing element in
+ * the tree that has the same key as element. This insert routine is only
+ * available in AvlMap because it is the only class that knows about a Value
+ * type.
+ *
+ * \returns The new element upon success, null upon failure.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ insert( const Key &key, const Value &val, Element **lastFound )
+{
+ long keyRelation;
+ Element *curEl = root, *parentEl = 0;
+ Element *lastLess = 0;
+
+ while (true) {
+ if ( curEl == 0 ) {
+ /* We are at an external element and did not find the key we were
+ * looking for. Create the new element, attach it underneath the leaf
+ * and rebalance. */
+ Element *element = new Element( key, val );
+ attachRebal( element, parentEl, lastLess );
+
+ if ( lastFound != 0 )
+ *lastFound = element;
+ return element;
+ }
+
+ keyRelation = compare(key, curEl->getKey());
+
+ /* Do we go left? */
+ if ( keyRelation < 0 ) {
+ parentEl = lastLess = curEl;
+ curEl = curEl->BASE_EL(left);
+ }
+ /* Do we go right? */
+ else if ( keyRelation > 0 ) {
+ parentEl = curEl;
+ curEl = curEl->BASE_EL(right);
+ }
+ /* We have hit the target. */
+ else {
+ if ( lastFound != 0 )
+ *lastFound = curEl;
+ return 0;
+ }
+ }
+}
+#endif /* AVLTREE_MAP */
+
+
+/**
+ * \brief Find a element in the tree with the given key.
+ *
+ * \returns The element if key exists, null if the key does not exist.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ find( const Key &key ) const
+{
+ Element *curEl = root;
+ long keyRelation;
+
+ while (curEl) {
+ keyRelation = compare( key, curEl->BASEKEY(getKey()) );
+
+ /* Do we go left? */
+ if ( keyRelation < 0 )
+ curEl = curEl->BASE_EL(left);
+ /* Do we go right? */
+ else if ( keyRelation > 0 )
+ curEl = curEl->BASE_EL(right);
+ /* We have hit the target. */
+ else {
+ return curEl;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * \brief Find a element, then detach it from the tree.
+ *
+ * The element is not deleted.
+ *
+ * \returns The element detached if the key is found, othewise returns null.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ detach(const Key &key)
+{
+ Element *element = find( key );
+ if ( element ) {
+ detach(element);
+ }
+
+ return element;
+}
+
+/**
+ * \brief Find, detach and delete a element from the tree.
+ *
+ * \returns True if the element was found and deleted, false otherwise.
+ */
+template <AVLMEL_TEMPDEF> bool AvlTree<AVLMEL_TEMPUSE>::
+ remove(const Key &key)
+{
+ /* Assume not found. */
+ bool retVal = false;
+
+ /* Look for the key. */
+ Element *element = find( key );
+ if ( element != 0 ) {
+ /* If found, detach the element and delete. */
+ detach( element );
+ delete element;
+ retVal = true;
+ }
+
+ return retVal;
+}
+
+#endif /* AVL_BASIC */
+#endif /* AVL_KEYLESS */
+
+
+/**
+ * \brief Detach and delete a element from the tree.
+ *
+ * If the element is not in the tree then undefined behaviour results.
+ */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ remove(Element *element)
+{
+ /* Detach and delete. */
+ detach(element);
+ delete element;
+}
+
+/**
+ * \brief Detach a element from the tree.
+ *
+ * If the element is not in the tree then undefined behaviour results.
+ *
+ * \returns The element given.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ detach(Element *element)
+{
+ Element *replacement, *fixfrom;
+ long lheight, rheight;
+
+#ifdef WALKABLE
+ /* Remove the element from the ordered list. */
+ BASELIST::detach( element );
+#endif
+
+ /* Update treeSize. */
+ treeSize--;
+
+ /* Find a replacement element. */
+ if (element->BASE_EL(right))
+ {
+ /* Find the leftmost element of the right subtree. */
+ replacement = element->BASE_EL(right);
+ while (replacement->BASE_EL(left))
+ replacement = replacement->BASE_EL(left);
+
+ /* If replacing the element the with its child then we need to start
+ * fixing at the replacement, otherwise we start fixing at the
+ * parent of the replacement. */
+ if (replacement->BASE_EL(parent) == element)
+ fixfrom = replacement;
+ else
+ fixfrom = replacement->BASE_EL(parent);
+
+#ifndef WALKABLE
+ if ( element == head )
+ head = replacement;
+#endif
+
+ removeEl(replacement, replacement->BASE_EL(right));
+ replaceEl(element, replacement);
+ }
+ else if (element->BASE_EL(left))
+ {
+ /* Find the rightmost element of the left subtree. */
+ replacement = element->BASE_EL(left);
+ while (replacement->BASE_EL(right))
+ replacement = replacement->BASE_EL(right);
+
+ /* If replacing the element the with its child then we need to start
+ * fixing at the replacement, otherwise we start fixing at the
+ * parent of the replacement. */
+ if (replacement->BASE_EL(parent) == element)
+ fixfrom = replacement;
+ else
+ fixfrom = replacement->BASE_EL(parent);
+
+#ifndef WALKABLE
+ if ( element == tail )
+ tail = replacement;
+#endif
+
+ removeEl(replacement, replacement->BASE_EL(left));
+ replaceEl(element, replacement);
+ }
+ else
+ {
+ /* We need to start fixing at the parent of the element. */
+ fixfrom = element->BASE_EL(parent);
+
+#ifndef WALKABLE
+ if ( element == head )
+ head = element->BASE_EL(parent);
+ if ( element == tail )
+ tail = element->BASE_EL(parent);
+#endif
+
+ /* The element we are deleting is a leaf element. */
+ removeEl(element, 0);
+ }
+
+ /* If fixfrom is null it means we just deleted
+ * the root of the tree. */
+ if ( fixfrom == 0 )
+ return element;
+
+ /* Fix the heights after the deletion. */
+ recalcHeights(fixfrom);
+
+ /* Fix every unbalanced element going up in the tree. */
+ Element *ub = findFirstUnbalEl(fixfrom);
+ while ( ub )
+ {
+ /* Find the element to rebalance by moving down from the first unbalanced
+ * element 2 levels in the direction of the greatest heights. On the
+ * second move down, the heights may be equal ( but not on the first ).
+ * In which case go in the direction of the first move. */
+ lheight = ub->BASE_EL(left) ? ub->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = ub->BASE_EL(right) ? ub->BASE_EL(right)->BASE_EL(height) : 0;
+ assert( lheight != rheight );
+ if (rheight > lheight)
+ {
+ ub = ub->BASE_EL(right);
+ lheight = ub->BASE_EL(left) ?
+ ub->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = ub->BASE_EL(right) ?
+ ub->BASE_EL(right)->BASE_EL(height) : 0;
+ if (rheight > lheight)
+ ub = ub->BASE_EL(right);
+ else if (rheight < lheight)
+ ub = ub->BASE_EL(left);
+ else
+ ub = ub->BASE_EL(right);
+ }
+ else
+ {
+ ub = ub->BASE_EL(left);
+ lheight = ub->BASE_EL(left) ?
+ ub->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = ub->BASE_EL(right) ?
+ ub->BASE_EL(right)->BASE_EL(height) : 0;
+ if (rheight > lheight)
+ ub = ub->BASE_EL(right);
+ else if (rheight < lheight)
+ ub = ub->BASE_EL(left);
+ else
+ ub = ub->BASE_EL(left);
+ }
+
+
+ /* rebalance returns the grandparant of the subtree formed
+ * by the element that were rebalanced.
+ * We must continue upward from there rebalancing. */
+ fixfrom = rebalance(ub);
+
+ /* Find the next unbalaced element. */
+ ub = findFirstUnbalEl(fixfrom);
+ }
+
+ return element;
+}
+
+
+/**
+ * \brief Empty the tree and delete all the element.
+ *
+ * Resets the tree to its initial state.
+ */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::empty()
+{
+ if ( root ) {
+ /* Recursively delete from the tree structure. */
+ deleteChildrenOf(root);
+ delete root;
+ root = 0;
+ treeSize = 0;
+
+#ifdef WALKABLE
+ BASELIST::abandon();
+#endif
+ }
+}
+
+/**
+ * \brief Forget all element in the tree.
+ *
+ * Does not delete element. Resets the the tree to it's initial state.
+ */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::abandon()
+{
+ root = 0;
+ treeSize = 0;
+
+#ifdef WALKABLE
+ BASELIST::abandon();
+#endif
+}
+
+/* Recursively delete all the children of a element. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ deleteChildrenOf( Element *element )
+{
+ /* Recurse left. */
+ if (element->BASE_EL(left)) {
+ deleteChildrenOf(element->BASE_EL(left));
+
+ /* Delete left element. */
+ delete element->BASE_EL(left);
+ element->BASE_EL(left) = 0;
+ }
+
+ /* Recurse right. */
+ if (element->BASE_EL(right)) {
+ deleteChildrenOf(element->BASE_EL(right));
+
+ /* Delete right element. */
+ delete element->BASE_EL(right);
+ element->BASE_EL(left) = 0;
+ }
+}
+
+/* rebalance from a element whose gradparent is unbalanced. Only
+ * call on a element that has a grandparent. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ rebalance(Element *n)
+{
+ long lheight, rheight;
+ Element *a, *b, *c;
+ Element *t1, *t2, *t3, *t4;
+
+ Element *p = n->BASE_EL(parent); /* parent (Non-NUL). L*/
+ Element *gp = p->BASE_EL(parent); /* Grand-parent (Non-NULL). */
+ Element *ggp = gp->BASE_EL(parent); /* Great grand-parent (may be NULL). */
+
+ if (gp->BASE_EL(right) == p)
+ {
+ /* gp
+ * \
+ * p
+ */
+ if (p->BASE_EL(right) == n)
+ {
+ /* gp
+ * \
+ * p
+ * \
+ * n
+ */
+ a = gp;
+ b = p;
+ c = n;
+ t1 = gp->BASE_EL(left);
+ t2 = p->BASE_EL(left);
+ t3 = n->BASE_EL(left);
+ t4 = n->BASE_EL(right);
+ }
+ else
+ {
+ /* gp
+ * \
+ * p
+ * /
+ * n
+ */
+ a = gp;
+ b = n;
+ c = p;
+ t1 = gp->BASE_EL(left);
+ t2 = n->BASE_EL(left);
+ t3 = n->BASE_EL(right);
+ t4 = p->BASE_EL(right);
+ }
+ }
+ else
+ {
+ /* gp
+ * /
+ * p
+ */
+ if (p->BASE_EL(right) == n)
+ {
+ /* gp
+ * /
+ * p
+ * \
+ * n
+ */
+ a = p;
+ b = n;
+ c = gp;
+ t1 = p->BASE_EL(left);
+ t2 = n->BASE_EL(left);
+ t3 = n->BASE_EL(right);
+ t4 = gp->BASE_EL(right);
+ }
+ else
+ {
+ /* gp
+ * /
+ * p
+ * /
+ * n
+ */
+ a = n;
+ b = p;
+ c = gp;
+ t1 = n->BASE_EL(left);
+ t2 = n->BASE_EL(right);
+ t3 = p->BASE_EL(right);
+ t4 = gp->BASE_EL(right);
+ }
+ }
+
+ /* Perform rotation.
+ */
+
+ /* Tie b to the great grandparent. */
+ if ( ggp == 0 )
+ root = b;
+ else if ( ggp->BASE_EL(left) == gp )
+ ggp->BASE_EL(left) = b;
+ else
+ ggp->BASE_EL(right) = b;
+ b->BASE_EL(parent) = ggp;
+
+ /* Tie a as a leftchild of b. */
+ b->BASE_EL(left) = a;
+ a->BASE_EL(parent) = b;
+
+ /* Tie c as a rightchild of b. */
+ b->BASE_EL(right) = c;
+ c->BASE_EL(parent) = b;
+
+ /* Tie t1 as a leftchild of a. */
+ a->BASE_EL(left) = t1;
+ if ( t1 != 0 ) t1->BASE_EL(parent) = a;
+
+ /* Tie t2 as a rightchild of a. */
+ a->BASE_EL(right) = t2;
+ if ( t2 != 0 ) t2->BASE_EL(parent) = a;
+
+ /* Tie t3 as a leftchild of c. */
+ c->BASE_EL(left) = t3;
+ if ( t3 != 0 ) t3->BASE_EL(parent) = c;
+
+ /* Tie t4 as a rightchild of c. */
+ c->BASE_EL(right) = t4;
+ if ( t4 != 0 ) t4->BASE_EL(parent) = c;
+
+ /* The heights are all recalculated manualy and the great
+ * grand-parent is passed to recalcHeights() to ensure
+ * the heights are correct up the tree.
+ *
+ * Note that recalcHeights() cuts out when it comes across
+ * a height that hasn't changed.
+ */
+
+ /* Fix height of a. */
+ lheight = a->BASE_EL(left) ? a->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = a->BASE_EL(right) ? a->BASE_EL(right)->BASE_EL(height) : 0;
+ a->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* Fix height of c. */
+ lheight = c->BASE_EL(left) ? c->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = c->BASE_EL(right) ? c->BASE_EL(right)->BASE_EL(height) : 0;
+ c->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* Fix height of b. */
+ lheight = a->BASE_EL(height);
+ rheight = c->BASE_EL(height);
+ b->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* Fix height of b's parents. */
+ recalcHeights(ggp);
+ return ggp;
+}
+
+/* Recalculates the heights of all the ancestors of element. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ recalcHeights(Element *element)
+{
+ long lheight, rheight, new_height;
+ while ( element != 0 )
+ {
+ lheight = element->BASE_EL(left) ? element->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = element->BASE_EL(right) ? element->BASE_EL(right)->BASE_EL(height) : 0;
+
+ new_height = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* If there is no chage in the height, then there will be no
+ * change in any of the ancestor's height. We can stop going up.
+ * If there was a change, continue upward. */
+ if (new_height == element->BASE_EL(height))
+ return;
+ else
+ element->BASE_EL(height) = new_height;
+
+ element = element->BASE_EL(parent);
+ }
+}
+
+/* Finds the first element whose grandparent is unbalanced. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ findFirstUnbalGP(Element *element)
+{
+ long lheight, rheight, balanceProp;
+ Element *gp;
+
+ if ( element == 0 || element->BASE_EL(parent) == 0 ||
+ element->BASE_EL(parent)->BASE_EL(parent) == 0 )
+ return 0;
+
+ /* Don't do anything if we we have no grandparent. */
+ gp = element->BASE_EL(parent)->BASE_EL(parent);
+ while ( gp != 0 )
+ {
+ lheight = gp->BASE_EL(left) ? gp->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = gp->BASE_EL(right) ? gp->BASE_EL(right)->BASE_EL(height) : 0;
+ balanceProp = lheight - rheight;
+
+ if ( balanceProp < -1 || balanceProp > 1 )
+ return element;
+
+ element = element->BASE_EL(parent);
+ gp = gp->BASE_EL(parent);
+ }
+ return 0;
+}
+
+
+/* Finds the first element that is unbalanced. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ findFirstUnbalEl(Element *element)
+{
+ if ( element == 0 )
+ return 0;
+
+ while ( element != 0 )
+ {
+ long lheight = element->BASE_EL(left) ?
+ element->BASE_EL(left)->BASE_EL(height) : 0;
+ long rheight = element->BASE_EL(right) ?
+ element->BASE_EL(right)->BASE_EL(height) : 0;
+ long balanceProp = lheight - rheight;
+
+ if ( balanceProp < -1 || balanceProp > 1 )
+ return element;
+
+ element = element->BASE_EL(parent);
+ }
+ return 0;
+}
+
+/* Replace a element in the tree with another element not in the tree. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ replaceEl(Element *element, Element *replacement)
+{
+ Element *parent = element->BASE_EL(parent),
+ *left = element->BASE_EL(left),
+ *right = element->BASE_EL(right);
+
+ replacement->BASE_EL(left) = left;
+ if (left)
+ left->BASE_EL(parent) = replacement;
+ replacement->BASE_EL(right) = right;
+ if (right)
+ right->BASE_EL(parent) = replacement;
+
+ replacement->BASE_EL(parent) = parent;
+ if (parent)
+ {
+ if (parent->BASE_EL(left) == element)
+ parent->BASE_EL(left) = replacement;
+ else
+ parent->BASE_EL(right) = replacement;
+ }
+ else
+ root = replacement;
+
+ replacement->BASE_EL(height) = element->BASE_EL(height);
+}
+
+/* Removes a element from a tree and puts filler in it's place.
+ * Filler should be null or a child of element. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ removeEl(Element *element, Element *filler)
+{
+ Element *parent = element->BASE_EL(parent);
+
+ if (parent)
+ {
+ if (parent->BASE_EL(left) == element)
+ parent->BASE_EL(left) = filler;
+ else
+ parent->BASE_EL(right) = filler;
+ }
+ else
+ root = filler;
+
+ if (filler)
+ filler->BASE_EL(parent) = parent;
+
+ return;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
diff --git a/aapl/avlibasic.h b/aapl/avlibasic.h
new file mode 100644
index 00000000..b916f742
--- /dev/null
+++ b/aapl/avlibasic.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLIBASIC_H
+#define _AAPL_AVLIBASIC_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliBasic
+ * \brief Linked AVL Tree in which the entire element structure is the key.
+ *
+ * AvliBasic is a linked AVL tree that does not distinguish between the
+ * element that it contains and the key. The entire element structure is the
+ * key that is used to compare the relative ordering of elements. This is
+ * similar to the BstSet structure.
+ *
+ * AvliBasic does not assume ownership of elements in the tree. Items must be
+ * explicitly de-allocated.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Compare
+#define AVLMEL_TEMPDEF class Element, class Compare
+#define AVLMEL_TEMPUSE Element, Compare
+#define AvlTree AvliBasic
+#define AVL_BASIC
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef AVL_BASIC
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIBASIC_H */
diff --git a/aapl/avlikeyless.h b/aapl/avlikeyless.h
new file mode 100644
index 00000000..0c606089
--- /dev/null
+++ b/aapl/avlikeyless.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002, 2003 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLIKEYLESS_H
+#define _AAPL_AVLIKEYLESS_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliKeyless
+ * \brief Linked AVL tree that has no insert/find/remove functions that take a
+ * key.
+ *
+ * AvliKeyless is an implementation of the AVL tree rebalancing functionality
+ * only. It provides the common code for the tiny AVL tree implementations.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASELIST DListMel< Element, AvliTreeEl<Element> >
+#define AVLMEL_CLASSDEF class Element
+#define AVLMEL_TEMPDEF class Element
+#define AVLMEL_TEMPUSE Element
+#define AvlTree AvliKeyless
+#define WALKABLE
+#define AVL_KEYLESS
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+#undef AVL_KEYLESS
+
+#endif /* _AAPL_AVLIKEYLESS_H */
diff --git a/aapl/avlimap.h b/aapl/avlimap.h
new file mode 100644
index 00000000..c207dc52
--- /dev/null
+++ b/aapl/avlimap.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLIMAP_H
+#define _AAPL_AVLIMAP_H
+
+#include "compare.h"
+#include "dlist.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliMap
+ * \brief Linked key and value oriented AVL tree.
+ *
+ * AvliMap stores key and value pairs in elements that managed by the tree. It
+ * is intendend to be similar to map template found in the STL. AvliMap
+ * requires that a Key type, a Value type, and a class containing a compare()
+ * routine for Key be given. Items can be inserted with just a key or with a
+ * key and value pair.
+ *
+ * AvliMap assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avlimap.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_MAP
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define BASELIST DList< AvliMapEl<Key,Value> >
+#define AVLMEL_CLASSDEF class Key, class Value, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Value, class Compare
+#define AVLMEL_TEMPUSE Key, Value, Compare
+#define AvlTree AvliMap
+#define Element AvliMapEl<Key,Value>
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef AVLTREE_MAP
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIMAP_H */
diff --git a/aapl/avlimel.h b/aapl/avlimel.h
new file mode 100644
index 00000000..bceddcd4
--- /dev/null
+++ b/aapl/avlimel.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLIMEL_H
+#define _AAPL_AVLIMEL_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliMel
+ * \brief Linked AVL tree for element appearing in multiple trees.
+ *
+ * AvliMel allows for an element to simultaneously be in multiple trees without
+ * the trees interferring with one another. For each tree that the element is
+ * to appear in, there must be a distinct set of AVL Tree management data that
+ * can be unambiguously referenced with some base class name. This name
+ * is passed to the tree as a template parameter and is used in the tree
+ * algorithms.
+ *
+ * The element must use the same key type and value in each tree that it
+ * appears in. If distinct keys are required, the AvliMelKey structure is
+ * available.
+ *
+ * AvliMel does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlimel.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) name
+#define BASELIST DListMel< Element, BaseEl >
+#define AVLMEL_CLASSDEF class Element, class Key, \
+ class BaseEl, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, \
+ class BaseEl, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, Compare
+#define AvlTree AvliMel
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIMEL_H */
diff --git a/aapl/avlimelkey.h b/aapl/avlimelkey.h
new file mode 100644
index 00000000..52d3a409
--- /dev/null
+++ b/aapl/avlimelkey.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLIMELKEY_H
+#define _AAPL_AVLIMELKEY_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliMelKey
+ * \brief Linked AVL tree for element appearing in multiple trees with different keys.
+ *
+ * AvliMelKey is similar to AvliMel, except that an additional template
+ * parameter, BaseKey, is provided for resolving ambiguous references to
+ * getKey(). This means that if an element is stored in multiple trees, each
+ * tree can use a different key for ordering the elements in it. Using
+ * AvliMelKey an array of data structures can be indexed with an O(log(n))
+ * search on two or more of the values contained within it and without
+ * allocating any additional data.
+ *
+ * AvliMelKey does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlimelkey.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) BaseKey::name
+#define BASELIST DListMel< Element, BaseEl >
+#define AVLMEL_CLASSDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, BaseKey, Compare
+#define AvlTree AvliMelKey
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIMELKEY_H */
diff --git a/aapl/avliset.h b/aapl/avliset.h
new file mode 100644
index 00000000..9594e7d7
--- /dev/null
+++ b/aapl/avliset.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLISET_H
+#define _AAPL_AVLISET_H
+
+#include "compare.h"
+#include "dlist.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliSet
+ * \brief Linked Key-only oriented tree.
+ *
+ * AvliSet stores only keys in elements that are managed by the tree. AvliSet
+ * requires that a Key type and a class containing a compare() routine
+ * for Key be given. Items are inserted with just a key value.
+ *
+ * AvliSet assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avliset.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_SET
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define BASELIST DList< AvliSetEl<Key> >
+#define AVLMEL_CLASSDEF class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Compare
+#define AVLMEL_TEMPUSE Key, Compare
+#define AvlTree AvliSet
+#define Element AvliSetEl<Key>
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef AVLTREE_SET
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+#undef WALKABLE
+
+#endif /* _AAPL_AVLISET_H */
diff --git a/aapl/avlitree.h b/aapl/avlitree.h
new file mode 100644
index 00000000..28394bb1
--- /dev/null
+++ b/aapl/avlitree.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLITREE_H
+#define _AAPL_AVLITREE_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliTree
+ * \brief Linked AVL tree.
+ *
+ * AvliTree is the standard linked by-structure AVL tree. To use this
+ * structure the user must define an element type and give it the necessary
+ * properties. At the very least it must have a getKey() function that will be
+ * used to compare the relative ordering of elements and tree management data
+ * necessary for the AVL algorithm. An element type can acquire the management
+ * data by inheriting the AvliTreeEl class.
+ *
+ * AvliTree does not presume to manage the allocation of elements in the tree.
+ * The destructor will not delete the items in the tree, instead the elements
+ * must be explicitly de-allocated by the user if necessary and when it is
+ * safe to do so. The empty() routine will traverse the tree and delete all
+ * items.
+ *
+ * Since the tree does not manage the elements, it can contain elements that
+ * are allocated statically or that are part of another data structure.
+ *
+ * \include ex_avlitree.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define BASELIST DListMel< Element, AvliTreeEl<Element> >
+#define AVLMEL_CLASSDEF class Element, class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class Compare
+#define AVLMEL_TEMPUSE Element, Key, Compare
+#define AvlTree AvliTree
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+
+#endif /* _AAPL_AVLITREE_H */
diff --git a/aapl/avlkeyless.h b/aapl/avlkeyless.h
new file mode 100644
index 00000000..fecf8bda
--- /dev/null
+++ b/aapl/avlkeyless.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002, 2003 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLKEYLESS_H
+#define _AAPL_AVLKEYLESS_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlKeyless
+ * \brief AVL tree that has no insert/find/remove functions that take a key.
+ *
+ * AvlKeyless is an implementation of the AVL tree rebalancing functionality
+ * only. It provides the common code for the tiny AVL tree implementations.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define AVLMEL_CLASSDEF class Element
+#define AVLMEL_TEMPDEF class Element
+#define AVLMEL_TEMPUSE Element
+#define AvlTree AvlKeyless
+#define AVL_KEYLESS
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef AVL_KEYLESS
+
+#endif /* _AAPL_AVLKEYLESS_H */
diff --git a/aapl/avlmap.h b/aapl/avlmap.h
new file mode 100644
index 00000000..378613cd
--- /dev/null
+++ b/aapl/avlmap.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLMAP_H
+#define _AAPL_AVLMAP_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlMap
+ * \brief Key and value oriented AVL tree.
+ *
+ * AvlMap stores key and value pairs in elements that managed by the tree. It
+ * is intendend to be similar to map template found in the STL. AvlMap
+ * requires that a Key type, a Value type, and a class containing a compare()
+ * routine for Key be given. Items can be inserted with just a key or with a
+ * key and value pair.
+ *
+ * AvlMap assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avlmap.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_MAP
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Key, class Value, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Value, class Compare
+#define AVLMEL_TEMPUSE Key, Value, Compare
+#define AvlTree AvlMap
+#define Element AvlMapEl<Key,Value>
+
+#include "avlcommon.h"
+
+#undef AVLTREE_MAP
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+
+
+
+#endif /* _AAPL_AVLMAP_H */
diff --git a/aapl/avlmel.h b/aapl/avlmel.h
new file mode 100644
index 00000000..6d0deb7d
--- /dev/null
+++ b/aapl/avlmel.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLMEL_H
+#define _AAPL_AVLMEL_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlMel
+ * \brief AVL tree for elements appearing in multiple trees.
+ *
+ * AvlMel allows for an element to simultaneously be in multiple trees without
+ * the trees interferring with one another. For each tree that the element is
+ * to appear in, there must be a distinct set of AVL Tree management data that
+ * can be unambiguously referenced with some base class name. This name
+ * is passed to the tree as a template parameter and is used in the tree
+ * algorithms.
+ *
+ * The element must use the same key type and value in each tree that it
+ * appears in. If distinct keys are required, the AvlMelKey structure is
+ * available.
+ *
+ * AvlMel does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlmel.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Key, \
+ class BaseEl, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, \
+ class BaseEl, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, Compare
+#define AvlTree AvlMel
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+
+#endif /* _AAPL_AVLMEL_H */
diff --git a/aapl/avlmelkey.h b/aapl/avlmelkey.h
new file mode 100644
index 00000000..5a66c9c2
--- /dev/null
+++ b/aapl/avlmelkey.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLMELKEY_H
+#define _AAPL_AVLMELKEY_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlMelKey
+ * \brief AVL tree for elements appearing in multiple trees with different keys.
+ *
+ * AvlMelKey is similar to AvlMel, except that an additional template
+ * parameter, BaseKey, is provided for resolving ambiguous references to
+ * getKey(). This means that if an element is stored in multiple trees, each
+ * tree can use a different key for ordering the elements in it. Using
+ * AvlMelKey an array of data structures can be indexed with an O(log(n))
+ * search on two or more of the values contained within it and without
+ * allocating any additional data.
+ *
+ * AvlMelKey does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlmelkey.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) BaseKey::name
+#define AVLMEL_CLASSDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, BaseKey, Compare
+#define AvlTree AvlMelKey
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+
+#endif /* _AAPL_AVLMELKEY_H */
diff --git a/aapl/avlset.h b/aapl/avlset.h
new file mode 100644
index 00000000..579378a3
--- /dev/null
+++ b/aapl/avlset.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLSET_H
+#define _AAPL_AVLSET_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlSet
+ * \brief Key-only oriented tree.
+ *
+ * AvlSet stores only keys in elements that are managed by the tree. AvlSet
+ * requires that a Key type and a class containing a compare() routine
+ * for Key be given. Items are inserted with just a key value.
+ *
+ * AvlSet assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avlset.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_SET
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Compare
+#define AVLMEL_TEMPUSE Key, Compare
+#define AvlTree AvlSet
+#define Element AvlSetEl<Key>
+
+#include "avlcommon.h"
+
+#undef AVLTREE_SET
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+
+#endif /* _AAPL_AVLSET_H */
diff --git a/aapl/avltree.h b/aapl/avltree.h
new file mode 100644
index 00000000..2aa8e15f
--- /dev/null
+++ b/aapl/avltree.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_AVLTREE_H
+#define _AAPL_AVLTREE_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlTree
+ * \brief Basic AVL tree.
+ *
+ * AvlTree is the standard by-structure AVL tree. To use this structure the
+ * user must define an element type and give it the necessary properties. At
+ * the very least it must have a getKey() function that will be used to
+ * compare the relative ordering of elements and tree management data
+ * necessary for the AVL algorithm. An element type can acquire the management
+ * data by inheriting the AvlTreeEl class.
+ *
+ * AvlTree does not presume to manage the allocation of elements in the tree.
+ * The destructor will not delete the items in the tree, instead the elements
+ * must be explicitly de-allocated by the user if necessary and when it is
+ * safe to do so. The empty() routine will traverse the tree and delete all
+ * items.
+ *
+ * Since the tree does not manage the elements, it can contain elements that
+ * are allocated statically or that are part of another data structure.
+ *
+ * \include ex_avltree.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class Compare
+#define AVLMEL_TEMPUSE Element, Key, Compare
+#define AvlTree AvlTree
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+
+#endif /* _AAPL_AVLTREE_H */
diff --git a/aapl/bstcommon.h b/aapl/bstcommon.h
new file mode 100644
index 00000000..888717f3
--- /dev/null
+++ b/aapl/bstcommon.h
@@ -0,0 +1,814 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This header is not wrapped in ifndefs because it is
+ * not intended to be included by users directly. */
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/* Binary Search Table */
+template < BST_TEMPL_DECLARE > class BstTable :
+ public Compare,
+ public Vector< Element, Resize >
+{
+ typedef Vector<Element, Resize> BaseVector;
+ typedef Table<Element> BaseTable;
+
+public:
+ /**
+ * \brief Default constructor.
+ *
+ * Create an empty binary search table.
+ */
+ BstTable() { }
+
+ /**
+ * \brief Construct with initial value.
+ *
+ * Constructs a binary search table with an initial item. Uses the default
+ * constructor for initializing Value.
+ */
+ BstTable(const Key &key)
+ { insert(key); }
+
+#if defined( BSTMAP )
+ /**
+ * \brief Construct with initial value.
+ *
+ * Constructs a binary search table with an initial key/value pair.
+ */
+ BstTable(const Key &key, const Value &val)
+ { insert(key, val); }
+#endif
+
+#if ! defined( BSTSET )
+ /**
+ * \brief Construct with initial value.
+ *
+ * Constructs a binary search table with an initial Element.
+ */
+ BstTable(const Element &el)
+ { insert(el); }
+#endif
+
+ Element *insert(const Key &key, Element **lastFound = 0);
+ Element *insertMulti(const Key &key);
+
+ bool insert(const BstTable &other);
+ void insertMulti(const BstTable &other);
+
+#if defined( BSTMAP )
+ Element *insert(const Key &key, const Value &val,
+ Element **lastFound = 0);
+ Element *insertMulti(const Key &key, const Value &val );
+#endif
+
+#if ! defined( BSTSET )
+ Element *insert(const Element &el, Element **lastFound = 0);
+ Element *insertMulti(const Element &el);
+#endif
+
+ Element *find(const Key &key, Element **lastFound = 0) const;
+ bool findMulti( const Key &key, Element *&lower,
+ Element *&upper ) const;
+
+ bool remove(const Key &key);
+ bool remove(Element *item);
+ long removeMulti(const Key &key);
+ long removeMulti(Element *lower, Element *upper);
+
+ /* The following provide access to the underlying insert and remove
+ * functions that my be hidden by the BST insert and remove. The insertDup
+ * and insertNew functions will never be hidden. They are provided for
+ * consistency. The difference between the non-shared and the shared
+ * tables is the documentation reference to the invoked function. */
+
+#if !defined( SHARED_BST )
+ /*@{*/
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes Vector::insert( long pos, const T &val ).
+ */
+ void vinsert(long pos, const Element &val)
+ { Vector< Element, Resize >::insert( pos, &val, 1 ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes Vector::insert( long pos, const T *val, long len ).
+ */
+ void vinsert(long pos, const Element *val, long len)
+ { Vector< Element, Resize >::insert( pos, val, len ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes Vector::insert( long pos, const Vector &v ).
+ */
+ void vinsert(long pos, const BstTable &v)
+ { Vector< Element, Resize >::insert( pos, v.data, v.tabLen ); }
+
+ /*@}*/
+
+ /*@{*/
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Provides access to the vector remove, which may become hidden.
+ * Invokes Vector::remove( long pos ).
+ */
+ void vremove(long pos)
+ { Vector< Element, Resize >::remove( pos, 1 ); }
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Proves access to the vector remove, which may become hidden.
+ * Invokes Vector::remove( long pos, long len ).
+ */
+ void vremove(long pos, long len)
+ { Vector< Element, Resize >::remove( pos, len ); }
+
+ /*@}*/
+#else /* SHARED_BST */
+ /*@{*/
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes SVector::insert( long pos, const T &val ).
+ */
+ void vinsert(long pos, const Element &val)
+ { Vector< Element, Resize >::insert( pos, &val, 1 ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes SVector::insert( long pos, const T *val, long len ).
+ */
+ void vinsert(long pos, const Element *val, long len)
+ { Vector< Element, Resize >::insert( pos, val, len ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes SVector::insert( long pos, const SVector &v ).
+ */
+ void vinsert(long pos, const BstTable &v)
+ { Vector< Element, Resize >::insert( pos, v.data, v.length() ); }
+
+ /*@}*/
+
+ /*@{*/
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Provides access to the vector remove, which may become hidden.
+ * Invokes SVector::remove( long pos ).
+ */
+ void vremove(long pos)
+ { Vector< Element, Resize >::remove( pos, 1 ); }
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Proves access to the vector remove, which may become hidden.
+ * Invokes SVector::remove( long pos, long len ).
+ */
+ void vremove(long pos, long len)
+ { Vector< Element, Resize >::remove( pos, len ); }
+
+ /*@}*/
+
+#endif /* SHARED_BST */
+};
+
+
+#if 0
+#if defined( SHARED_BST )
+/**
+ * \brief Construct a binary search table with an initial amount of
+ * allocation.
+ *
+ * The table is initialized to have room for allocLength elements. The
+ * table starts empty.
+ */
+template <BST_TEMPL_DEF> BstTable<BST_TEMPL_USE>::
+ BstTable( long allocLen )
+{
+ /* Allocate the space if we are given a positive allocLen. */
+ if ( allocLen > 0 ) {
+ /* Allocate the data needed. */
+ STabHead *head = (STabHead*)
+ malloc( sizeof(STabHead) + sizeof(Element) * allocLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header and save the data pointer. */
+ head->refCount = 1;
+ head->allocLen = allocLen;
+ head->tabLen = 0;
+ BaseTable::data = (Element*) (head + 1);
+ }
+}
+#else
+/**
+ * \brief Construct a binary search table with an initial amount of
+ * allocation.
+ *
+ * The table is initialized to have room for allocLength elements. The
+ * table starts empty.
+ */
+template <BST_TEMPL_DEF> BstTable<BST_TEMPL_USE>::
+ BstTable( long allocLen )
+{
+ /* Allocate the space if we are given a positive allocLen. */
+ BaseTable::allocLen = allocLen;
+ if ( BaseTable::allocLen > 0 ) {
+ BaseTable::data = (Element*) malloc(sizeof(Element) * BaseTable::allocLen);
+ if ( BaseTable::data == NULL )
+ throw std::bad_alloc();
+ }
+}
+
+#endif
+#endif
+
+/**
+ * \brief Find the element with the given key and remove it.
+ *
+ * If multiple elements with the given key exist, then it is unspecified which
+ * element will be removed.
+ *
+ * \returns True if an element is found and consequently removed, false
+ * otherwise.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ remove(const Key &key)
+{
+ Element *el = find(key);
+ if ( el != 0 ) {
+ Vector< Element >::remove(el - BaseTable::data);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * \brief Remove the element pointed to by item.
+ *
+ * If item does not point to an element in the tree, then undefined behaviour
+ * results. If item is null, then remove has no effect.
+ *
+ * \returns True if item is not null, false otherwise.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ remove( Element *item )
+{
+ if ( item != 0 ) {
+ Vector< Element >::remove(item - BaseTable::data);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * \brief Find and remove the entire range of elements with the given key.
+ *
+ * \returns The number of elements removed.
+ */
+template <BST_TEMPL_DEF> long BstTable<BST_TEMPL_USE>::
+ removeMulti(const Key &key)
+{
+ Element *low, *high;
+ if ( findMulti(key, low, high) ) {
+ /* Get the length of the range. */
+ long num = high - low + 1;
+ Vector< Element >::remove(low - BaseTable::data, num);
+ return num;
+ }
+
+ return 0;
+}
+
+template <BST_TEMPL_DEF> long BstTable<BST_TEMPL_USE>::
+ removeMulti(Element *lower, Element *upper)
+{
+ /* Get the length of the range. */
+ long num = upper - lower + 1;
+ Vector< Element >::remove(lower - BaseTable::data, num);
+ return num;
+}
+
+
+/**
+ * \brief Find a range of elements with the given key.
+ *
+ * If any elements with the given key exist then lower and upper are set to
+ * the low and high ends of the continous range of elements with the key.
+ * Lower and upper will point to the first and last elements with the key.
+ *
+ * \returns True if any elements are found, false otherwise.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ findMulti(const Key &key, Element *&low, Element *&high ) const
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation;
+ const long tblLen = BaseTable::length();
+
+ if ( BaseTable::data == 0 )
+ return false;
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the fd in the array. */
+ return false;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ Element *lowEnd = BaseTable::data - 1;
+ Element *highEnd = BaseTable::data + tblLen;
+
+ lower = mid - 1;
+ while ( lower != lowEnd &&
+ compare(key, GET_KEY(*lower)) == 0 )
+ lower--;
+
+ upper = mid + 1;
+ while ( upper != highEnd &&
+ compare(key, GET_KEY(*upper)) == 0 )
+ upper++;
+
+ low = (Element*)lower + 1;
+ high = (Element*)upper - 1;
+ return true;
+ }
+ }
+}
+
+/**
+ * \brief Find an element with the given key.
+ *
+ * If the find succeeds then lastFound is set to the element found. If the
+ * find fails then lastFound is set the location where the key would be
+ * inserted. If there is more than one element in the tree with the given key,
+ * then it is unspecified which element is returned as the match.
+ *
+ * \returns The element found on success, null on failure.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ find( const Key &key, Element **lastFound ) const
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation;
+ const long tblLen = BaseTable::length();
+
+ if ( BaseTable::data == 0 )
+ return 0;
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key. Last found gets the insert location. */
+ if ( lastFound != 0 )
+ *lastFound = (Element*)lower;
+ return 0;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ /* Key is found. Last found gets the found record. */
+ if ( lastFound != 0 )
+ *lastFound = (Element*)mid;
+ return (Element*)mid;
+ }
+ }
+}
+
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insert(const Key &key, Element **lastFound)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ if ( lastFound != 0 )
+ *lastFound = (Element*)mid;
+ return 0;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. After makeRawSpaceFor, lower pointer is no good. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key);
+
+ /* Set lastFound */
+ if ( lastFound != 0 )
+ *lastFound = BaseTable::data + insertPos;
+ return BaseTable::data + insertPos;
+}
+
+
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insertMulti(const Key &key)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ lower = mid;
+ goto insert;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key);
+
+ /* Return the element inserted. */
+ return BaseTable::data + insertPos;
+}
+
+/**
+ * \brief Insert each element from other.
+ *
+ * Always attempts to insert all elements even if the insert of some item from
+ * other fails.
+ *
+ * \returns True if all items inserted successfully, false if any insert
+ * failed.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ insert(const BstTable &other)
+{
+ bool allSuccess = true;
+ long otherLen = other.length();
+ for ( long i = 0; i < otherLen; i++ ) {
+ Element *el = insert( other.data[i] );
+ if ( el == 0 )
+ allSuccess = false;
+ }
+ return allSuccess;
+}
+
+/**
+ * \brief Insert each element from other even if the elements exist already.
+ *
+ * No individual insertMulti can fail.
+ */
+template <BST_TEMPL_DEF> void BstTable<BST_TEMPL_USE>::
+ insertMulti(const BstTable &other)
+{
+ long otherLen = other.length();
+ for ( long i = 0; i < otherLen; i++ )
+ insertMulti( other.data[i] );
+}
+
+#if ! defined( BSTSET )
+
+/**
+ * \brief Insert the given element.
+ *
+ * If the key in the given element does not already exist in the table then a
+ * new element is inserted. They element copy constructor is used to place the
+ * element into the table. If lastFound is given, it is set to the new element
+ * created. If the insert fails then lastFound is set to the existing element
+ * of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insert(const Element &el, Element **lastFound )
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = compare(GET_KEY(el), GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ if ( lastFound != 0 )
+ *lastFound = (Element*)mid;
+ return 0;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. After makeRawSpaceFor, lower pointer is no good. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(el);
+
+ /* Set lastFound */
+ if ( lastFound != 0 )
+ *lastFound = BaseTable::data + insertPos;
+ return BaseTable::data + insertPos;
+}
+
+/**
+ * \brief Insert the given element even if it exists already.
+ *
+ * If the key in the given element exists already then the new element is
+ * placed next to some other element of the same key. InsertMulti cannot fail.
+ * The element copy constructor is used to place the element in the table.
+ *
+ * \returns The new element created.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insertMulti(const Element &el)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the fd in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = compare(GET_KEY(el), GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ lower = mid;
+ goto insert;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(el);
+
+ /* Return the element inserted. */
+ return BaseTable::data + insertPos;
+}
+#endif
+
+
+#if defined( BSTMAP )
+
+/**
+ * \brief Insert the given key-value pair.
+ *
+ * If the given key does not already exist in the table then the key-value
+ * pair is inserted. Copy constructors are used to place the pair in the
+ * table. If lastFound is given, it is set to the new entry created. If the
+ * insert fails then lastFound is set to the existing pair of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insert(const Key &key, const Value &val, Element **lastFound)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the fd in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = Compare::compare(key, mid->key);
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ if ( lastFound != NULL )
+ *lastFound = (Element*)mid;
+ return 0;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key, val);
+
+ /* Set lastFound */
+ if ( lastFound != NULL )
+ *lastFound = BaseTable::data + insertPos;
+ return BaseTable::data + insertPos;
+}
+
+
+/**
+ * \brief Insert the given key-value pair even if the key exists already.
+ *
+ * If the key exists already then the key-value pair is placed next to some
+ * other pair of the same key. InsertMulti cannot fail. Copy constructors are
+ * used to place the pair in the table.
+ *
+ * \returns The new element created.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insertMulti(const Key &key, const Value &val)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = Compare::compare(key, mid->key);
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ lower = mid;
+ goto insert;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key, val);
+
+ /* Return the element inserted. */
+ return BaseTable::data + insertPos;
+}
+
+#endif
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
diff --git a/aapl/bstmap.h b/aapl/bstmap.h
new file mode 100644
index 00000000..30c8e3c5
--- /dev/null
+++ b/aapl/bstmap.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_BSTMAP_H
+#define _AAPL_BSTMAP_H
+
+#include "compare.h"
+#include "vector.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \brief Element for BstMap.
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct BstMapEl
+{
+ BstMapEl() {}
+ BstMapEl(const Key &key) : key(key) {}
+ BstMapEl(const Key &key, const Value &val) : key(key), value(val) {}
+
+ /** \brief The key */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class BstMap
+ * \brief Binary search table for key and value pairs.
+ *
+ * BstMap stores key and value pairs in each element. The key and value can be
+ * any type. A compare class for the key must be supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Key, class Value, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Value, class Compare, class Resize
+#define BST_TEMPL_USE Key, Value, Compare, Resize
+#define GET_KEY(el) ((el).key)
+#define BstTable BstMap
+#define Element BstMapEl<Key, Value>
+#define BSTMAP
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Element
+#undef BSTMAP
+
+/**
+ * \fn BstMap::insert(const Key &key, BstMapEl<Key, Value> **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then a new element
+ * having key is inserted. They key copy constructor and value default
+ * constructor are used to place the pair in the table. If lastFound is given,
+ * it is set to the new entry created. If the insert fails then lastFound is
+ * set to the existing pair of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn BstMap::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then the new element having key is placed next
+ * to some other pair of the same key. InsertMulti cannot fail. The key copy
+ * constructor and the value default constructor are used to place the pair in
+ * the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_BSTMAP_H */
diff --git a/aapl/bstset.h b/aapl/bstset.h
new file mode 100644
index 00000000..4a0f88ee
--- /dev/null
+++ b/aapl/bstset.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_BSTSET_H
+#define _AAPL_BSTSET_H
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class BstSet
+ * \brief Binary search table for types that are the key.
+ *
+ * BstSet is suitable for types that comprise the entire key. Rather than look
+ * into the element to retrieve the key, the element is the key. A class that
+ * contains a comparison routine for the key must be given.
+ */
+
+/*@}*/
+
+#include "compare.h"
+#include "vector.h"
+
+#define BST_TEMPL_DECLARE class Key, class Compare = CmpOrd<Key>, \
+ class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Compare, class Resize
+#define BST_TEMPL_USE Key, Compare, Resize
+#define GET_KEY(el) (el)
+#define BstTable BstSet
+#define Element Key
+#define BSTSET
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Element
+#undef BSTSET
+
+/**
+ * \fn BstSet::insert(const Key &key, Key **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then it is inserted.
+ * The key's copy constructor is used to place the item in the table. If
+ * lastFound is given, it is set to the new entry created. If the insert fails
+ * then lastFound is set to the existing key of the same value.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn BstSet::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then it is placed next to some other key of the
+ * same value. InsertMulti cannot fail. The key's copy constructor is used to
+ * place the item in the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_BSTSET_H */
diff --git a/aapl/bsttable.h b/aapl/bsttable.h
new file mode 100644
index 00000000..4e4babc3
--- /dev/null
+++ b/aapl/bsttable.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_BSTTABLE_H
+#define _AAPL_BSTTABLE_H
+
+#include "compare.h"
+#include "vector.h"
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class BstTable
+ * \brief Binary search table for structures that contain a key.
+ *
+ * This is the basic binary search table. It can be used to contain a
+ * structure that has a key and possibly some data. The key should be a member
+ * of the element class and accessible with getKey(). A class containing the
+ * compare routine must be supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Element, class Key, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Element, class Key, class Compare, class Resize
+#define BST_TEMPL_USE Element, Key, Compare, Resize
+#define GET_KEY(el) ((el).getKey())
+#define BSTTABLE
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BSTTABLE
+
+/**
+ * \fn BstTable::insert(const Key &key, Element **lastFound)
+ * \brief Insert a new element with the given key.
+ *
+ * If the given key does not already exist in the table a new element is
+ * inserted with the given key. A constructor taking only const Key& is used
+ * to initialize the new element. If lastFound is given, it is set to the new
+ * element created. If the insert fails then lastFound is set to the existing
+ * element with the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn BstTable::insertMulti(const Key &key)
+ * \brief Insert a new element even if the key exists already.
+ *
+ * If the key exists already then the new element is placed next to some
+ * element with the same key. InsertMulti cannot fail. A constructor taking
+ * only const Key& is used to initialize the new element.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_BSTTABLE_H */
diff --git a/aapl/bubblesort.h b/aapl/bubblesort.h
new file mode 100644
index 00000000..bcc2fb6a
--- /dev/null
+++ b/aapl/bubblesort.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_BUBBLESORT_H
+#define _AAPL_BUBBLESORT_H
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class BubbleSort
+ * \brief Bubble sort an array of data.
+ *
+ * BubbleSort can be used to sort any array of objects of type T provided a
+ * compare class is given. BubbleSort is in-place. It does not require any
+ * temporary storage.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * BubbleSort runs in O(n^2) time. It is most useful when sorting arrays that
+ * are nearly sorted. It is best when neighbouring pairs are out of place.
+ * BubbleSort is a stable sort, meaning that objects with the same key have
+ * their relative ordering preserved.
+ */
+
+/*@}*/
+
+/* BubbleSort. */
+template <class T, class Compare> class BubbleSort
+ : public Compare
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+};
+
+
+/**
+ * \brief Bubble sort an array of data.
+ */
+template <class T, class Compare> void BubbleSort<T,Compare>::
+ sort(T *data, long len)
+{
+ bool changed = true;
+ for ( long pass = 1; changed && pass < len; pass ++ ) {
+ changed = false;
+ for ( long i = 0; i < len-pass; i++ ) {
+ /* Do we swap pos with the next one? */
+ if ( compare( data[i], data[i+1] ) > 0 ) {
+ char tmp[sizeof(T)];
+
+ /* Swap the two items. */
+ memcpy( tmp, data+i, sizeof(T) );
+ memcpy( data+i, data+i+1, sizeof(T) );
+ memcpy( data+i+1, tmp, sizeof(T) );
+
+ /* Note that we made a change. */
+ changed = true;
+ }
+ }
+ }
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_BUBBLESORT_H */
diff --git a/aapl/compare.h b/aapl/compare.h
new file mode 100644
index 00000000..22937e9b
--- /dev/null
+++ b/aapl/compare.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_COMPARE_H
+#define _AAPL_COMPARE_H
+
+#include <string.h>
+#include "astring.h"
+#include "table.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \defgroup compare Compare
+ * \brief Basic compare clases.
+ *
+ * Compare classes are used by data structures that need to know the relative
+ * ordering of elemets. To become a compare class, a class must imlement a
+ * routine long compare(const T &key1, const T &key2) that behaves just like
+ * strcmp.
+ *
+ * Compare classes are passed to the template data structure as a template
+ * parameter and are inherited. In most cases the compare routine will base
+ * the key comparision only on the two keys and the compare routine can
+ * therefore be static. Though sometimes it is useful to include data in the
+ * compare class and use this data in the comparison. For example the compare
+ * class may contain a pointer to some other data structure to which the
+ * comparison is delegated.
+ *
+ * @{
+ */
+
+/**
+ * \brief Compare two null terminated character sequences.
+ *
+ * This comparision class is a wrapper for strcmp.
+ */
+template<class T> struct CmpStrTmpl
+{
+ /**
+ * \brief Compare two null terminated string types.
+ */
+ static inline long compare( const char *k1, const char *k2 )
+ { return strcmp(k1, k2); }
+
+ static int compare( const StrTmpl<T> &s1, const StrTmpl<T> &s2 )
+ {
+ if ( s1.length() < s2.length() )
+ return -1;
+ else if ( s1.length() > s2.length() )
+ return 1;
+ else
+ return memcmp( s1.data, s2.data, s1.length() );
+ }
+};
+
+typedef CmpStrTmpl<char> CmpStr;
+
+/**
+ * \brief Compare a type for which < and > are implemented.
+ *
+ * CmpOrd is suitable for simple types such as integers and pointers that by
+ * default have the less-than and greater-than operators defined.
+ */
+template <class T> struct CmpOrd
+{
+ /**
+ * \brief Compare two ordinal types.
+ *
+ * This compare routine copies its arguements in by value.
+ */
+ static inline long compare(const T k1, const T k2)
+ {
+ if (k1 < k2)
+ return -1;
+ else if (k1 > k2)
+ return 1;
+ else
+ return 0;
+ }
+};
+
+/**
+ * \brief Compare two tables of type T
+ *
+ * Table comparison is useful for keying a data structure on a vector or
+ * binary search table. T is the element type stored in the table.
+ * CompareT is the comparison structure used to compare the individual values
+ * in the table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpTable
+ : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ static inline long compare(const Table<T> &t1, const Table<T> &t2)
+ {
+ if ( t1.tabLen < t2.tabLen )
+ return -1;
+ else if ( t1.tabLen > t2.tabLen )
+ return 1;
+ else
+ {
+ T *i1 = t1.data, *i2 = t2.data;
+ long len = t1.tabLen, cmpResult;
+ for ( long pos = 0; pos < len;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+/**
+ * \brief Compare two tables of type T -- non-static version.
+ *
+ * CmpTableNs is identical to CmpTable, however the compare routine is
+ * non-static. If the CompareT class contains a non-static compare, then this
+ * version must be used because a static member cannot invoke a non-static
+ * member.
+ *
+ * Table comparison is useful for keying a data structure on a vector or binary
+ * search table. T is the element type stored in the table. CompareT
+ * is the comparison structure used to compare the individual values in the
+ * table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpTableNs
+ : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ inline long compare(const Table<T> &t1, const Table<T> &t2)
+ {
+ if ( t1.tabLen < t2.tabLen )
+ return -1;
+ else if ( t1.tabLen > t2.tabLen )
+ return 1;
+ else
+ {
+ T *i1 = t1.data, *i2 = t2.data;
+ long len = t1.tabLen, cmpResult;
+ for ( long pos = 0; pos < len;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+/**
+ * \brief Compare two implicitly shared tables of type T
+ *
+ * This table comparison is for data structures based on implicitly
+ * shared tables.
+ *
+ * Table comparison is useful for keying a data structure on a vector or
+ * binary search table. T is the element type stored in the table.
+ * CompareT is the comparison structure used to compare the individual values
+ * in the table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpSTable : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ static inline long compare(const STable<T> &t1, const STable<T> &t2)
+ {
+ long t1Length = t1.length();
+ long t2Length = t2.length();
+
+ /* Compare lengths. */
+ if ( t1Length < t2Length )
+ return -1;
+ else if ( t1Length > t2Length )
+ return 1;
+ else {
+ /* Compare the table data. */
+ T *i1 = t1.data, *i2 = t2.data;
+ for ( long pos = 0; pos < t1Length;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ long cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+/**
+ * \brief Compare two implicitly shared tables of type T -- non-static
+ * version.
+ *
+ * This is a non-static table comparison for data structures based on
+ * implicitly shared tables. If the CompareT class contains a non-static
+ * compare, then this version must be used because a static member cannot
+ * invoke a non-static member.
+ *
+ * Table comparison is useful for keying a data structure on a vector or
+ * binary search table. T is the element type stored in the table.
+ * CompareT is the comparison structure used to compare the individual values
+ * in the table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpSTableNs
+ : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ inline long compare(const STable<T> &t1, const STable<T> &t2)
+ {
+ long t1Length = t1.length();
+ long t2Length = t2.length();
+
+ /* Compare lengths. */
+ if ( t1Length < t2Length )
+ return -1;
+ else if ( t1Length > t2Length )
+ return 1;
+ else {
+ /* Compare the table data. */
+ T *i1 = t1.data, *i2 = t2.data;
+ for ( long pos = 0; pos < t1Length;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ long cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+
+/*@}*/
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_COMPARE_H */
diff --git a/aapl/dlcommon.h b/aapl/dlcommon.h
new file mode 100644
index 00000000..91dff25f
--- /dev/null
+++ b/aapl/dlcommon.h
@@ -0,0 +1,790 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This header is not wrapped in ifndef becuase it is not intended to
+ * be included by the user. */
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+#if defined( DOUBLELIST_VALUE )
+/**
+ * \brief Double list element for DListVal.
+ *
+ * DListValEl stores the type T of DListVal by value.
+ */
+template <class T> struct DListValEl
+{
+ /**
+ * \brief Construct a DListValEl with a given value.
+ *
+ * The only constructor available initializes the value element. This
+ * enforces that DListVal elements are never created without having their
+ * value intialzed by the user. T's copy constructor is used to copy the
+ * value in.
+ */
+ DListValEl( const T &val ) : value(val) { }
+
+ /**
+ * \brief Value stored by the list element.
+ *
+ * Value is always copied into new list elements using the copy
+ * constructor.
+ */
+ T value;
+
+ /**
+ * \brief List previous pointer.
+ *
+ * Points to the previous item in the list. If this is the first item in
+ * the list, then prev is NULL. If this element is not in a list then
+ * prev is undefined.
+ */
+ DListValEl<T> *prev;
+
+ /**
+ * \brief List next pointer.
+ *
+ * Points to the next item in the list. If this is the list item in the
+ * list, then next is NULL. If this element is not in a list then next is
+ * undefined.
+ */
+ DListValEl<T> *next;
+};
+#else
+
+#ifndef __AAPL_DOUBLE_LIST_EL
+#define __AAPL_DOUBLE_LIST_EL
+/**
+ * \brief Double list element properties.
+ *
+ * This class can be inherited to make a class suitable to be a double list
+ * element. It simply provides the next and previous pointers. An alternative
+ * is to put the next and previous pointers in the class directly.
+ */
+template <class Element> struct DListEl
+{
+ /**
+ * \brief List previous pointer.
+ *
+ * Points to the previous item in the list. If this is the first item in
+ * the list, then prev is NULL. If this element is not in a list then
+ * prev is undefined.
+ */
+ Element *prev;
+
+ /**
+ * \brief List next pointer.
+ *
+ * Points to the next item in the list. If this is the list item in the
+ * list, then next is NULL. If this element is not in a list then next is
+ * undefined.
+ */
+ Element *next;
+};
+#endif /* __AAPL_DOUBLE_LIST_EL */
+
+#endif
+
+/* Doubly Linked List */
+template <DLMEL_TEMPDEF> class DList
+{
+public:
+ /** \brief Initialize an empty list. */
+ DList() : head(0), tail(0), listLen(0) {}
+
+ /**
+ * \brief Perform a deep copy of the list.
+ *
+ * The elements of the other list are duplicated and put into this list.
+ * Elements are copied using the copy constructor.
+ */
+ DList(const DList &other);
+
+#ifdef DOUBLELIST_VALUE
+ /**
+ * \brief Clear the double list contents.
+ *
+ * All elements are deleted.
+ */
+ ~DList() { empty(); }
+
+ /**
+ * \brief Assign another list into this list using a deep copy.
+ *
+ * The elements of the other list are duplicated and put into this list.
+ * Each list item is created using the copy constructor. If this list
+ * contains any elements before the copy, they are deleted first.
+ *
+ * \returns A reference to this.
+ */
+ DList &operator=(const DList &other);
+
+ /**
+ * \brief Transfer the contents of another list into this list.
+ *
+ * The elements of the other list moved in. The other list will be empty
+ * afterwards. If this list contains any elements before the copy, then
+ * they are deleted.
+ */
+ void transfer(DList &other);
+#else
+ /**
+ * \brief Abandon all elements in the list.
+ *
+ * List elements are not deleted.
+ */
+ ~DList() {}
+
+ /**
+ * \brief Perform a deep copy of the list.
+ *
+ * The elements of the other list are duplicated and put into this list.
+ * Each list item is created using the copy constructor. If this list
+ * contains any elements before the copy, they are abandoned.
+ *
+ * \returns A reference to this.
+ */
+ DList &operator=(const DList &other);
+
+ /**
+ * \brief Transfer the contents of another list into this list.
+ *
+ * The elements of the other list moved in. The other list will be empty
+ * afterwards. If this list contains any elements before the copy, they
+ * are abandoned.
+ */
+ void transfer(DList &other);
+#endif
+
+
+#ifdef DOUBLELIST_VALUE
+ /**
+ * \brief Make a new element and prepend it to the front of the list.
+ *
+ * The item is copied into the new element using the copy constructor.
+ * Equivalent to list.addBefore(list.head, item).
+ */
+ void prepend(const T &item);
+
+ /**
+ * \brief Make a new element and append it to the end of the list.
+ *
+ * The item is copied into the new element using the copy constructor.
+ * Equivalent to list.addAfter(list.tail, item).
+ */
+ void append(const T &item);
+
+ /**
+ * \brief Make a new element and insert it immediately after an element in
+ * the list.
+ *
+ * The item is copied into the new element using the copy constructor. If
+ * prev_el is NULL then the new element is prepended to the front of the
+ * list. If prev_el is not already in the list then undefined behaviour
+ * results. Equivalent to list.addAfter(prev_el, new DListValEl(item)).
+ */
+ void addAfter(Element *prev_el, const T &item);
+
+ /**
+ * \brief Make a new element and insert it immediately before an element
+ * in the list.
+ *
+ * The item is copied into the new element using the copy construcotor. If
+ * next_el is NULL then the new element is appended to the end of the
+ * list. If next_el is not already in the list then undefined behaviour
+ * results. Equivalent to list.addBefore(next_el, new DListValEl(item)).
+ */
+ void addBefore(Element *next_el, const T &item);
+#endif
+
+ /**
+ * \brief Prepend a single element to the front of the list.
+ *
+ * If new_el is already an element of some list, then undefined behaviour
+ * results. Equivalent to list.addBefore(list.head, new_el).
+ */
+ void prepend(Element *new_el) { addBefore(head, new_el); }
+
+ /**
+ * \brief Append a single element to the end of the list.
+ *
+ * If new_el is alreay an element of some list, then undefined behaviour
+ * results. Equivalent to list.addAfter(list.tail, new_el).
+ */
+ void append(Element *new_el) { addAfter(tail, new_el); }
+
+ /**
+ * \brief Prepend an entire list to the beginning of this list.
+ *
+ * All items are moved, not copied. Afterwards, the other list is emtpy.
+ * All items are prepended at once, so this is an O(1) operation.
+ * Equivalent to list.addBefore(list.head, dl).
+ */
+ void prepend(DList &dl) { addBefore(head, dl); }
+
+ /**
+ * \brief Append an entire list to the end of the list.
+ *
+ * All items are moved, not copied. Afterwards, the other list is empty.
+ * All items are appened at once, so this is an O(1) operation.
+ * Equivalent to list.addAfter(list.tail, dl).
+ */
+ void append(DList &dl) { addAfter(tail, dl); }
+
+ void addAfter(Element *prev_el, Element *new_el);
+ void addBefore(Element *next_el, Element *new_el);
+
+ void addAfter(Element *prev_el, DList &dl);
+ void addBefore(Element *next_el, DList &dl);
+
+ /**
+ * \brief Detach the head of the list
+ *
+ * The element detached is not deleted. If there is no head of the list
+ * (the list is empty) then undefined behaviour results. Equivalent to
+ * list.detach(list.head).
+ *
+ * \returns The element detached.
+ */
+ Element *detachFirst() { return detach(head); }
+
+ /**
+ * \brief Detach the tail of the list
+ *
+ * The element detached is not deleted. If there is no tail of the list
+ * (the list is empty) then undefined behaviour results. Equivalent to
+ * list.detach(list.tail).
+ *
+ * \returns The element detached.
+ */
+ Element *detachLast() { return detach(tail); }
+
+ /* Detaches an element from the list. Does not free any memory. */
+ Element *detach(Element *el);
+
+ /**
+ * \brief Detach and delete the first element in the list.
+ *
+ * If there is no first element (the list is empty) then undefined
+ * behaviour results. Equivalent to delete list.detach(list.head);
+ */
+ void removeFirst() { delete detach( head ); }
+
+ /**
+ * \brief Detach and delete the last element in the list.
+ *
+ * If there is no last element (the list is emtpy) then undefined
+ * behaviour results. Equivalent to delete list.detach(list.tail);
+ */
+ void removeLast() { delete detach( tail ); }
+
+ /**
+ * \brief Detach and delete an element from the list.
+ *
+ * If the element is not in the list, then undefined behaviour results.
+ * Equivalent to delete list.detach(el);
+ */
+ void remove(Element *el) { delete detach( el ); }
+
+ void empty();
+ void abandon();
+
+ /** \brief The number of elements in the list. */
+ long length() const { return listLen; }
+
+ /** \brief Head and tail of the linked list. */
+ Element *head, *tail;
+
+ /** \brief The number of element in the list. */
+ long listLen;
+
+ /* Convenience access. */
+ long size() const { return listLen; }
+
+ /* Forward this so a ref can be used. */
+ struct Iter;
+
+ /* Class for setting the iterator. */
+ struct IterFirst { IterFirst( const DList &l ) : l(l) { } const DList &l; };
+ struct IterLast { IterLast( const DList &l ) : l(l) { } const DList &l; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+ /**
+ * \brief Double List Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Default construct. */
+ Iter() : ptr(0) { }
+
+ /* Construct from a double list. */
+ Iter( const DList &dl ) : ptr(dl.head) { }
+ Iter( Element *el ) : ptr(el) { }
+ Iter( const IterFirst &dlf ) : ptr(dlf.l.head) { }
+ Iter( const IterLast &dll ) : ptr(dll.l.tail) { }
+ Iter( const IterNext &dln ) : ptr(dln.i.ptr->BASE_EL(next)) { }
+ Iter( const IterPrev &dlp ) : ptr(dlp.i.ptr->BASE_EL(prev)) { }
+
+ /* Assign from a double list. */
+ Iter &operator=( const DList &dl ) { ptr = dl.head; return *this; }
+ Iter &operator=( Element *el ) { ptr = el; return *this; }
+ Iter &operator=( const IterFirst &af ) { ptr = af.l.head; return *this; }
+ Iter &operator=( const IterLast &al ) { ptr = al.l.tail; return *this; }
+ Iter &operator=( const IterNext &an ) { ptr = an.i.ptr->BASE_EL(next); return *this; }
+ Iter &operator=( const IterPrev &ap ) { ptr = ap.i.ptr->BASE_EL(prev); return *this; }
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != 0; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == 0; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != 0; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == 0; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr && ptr->BASE_EL(prev) == 0; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr && ptr->BASE_EL(next) == 0; }
+
+ /** \brief Implicit cast to Element*. */
+ operator Element*() const { return ptr; }
+
+ /** \brief Dereference operator returns Element&. */
+ Element &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns Element*. */
+ Element *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ inline Element *operator++() { return ptr = ptr->BASE_EL(next); }
+
+ /** \brief Move to next item. */
+ inline Element *increment() { return ptr = ptr->BASE_EL(next); }
+
+ /** \brief Move to next item. */
+ inline Element *operator++(int);
+
+ /** \brief Move to previous item. */
+ inline Element *operator--() { return ptr = ptr->BASE_EL(prev); }
+
+ /** \brief Move to previous item. */
+ inline Element *decrement() { return ptr = ptr->BASE_EL(prev); }
+
+ /** \brief Move to previous item. */
+ inline Element *operator--(int);
+
+ /** \brief Return the next item. Does not modify this. */
+ inline IterNext next() const { return IterNext(*this); }
+
+ /** \brief Return the prev item. Does not modify this. */
+ inline IterPrev prev() const { return IterPrev(*this); }
+
+ /** \brief The iterator is simply a pointer. */
+ Element *ptr;
+ };
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst(*this); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast(*this); }
+};
+
+/* Copy constructor, does a deep copy of other. */
+template <DLMEL_TEMPDEF> DList<DLMEL_TEMPUSE>::
+ DList(const DList<DLMEL_TEMPUSE> &other) :
+ head(0), tail(0), listLen(0)
+{
+ Element *el = other.head;
+ while( el != 0 ) {
+ append( new Element(*el) );
+ el = el->BASE_EL(next);
+ }
+}
+
+#ifdef DOUBLELIST_VALUE
+
+/* Assignement operator does deep copy. */
+template <DLMEL_TEMPDEF> DList<DLMEL_TEMPUSE> &DList<DLMEL_TEMPUSE>::
+ operator=(const DList &other)
+{
+ /* Free the old list. The value list assumes items were allocated on the
+ * heap by itself. */
+ empty();
+
+ Element *el = other.head;
+ while( el != 0 ) {
+ append( new Element(*el) );
+ el = el->BASE_EL(next);
+ }
+ return *this;
+}
+
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ transfer(DList &other)
+{
+ /* Free the old list. The value list assumes items were allocated on the
+ * heap by itself. */
+ empty();
+
+ head = other.head;
+ tail = other.tail;
+ listLen = other.listLen;
+
+ other.abandon();
+}
+
+#else
+
+/* Assignement operator does deep copy. */
+template <DLMEL_TEMPDEF> DList<DLMEL_TEMPUSE> &DList<DLMEL_TEMPUSE>::
+ operator=(const DList &other)
+{
+ Element *el = other.head;
+ while( el != 0 ) {
+ append( new Element(*el) );
+ el = el->BASE_EL(next);
+ }
+ return *this;
+}
+
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ transfer(DList &other)
+{
+ head = other.head;
+ tail = other.tail;
+ listLen = other.listLen;
+
+ other.abandon();
+}
+
+#endif
+
+#ifdef DOUBLELIST_VALUE
+
+/* Prepend a new item. Inlining this bloats the caller with new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ prepend(const T &item)
+{
+ addBefore(head, new Element(item));
+}
+
+/* Append a new item. Inlining this bloats the caller with the new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ append(const T &item)
+{
+ addAfter(tail, new Element(item));
+}
+
+/* Add a new item after a prev element. Inlining this bloats the caller with
+ * the new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addAfter(Element *prev_el, const T &item)
+{
+ addAfter(prev_el, new Element(item));
+}
+
+/* Add a new item before a next element. Inlining this bloats the caller with
+ * the new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addBefore(Element *next_el, const T &item)
+{
+ addBefore(next_el, new Element(item));
+}
+
+#endif
+
+/*
+ * The larger iterator operators.
+ */
+
+/* Postfix ++ */
+template <DLMEL_TEMPDEF> Element *DList<DLMEL_TEMPUSE>::Iter::
+ operator++(int)
+{
+ Element *rtn = ptr;
+ ptr = ptr->BASE_EL(next);
+ return rtn;
+}
+
+/* Postfix -- */
+template <DLMEL_TEMPDEF> Element *DList<DLMEL_TEMPUSE>::Iter::
+ operator--(int)
+{
+ Element *rtn = ptr;
+ ptr = ptr->BASE_EL(prev);
+ return rtn;
+}
+
+/**
+ * \brief Insert an element immediately after an element in the list.
+ *
+ * If prev_el is NULL then new_el is prepended to the front of the list. If
+ * prev_el is not in the list or if new_el is already in a list, then
+ * undefined behaviour results.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addAfter(Element *prev_el, Element *new_el)
+{
+ /* Set the previous pointer of new_el to prev_el. We do
+ * this regardless of the state of the list. */
+ new_el->BASE_EL(prev) = prev_el;
+
+ /* Set forward pointers. */
+ if (prev_el == 0) {
+ /* There was no prev_el, we are inserting at the head. */
+ new_el->BASE_EL(next) = head;
+ head = new_el;
+ }
+ else {
+ /* There was a prev_el, we can access previous next. */
+ new_el->BASE_EL(next) = prev_el->BASE_EL(next);
+ prev_el->BASE_EL(next) = new_el;
+ }
+
+ /* Set reverse pointers. */
+ if (new_el->BASE_EL(next) == 0) {
+ /* There is no next element. Set the tail pointer. */
+ tail = new_el;
+ }
+ else {
+ /* There is a next element. Set it's prev pointer. */
+ new_el->BASE_EL(next)->BASE_EL(prev) = new_el;
+ }
+
+ /* Update list length. */
+ listLen++;
+}
+
+/**
+ * \brief Insert an element immediatly before an element in the list.
+ *
+ * If next_el is NULL then new_el is appended to the end of the list. If
+ * next_el is not in the list or if new_el is already in a list, then
+ * undefined behaviour results.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addBefore(Element *next_el, Element *new_el)
+{
+ /* Set the next pointer of the new element to next_el. We do
+ * this regardless of the state of the list. */
+ new_el->BASE_EL(next) = next_el;
+
+ /* Set reverse pointers. */
+ if (next_el == 0) {
+ /* There is no next elememnt. We are inserting at the tail. */
+ new_el->BASE_EL(prev) = tail;
+ tail = new_el;
+ }
+ else {
+ /* There is a next element and we can access next's previous. */
+ new_el->BASE_EL(prev) = next_el->BASE_EL(prev);
+ next_el->BASE_EL(prev) = new_el;
+ }
+
+ /* Set forward pointers. */
+ if (new_el->BASE_EL(prev) == 0) {
+ /* There is no previous element. Set the head pointer.*/
+ head = new_el;
+ }
+ else {
+ /* There is a previous element, set it's next pointer to new_el. */
+ new_el->BASE_EL(prev)->BASE_EL(next) = new_el;
+ }
+
+ /* Update list length. */
+ listLen++;
+}
+
+/**
+ * \brief Insert an entire list immediatly after an element in this list.
+ *
+ * Elements are moved, not copied. Afterwards, the other list is empty. If
+ * prev_el is NULL then the elements are prepended to the front of the list.
+ * If prev_el is not in the list then undefined behaviour results. All
+ * elements are inserted into the list at once, so this is an O(1) operation.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addAfter( Element *prev_el, DList<DLMEL_TEMPUSE> &dl )
+{
+ /* Do not bother if dl has no elements. */
+ if ( dl.listLen == 0 )
+ return;
+
+ /* Set the previous pointer of dl.head to prev_el. We do
+ * this regardless of the state of the list. */
+ dl.head->BASE_EL(prev) = prev_el;
+
+ /* Set forward pointers. */
+ if (prev_el == 0) {
+ /* There was no prev_el, we are inserting at the head. */
+ dl.tail->BASE_EL(next) = head;
+ head = dl.head;
+ }
+ else {
+ /* There was a prev_el, we can access previous next. */
+ dl.tail->BASE_EL(next) = prev_el->BASE_EL(next);
+ prev_el->BASE_EL(next) = dl.head;
+ }
+
+ /* Set reverse pointers. */
+ if (dl.tail->BASE_EL(next) == 0) {
+ /* There is no next element. Set the tail pointer. */
+ tail = dl.tail;
+ }
+ else {
+ /* There is a next element. Set it's prev pointer. */
+ dl.tail->BASE_EL(next)->BASE_EL(prev) = dl.tail;
+ }
+
+ /* Update the list length. */
+ listLen += dl.listLen;
+
+ /* Empty out dl. */
+ dl.head = dl.tail = 0;
+ dl.listLen = 0;
+}
+
+/**
+ * \brief Insert an entire list immediately before an element in this list.
+ *
+ * Elements are moved, not copied. Afterwards, the other list is empty. If
+ * next_el is NULL then the elements are appended to the end of the list. If
+ * next_el is not in the list then undefined behaviour results. All elements
+ * are inserted at once, so this is an O(1) operation.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addBefore( Element *next_el, DList<DLMEL_TEMPUSE> &dl )
+{
+ /* Do not bother if dl has no elements. */
+ if ( dl.listLen == 0 )
+ return;
+
+ /* Set the next pointer of dl.tail to next_el. We do
+ * this regardless of the state of the list. */
+ dl.tail->BASE_EL(next) = next_el;
+
+ /* Set reverse pointers. */
+ if (next_el == 0) {
+ /* There is no next elememnt. We are inserting at the tail. */
+ dl.head->BASE_EL(prev) = tail;
+ tail = dl.tail;
+ }
+ else {
+ /* There is a next element and we can access next's previous. */
+ dl.head->BASE_EL(prev) = next_el->BASE_EL(prev);
+ next_el->BASE_EL(prev) = dl.tail;
+ }
+
+ /* Set forward pointers. */
+ if (dl.head->BASE_EL(prev) == 0) {
+ /* There is no previous element. Set the head pointer.*/
+ head = dl.head;
+ }
+ else {
+ /* There is a previous element, set it's next pointer to new_el. */
+ dl.head->BASE_EL(prev)->BASE_EL(next) = dl.head;
+ }
+
+ /* Update list length. */
+ listLen += dl.listLen;
+
+ /* Empty out dl. */
+ dl.head = dl.tail = 0;
+ dl.listLen = 0;
+}
+
+
+/**
+ * \brief Detach an element from the list.
+ *
+ * The element is not deleted. If the element is not in the list, then
+ * undefined behaviour results.
+ *
+ * \returns The element detached.
+ */
+template <DLMEL_TEMPDEF> Element *DList<DLMEL_TEMPUSE>::
+ detach(Element *el)
+{
+ /* Set forward pointers to skip over el. */
+ if (el->BASE_EL(prev) == 0)
+ head = el->BASE_EL(next);
+ else {
+ el->BASE_EL(prev)->BASE_EL(next) =
+ el->BASE_EL(next);
+ }
+
+ /* Set reverse pointers to skip over el. */
+ if (el->BASE_EL(next) == 0)
+ tail = el->BASE_EL(prev);
+ else {
+ el->BASE_EL(next)->BASE_EL(prev) =
+ el->BASE_EL(prev);
+ }
+
+ /* Update List length and return element we detached. */
+ listLen--;
+ return el;
+}
+
+/**
+ * \brief Clear the list by deleting all elements.
+ *
+ * Each item in the list is deleted. The list is reset to its initial state.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::empty()
+{
+ Element *nextToGo = 0, *cur = head;
+
+ while (cur != 0)
+ {
+ nextToGo = cur->BASE_EL(next);
+ delete cur;
+ cur = nextToGo;
+ }
+ head = tail = 0;
+ listLen = 0;
+}
+
+/**
+ * \brief Clear the list by forgetting all elements.
+ *
+ * All elements are abandoned, not deleted. The list is reset to it's initial
+ * state.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::abandon()
+{
+ head = tail = 0;
+ listLen = 0;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
diff --git a/aapl/dlist.h b/aapl/dlist.h
new file mode 100644
index 00000000..e34c8da4
--- /dev/null
+++ b/aapl/dlist.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_DLIST_H
+#define _AAPL_DLIST_H
+
+#define BASE_EL(name) name
+#define DLMEL_TEMPDEF class Element
+#define DLMEL_TEMPUSE Element
+#define DList DList
+
+/**
+ * \addtogroup dlist
+ * @{
+ */
+
+/**
+ * \class DList
+ * \brief Basic doubly linked list.
+ *
+ * DList is the standard by-structure list type. This class requires the
+ * programmer to declare a list element type that has the necessary next and
+ * previous pointers in it. This can be achieved by inheriting from the
+ * DListEl class or by simply adding next and previous pointers directly into
+ * the list element class.
+ *
+ * DList does not assume ownership of elements in the list. If the elements
+ * are known to reside on the heap, the provided empty() routine can be used to
+ * delete all elements, however the destructor will not call this routine, it
+ * will simply abandon all the elements. It is up to the programmer to
+ * explicitly de-allocate items when necessary.
+ *
+ * \include ex_dlist.cpp
+ */
+
+/*@}*/
+
+#include "dlcommon.h"
+
+#undef BASE_EL
+#undef DLMEL_TEMPDEF
+#undef DLMEL_TEMPUSE
+#undef DList
+
+#endif /* _AAPL_DLIST_H */
+
diff --git a/aapl/dlistmel.h b/aapl/dlistmel.h
new file mode 100644
index 00000000..17de5432
--- /dev/null
+++ b/aapl/dlistmel.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_DLISTMEL_H
+#define _AAPL_DLISTMEL_H
+
+/**
+ * \addtogroup dlist
+ * @{
+ */
+
+/**
+ * \class DListMel
+ * \brief Doubly linked list for elements that may appear in multiple lists.
+ *
+ * This class is similar to DList, except that the user defined list element
+ * can inherit from multple DListEl classes and consequently be an element in
+ * multiple lists. In other words, DListMel allows a single instance of a data
+ * structure to be an element in multiple lists without the lists interfereing
+ * with one another.
+ *
+ * For each list that an element class is to appear in, the element must have
+ * unique next and previous pointers that can be unambiguously refered to with
+ * some base class name. This name is given to DListMel as a template argument
+ * so it can use the correct next and previous pointers in its list
+ * operations.
+ *
+ * DListMel does not assume ownership of elements in the list. If the elements
+ * are known to reside on the heap and are not contained in any other list or
+ * data structure, the provided empty() routine can be used to delete all
+ * elements, however the destructor will not call this routine, it will simply
+ * abandon all the elements. It is up to the programmer to explicitly
+ * de-allocate items when it is safe to do so.
+ *
+ * \include ex_dlistmel.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define DLMEL_TEMPDEF class Element, class BaseEl
+#define DLMEL_TEMPUSE Element, BaseEl
+#define DList DListMel
+
+#include "dlcommon.h"
+
+#undef BASE_EL
+#undef DLMEL_TEMPDEF
+#undef DLMEL_TEMPUSE
+#undef DList
+
+#endif /* _AAPL_DLISTMEL_H */
+
diff --git a/aapl/dlistval.h b/aapl/dlistval.h
new file mode 100644
index 00000000..4fcf33fa
--- /dev/null
+++ b/aapl/dlistval.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_DLISTVAL_H
+#define _AAPL_DLISTVAL_H
+
+/**
+ * \addtogroup dlist
+ * @{
+ */
+
+/**
+ * \class DListVal
+ * \brief By-value doubly linked list.
+ *
+ * This class is a doubly linked list that does not require a list element
+ * type to be declared. The user instead gives a type that is to be stored in
+ * the list element. When inserting a new data item, the value is copied into
+ * a newly allocated element. This list is inteded to behave and be utilized
+ * like the list template found in the STL.
+ *
+ * DListVal is different from the other lists in that it allocates elements
+ * itself. The raw element insert interface is still exposed for convenience,
+ * however, the list assumes all elements in the list are allocated on the
+ * heap and are to be managed by the list. The destructor WILL delete the
+ * contents of the list. If the list is ever copied in from another list, the
+ * existing contents are deleted first. This is in contrast to DList and
+ * DListMel, which will never delete their contents to allow for statically
+ * allocated elements.
+ *
+ * \include ex_dlistval.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define DLMEL_TEMPDEF class T
+#define DLMEL_TEMPUSE T
+#define DList DListVal
+#define Element DListValEl<T>
+#define DOUBLELIST_VALUE
+
+#include "dlcommon.h"
+
+#undef BASE_EL
+#undef DLMEL_TEMPDEF
+#undef DLMEL_TEMPUSE
+#undef DList
+#undef Element
+#undef DOUBLELIST_VALUE
+
+#endif /* _AAPL_DLISTVAL_H */
+
diff --git a/aapl/insertsort.h b/aapl/insertsort.h
new file mode 100644
index 00000000..94aef7b2
--- /dev/null
+++ b/aapl/insertsort.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_INSERTSORT_H
+#define _AAPL_INSERTSORT_H
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class InsertSort
+ * \brief Insertion sort an array of data.
+ *
+ * InsertSort can be used to sort any array of objects of type T provided a
+ * compare class is given. InsertSort is in-place. It does not require any
+ * temporary storage.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * InsertSort runs in O(n^2) time. It is most useful when sorting small arrays.
+ * where it can outperform the O(n*log(n)) sorters due to its simplicity.
+ * InsertSort is a not a stable sort. Elements with the same key will not have
+ * their relative ordering preserved.
+ */
+
+/*@}*/
+
+/* InsertSort. */
+template <class T, class Compare> class InsertSort
+ : public Compare
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+};
+
+
+/**
+ * \brief Insertion sort an array of data.
+ */
+template <class T, class Compare>
+ void InsertSort<T,Compare>::sort(T *data, long len)
+{
+ /* For each next largest spot in the sorted array... */
+ for ( T *dest = data; dest < data+len-1; dest++ ) {
+ /* Find the next smallest element in the unsorted array. */
+ T *smallest = dest;
+ for ( T *src = dest+1; src < data+len; src++ ) {
+ /* If src is smaller than the current src, then use it. */
+ if ( compare( *src, *smallest ) < 0 )
+ smallest = src;
+ }
+
+ if ( smallest != dest ) {
+ /* Swap dest, smallest. */
+ char tmp[sizeof(T)];
+ memcpy( tmp, dest, sizeof(T) );
+ memcpy( dest, smallest, sizeof(T) );
+ memcpy( smallest, tmp, sizeof(T) );
+ }
+ }
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_INSERTSORT_H */
diff --git a/aapl/mergesort.h b/aapl/mergesort.h
new file mode 100644
index 00000000..68b84260
--- /dev/null
+++ b/aapl/mergesort.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2001, 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_MERGESORT_H
+#define _AAPL_MERGESORT_H
+
+#include "bubblesort.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class MergeSort
+ * \brief Merge sort an array of data.
+ *
+ * MergeSort can be used to sort any array of objects of type T provided a
+ * compare class is given. MergeSort is not in-place, it requires temporary
+ * storage equal to the size of the array. The temporary storage is allocated
+ * on the heap.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * MergeSort runs in worst case O(n*log(n)) time. In most cases it is slower
+ * than QuickSort because more copying is neccessary. But on the other hand,
+ * it is a stable sort, meaning that objects with the same key have their
+ * relative ordering preserved. Also, its worst case is better. MergeSort
+ * switches to a BubbleSort when the size of the array being sorted is small.
+ * This happens when directly sorting a small array or when MergeSort calls
+ * itself recursively on a small portion of a larger array.
+ */
+
+/*@}*/
+
+
+/* MergeSort. */
+template <class T, class Compare> class MergeSort
+ : public BubbleSort<T, Compare>
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+
+private:
+ /* Recursive worker. */
+ void doSort(T *tmpStor, T *data, long len);
+};
+
+#define _MS_BUBBLE_THRESH 16
+
+/* Recursive mergesort worker. Split data, make recursive calls, merge
+ * results. */
+template< class T, class Compare> void MergeSort<T,Compare>::
+ doSort(T *tmpStor, T *data, long len)
+{
+ if ( len <= 1 )
+ return;
+
+ if ( len <= _MS_BUBBLE_THRESH ) {
+ BubbleSort<T, Compare>::sort( data, len );
+ return;
+ }
+
+ long mid = len / 2;
+
+ doSort( tmpStor, data, mid );
+ doSort( tmpStor + mid, data + mid, len - mid );
+
+ /* Merge the data. */
+ T *endLower = data + mid, *lower = data;
+ T *endUpper = data + len, *upper = data + mid;
+ T *dest = tmpStor;
+ while ( true ) {
+ if ( lower == endLower ) {
+ /* Possibly upper left. */
+ if ( upper != endUpper )
+ memcpy( dest, upper, (endUpper - upper) * sizeof(T) );
+ break;
+ }
+ else if ( upper == endUpper ) {
+ /* Only lower left. */
+ if ( lower != endLower )
+ memcpy( dest, lower, (endLower - lower) * sizeof(T) );
+ break;
+ }
+ else {
+ /* Both upper and lower left. */
+ if ( compare(*lower, *upper) <= 0 )
+ memcpy( dest++, lower++, sizeof(T) );
+ else
+ memcpy( dest++, upper++, sizeof(T) );
+ }
+ }
+
+ /* Copy back from the tmpStor array. */
+ memcpy( data, tmpStor, sizeof( T ) * len );
+}
+
+/**
+ * \brief Merge sort an array of data.
+ */
+template< class T, class Compare>
+ void MergeSort<T,Compare>::sort(T *data, long len)
+{
+ /* Allocate the tmp space needed by merge sort, sort and free. */
+ T *tmpStor = (T*) new char[sizeof(T) * len];
+ doSort( tmpStor, data, len );
+ delete[] (char*) tmpStor;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_MERGESORT_H */
diff --git a/aapl/quicksort.h b/aapl/quicksort.h
new file mode 100644
index 00000000..bb6941ef
--- /dev/null
+++ b/aapl/quicksort.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_QUICKSORT_H
+#define _AAPL_QUICKSORT_H
+
+#include "insertsort.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class QuickSort
+ * \brief Quick sort an array of data.
+ *
+ * QuickSort can be used to sort any array of objects of type T provided a
+ * compare class is given. QuickSort is in-place. It does not require any
+ * temporary storage.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * QuickSort runs in O(n*log(n)) time in the average case. It is faster than
+ * mergsort in the average case because it does less moving of data. The
+ * performance of quicksort depends mostly on the choice of pivot. This
+ * implementation picks the pivot as the median of first, middle, last. This
+ * choice of pivot avoids the O(n^2) worst case for input already sorted, but
+ * it is still possible to encounter the O(n^2) worst case. For example an
+ * array of identical elements will run in O(n^2)
+ *
+ * QuickSort is not a stable sort. Elements with the same key will not have
+ * their relative ordering preserved. QuickSort switches to an InsertSort
+ * when the size of the array being sorted is small. This happens when
+ * directly sorting a small array or when QuickSort calls iteself recursively
+ * on a small portion of a larger array.
+ */
+
+/*@}*/
+
+/* QuickSort. */
+template <class T, class Compare> class QuickSort :
+ public InsertSort<T, Compare>
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+
+private:
+ /* Recursive worker. */
+ void doSort(T *start, T *end);
+ T *partition(T *start, T *end);
+ inline T *median(T *start, T *end);
+};
+
+#define _QS_INSERTION_THRESH 16
+
+/* Finds the median of start, middle, end. */
+template <class T, class Compare> T *QuickSort<T,Compare>::
+ median(T *start, T *end)
+{
+ T *pivot, *mid = start + (end-start)/2;
+
+ /* CChoose the pivot. */
+ if ( compare(*start, *mid) < 0 ) {
+ if ( compare(*mid, *end) < 0 )
+ pivot = mid;
+ else if ( compare(*start, *end) < 0 )
+ pivot = end;
+ else
+ pivot = start;
+ }
+ else if ( compare(*start, *end) < 0 )
+ pivot = start;
+ else if ( compare(*mid, *end) < 0 )
+ pivot = end;
+ else
+ pivot = mid;
+
+ return pivot;
+}
+
+template <class T, class Compare> T *QuickSort<T,Compare>::
+ partition(T *start, T *end)
+{
+ /* Use the median of start, middle, end as the pivot. First save
+ * it off then move the last element to the free spot. */
+ char pcPivot[sizeof(T)];
+ T *pivot = median(start, end);
+
+ memcpy( pcPivot, pivot, sizeof(T) );
+ if ( pivot != end )
+ memcpy( pivot, end, sizeof(T) );
+
+ T *first = start-1;
+ T *last = end;
+ pivot = (T*) pcPivot;
+
+ /* Shuffle element to the correct side of the pivot, ending
+ * up with the free spot where the pivot will go. */
+ while ( true ) {
+ /* Throw one element ahead to the free spot at last. */
+ while ( true ) {
+ first += 1;
+ if ( first == last )
+ goto done;
+ if ( compare( *first, *pivot ) > 0 ) {
+ memcpy(last, first, sizeof(T));
+ break;
+ }
+ }
+
+ /* Throw one element back to the free spot at first. */
+ while ( true ) {
+ last -= 1;
+ if ( last == first )
+ goto done;
+ if ( compare( *last, *pivot ) < 0 ) {
+ memcpy(first, last, sizeof(T));
+ break;
+ }
+ }
+ }
+done:
+ /* Put the pivot into the middle spot for it. */
+ memcpy( first, pivot, sizeof(T) );
+ return first;
+}
+
+
+template< class T, class Compare> void QuickSort<T,Compare>::
+ doSort(T *start, T *end)
+{
+ long len = end - start + 1;
+ if ( len > _QS_INSERTION_THRESH ) {
+ /* Use quicksort. */
+ T *pivot = partition( start, end );
+ doSort(start, pivot-1);
+ doSort(pivot+1, end);
+ }
+ else if ( len > 1 ) {
+ /* Array is small, use insertion sort. */
+ InsertSort<T, Compare>::sort( start, len );
+ }
+}
+
+/**
+ * \brief Quick sort an array of data.
+ */
+template< class T, class Compare>
+ void QuickSort<T,Compare>::sort(T *data, long len)
+{
+ /* Call recursive worker. */
+ doSort(data, data+len-1);
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_QUICKSORT_H */
diff --git a/aapl/resize.h b/aapl/resize.h
new file mode 100644
index 00000000..9e8491aa
--- /dev/null
+++ b/aapl/resize.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_RESIZE_H
+#define _AAPL_RESIZE_H
+
+#include <assert.h>
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/* This step is expressed in units of T. Changing this requires changes to
+ * docs in ResizeLin constructor. */
+#define LIN_DEFAULT_STEP 256
+
+/*
+ * Resizing macros giving different resize methods.
+ */
+
+/* If needed is greater than existing, give twice needed. */
+#define EXPN_UP( existing, needed ) \
+ needed > existing ? (needed<<1) : existing
+
+/* If needed is less than 1 quarter existing, give twice needed. */
+#define EXPN_DOWN( existing, needed ) \
+ needed < (existing>>2) ? (needed<<1) : existing
+
+/* If needed is greater than existing, give needed plus step. */
+#define LIN_UP( existing, needed ) \
+ needed > existing ? (needed+step) : existing
+
+/* If needed is less than existing - 2 * step then give needed plus step. */
+#define LIN_DOWN( existing, needed ) \
+ needed < (existing-(step<<1)) ? (needed+step) : existing
+
+/* Return existing. */
+#define CONST_UP( existing, needed ) existing
+
+/* Return existing. */
+#define CONST_DOWN( existing, needed ) existing
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeLin
+ * \brief Linear table resizer.
+ *
+ * When an up resize or a down resize is needed, ResizeLin allocates the space
+ * needed plus some user defined step. The result is that when growing the
+ * vector in a linear fashion, the number of resizes is also linear.
+ *
+ * If only up resizing is done, then there will never be more than step unused
+ * spaces in the vector. If down resizing is done as well, there will never be
+ * more than 2*step unused spaces in the vector. The up resizing and down
+ * resizing policies are offset to improve performance when repeatedly
+ * inserting and removing a small number of elements relative to the step.
+ * This scheme guarantees that repetitive inserting and removing of a small
+ * number of elements will never result in repetative reallocation.
+ *
+ * The vectors pass sizes to the resizer in units of T, so the step gets
+ * interpreted as units of T.
+ */
+
+/*@}*/
+
+/* Linear resizing. */
+class ResizeLin
+{
+protected:
+ /**
+ * \brief Default constructor.
+ *
+ * Intializes resize step to 256 units of the table type T.
+ */
+ ResizeLin() : step(LIN_DEFAULT_STEP) { }
+
+ /**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed, then allocate
+ * the space needed plus the step. The step is in units of T.
+ */
+ inline long upResize( long existing, long needed )
+ { return LIN_UP(existing, needed); }
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * If space needed is less than the existing - 2*step, then allocate the
+ * space needed space plus the step. The step is in units of T.
+ */
+ inline long downResize( long existing, long needed )
+ { return LIN_DOWN(existing, needed); }
+
+public:
+ /**
+ * \brief Step for linear resize.
+ *
+ * Amount of extra space in units of T added each time a resize must take
+ * place. This may be changed at any time. The step should be >= 0.
+ */
+ long step;
+};
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeCtLin
+ * \brief Linear table resizer with compile time step.
+ *
+ * When an up resize or a down resize is needed, ResizeCtLin allocates the
+ * space needed plus some compile time defined step. The result is that when
+ * growing the vector in a linear fashion, the number of resizes is also
+ * linear.
+ *
+ * If only up resizing is done, then there will never be more than step unused
+ * spaces in the vector. If down resizing is done as well, there will never be
+ * more than 2*step unused spaces in the vector. The up resizing and down
+ * resizing policies are offset to improve performance when repeatedly
+ * inserting and removing a small number of elements relative to the step.
+ * This scheme guarantees that repetitive inserting and removing of a small
+ * number of elements will never result in repetative reallocation.
+ *
+ * The vectors pass sizes to the resizer in units of T, so the step gets
+ * interpreted as units of T.
+ */
+
+/*@}*/
+
+/* Linear resizing. */
+template <long step> class ResizeCtLin
+{
+protected:
+ /**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed, then allocate
+ * the space needed plus the step. The step is in units of T.
+ */
+ inline long upResize( long existing, long needed )
+ { return LIN_UP(existing, needed); }
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * If space needed is less than the existing - 2*step, then allocate the
+ * space needed space plus the step. The step is in units of T.
+ */
+ inline long downResize( long existing, long needed )
+ { return LIN_DOWN(existing, needed); }
+};
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeConst
+ * \brief Constant table resizer.
+ *
+ * When an up resize is needed the existing size is always used. ResizeConst
+ * does not allow dynamic resizing. To use ResizeConst, the vector needs to be
+ * constructed with and initial allocation amount otherwise it will be
+ * unusable.
+ */
+
+/*@}*/
+
+/* Constant table resizing. */
+class ResizeConst
+{
+protected:
+ /* Assert don't need more than exists. Return existing. */
+ static inline long upResize( long existing, long needed );
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * Always returns the existing table size.
+ */
+ static inline long downResize( long existing, long needed )
+ { return CONST_DOWN(existing, needed); }
+};
+
+/**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed, then an assertion
+ * will fail. Otherwise returns the existing size.
+ */
+inline long ResizeConst::upResize( long existing, long needed )
+{
+ assert( needed <= existing );
+ return CONST_UP(existing, needed);
+}
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeRunTime
+ * \brief Run time settable table resizer.
+ *
+ * ResizeRunTime can have it's up and down resizing policies set at run time.
+ * Both up and down policies can be set independently to one of Exponential,
+ * Linear, or Constant. See the documentation for ResizeExpn, ResizeLin, and
+ * ResizeConst for the details of the resizing policies.
+ *
+ * The policies may be changed at any time. The default policies are
+ * both Exponential.
+ */
+
+/*@}*/
+
+/* Run time resizing. */
+class ResizeRunTime
+{
+protected:
+ /**
+ * \brief Default constuctor.
+ *
+ * The up and down resizing it initialized to Exponetial. The step
+ * defaults to 256 units of T.
+ */
+ inline ResizeRunTime();
+
+ /**
+ * \brief Resizing policies.
+ */
+ enum ResizeType {
+ Exponential, /*!< Exponential resizing. */
+ Linear, /*!< Linear resizing. */
+ Constant /*!< Constant table size. */
+ };
+
+ inline long upResize( long existing, long needed );
+ inline long downResize( long existing, long needed );
+
+public:
+ /**
+ * \brief Step for linear resize.
+ *
+ * Amount of extra space in units of T added each time a resize must take
+ * place. This may be changed at any time. The step should be >= 0.
+ */
+ long step;
+
+ /**
+ * \brief Up resizing policy.
+ */
+ ResizeType upResizeType;
+
+ /**
+ * \brief Down resizing policy.
+ */
+ ResizeType downResizeType;
+};
+
+inline ResizeRunTime::ResizeRunTime()
+:
+ step( LIN_DEFAULT_STEP ),
+ upResizeType( Exponential ),
+ downResizeType( Exponential )
+{
+}
+
+/**
+ * \brief Determine the new table size when up resizing.
+ *
+ * Type of up resizing is determined by upResizeType. Exponential, Linear and
+ * Constant resizing is the same as that of ResizeExpn, ResizeLin and
+ * ResizeConst.
+ */
+inline long ResizeRunTime::upResize( long existing, long needed )
+{
+ switch ( upResizeType ) {
+ case Exponential:
+ return EXPN_UP(existing, needed);
+ case Linear:
+ return LIN_UP(existing, needed);
+ case Constant:
+ assert( needed <= existing );
+ return CONST_UP(existing, needed);
+ }
+ return 0;
+};
+
+/**
+ * \brief Determine the new table size when down resizing.
+ *
+ * Type of down resizing is determined by downResiizeType. Exponential, Linear
+ * and Constant resizing is the same as that of ResizeExpn, ResizeLin and
+ * ResizeConst.
+ */
+inline long ResizeRunTime::downResize( long existing, long needed )
+{
+ switch ( downResizeType ) {
+ case Exponential:
+ return EXPN_DOWN(existing, needed);
+ case Linear:
+ return LIN_DOWN(existing, needed);
+ case Constant:
+ return CONST_DOWN(existing, needed);
+ }
+ return 0;
+}
+
+/* Don't need these anymore. */
+#undef EXPN_UP
+#undef EXPN_DOWN
+#undef LIN_UP
+#undef LIN_DOWN
+#undef CONST_UP
+#undef CONST_DOWN
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_RESIZE_H */
diff --git a/aapl/sbstmap.h b/aapl/sbstmap.h
new file mode 100644
index 00000000..e3975a1c
--- /dev/null
+++ b/aapl/sbstmap.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_SBSTMAP_H
+#define _AAPL_SBSTMAP_H
+
+#include "compare.h"
+#include "svector.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \brief Element for BstMap.
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct SBstMapEl
+{
+ SBstMapEl() {}
+ SBstMapEl(const Key &key) : key(key) {}
+ SBstMapEl(const Key &key, const Value &val) : key(key), value(val) {}
+
+ /** \brief The key */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class SBstMap
+ * \brief Copy-on-write binary search table for key and value pairs.
+ *
+ * This is a map style binary search table that employs the copy-on-write
+ * mechanism for table data. BstMap stores key and value pairs in each
+ * element. The key and value can be any type. A compare class for the key
+ * must be supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Key, class Value, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Value, class Compare, class Resize
+#define BST_TEMPL_USE Key, Value, Compare, Resize
+#define GET_KEY(el) ((el).key)
+#define BstTable SBstMap
+#define Vector SVector
+#define Table STable
+#define Element SBstMapEl<Key, Value>
+#define BSTMAP
+#define SHARED_BST
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Vector
+#undef Table
+#undef Element
+#undef BSTMAP
+#undef SHARED_BST
+
+/**
+ * \fn SBstMap::insert(const Key &key, BstMapEl<Key, Value> **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then a new element
+ * having key is inserted. They key copy constructor and value default
+ * constructor are used to place the pair in the table. If lastFound is given,
+ * it is set to the new entry created. If the insert fails then lastFound is
+ * set to the existing pair of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn SBstMap::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then the new element having key is placed next
+ * to some other pair of the same key. InsertMulti cannot fail. The key copy
+ * constructor and the value default constructor are used to place the pair in
+ * the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_SBSTMAP_H */
diff --git a/aapl/sbstset.h b/aapl/sbstset.h
new file mode 100644
index 00000000..3487ee75
--- /dev/null
+++ b/aapl/sbstset.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_SBSTSET_H
+#define _AAPL_SBSTSET_H
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class SBstSet
+ * \brief Copy-on-write binary search table for types that are the key.
+ *
+ * This is a set style binary search table that employs the copy-on-write
+ * mechanism for storing table data. BstSet is suitable for types that
+ * comprise the entire key. Rather than look into the element to retrieve the
+ * key, the element is the key. A class that contains a comparison routine
+ * for the key must be given.
+ */
+
+/*@}*/
+
+#include "compare.h"
+#include "svector.h"
+
+#define BST_TEMPL_DECLARE class Key, class Compare = CmpOrd<Key>, \
+ class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Compare, class Resize
+#define BST_TEMPL_USE Key, Compare, Resize
+#define GET_KEY(el) (el)
+#define BstTable SBstSet
+#define Vector SVector
+#define Table STable
+#define Element Key
+#define BSTSET
+#define SHARED_BST
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Vector
+#undef Table
+#undef Element
+#undef BSTSET
+#undef SHARED_BST
+
+/**
+ * \fn SBstSet::insert(const Key &key, Key **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then it is inserted.
+ * The key's copy constructor is used to place the item in the table. If
+ * lastFound is given, it is set to the new entry created. If the insert fails
+ * then lastFound is set to the existing key of the same value.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn SBstSet::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then it is placed next to some other key of the
+ * same value. InsertMulti cannot fail. The key's copy constructor is used to
+ * place the item in the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_SBSTSET_H */
diff --git a/aapl/sbsttable.h b/aapl/sbsttable.h
new file mode 100644
index 00000000..348f1fd0
--- /dev/null
+++ b/aapl/sbsttable.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_SBSTTABLE_H
+#define _AAPL_SBSTTABLE_H
+
+#include "compare.h"
+#include "svector.h"
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class SBstTable
+ * \brief Copy-on-write binary search table for structures that contain a key.
+ *
+ * This is a basic binary search table that employs a copy-on-write data
+ * storage mechanism. It can be used to contain a structure that has a key and
+ * possibly some data. The key should be a member of the element class and
+ * accessible with getKey(). A class containing the compare routine must be
+ * supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Element, class Key, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Element, class Key, class Compare, class Resize
+#define BST_TEMPL_USE Element, Key, Compare, Resize
+#define GET_KEY(el) ((el).getKey())
+#define BstTable SBstTable
+#define Vector SVector
+#define Table STable
+#define BSTTABLE
+#define SHARED_BST
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Vector
+#undef Table
+#undef BSTTABLE
+#undef SHARED_BST
+
+/**
+ * \fn SBstTable::insert(const Key &key, Element **lastFound)
+ * \brief Insert a new element with the given key.
+ *
+ * If the given key does not already exist in the table a new element is
+ * inserted with the given key. A constructor taking only const Key& is used
+ * to initialize the new element. If lastFound is given, it is set to the new
+ * element created. If the insert fails then lastFound is set to the existing
+ * element with the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn SBstTable::insertMulti(const Key &key)
+ * \brief Insert a new element even if the key exists already.
+ *
+ * If the key exists already then the new element is placed next to some
+ * element with the same key. InsertMulti cannot fail. A constructor taking
+ * only const Key& is used to initialize the new element.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_SBSTTABLE_H */
diff --git a/aapl/svector.h b/aapl/svector.h
new file mode 100644
index 00000000..7dcae62c
--- /dev/null
+++ b/aapl/svector.h
@@ -0,0 +1,1350 @@
+/*
+ * Copyright 2002, 2006 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_SVECTOR_H
+#define _AAPL_SVECTOR_H
+
+#include <new>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "table.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class SVector
+ * \brief Copy-on-write dynamic array.
+ *
+ * SVector is a variant of Vector that employs copy-on-write behaviour. The
+ * SVector copy constructor and = operator make shallow copies. If a vector
+ * that references shared data is modified with insert, replace, append,
+ * prepend, setAs or remove, a new copy is made so as not to interfere with
+ * the shared data. However, shared individual elements may be modified by
+ * bypassing the SVector interface.
+ *
+ * SVector is a dynamic array that can be used to contain complex data
+ * structures that have constructors and destructors as well as simple types
+ * such as integers and pointers.
+ *
+ * SVector supports inserting, overwriting, and removing single or multiple
+ * elements at once. Constructors and destructors are called wherever
+ * appropriate. For example, before an element is overwritten, it's
+ * destructor is called.
+ *
+ * SVector provides automatic resizing of allocated memory as needed and
+ * offers different allocation schemes for controlling how the automatic
+ * allocation is done. Two senses of the the length of the data is
+ * maintained: the amount of raw memory allocated to the vector and the number
+ * of actual elements in the vector. The various allocation schemes control
+ * how the allocated space is changed in relation to the number of elements in
+ * the vector.
+ */
+
+/*@}*/
+
+/* SVector */
+template < class T, class Resize = ResizeExpn > class SVector :
+ public STable<T>, public Resize
+{
+private:
+ typedef STable<T> BaseTable;
+
+public:
+ /**
+ * \brief Initialize an empty vector with no space allocated.
+ *
+ * If a linear resizer is used, the step defaults to 256 units of T. For a
+ * runtime vector both up and down allocation schemes default to
+ * Exponential.
+ */
+ SVector() { }
+
+ /**
+ * \brief Create a vector that contains an initial element.
+ *
+ * The vector becomes one element in length. The element's copy
+ * constructor is used to place the value in the vector.
+ */
+ SVector(const T &val) { setAs(&val, 1); }
+
+ /**
+ * \brief Create a vector that contains an array of elements.
+ *
+ * The vector becomes len elements in length. Copy constructors are used
+ * to place the new elements in the vector.
+ */
+ SVector(const T *val, long len) { setAs(val, len); }
+
+ /* Shallow copy. */
+ SVector( const SVector &v );
+
+ /**
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+ ~SVector() { empty(); }
+
+ /* Delete all items. */
+ void empty();
+
+ /**
+ * \brief Deep copy another vector into this vector.
+ *
+ * Copies the entire contents of the other vector into this vector. Any
+ * existing contents are first deleted. Equivalent to setAs.
+ */
+ void deepCopy( const SVector &v ) { setAs(v.data, v.length()); }
+
+ /* Perform a shallow copy of another vector. */
+ SVector &operator=( const SVector &v );
+
+
+ /*@{*/
+ /**
+ * \brief Insert one element at position pos.
+ *
+ * Elements in the vector from pos onward are shifted one space to the
+ * right. The copy constructor is used to place the element into this
+ * vector. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative then it is treated as an offset
+ * relative to the length of the vector.
+ */
+ void insert(long pos, const T &val) { insert(pos, &val, 1); }
+
+ /* Insert an array of values. */
+ void insert(long pos, const T *val, long len);
+
+ /**
+ * \brief Insert all the elements from another vector at position pos.
+ *
+ * Elements in this vector from pos onward are shifted v.length() spaces
+ * to the right. The element's copy constructor is used to copy the items
+ * into this vector. The other vector is left unchanged. If pos is off the
+ * end of the vector, then undefined behaviour results. If pos is negative
+ * then it is treated as an offset relative to the length of the vector.
+ * Equivalent to vector.insert(pos, other.data, other.length()).
+ */
+ void insert(long pos, const SVector &v) { insert(pos, v.data, v.length()); }
+
+ /* Insert len copies of val into the vector. */
+ void insertDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Insert one new element using the default constrcutor.
+ *
+ * Elements in the vector from pos onward are shifted one space to the right.
+ * The default constructor is used to init the new element. If pos is greater
+ * than the length of the vector then undefined behaviour results. If pos is
+ * negative then it is treated as an offset relative to the length of the
+ * vector.
+ */
+ void insertNew(long pos) { insertNew(pos, 1); }
+
+ /* Insert len new items using default constructor. */
+ void insertNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Remove one element at position pos.
+ *
+ * The element's destructor is called. Elements to the right of pos are
+ * shifted one space to the left to take up the free space. If pos is greater
+ * than or equal to the length of the vector then undefined behavior results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+ void remove(long pos) { remove(pos, 1); }
+
+ /* Delete a number of elements. */
+ void remove(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Replace one element at position pos.
+ *
+ * If there is an existing element at position pos (if pos is less than the
+ * length of the vector) then its destructor is called before the space is
+ * used. The copy constructor is used to place the element into the vector.
+ * If pos is greater than the length of the vector then undefined behaviour
+ * results. If pos is negative then it is treated as an offset relative to
+ * the length of the vector.
+ */
+ void replace(long pos, const T &val) { replace(pos, &val, 1); }
+
+ /* Replace with an array of values. */
+ void replace(long pos, const T *val, long len);
+
+ /**
+ * \brief Replace at position pos with all the elements of another vector.
+ *
+ * Replace at position pos with all the elements of another vector. The other
+ * vector is left unchanged. If there are existing elements at the positions
+ * to be replaced, then destructors are called before the space is used. Copy
+ * constructors are used to place the elements into this vector. It is
+ * allowable for the pos and length of the other vector to specify a
+ * replacement that overwrites existing elements and creates new ones. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative, then it is treated as an offset relative to the length
+ * of the vector.
+ */
+ void replace(long pos, const SVector &v) { replace(pos, v.data, v.length()); }
+
+ /* Replace len items with len copies of val. */
+ void replaceDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Replace at position pos with one new element.
+ *
+ * If there is an existing element at the position to be replaced (pos is
+ * less than the length of the vector) then the element's destructor is
+ * called before the space is used. The default constructor is used to
+ * initialize the new element. If pos is greater than the length of the
+ * vector then undefined behaviour results. If pos is negative, then it is
+ * treated as an offset relative to the length of the vector.
+ */
+ void replaceNew(long pos) { replaceNew(pos, 1); }
+
+ /* Replace len items at pos with newly constructed objects. */
+ void replaceNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+
+ /**
+ * \brief Set the contents of the vector to be val exactly.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used to
+ * place the val in the vector.
+ */
+ void setAs(const T &val) { setAs(&val, 1); }
+
+ /* Set to the contents of an array. */
+ void setAs(const T *val, long len);
+
+ /**
+ * \brief Set the vector to exactly the contents of another vector.
+ *
+ * The vector becomes v.length() elements in length. Destructors are called
+ * on any existing elements. Copy constructors are used to place the new
+ * elements in the vector.
+ */
+ void setAs(const SVector &v) { setAs(v.data, v.length()); }
+
+ /* Set as len copies of item. */
+ void setAsDup(const T &item, long len);
+
+ /**
+ * \brief Set the vector to exactly one new item.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The default constructor is used to
+ * init the new item.
+ */
+ void setAsNew() { setAsNew(1); }
+
+ /* Set as newly constructed objects using the default constructor. */
+ void setAsNew(long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Append one elment to the end of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void append(const T &val) { replace(BaseTable::length(), &val, 1); }
+
+ /**
+ * \brief Append len elements to the end of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void append(const T *val, long len) { replace(BaseTable::length(), val, len); }
+
+ /**
+ * \brief Append the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place
+ * the elements in the vector.
+ */
+ void append(const SVector &v)
+ { replace(BaseTable::length(), v.data, v.length()); }
+
+ /**
+ * \brief Append len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void appendDup(const T &item, long len) { replaceDup(BaseTable::length(), item, len); }
+
+ /**
+ * \brief Append a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void appendNew() { replaceNew(BaseTable::length(), 1); }
+
+ /**
+ * \brief Append len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void appendNew(long len) { replaceNew(BaseTable::length(), len); }
+ /*@}*/
+
+
+ /*@{*/
+ /**
+ * \brief Prepend one elment to the front of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void prepend(const T &val) { insert(0, &val, 1); }
+
+ /**
+ * \brief Prepend len elements to the front of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void prepend(const T *val, long len) { insert(0, val, len); }
+
+ /**
+ * \brief Prepend the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place
+ * the elements in the vector.
+ */
+ void prepend(const SVector &v) { insert(0, v.data, v.length()); }
+
+ /**
+ * \brief Prepend len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void prependDup(const T &item, long len) { insertDup(0, item, len); }
+
+ /**
+ * \brief Prepend a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void prependNew() { insertNew(0, 1); }
+
+ /**
+ * \brief Prepend len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void prependNew(long len) { insertNew(0, len); }
+ /*@}*/
+
+ /* Convenience access. */
+ T &operator[](int i) const { return BaseTable::data[i]; }
+ long size() const { return BaseTable::length(); }
+
+ /* Various classes for setting the iterator */
+ struct Iter;
+ struct IterFirst { IterFirst( const SVector &v ) : v(v) { } const SVector &v; };
+ struct IterLast { IterLast( const SVector &v ) : v(v) { } const SVector &v; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+ /**
+ * \brief Shared Vector Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Construct, assign. */
+ Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
+
+ /* Construct. */
+ Iter( const SVector &v );
+ Iter( const IterFirst &vf );
+ Iter( const IterLast &vl );
+ inline Iter( const IterNext &vn );
+ inline Iter( const IterPrev &vp );
+
+ /* Assign. */
+ Iter &operator=( const SVector &v );
+ Iter &operator=( const IterFirst &vf );
+ Iter &operator=( const IterLast &vl );
+ inline Iter &operator=( const IterNext &vf );
+ inline Iter &operator=( const IterPrev &vl );
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != ptrEnd; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == ptrEnd; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != ptrBeg; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == ptrBeg; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr == ptrBeg+1; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr == ptrEnd-1; }
+
+ /* Return the position. */
+ long pos() const { return ptr - ptrBeg - 1; }
+ T &operator[](int i) const { return ptr[i]; }
+
+ /** \brief Implicit cast to T*. */
+ operator T*() const { return ptr; }
+
+ /** \brief Dereference operator returns T&. */
+ T &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns T*. */
+ T *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++() { return ++ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++(int) { return ptr++; }
+
+ /** \brief Move to next item. */
+ T *increment() { return ++ptr; }
+
+ /** \brief Move to previous item. */
+ T *operator--() { return --ptr; }
+
+ /** \brief Move to previous item. */
+ T *operator--(int) { return ptr--; }
+
+ /** \brief Move to previous item. */
+ T *decrement() { return --ptr; }
+
+ /** \brief Return the next item. Does not modify this. */
+ inline IterNext next() const { return IterNext(*this); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ inline IterPrev prev() const { return IterPrev(*this); }
+
+ /** \brief The iterator is simply a pointer. */
+ T *ptr;
+
+ /* For testing endpoints. */
+ T *ptrBeg, *ptrEnd;
+ };
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst( *this ); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast( *this ); }
+
+protected:
+ void makeRawSpaceFor(long pos, long len);
+
+ void setAsCommon(long len);
+ long replaceCommon(long pos, long len);
+ long insertCommon(long pos, long len);
+
+ void upResize(long len);
+ void upResizeDup(long len);
+ void upResizeFromEmpty(long len);
+ void downResize(long len);
+ void downResizeDup(long len);
+};
+
+/**
+ * \brief Perform a shallow copy of the vector.
+ *
+ * Takes a reference to the contents of the other vector.
+ */
+template <class T, class Resize> SVector<T, Resize>::
+ SVector(const SVector<T, Resize> &v)
+{
+ /* Take a reference to other, if any data is allocated. */
+ if ( v.data == 0 )
+ BaseTable::data = 0;
+ else {
+ /* Get the source header, up the refcount and ref it. */
+ STabHead *srcHead = ((STabHead*) v.data) - 1;
+ srcHead->refCount += 1;
+ BaseTable::data = (T*) (srcHead + 1);
+ }
+}
+
+/**
+ * \brief Shallow copy another vector into this vector.
+ *
+ * Takes a reference to the other vector. The contents of this vector are
+ * first emptied.
+ *
+ * \returns A reference to this.
+ */
+template <class T, class Resize> SVector<T, Resize> &
+ SVector<T, Resize>:: operator=( const SVector &v )
+{
+ /* First clean out the current contents. */
+ empty();
+
+ /* Take a reference to other, if any data is allocated. */
+ if ( v.data == 0 )
+ BaseTable::data = 0;
+ else {
+ /* Get the source header, up the refcount and ref it. */
+ STabHead *srcHead = ((STabHead*) v.data) - 1;
+ srcHead->refCount += 1;
+ BaseTable::data = (T*) (srcHead + 1);
+ }
+ return *this;
+}
+
+/* Init a vector iterator with just a vector. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const SVector &v )
+{
+ long length;
+ if ( v.data == 0 || (length=(((STabHead*)v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+length;
+ }
+}
+
+/* Init a vector iterator with the first of a vector. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterFirst &vf )
+{
+ long length;
+ if ( vf.v.data == 0 || (length=(((STabHead*)vf.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+length;
+ }
+}
+
+/* Init a vector iterator with the last of a vector. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterLast &vl )
+{
+ long length;
+ if ( vl.v.data == 0 || (length=(((STabHead*)vl.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+length-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+length;
+ }
+}
+
+/* Init a vector iterator with the next of some other iterator. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterNext &vn )
+:
+ ptr(vn.i.ptr+1),
+ ptrBeg(vn.i.ptrBeg),
+ ptrEnd(vn.i.ptrEnd)
+{
+}
+
+/* Init a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterPrev &vp )
+:
+ ptr(vp.i.ptr-1),
+ ptrBeg(vp.i.ptrBeg),
+ ptrEnd(vp.i.ptrEnd)
+{
+}
+
+/* Set a vector iterator with some vector. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const SVector &v )
+{
+ long length;
+ if ( v.data == 0 || (length=(((STabHead*)v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+length;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the first element in a vector. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterFirst &vf )
+{
+ long length;
+ if ( vf.v.data == 0 || (length=(((STabHead*)vf.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+length;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the last element in a vector. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterLast &vl )
+{
+ long length;
+ if ( vl.v.data == 0 || (length=(((STabHead*)vl.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+length-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+length;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the next of some other iterator. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterNext &vn )
+{
+ ptr = vn.i.ptr+1;
+ ptrBeg = vn.i.ptrBeg;
+ ptrEnd = vn.i.ptrEnd;
+ return *this;
+}
+
+/* Set a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterPrev &vp )
+{
+ ptr = vp.i.ptr-1;
+ ptrBeg = vp.i.ptrBeg;
+ ptrEnd = vp.i.ptrEnd;
+ return *this;
+}
+
+/* Up resize the data for len elements using Resize::upResize to tell us the
+ * new length. Reads and writes allocLen. Does not read or write length.
+ * Assumes that there is some data allocated already. */
+template <class T, class Resize> void SVector<T, Resize>::
+ upResize(long len)
+{
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::upResize(head->allocLen, len);
+
+ /* Did the data grow? */
+ if ( newLen > head->allocLen ) {
+ head->allocLen = newLen;
+
+ /* Table exists already, resize it up. */
+ head = (STabHead*) realloc( head, sizeof(STabHead) +
+ sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Save the data pointer. */
+ BaseTable::data = (T*) (head + 1);
+ }
+}
+
+/* Allocates a new buffer for an up resize that requires a duplication of the
+ * data. Uses Resize::upResize to get the allocation length. Reads and writes
+ * allocLen. This upResize does write the new length. Assumes that there is
+ * some data allocated already. */
+template <class T, class Resize> void SVector<T, Resize>::
+ upResizeDup(long len)
+{
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::upResize(head->allocLen, len);
+
+ /* Dereferencing the existing data, decrement the refcount. */
+ head->refCount -= 1;
+
+ /* Table exists already, resize it up. */
+ head = (STabHead*) malloc( sizeof(STabHead) + sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ head->refCount = 1;
+ head->allocLen = newLen;
+ head->tabLen = len;
+
+ /* Save the data pointer. */
+ BaseTable::data = (T*) (head + 1);
+}
+
+/* Up resize the data for len elements using Resize::upResize to tell us the
+ * new length. Reads and writes allocLen. This upresize DOES write length.
+ * Assumes that no data is allocated. */
+template <class T, class Resize> void SVector<T, Resize>::
+ upResizeFromEmpty(long len)
+{
+ /* There is no table yet. If the len is zero, then there is no need to
+ * create a table. */
+ if ( len > 0 ) {
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::upResize(0, len);
+
+ /* If len is greater than zero then we are always allocating the table. */
+ STabHead *head = (STabHead*) malloc( sizeof(STabHead) +
+ sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header and save the data pointer. Note that we set the
+ * length here. This differs from the other upResizes. */
+ head->refCount = 1;
+ head->allocLen = newLen;
+ head->tabLen = len;
+ BaseTable::data = (T*) (head + 1);
+ }
+}
+
+/* Down resize the data for len elements using Resize::downResize to determine
+ * the new length. Reads and writes allocLen. Does not read or write length. */
+template <class T, class Resize> void SVector<T, Resize>::
+ downResize(long len)
+{
+ /* If there is already no length, then there is nothing we can do. */
+ if ( BaseTable::data != 0 ) {
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::downResize( head->allocLen, len );
+
+ /* Did the data shrink? */
+ if ( newLen < head->allocLen ) {
+ if ( newLen == 0 ) {
+ /* Simply free the data. */
+ free( head );
+ BaseTable::data = 0;
+ }
+ else {
+ /* Save the new allocated length. */
+ head->allocLen = newLen;
+
+ /* Not shrinking to size zero, realloc it to the smaller size. */
+ head = (STabHead*) realloc( head, sizeof(STabHead) +
+ sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Save the new data ptr. */
+ BaseTable::data = (T*) (head + 1);
+ }
+ }
+ }
+}
+
+/* Allocate a new buffer for a down resize and duplication of the array. The
+ * new array will be len long and allocation size will be determined using
+ * Resize::downResize with the old array's allocLen. Does not actually copy
+ * any data. Reads and writes allocLen and writes the new len. */
+template <class T, class Resize> void SVector<T, Resize>::
+ downResizeDup(long len)
+{
+ /* If there is already no length, then there is nothing we can do. */
+ if ( BaseTable::data != 0 ) {
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::downResize( head->allocLen, len );
+
+ /* Detaching from the existing head, decrement the refcount. */
+ head->refCount -= 1;
+
+ /* Not shrinking to size zero, malloc it to the smaller size. */
+ head = (STabHead*) malloc( sizeof(STabHead) + sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Save the new allocated length. */
+ head->refCount = 1;
+ head->allocLen = newLen;
+ head->tabLen = len;
+
+ /* Save the data pointer. */
+ BaseTable::data = (T*) (head + 1);
+ }
+}
+
+/**
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ empty()
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header and drop the refcount on the data. */
+ STabHead *head = ((STabHead*) BaseTable::data) - 1;
+ head->refCount -= 1;
+
+ /* If the refcount just went down to zero nobody else is referencing
+ * the data. */
+ if ( head->refCount == 0 ) {
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < head->tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Free the data space. */
+ free( head );
+ }
+
+ /* Clear the pointer. */
+ BaseTable::data = 0;
+ }
+}
+
+/* Prepare for setting the contents of the vector to some array len long.
+ * Handles reusing the existing space, detaching from a common space or
+ * growing from zero length automatically. */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAsCommon(long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If the refCount is one, then we can reuse the space. Otherwise we
+ * must detach from the referenced data create new space. */
+ if ( head->refCount == 1 ) {
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < head->tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < head->tabLen )
+ downResize( len );
+ else if ( len > head->tabLen )
+ upResize( len );
+
+ if ( BaseTable::data != 0 ) {
+ /* Get the header again and set the length. */
+ head = ((STabHead*)BaseTable::data) - 1;
+ head->tabLen = len;
+ }
+ }
+ else {
+ /* Just detach from the data. */
+ head->refCount -= 1;
+ BaseTable::data = 0;
+
+ /* Make enough space. This will set the length. */
+ upResizeFromEmpty( len );
+ }
+ }
+ else {
+ /* The table is currently empty. Make enough space. This will set the
+ * length. */
+ upResizeFromEmpty( len );
+ }
+}
+
+/**
+ * \brief Set the contents of the vector to be len elements exactly.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Copy constructors are used to place the
+ * new elements in the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAs(const T *val, long len)
+{
+ /* Common stuff for setting the array to len long. */
+ setAsCommon( len );
+
+ /* Copy data in. */
+ T *dst = BaseTable::data;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+
+/**
+ * \brief Set the vector to len copies of item.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used to
+ * copy the item into the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAsDup(const T &item, long len)
+{
+ /* Do the common stuff for setting the array to len long. */
+ setAsCommon( len );
+
+ /* Copy item in one spot at a time. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+}
+
+/**
+ * \brief Set the vector to exactly len new items.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Default constructors are used to init the
+ * new items.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAsNew(long len)
+{
+ /* Do the common stuff for setting the array to len long. */
+ setAsCommon( len );
+
+ /* Create items using default constructor. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/* Make space in vector for a replacement at pos of len items. Handles reusing
+ * existing space, detaching or growing from zero space. */
+template <class T, class Resize> long SVector<T, Resize>::
+ replaceCommon(long pos, long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If we are given a negative position to replace at then treat it as
+ * a position relative to the length. This doesn't have any meaning
+ * unless the length is at least one. */
+ if ( pos < 0 )
+ pos = head->tabLen + pos;
+
+ /* The end is the one past the last item that we want to write to. */
+ long i, endPos = pos + len;
+
+ if ( head->refCount == 1 ) {
+ /* We can reuse the space. Make sure we have enough space. */
+ if ( endPos > head->tabLen ) {
+ upResize( endPos );
+
+ /* Get the header again, whose addr may have changed after
+ * resizing. */
+ head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Delete any objects we need to delete. */
+ T *item = BaseTable::data + pos;
+ for ( i = pos; i < head->tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ head->tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ T *item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+ }
+ else {
+ /* Use endPos to calc the end of the vector. */
+ long newLen = endPos;
+ if ( newLen < head->tabLen )
+ newLen = head->tabLen;
+
+ /* Duplicate and grow up to endPos. This will set the length. */
+ upResizeDup( newLen );
+
+ /* Copy from src up to pos. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++)
+ new(dst) T(*src);
+
+ /* Copy any items after the replace range. */
+ for ( i += len, src += len, dst += len;
+ i < head->tabLen; i++, dst++, src++ )
+ new(dst) T(*src);
+ }
+ }
+ else {
+ /* There is no data initially, must grow from zero. This will set the
+ * new length. */
+ upResizeFromEmpty( len );
+ }
+
+ return pos;
+}
+
+
+/**
+ * \brief Replace len elements at position pos.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. Copy constructors are used
+ * to place the elements into the vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ replace(long pos, const T *val, long len)
+{
+ /* Common work for replacing in the vector. */
+ pos = replaceCommon( pos, len );
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Replace at position pos with len copies of an item.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The copy constructor is
+ * used to place the element into this vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ replaceDup(long pos, const T &val, long len)
+{
+ /* Common replacement stuff. */
+ pos = replaceCommon( pos, len );
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(val);
+}
+
+/**
+ * \brief Replace at position pos with len new elements.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The default constructor is
+ * used to initialize the new elements. It is allowable for the pos and length
+ * to specify a replacement that overwrites existing elements and creates new
+ * ones. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative, then it is treated as an offset
+ * relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ replaceNew(long pos, long len)
+{
+ /* Do the common replacement stuff. */
+ pos = replaceCommon( pos, len );
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/**
+ * \brief Remove len elements at position pos.
+ *
+ * Destructor is called on all elements removed. Elements to the right of pos
+ * are shifted len spaces to the left to take up the free space. If pos is
+ * greater than or equal to the length of the vector then undefined behavior
+ * results. If pos is negative then it is treated as an offset relative to the
+ * length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ remove(long pos, long len)
+{
+ /* If there is no data, we can't delete anything anyways. */
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If we are given a negative position to remove at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = head->tabLen + pos;
+
+ /* The first position after the last item deleted. */
+ long endPos = pos + len;
+
+ /* The New data length. */
+ long i, newLen = head->tabLen - len;
+
+ if ( head->refCount == 1 ) {
+ /* We are the only ones using the data. We can reuse
+ * the existing space. */
+
+ /* The place in the data we are deleting at. */
+ T *dst = BaseTable::data + pos;
+
+ /* Call Destructors. */
+ T *item = BaseTable::data + pos;
+ for ( i = 0; i < len; i += 1, item += 1 )
+ item->~T();
+
+ /* Shift data over if necessary. */
+ long lenToSlideOver = head->tabLen - endPos;
+ if ( len > 0 && lenToSlideOver > 0 )
+ memmove(BaseTable::data + pos, dst + len, sizeof(T)*lenToSlideOver);
+
+ /* Shrink the data if necessary. */
+ downResize( newLen );
+
+ if ( BaseTable::data != 0 ) {
+ /* Get the header again (because of the resize) and set the
+ * new data length. */
+ head = ((STabHead*)BaseTable::data) - 1;
+ head->tabLen = newLen;
+ }
+ }
+ else {
+ /* Must detach from the common data. Just copy the non-deleted
+ * items from the common data. */
+
+ /* Duplicate and grow down to newLen. This will set the length. */
+ downResizeDup( newLen );
+
+ /* Copy over just the non-deleted parts. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* ... and the second half. */
+ for ( i += len, src += len; i < head->tabLen; i++, src++, dst++ )
+ new(dst) T(*src);
+ }
+ }
+}
+
+/* Shift over existing data. Handles reusing existing space, detaching or
+ * growing from zero space. */
+template <class T, class Resize> long SVector<T, Resize>::
+ insertCommon(long pos, long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If we are given a negative position to insert at then treat it as a
+ * position relative to the length. This only has meaning if there is
+ * existing data. */
+ if ( pos < 0 )
+ pos = head->tabLen + pos;
+
+ /* Calculate the new length. */
+ long i, newLen = head->tabLen + len;
+
+ if ( head->refCount == 1 ) {
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Get the header again, (the addr may have changed after
+ * resizing). */
+ head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < head->tabLen ) {
+ memmove( BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(head->tabLen - pos) );
+ }
+
+ /* Grow the length by the len inserted. */
+ head->tabLen += len;
+ }
+ else {
+ /* Need to detach from the existing array. Copy over the other
+ * parts. This will set the length. */
+ upResizeDup( newLen );
+
+ /* Copy over the parts around the insert. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* ... and the second half. */
+ for ( dst += len; i < head->tabLen; i++, src++, dst++ )
+ new(dst) T(*src);
+ }
+ }
+ else {
+ /* There is no existing data. Start from zero. This will set the
+ * length. */
+ upResizeFromEmpty( len );
+ }
+
+ return pos;
+}
+
+
+/**
+ * \brief Insert len elements at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the elements into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ insert(long pos, const T *val, long len)
+{
+ /* Do the common insertion stuff. */
+ pos = insertCommon( pos, len );
+
+ /* Copy data in element by element. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Insert len copies of item at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the element into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ insertDup(long pos, const T &item, long len)
+{
+ /* Do the common insertion stuff. */
+ pos = insertCommon( pos, len );
+
+ /* Copy the data item in one at a time. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+}
+
+
+/**
+ * \brief Insert len new elements using the default constructor.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * Default constructors are used to init the new elements. If pos is off the
+ * end of the vector then undefined behaviour results. If pos is negative then
+ * it is treated as an offset relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ insertNew(long pos, long len)
+{
+ /* Do the common insertion stuff. */
+ pos = insertCommon( pos, len );
+
+ /* Init new data with default constructors. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/* Makes space for len items, Does not init the items in any way. If pos is
+ * greater than the length of the vector then undefined behaviour results.
+ * Updates the length of the vector. */
+template <class T, class Resize> void SVector<T, Resize>::
+ makeRawSpaceFor(long pos, long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Calculate the new length. */
+ long i, newLen = head->tabLen + len;
+
+ if ( head->refCount == 1 ) {
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Get the header again, (the addr may have changed after
+ * resizing). */
+ head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < head->tabLen ) {
+ memmove( BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(head->tabLen - pos) );
+ }
+
+ /* Grow the length by the len inserted. */
+ head->tabLen += len;
+ }
+ else {
+ /* Need to detach from the existing array. Copy over the other
+ * parts. This will set the length. */
+ upResizeDup( newLen );
+
+ /* Copy over the parts around the insert. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* ... and the second half. */
+ for ( dst += len; i < head->tabLen; i++, src++, dst++ )
+ new(dst) T(*src);
+ }
+ }
+ else {
+ /* There is no existing data. Start from zero. This will set the
+ * length. */
+ upResizeFromEmpty( len );
+ }
+}
+
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+
+#endif /* _AAPL_SVECTOR_H */
diff --git a/aapl/table.h b/aapl/table.h
new file mode 100644
index 00000000..c218281b
--- /dev/null
+++ b/aapl/table.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2001, 2002 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_TABLE_H
+#define _AAPL_TABLE_H
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class Table
+ * \brief Base class for dynamic arrays.
+ *
+ * Table is used as the common data storage class for vectors. It does not
+ * provide any methods to operate on the data and as such it is not intended
+ * to be used directly. It exists so that algorithms that operatate on dynamic
+ * arrays can be written without knowing about the various vector classes that
+ * my exist.
+ */
+
+/*@}*/
+
+/* Table class. */
+template <class T> class Table
+{
+public:
+ /* Default Constructor. */
+ inline Table();
+
+ /**
+ * \brief Get the length of the vector.
+ *
+ * \returns the length of the vector.
+ */
+ long length() const
+ { return tabLen; }
+
+ /**
+ * \brief Table data.
+ *
+ * The pointer to the elements in the vector. Modifying the vector may
+ * cause this pointer to change.
+ */
+ T *data;
+
+ /**
+ * \brief Table length.
+ *
+ * The number of items of type T in the table.
+ */
+ long tabLen;
+
+ /**
+ * \brief Allocated length.
+ *
+ * The number of items for which there is room in the current allocation.
+ */
+ long allocLen;
+};
+
+/**
+ * \brief Default constructor
+ *
+ * Initialize table data to empty.
+ */
+template <class T> inline Table<T>::Table()
+:
+ data(0),
+ tabLen(0),
+ allocLen(0)
+{
+}
+
+/* Default shared table header class. */
+struct STabHead
+{
+ /**
+ * \brief Table length.
+ *
+ * The number of items of type T in the table.
+ */
+ long tabLen;
+
+ /**
+ * \brief Allocated length.
+ *
+ * The number of items for which there is room in the current allocation.
+ */
+ long allocLen;
+
+ /**
+ * \brief Ref Count.
+ *
+ * The number of shared vectors referencing this data.
+ */
+ long refCount;
+};
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class STable
+ * \brief Base class for implicitly shared dynamic arrays.
+ *
+ * STable is used as the common data storage class for shared vectors. It does
+ * not provide any methods to operate on the data and as such it is not
+ * intended to be used directly. It exists so that algorithms that operatate
+ * on dynamic arrays can be written without knowing about the various shared
+ * vector classes that my exist.
+ */
+
+/*@}*/
+
+/* STable class. */
+template <class T> class STable
+{
+public:
+ /* Default Constructor. */
+ inline STable();
+
+ /**
+ * \brief Get the length of the shared vector.
+ *
+ * \returns the length of the shared vector.
+ */
+ long length() const
+ { return data == 0 ? 0 : (((STabHead*)data) - 1)->tabLen; }
+
+ /**
+ * \brief Get header of the shared vector.
+ *
+ * \returns the header of the shared vector.
+ */
+ STabHead *header() const
+ { return data == 0 ? 0 : (((STabHead*)data) - 1); }
+
+ /**
+ * \brief Table data.
+ *
+ * The pointer to the elements in the vector. The shared table header is
+ * located just behind the data. Modifying the vector may cause this
+ * pointer to change.
+ */
+ T *data;
+};
+
+/**
+ * \brief Default constructor
+ *
+ * Initialize shared table data to empty.
+ */
+template <class T> inline STable<T>::STable()
+:
+ data(0)
+{
+}
+
+/* If needed is greater than existing, give twice needed. */
+#define EXPN_UP( existing, needed ) \
+ needed > existing ? (needed<<1) : existing
+
+/* If needed is less than 1 quarter existing, give twice needed. */
+#define EXPN_DOWN( existing, needed ) \
+ needed < (existing>>2) ? (needed<<1) : existing
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeExpn
+ * \brief Exponential table resizer.
+ *
+ * ResizeExpn is the default table resizer. When an up resize is needed, space
+ * is doubled. When a down resize is needed, space is halved. The result is
+ * that when growing the vector in a linear fashion, the number of resizes of
+ * the allocated space behaves logarithmically.
+ *
+ * If only up resizes are done, there will never be more than 2 times the
+ * needed space allocated. If down resizes are done as well, there will never
+ * be more than 4 times the needed space allocated. ResizeExpn uses this 50%
+ * usage policy on up resizing and 25% usage policy on down resizing to
+ * improve performance when repeatedly inserting and removing a small number
+ * of elements relative to the size of the array. This scheme guarantees that
+ * repetitive inserting and removing of a small number of elements will never
+ * result in repetative reallocation.
+ *
+ * The sizes passed to the resizer from the vectors are in units of T.
+ */
+
+/*@}*/
+
+/* Exponential resizer. */
+class ResizeExpn
+{
+protected:
+ /**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed then allocate
+ * twice the space needed. Otherwise use the existing size.
+ *
+ * \returns The new table size.
+ */
+ static inline long upResize( long existing, long needed )
+ { return EXPN_UP( existing, needed ); }
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * If the space needed is less than one quarter of the existing size then
+ * allocate twice the space needed. Otherwise use the exitsing size.
+ *
+ * \returns The new table size.
+ */
+ static inline long downResize( long existing, long needed )
+ { return EXPN_DOWN( existing, needed ); }
+};
+
+#undef EXPN_UP
+#undef EXPN_DOWN
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_TABLE_H */
diff --git a/aapl/vector.h b/aapl/vector.h
new file mode 100644
index 00000000..5e7f9e57
--- /dev/null
+++ b/aapl/vector.h
@@ -0,0 +1,1189 @@
+/*
+ * Copyright 2002, 2006 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Aapl.
+ *
+ * Aapl is free software; you can redistribute it and/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.
+ *
+ * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AAPL_VECTOR_H
+#define _AAPL_VECTOR_H
+
+#include <new>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "table.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class Vector
+ * \brief Dynamic array.
+ *
+ * This is typical vector implementation. It is a dynamic array that can be
+ * used to contain complex data structures that have constructors and
+ * destructors as well as simple types such as integers and pointers.
+ *
+ * Vector supports inserting, overwriting, and removing single or multiple
+ * elements at once. Constructors and destructors are called wherever
+ * appropriate. For example, before an element is overwritten, it's
+ * destructor is called.
+ *
+ * Vector provides automatic resizing of allocated memory as needed and offers
+ * different allocation schemes for controlling how the automatic allocation
+ * is done. Two senses of the the length of the data is maintained: the
+ * amount of raw memory allocated to the vector and the number of actual
+ * elements in the vector. The various allocation schemes control how the
+ * allocated space is changed in relation to the number of elements in the
+ * vector.
+ *
+ * \include ex_vector.cpp
+ */
+
+/*@}*/
+
+template < class T, class Resize = ResizeExpn > class Vector
+ : public Table<T>, public Resize
+{
+private:
+ typedef Table<T> BaseTable;
+
+public:
+ /**
+ * \brief Initialize an empty vector with no space allocated.
+ *
+ * If a linear resizer is used, the step defaults to 256 units of T. For a
+ * runtime vector both up and down allocation schemes default to
+ * Exponential.
+ */
+ Vector() { }
+
+ /**
+ * \brief Create a vector that contains an initial element.
+ *
+ * The vector becomes one element in length. The element's copy
+ * constructor is used to place the value in the vector.
+ */
+ Vector(const T &val) { setAs(&val, 1); }
+
+ /**
+ * \brief Create a vector that contains an array of elements.
+ *
+ * The vector becomes len elements in length. Copy constructors are used
+ * to place the new elements in the vector.
+ */
+ Vector(const T *val, long len) { setAs(val, len); }
+
+ /* Deep copy. */
+ Vector( const Vector &v );
+
+ /* Free all mem used by the vector. */
+ ~Vector() { empty(); }
+
+ /* Delete all items. */
+ void empty();
+
+ /* Abandon the contents of the vector without deleteing. */
+ void abandon();
+
+ /* Transfers the elements of another vector into this vector. First emptys
+ * the current vector. */
+ void transfer( Vector &v );
+
+ /* Perform a deep copy of another vector into this vector. */
+ Vector &operator=( const Vector &v );
+
+ /* Stack operations. */
+ void push( const T &t ) { append( t ); }
+ void pop() { remove( BaseTable::tabLen - 1 ); }
+ T &top() { return BaseTable::data[BaseTable::tabLen - 1]; }
+
+ /*@{*/
+ /**
+ * \brief Insert one element at position pos.
+ *
+ * Elements in the vector from pos onward are shifted one space to the
+ * right. The copy constructor is used to place the element into this
+ * vector. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative then it is treated as an offset
+ * relative to the length of the vector.
+ */
+ void insert(long pos, const T &val) { insert(pos, &val, 1); }
+
+ /* Insert an array of values. */
+ void insert(long pos, const T *val, long len);
+
+ /**
+ * \brief Insert all the elements from another vector at position pos.
+ *
+ * Elements in this vector from pos onward are shifted v.tabLen spaces to
+ * the right. The element's copy constructor is used to copy the items
+ * into this vector. The other vector is left unchanged. If pos is off the
+ * end of the vector, then undefined behaviour results. If pos is negative
+ * then it is treated as an offset relative to the length of the vector.
+ * Equivalent to vector.insert(pos, other.data, other.tabLen).
+ */
+ void insert(long pos, const Vector &v) { insert(pos, v.data, v.tabLen); }
+
+ /* Insert len copies of val into the vector. */
+ void insertDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Insert one new element using the default constrcutor.
+ *
+ * Elements in the vector from pos onward are shifted one space to the
+ * right. The default constructor is used to init the new element. If pos
+ * is greater than the length of the vector then undefined behaviour
+ * results. If pos is negative then it is treated as an offset relative to
+ * the length of the vector.
+ */
+ void insertNew(long pos) { insertNew(pos, 1); }
+
+ /* Insert len new items using default constructor. */
+ void insertNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Remove one element at position pos.
+ *
+ * The element's destructor is called. Elements to the right of pos are
+ * shifted one space to the left to take up the free space. If pos is greater
+ * than or equal to the length of the vector then undefined behavior results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+ void remove(long pos) { remove(pos, 1); }
+
+ /* Delete a number of elements. */
+ void remove(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Replace one element at position pos.
+ *
+ * If there is an existing element at position pos (if pos is less than
+ * the length of the vector) then its destructor is called before the
+ * space is used. The copy constructor is used to place the element into
+ * the vector. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative then it is treated as
+ * an offset relative to the length of the vector.
+ */
+ void replace(long pos, const T &val) { replace(pos, &val, 1); }
+
+ /* Replace with an array of values. */
+ void replace(long pos, const T *val, long len);
+
+ /**
+ * \brief Replace at position pos with all the elements of another vector.
+ *
+ * Replace at position pos with all the elements of another vector. The
+ * other vector is left unchanged. If there are existing elements at the
+ * positions to be replaced, then destructors are called before the space
+ * is used. Copy constructors are used to place the elements into this
+ * vector. It is allowable for the pos and length of the other vector to
+ * specify a replacement that overwrites existing elements and creates new
+ * ones. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative, then it is treated as an offset
+ * relative to the length of the vector.
+ */
+ void replace(long pos, const Vector &v) { replace(pos, v.data, v.tabLen); }
+
+ /* Replace len items with len copies of val. */
+ void replaceDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Replace at position pos with one new element.
+ *
+ * If there is an existing element at the position to be replaced (pos is
+ * less than the length of the vector) then the element's destructor is
+ * called before the space is used. The default constructor is used to
+ * initialize the new element. If pos is greater than the length of the
+ * vector then undefined behaviour results. If pos is negative, then it is
+ * treated as an offset relative to the length of the vector.
+ */
+ void replaceNew(long pos) { replaceNew(pos, 1); }
+
+ /* Replace len items at pos with newly constructed objects. */
+ void replaceNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Set the contents of the vector to be val exactly.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used
+ * to place the val in the vector.
+ */
+ void setAs(const T &val) { setAs(&val, 1); }
+
+ /* Set to the contents of an array. */
+ void setAs(const T *val, long len);
+
+ /**
+ * \brief Set the vector to exactly the contents of another vector.
+ *
+ * The vector becomes v.tabLen elements in length. Destructors are called
+ * on any existing elements. Copy constructors are used to place the new
+ * elements in the vector.
+ */
+ void setAs(const Vector &v) { setAs(v.data, v.tabLen); }
+
+ /* Set as len copies of item. */
+ void setAsDup(const T &item, long len);
+
+ /**
+ * \brief Set the vector to exactly one new item.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The default constructor is used to
+ * init the new item.
+ */
+ void setAsNew() { setAsNew(1); }
+
+ /* Set as newly constructed objects using the default constructor. */
+ void setAsNew(long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Append one elment to the end of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void append(const T &val) { replace(BaseTable::tabLen, &val, 1); }
+
+ /**
+ * \brief Append len elements to the end of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void append(const T *val, long len) { replace(BaseTable::tabLen, val, len); }
+
+ /**
+ * \brief Append the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place the
+ * elements in the vector.
+ */
+ void append(const Vector &v) { replace(BaseTable::tabLen, v.data, v.tabLen); }
+
+ /**
+ * \brief Append len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void appendDup(const T &item, long len) { replaceDup(BaseTable::tabLen, item, len); }
+
+ /**
+ * \brief Append a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void appendNew() { replaceNew(BaseTable::tabLen, 1); }
+
+ /**
+ * \brief Append len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void appendNew(long len) { replaceNew(BaseTable::tabLen, len); }
+ /*@}*/
+
+ /*@{*/
+ /** \fn Vector::prepend(const T &val)
+ * \brief Prepend one elment to the front of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void prepend(const T &val) { insert(0, &val, 1); }
+
+ /**
+ * \brief Prepend len elements to the front of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void prepend(const T *val, long len) { insert(0, val, len); }
+
+ /**
+ * \brief Prepend the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place the
+ * elements in the vector.
+ */
+ void prepend(const Vector &v) { insert(0, v.data, v.tabLen); }
+
+ /**
+ * \brief Prepend len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void prependDup(const T &item, long len) { insertDup(0, item, len); }
+
+ /**
+ * \brief Prepend a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void prependNew() { insertNew(0, 1); }
+
+ /**
+ * \brief Prepend len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void prependNew(long len) { insertNew(0, len); }
+ /*@}*/
+
+ /* Convenience access. */
+ T &operator[](int i) const { return BaseTable::data[i]; }
+ long size() const { return BaseTable::tabLen; }
+
+ /* Forward this so a ref can be used. */
+ struct Iter;
+
+ /* Various classes for setting the iterator */
+ struct IterFirst { IterFirst( const Vector &v ) : v(v) { } const Vector &v; };
+ struct IterLast { IterLast( const Vector &v ) : v(v) { } const Vector &v; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+ /**
+ * \brief Vector Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Construct, assign. */
+ Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
+
+ /* Construct. */
+ Iter( const Vector &v );
+ Iter( const IterFirst &vf );
+ Iter( const IterLast &vl );
+ inline Iter( const IterNext &vn );
+ inline Iter( const IterPrev &vp );
+
+ /* Assign. */
+ Iter &operator=( const Vector &v );
+ Iter &operator=( const IterFirst &vf );
+ Iter &operator=( const IterLast &vl );
+ inline Iter &operator=( const IterNext &vf );
+ inline Iter &operator=( const IterPrev &vl );
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != ptrEnd; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == ptrEnd; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != ptrBeg; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == ptrBeg; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr == ptrBeg+1; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr == ptrEnd-1; }
+
+ /* Return the position. */
+ long pos() const { return ptr - ptrBeg - 1; }
+ T &operator[](int i) const { return ptr[i]; }
+
+ /** \brief Implicit cast to T*. */
+ operator T*() const { return ptr; }
+
+ /** \brief Dereference operator returns T&. */
+ T &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns T*. */
+ T *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++() { return ++ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++(int) { return ptr++; }
+
+ /** \brief Move to next item. */
+ T *increment() { return ++ptr; }
+
+ /** \brief Move n items forward. */
+ T *operator+=(long n) { return ptr+=n; }
+
+ /** \brief Move to previous item. */
+ T *operator--() { return --ptr; }
+
+ /** \brief Move to previous item. */
+ T *operator--(int) { return ptr--; }
+
+ /** \brief Move to previous item. */
+ T *decrement() { return --ptr; }
+
+ /** \brief Move n items back. */
+ T *operator-=(long n) { return ptr-=n; }
+
+ /** \brief Return the next item. Does not modify this. */
+ inline IterNext next() const { return IterNext(*this); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ inline IterPrev prev() const { return IterPrev(*this); }
+
+ /** \brief The iterator is simply a pointer. */
+ T *ptr;
+
+ /* For testing endpoints. */
+ T *ptrBeg, *ptrEnd;
+ };
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst( *this ); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast( *this ); }
+
+protected:
+ void makeRawSpaceFor(long pos, long len);
+
+ void upResize(long len);
+ void downResize(long len);
+};
+
+/* Init a vector iterator with just a vector. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter( const Vector &v )
+{
+ if ( v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+v.tabLen;
+ }
+}
+
+/* Init a vector iterator with the first of a vector. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterFirst &vf )
+{
+ if ( vf.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+vf.v.tabLen;
+ }
+}
+
+/* Init a vector iterator with the last of a vector. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterLast &vl )
+{
+ if ( vl.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+vl.v.tabLen-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+vl.v.tabLen;
+ }
+}
+
+/* Init a vector iterator with the next of some other iterator. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterNext &vn )
+:
+ ptr(vn.i.ptr+1),
+ ptrBeg(vn.i.ptrBeg),
+ ptrEnd(vn.i.ptrEnd)
+{
+}
+
+/* Init a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterPrev &vp )
+:
+ ptr(vp.i.ptr-1),
+ ptrBeg(vp.i.ptrBeg),
+ ptrEnd(vp.i.ptrEnd)
+{
+}
+
+/* Set a vector iterator with some vector. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const Vector &v )
+{
+ if ( v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+v.tabLen;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the first element in a vector. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterFirst &vf )
+{
+ if ( vf.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+vf.v.tabLen;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the last element in a vector. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterLast &vl )
+{
+ if ( vl.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+vl.v.tabLen-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+vl.v.tabLen;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the next of some other iterator. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterNext &vn )
+{
+ ptr = vn.i.ptr+1;
+ ptrBeg = vn.i.ptrBeg;
+ ptrEnd = vn.i.ptrEnd;
+ return *this;
+}
+
+/* Set a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterPrev &vp )
+{
+ ptr = vp.i.ptr-1;
+ ptrBeg = vp.i.ptrBeg;
+ ptrEnd = vp.i.ptrEnd;
+ return *this;
+}
+
+/**
+ * \brief Forget all elements in the vector.
+ *
+ * The contents of the vector are reset to null without without the space
+ * being freed.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ abandon()
+{
+ BaseTable::data = 0;
+ BaseTable::tabLen = 0;
+ BaseTable::allocLen = 0;
+}
+
+/**
+ * \brief Transfer the contents of another vector into this vector.
+ *
+ * The dynamic array of the other vector is moved into this vector by
+ * reference. If this vector is non-empty then its contents are first deleted.
+ * Afterward the other vector will be empty.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ transfer( Vector &v )
+{
+ empty();
+
+ BaseTable::data = v.data;
+ BaseTable::tabLen = v.tabLen;
+ BaseTable::allocLen = v.allocLen;
+
+ v.abandon();
+}
+
+/**
+ * \brief Deep copy another vector into this vector.
+ *
+ * Copies the entire contents of the other vector into this vector. Any
+ * existing contents are first deleted. Equivalent to setAs.
+ *
+ * \returns A reference to this.
+ */
+template<class T, class Resize> Vector<T, Resize> &Vector<T, Resize>::
+ operator=( const Vector &v )
+{
+ setAs(v.data, v.tabLen);
+ return *this;
+}
+
+/* Up resize the data for len elements using Resize::upResize to tell us the
+ * new tabLen. Reads and writes allocLen. Does not read or write tabLen. */
+template<class T, class Resize> void Vector<T, Resize>::
+ upResize(long len)
+{
+ /* Ask the resizer what the new tabLen will be. */
+ long newLen = Resize::upResize(BaseTable::allocLen, len);
+
+ /* Did the data grow? */
+ if ( newLen > BaseTable::allocLen ) {
+ BaseTable::allocLen = newLen;
+ if ( BaseTable::data != 0 ) {
+ /* Table exists already, resize it up. */
+ BaseTable::data = (T*) realloc( BaseTable::data, sizeof(T) * newLen );
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+ }
+ else {
+ /* Create the data. */
+ BaseTable::data = (T*) malloc( sizeof(T) * newLen );
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+ }
+ }
+}
+
+/* Down resize the data for len elements using Resize::downResize to determine
+ * the new tabLen. Reads and writes allocLen. Does not read or write tabLen. */
+template<class T, class Resize> void Vector<T, Resize>::
+ downResize(long len)
+{
+ /* Ask the resizer what the new tabLen will be. */
+ long newLen = Resize::downResize( BaseTable::allocLen, len );
+
+ /* Did the data shrink? */
+ if ( newLen < BaseTable::allocLen ) {
+ BaseTable::allocLen = newLen;
+ if ( newLen == 0 ) {
+ /* Simply free the data. */
+ free( BaseTable::data );
+ BaseTable::data = 0;
+ }
+ else {
+ /* Not shrinking to size zero, realloc it to the smaller size. */
+ BaseTable::data = (T*) realloc( BaseTable::data, sizeof(T) * newLen );
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+ }
+ }
+}
+
+/**
+ * \brief Perform a deep copy of the vector.
+ *
+ * The contents of the other vector are copied into this vector. This vector
+ * gets the same allocation size as the other vector. All items are copied
+ * using the element's copy constructor.
+ */
+template<class T, class Resize> Vector<T, Resize>::
+ Vector(const Vector<T, Resize> &v)
+{
+ BaseTable::tabLen = v.tabLen;
+ BaseTable::allocLen = v.allocLen;
+
+ if ( BaseTable::allocLen > 0 ) {
+ /* Allocate needed space. */
+ BaseTable::data = (T*) malloc(sizeof(T) * BaseTable::allocLen);
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+
+ /* If there are any items in the src data, copy them in. */
+ T *dst = BaseTable::data, *src = v.data;
+ for (long pos = 0; pos < BaseTable::tabLen; pos++, dst++, src++ )
+ new(dst) T(*src);
+ }
+ else {
+ /* Nothing allocated. */
+ BaseTable::data = 0;
+ }
+}
+
+/** \fn Vector::~Vector()
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+
+
+/**
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ empty()
+{
+ if ( BaseTable::data != 0 ) {
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Free the data space. */
+ free( BaseTable::data );
+ BaseTable::data = 0;
+ BaseTable::tabLen = BaseTable::allocLen = 0;
+ }
+}
+
+/**
+ * \brief Set the contents of the vector to be len elements exactly.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Copy constructors are used to place the
+ * new elements in the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ setAs(const T *val, long len)
+{
+ /* Call All destructors. */
+ long i;
+ T *pos = BaseTable::data;
+ for ( i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < BaseTable::tabLen )
+ downResize( len );
+ else if ( len > BaseTable::tabLen )
+ upResize( len );
+
+ /* Set the new data length to exactly len. */
+ BaseTable::tabLen = len;
+
+ /* Copy data in. */
+ T *dst = BaseTable::data;
+ const T *src = val;
+ for ( i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Set the vector to len copies of item.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used to
+ * copy the item into the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ setAsDup(const T &item, long len)
+{
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < BaseTable::tabLen )
+ downResize( len );
+ else if ( len > BaseTable::tabLen )
+ upResize( len );
+
+ /* Set the new data length to exactly len. */
+ BaseTable::tabLen = len;
+
+ /* Copy item in one spot at a time. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+}
+
+/**
+ * \brief Set the vector to exactly len new items.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Default constructors are used to init the
+ * new items.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ setAsNew(long len)
+{
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < BaseTable::tabLen )
+ downResize( len );
+ else if ( len > BaseTable::tabLen )
+ upResize( len );
+
+ /* Set the new data length to exactly len. */
+ BaseTable::tabLen = len;
+
+ /* Create items using default constructor. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+
+/**
+ * \brief Replace len elements at position pos.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. Copy constructors are used
+ * to place the elements into the vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ replace(long pos, const T *val, long len)
+{
+ long endPos, i;
+ T *item;
+
+ /* If we are given a negative position to replace at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The end is the one past the last item that we want
+ * to write to. */
+ endPos = pos + len;
+
+ /* Make sure we have enough space. */
+ if ( endPos > BaseTable::tabLen ) {
+ upResize( endPos );
+
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < BaseTable::tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ BaseTable::tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Replace at position pos with len copies of an item.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The copy constructor is
+ * used to place the element into this vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ replaceDup(long pos, const T &val, long len)
+{
+ long endPos, i;
+ T *item;
+
+ /* If we are given a negative position to replace at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The end is the one past the last item that we want
+ * to write to. */
+ endPos = pos + len;
+
+ /* Make sure we have enough space. */
+ if ( endPos > BaseTable::tabLen ) {
+ upResize( endPos );
+
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < BaseTable::tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ BaseTable::tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(val);
+}
+
+/**
+ * \brief Replace at position pos with len new elements.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The default constructor is
+ * used to initialize the new elements. It is allowable for the pos and length
+ * to specify a replacement that overwrites existing elements and creates new
+ * ones. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative, then it is treated as an offset
+ * relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ replaceNew(long pos, long len)
+{
+ long endPos, i;
+ T *item;
+
+ /* If we are given a negative position to replace at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The end is the one past the last item that we want
+ * to write to. */
+ endPos = pos + len;
+
+ /* Make sure we have enough space. */
+ if ( endPos > BaseTable::tabLen ) {
+ upResize( endPos );
+
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < BaseTable::tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ BaseTable::tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/**
+ * \brief Remove len elements at position pos.
+ *
+ * Destructor is called on all elements removed. Elements to the right of pos
+ * are shifted len spaces to the left to take up the free space. If pos is
+ * greater than or equal to the length of the vector then undefined behavior
+ * results. If pos is negative then it is treated as an offset relative to the
+ * length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ remove(long pos, long len)
+{
+ long newLen, lenToSlideOver, endPos;
+ T *dst, *item;
+
+ /* If we are given a negative position to remove at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The first position after the last item deleted. */
+ endPos = pos + len;
+
+ /* The new data length. */
+ newLen = BaseTable::tabLen - len;
+
+ /* The place in the data we are deleting at. */
+ dst = BaseTable::data + pos;
+
+ /* Call Destructors. */
+ item = dst;
+ for ( long i = 0; i < len; i += 1, item += 1 )
+ item->~T();
+
+ /* Shift data over if necessary. */
+ lenToSlideOver = BaseTable::tabLen - endPos;
+ if ( len > 0 && lenToSlideOver > 0 )
+ memmove(dst, dst + len, sizeof(T)*lenToSlideOver);
+
+ /* Shrink the data if necessary. */
+ downResize( newLen );
+
+ /* Set the new data length. */
+ BaseTable::tabLen = newLen;
+}
+
+/**
+ * \brief Insert len elements at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the elements into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ insert(long pos, const T *val, long len)
+{
+ /* If we are given a negative position to insert at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Copy data in element by element. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* Set the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+/**
+ * \brief Insert len copies of item at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the element into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ insertDup(long pos, const T &item, long len)
+{
+ /* If we are given a negative position to insert at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Copy the data item in one at a time. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+
+ /* Set the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+/**
+ * \brief Insert len new elements using the default constructor.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * Default constructors are used to init the new elements. If pos is off the
+ * end of the vector then undefined behaviour results. If pos is negative then
+ * it is treated as an offset relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ insertNew(long pos, long len)
+{
+ /* If we are given a negative position to insert at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Init new data with default constructors. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+
+ /* Set the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+/* Makes space for len items, Does not init the items in any way. If pos is
+ * greater than the length of the vector then undefined behaviour results.
+ * Updates the length of the vector. */
+template<class T, class Resize> void Vector<T, Resize>::
+ makeRawSpaceFor(long pos, long len)
+{
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Save the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_VECTOR_H */
diff --git a/colm.vim b/colm.vim
new file mode 100644
index 00000000..8b7b5799
--- /dev/null
+++ b/colm.vim
@@ -0,0 +1,91 @@
+" Vim syntax file
+"
+" Language: Colm
+" Author: Adrian Thurston
+
+syntax clear
+
+"
+" Regular Language Types
+"
+
+" Identifiers
+syntax match rlId "[a-zA-Z_][a-zA-Z_0-9]*" contained
+
+" Literals
+syntax match rlLiteral "'\(\\.\|[^'\\]\)*'[i]*" contained
+syntax match rlLiteral "\"\(\\.\|[^\"\\]\)*\"[i]*" contained
+syntax match rlLiteral "\[\(\\.\|[^\]\\]\)*\]" contained
+
+" Numbers
+syntax match rlNumber "[0-9][0-9]*" contained
+syntax match rlNumber "0x[0-9a-fA-F][0-9a-fA-F]*" contained
+
+" Operators
+syntax match rlOtherOps ":>" contained
+syntax match rlOtherOps ":>>" contained
+syntax match rlOtherOps "<:" contained
+
+syntax cluster rlTypes contains=rlId,rlLiteral,rlNumber,rlOtherOps
+syntax region rlTypeRegion matchgroup=regionDelimiter start="/" end="/"
+ \ contains=@rlTypes
+
+syntax region cflTypeRegion matchgroup=regionDelimiter start="\[" end="\]"
+ \ contains=cflTypeRegion,patRegion,otLit,typeKeywords
+syntax region patRegion matchgroup=String start="\"" end="\"" end="\n"
+ \ contains=char,cflTypeRegion
+
+syntax match char "[^\"\[]" contained
+syntax match char "\\." contained
+
+syntax match otLit "\~.*$"
+syntax match otLit "'\(\\.\|[^'\\]\)*'[i]*"
+
+"
+" Other stuff
+"
+
+syntax match tlComment "#.*$"
+syntax match tlIdentifier "[a-zA-Z_][a-zA-Z_0-9]*"
+syntax match tlNumber "[0-9][0-9]*"
+syntax match tlNumber "nil"
+syntax match tlNumber "true"
+syntax match tlNumber "false"
+
+syntax keyword Type
+ \ commit include literal iter
+ \ namespace lex reducefirst global include
+ \ construct parse parse_stop match require
+ \ preeof left right nonassoc prec
+
+syntax keyword typeKeywords
+ \ int str bool any ref vector map list ptr
+
+syntax keyword Keyword
+ \ reject else elsif return yield for while if
+ \ typeid in break
+ \ new deref
+
+syntax match tokenName "[a-zA-Z_][a-zA-Z_0-9]*" contained
+
+syntax region defTypes matchgroup=defKeywords
+ \ start="\<rl\>" start="\<def\>" start="\<token\>" start="\<ignore\>"
+ \ matchgroup=Function end="[a-zA-Z_][a-zA-Z0-9_]*" end="/"me=e-1
+
+syntax sync match colmSyncPat grouphere NONE "([{}]|\<token\>|\<ignore\>|\<def\>)"
+
+"
+" Specifying Groups
+"
+hi link tlComment Comment
+hi link tlNumber Number
+hi link otLit String
+hi link rlNumber Number
+hi link rlLiteral String
+hi link defKeywords Type
+hi link typeKeywords Type
+hi link regionDelimiter Type
+hi link char String
+hi link tokenName Function
+
+let b:current_syntax = "colm"
diff --git a/colm/Makefile.in b/colm/Makefile.in
new file mode 100644
index 00000000..9b247eae
--- /dev/null
+++ b/colm/Makefile.in
@@ -0,0 +1,161 @@
+#
+# Copyright 2001-2007 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+# Logging:
+# colm: rt on/off
+# rt_prd: off
+# rt_db: on
+# rt_clm: rt on/off
+
+INCS += -I../aapl
+
+DEFS_COLM += -DCOLM_LOG -DPREFIX='"$(prefix)"'
+DEFS_RT_P +=
+DEFS_RT_D += -DCOLM_LOG
+
+CFLAGS += -g -Wall -Wwrite-strings
+LDFLAGS +=
+
+# Frequently changed ones first.
+COLM_SRC = \
+ compile.cpp \
+ lmparse.cpp \
+ lmscan.cpp \
+ parsetree.cpp \
+ parsedata.cpp \
+ fsmstate.cpp \
+ fsmbase.cpp \
+ fsmattach.cpp \
+ fsmmin.cpp \
+ fsmgraph.cpp \
+ pdagraph.cpp \
+ pdabuild.cpp \
+ pdacodegen.cpp \
+ fsmcodegen.cpp \
+ redfsm.cpp \
+ fsmexec.cpp \
+ main.cpp \
+ redbuild.cpp \
+ closure.cpp \
+ fsmap.cpp \
+ dotgen.cpp \
+ pcheck.cpp
+
+RUNTIME_SRC = fsmrun.cpp pdarun.cpp bytecode.cpp list.cpp \
+ map.cpp string.cpp input.cpp tree.cpp
+
+ALL_SRC = $(COLM_SRC) $(RUNTIME_SRC)
+
+# Files in ALL_SRC that are generated.
+GEN_SRC = version.h lmscan.cpp lmparse.h lmparse.cpp
+
+RUNTIME_P = libcolmp.a
+RUNTIME_D = libcolmd.a
+
+LIBS =
+
+#*************************************
+
+# Get the version info.
+include ../version.mk
+
+prefix = @prefix@
+
+BUILD_PARSERS = @BUILD_PARSERS@
+
+# Programs
+CXX = @CXX@
+
+# Get objects and dependencies from sources.
+COLM_OBJ = $(COLM_SRC:%.cpp=%.o)
+RUNTIME_OBJ_P = $(RUNTIME_SRC:%.cpp=%_p.o)
+RUNTIME_OBJ_D = $(RUNTIME_SRC:%.cpp=%_d.o)
+
+DEPS = $(COLM_SRC:%.cpp=.%.d) $(RUNTIME_SRC:%.cpp=.%_p.d) $(RUNTIME_SRC:%.cpp=.%_d.d)
+
+# Rules.
+all: colm $(RUNTIME_P) $(RUNTIME_D)
+
+colm: $(GEN_SRC) $(COLM_OBJ) $(RUNTIME_OBJ_D) $(LIBS)
+ $(CXX) $(LDFLAGS) -o $@ $(COLM_OBJ) $(RUNTIME_OBJ_D) $(LIBS)
+
+$(RUNTIME_P): $(RUNTIME_OBJ_P)
+ ar -cr $@ $^
+
+$(RUNTIME_D): $(RUNTIME_OBJ_D)
+ ar -cr $@ $^
+
+version.h: ../version.mk
+ echo '#define VERSION "$(VERSION)"' > version.h
+ echo '#define PUBDATE "$(PUBDATE)"' >> version.h
+
+ifeq ($(BUILD_PARSERS),true)
+
+lmparse.h: lmparse.kh
+ kelbt -o $@ $<
+
+lmparse.cpp: lmparse.kl lmparse.kh
+ kelbt -o $@ $<
+
+lmscan.cpp: lmparse.h
+
+lmscan.cpp: lmscan.rl
+ ragel -G2 -o $@ $<
+
+endif
+
+$(COLM_OBJ): %.o: %.cpp
+ @$(CXX) -M $(DEFS_COLM) $(INCS) $< > .$*.d
+ $(CXX) -c $(CFLAGS) $(DEFS_COLM) $(INCS) -o $@ $<
+
+$(RUNTIME_OBJ_P): %_p.o: %.cpp
+ @$(CXX) -M -MT $@ $(DEFS_RT_P) $(INCS) $< > .$*_p.d
+ $(CXX) -c $(CFLAGS) $(DEFS_RT_P) $(INCS) -o $@ $<
+
+$(RUNTIME_OBJ_D): %_d.o: %.cpp
+ @$(CXX) -M -MT $@ $(DEFS_RT_D) $(INCS) $< > .$*_d.d
+ $(CXX) -c $(CFLAGS) $(DEFS_RT_D) $(INCS) -o $@ $<
+
+
+distclean: clean
+ rm -f Makefile config.h
+
+ifeq ($(BUILD_PARSERS),true)
+EXTRA_CLEAN = $(GEN_SRC)
+endif
+
+clean:
+ rm -f tags .*.d *.o colm $(EXTRA_CLEAN) $(RUNTIME_P) $(RUNTIME_D)
+
+install: all
+ install -d $(prefix)/bin
+ install -d $(prefix)/include
+ install -d $(prefix)/include/colm
+ install -d $(prefix)/lib
+ install -s colm $(prefix)/bin/colm
+ install libcolmp.a libcolmd.a $(prefix)/lib
+ install ../aapl/astring.h ../aapl/avlcommon.h ../aapl/avlmap.h \
+ ../aapl/compare.h ../aapl/dlcommon.h ../aapl/dlist.h \
+ ../aapl/dlistval.h ../aapl/resize.h ../aapl/table.h \
+ ../aapl/vector.h bytecode.h config.h fsmrun.h input.h \
+ pdarun.h $(prefix)/include/colm
+
+-include $(DEPS)
diff --git a/buffer.h b/colm/buffer.h
index 9039ad4b..9039ad4b 100644
--- a/buffer.h
+++ b/colm/buffer.h
diff --git a/bytecode.cpp b/colm/bytecode.cpp
index 03474e73..03474e73 100644
--- a/bytecode.cpp
+++ b/colm/bytecode.cpp
diff --git a/bytecode.h b/colm/bytecode.h
index fc326906..fc326906 100644
--- a/bytecode.h
+++ b/colm/bytecode.h
diff --git a/closure.cpp b/colm/closure.cpp
index 5ee6538e..5ee6538e 100644
--- a/closure.cpp
+++ b/colm/closure.cpp
diff --git a/colm.h b/colm/colm.h
index 721529bd..721529bd 100644
--- a/colm.h
+++ b/colm/colm.h
diff --git a/compile.cpp b/colm/compile.cpp
index 19f42293..19f42293 100644
--- a/compile.cpp
+++ b/colm/compile.cpp
diff --git a/config.h.in b/colm/config.h.in
index f9da39b1..f9da39b1 100644
--- a/config.h.in
+++ b/colm/config.h.in
diff --git a/dotgen.cpp b/colm/dotgen.cpp
index eb69ba16..eb69ba16 100644
--- a/dotgen.cpp
+++ b/colm/dotgen.cpp
diff --git a/dotgen.h b/colm/dotgen.h
index e370866c..e370866c 100644
--- a/dotgen.h
+++ b/colm/dotgen.h
diff --git a/fsmap.cpp b/colm/fsmap.cpp
index 45e02f3e..45e02f3e 100644
--- a/fsmap.cpp
+++ b/colm/fsmap.cpp
diff --git a/fsmattach.cpp b/colm/fsmattach.cpp
index 31783ae0..31783ae0 100644
--- a/fsmattach.cpp
+++ b/colm/fsmattach.cpp
diff --git a/fsmbase.cpp b/colm/fsmbase.cpp
index 823a7858..823a7858 100644
--- a/fsmbase.cpp
+++ b/colm/fsmbase.cpp
diff --git a/fsmcodegen.cpp b/colm/fsmcodegen.cpp
index 0f5b1960..fe5a6fb3 100644
--- a/fsmcodegen.cpp
+++ b/colm/fsmcodegen.cpp
@@ -231,7 +231,7 @@ void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
ret <<
" }\n"
"\t"
- " return;\n";
+ " goto _resume;\n";
}
void FsmCodeGen::LM_ON_LAST( ostream &ret, InlineItem *item )
@@ -240,7 +240,7 @@ void FsmCodeGen::LM_ON_LAST( ostream &ret, InlineItem *item )
ret << " " << P() << " += 1;\n";
EMIT_TOKEN( ret, item->longestMatchPart->token );
- ret << " return;\n";
+ ret << " goto _resume;\n";
}
void FsmCodeGen::LM_ON_NEXT( ostream &ret, InlineItem *item )
@@ -248,7 +248,7 @@ void FsmCodeGen::LM_ON_NEXT( ostream &ret, InlineItem *item )
assert( item->longestMatchPart->token != 0 );
EMIT_TOKEN( ret, item->longestMatchPart->token );
- ret << " return;\n";
+ ret << " goto _resume;\n";
}
void FsmCodeGen::LM_ON_LAG_BEHIND( ostream &ret, InlineItem *item )
@@ -257,7 +257,7 @@ void FsmCodeGen::LM_ON_LAG_BEHIND( ostream &ret, InlineItem *item )
ret << " " << P() << " = " << TOKEND() << ";\n";
EMIT_TOKEN( ret, item->longestMatchPart->token );
- ret << " return;\n";
+ ret << " goto _resume;\n";
}
diff --git a/fsmcodegen.h b/colm/fsmcodegen.h
index 06e998c3..06e998c3 100644
--- a/fsmcodegen.h
+++ b/colm/fsmcodegen.h
diff --git a/fsmexec.cpp b/colm/fsmexec.cpp
index d08158b3..8f5d7600 100644
--- a/fsmexec.cpp
+++ b/colm/fsmexec.cpp
@@ -68,21 +68,21 @@ void FsmRun::execAction( GenAction *genAction )
emitToken( lmi->token );
}
}
- returnResult = true;
+ gotoResume = true;
break;
case InlineItem::LmOnLast:
p += 1;
emitToken( item->longestMatchPart->token );
- returnResult = true;
+ gotoResume = true;
break;
case InlineItem::LmOnNext:
emitToken( item->longestMatchPart->token );
- returnResult = true;
+ gotoResume = true;
break;
case InlineItem::LmOnLagBehind:
p = tokend;
emitToken( item->longestMatchPart->token );
- returnResult = true;
+ gotoResume = true;
break;
}
}
@@ -99,7 +99,7 @@ void FsmRun::execute()
unsigned int _nacts;
const char *_keys;
-//_resume:
+_resume:
if ( cs == tables->errorState )
goto out;
@@ -166,13 +166,13 @@ _match:
if ( tables->transActionsWI[_trans] == 0 )
goto _again;
- returnResult = false;
+ gotoResume = false;
_acts = tables->actions + tables->transActionsWI[_trans];
_nacts = (unsigned int) *_acts++;
while ( _nacts-- > 0 )
execAction( tables->actionSwitch[*_acts++] );
- if ( returnResult )
- return;
+ if ( gotoResume )
+ goto _resume;
_again:
_acts = tables->actions + tables->toStateActions[cs];
@@ -187,7 +187,7 @@ _again:
goto _loop_head;
out:
if ( p == peof ) {
- returnResult = false;
+ gotoResume = false;
_acts = tables->actions + tables->eofActions[cs];
_nacts = (unsigned int) *_acts++;
@@ -196,8 +196,8 @@ out:
while ( _nacts-- > 0 )
execAction( tables->actionSwitch[*_acts++] );
- if ( returnResult )
- return;
+ if ( gotoResume )
+ goto _resume;
}
}
diff --git a/fsmgraph.cpp b/colm/fsmgraph.cpp
index af643721..af643721 100644
--- a/fsmgraph.cpp
+++ b/colm/fsmgraph.cpp
diff --git a/fsmgraph.h b/colm/fsmgraph.h
index f898a3d6..f898a3d6 100644
--- a/fsmgraph.h
+++ b/colm/fsmgraph.h
diff --git a/fsmmin.cpp b/colm/fsmmin.cpp
index 3abc4e88..3abc4e88 100644
--- a/fsmmin.cpp
+++ b/colm/fsmmin.cpp
diff --git a/fsmrun.cpp b/colm/fsmrun.cpp
index 7281c76b..7281c76b 100644
--- a/fsmrun.cpp
+++ b/colm/fsmrun.cpp
diff --git a/fsmrun.h b/colm/fsmrun.h
index 1da1c266..ed25c829 100644
--- a/fsmrun.h
+++ b/colm/fsmrun.h
@@ -123,7 +123,7 @@ struct FsmRun
char *p, *pe, *peof;
bool eofSent;
RunBuf *runBuf;
- bool returnResult;
+ bool gotoResume;
char *mark[MARK_SLOTS];
};
diff --git a/fsmstate.cpp b/colm/fsmstate.cpp
index ab5bd93a..ab5bd93a 100644
--- a/fsmstate.cpp
+++ b/colm/fsmstate.cpp
diff --git a/input.cpp b/colm/input.cpp
index 5434b2d6..5434b2d6 100644
--- a/input.cpp
+++ b/colm/input.cpp
diff --git a/input.h b/colm/input.h
index 41feef25..41feef25 100644
--- a/input.h
+++ b/colm/input.h
diff --git a/keyops.h b/colm/keyops.h
index b5af65e7..b5af65e7 100644
--- a/keyops.h
+++ b/colm/keyops.h
diff --git a/list.cpp b/colm/list.cpp
index 8671fd51..8671fd51 100644
--- a/list.cpp
+++ b/colm/list.cpp
diff --git a/lmparse.kh b/colm/lmparse.kh
index 2cc3e99a..2cc3e99a 100644
--- a/lmparse.kh
+++ b/colm/lmparse.kh
diff --git a/lmparse.kl b/colm/lmparse.kl
index d4618c00..d4618c00 100644
--- a/lmparse.kl
+++ b/colm/lmparse.kl
diff --git a/lmscan.h b/colm/lmscan.h
index 8aa0d6da..8aa0d6da 100644
--- a/lmscan.h
+++ b/colm/lmscan.h
diff --git a/lmscan.rl b/colm/lmscan.rl
index d5e5f0f8..d5e5f0f8 100644
--- a/lmscan.rl
+++ b/colm/lmscan.rl
diff --git a/main.cpp b/colm/main.cpp
index a6170f0d..a6170f0d 100644
--- a/main.cpp
+++ b/colm/main.cpp
diff --git a/map.cpp b/colm/map.cpp
index 0a98ae5f..0a98ae5f 100644
--- a/map.cpp
+++ b/colm/map.cpp
diff --git a/parsedata.cpp b/colm/parsedata.cpp
index 32da2e5c..32da2e5c 100644
--- a/parsedata.cpp
+++ b/colm/parsedata.cpp
diff --git a/parsedata.h b/colm/parsedata.h
index 8d4dcb23..8d4dcb23 100644
--- a/parsedata.h
+++ b/colm/parsedata.h
diff --git a/parsetree.cpp b/colm/parsetree.cpp
index 5c951324..5c951324 100644
--- a/parsetree.cpp
+++ b/colm/parsetree.cpp
diff --git a/parsetree.h b/colm/parsetree.h
index 87880364..87880364 100644
--- a/parsetree.h
+++ b/colm/parsetree.h
diff --git a/pcheck.cpp b/colm/pcheck.cpp
index ee1985c7..ee1985c7 100644
--- a/pcheck.cpp
+++ b/colm/pcheck.cpp
diff --git a/pcheck.h b/colm/pcheck.h
index 5be60426..5be60426 100644
--- a/pcheck.h
+++ b/colm/pcheck.h
diff --git a/pdabuild.cpp b/colm/pdabuild.cpp
index d22a7db3..d22a7db3 100644
--- a/pdabuild.cpp
+++ b/colm/pdabuild.cpp
diff --git a/pdacodegen.cpp b/colm/pdacodegen.cpp
index 04a980ba..04a980ba 100644
--- a/pdacodegen.cpp
+++ b/colm/pdacodegen.cpp
diff --git a/pdacodegen.h b/colm/pdacodegen.h
index 7ca32546..7ca32546 100644
--- a/pdacodegen.h
+++ b/colm/pdacodegen.h
diff --git a/pdagraph.cpp b/colm/pdagraph.cpp
index ce3c3a7f..ce3c3a7f 100644
--- a/pdagraph.cpp
+++ b/colm/pdagraph.cpp
diff --git a/pdagraph.h b/colm/pdagraph.h
index 479a60de..479a60de 100644
--- a/pdagraph.h
+++ b/colm/pdagraph.h
diff --git a/pdarun.cpp b/colm/pdarun.cpp
index b85a32c0..b85a32c0 100644
--- a/pdarun.cpp
+++ b/colm/pdarun.cpp
diff --git a/pdarun.h b/colm/pdarun.h
index 240d97a4..240d97a4 100644
--- a/pdarun.h
+++ b/colm/pdarun.h
diff --git a/redbuild.cpp b/colm/redbuild.cpp
index 47b8c60d..47b8c60d 100644
--- a/redbuild.cpp
+++ b/colm/redbuild.cpp
diff --git a/redbuild.h b/colm/redbuild.h
index 2bc2b2f9..2bc2b2f9 100644
--- a/redbuild.h
+++ b/colm/redbuild.h
diff --git a/redfsm.cpp b/colm/redfsm.cpp
index 31995c91..31995c91 100644
--- a/redfsm.cpp
+++ b/colm/redfsm.cpp
diff --git a/redfsm.h b/colm/redfsm.h
index 305b67f9..305b67f9 100644
--- a/redfsm.h
+++ b/colm/redfsm.h
diff --git a/string.cpp b/colm/string.cpp
index d2452862..d2452862 100644
--- a/string.cpp
+++ b/colm/string.cpp
diff --git a/tree.cpp b/colm/tree.cpp
index f856ad3a..f856ad3a 100644
--- a/tree.cpp
+++ b/colm/tree.cpp
diff --git a/configure b/configure
new file mode 100755
index 00000000..f08d8a02
--- /dev/null
+++ b/configure
@@ -0,0 +1,4177 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="colm/main.cpp"
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+BUILD_PARSERS
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CXX
+CXXFLAGS
+ac_ct_CXX
+SET_MAKE
+RAGEL
+KELBT
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers colm/config.h"
+
+
+BUILD_PARSERS=true
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat >>confdefs.h <<_ACEOF
+#define CC $CC
+_ACEOF
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat >>confdefs.h <<_ACEOF
+#define CXX $CXX
+_ACEOF
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# Logging features
+# AC_ARG_ENABLE(log, "turn on logging", AC_DEFINE(COLM_LOG))
+# AC_ARG_ENABLE(log-bytecode, "turns on bytecode logging", AC_DEFINE(COLM_LOG_BYTECODE))
+# AC_ARG_ENABLE(log-parse, "turns on parse logging", AC_DEFINE(COLM_LOG_PARSE))
+# AC_ARG_ENABLE(log-match, "turns on match logging", AC_DEFINE(COLM_LOG_MATCH))
+# AC_ARG_ENABLE(log-compile, "turns on compile logging", AC_DEFINE(COLM_LOG_COMPILE))
+
+if test $BUILD_PARSERS = true; then
+
+# Extract the first word of "ragel", so it can be a program name with args.
+set dummy ragel; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RAGEL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RAGEL"; then
+ ac_cv_prog_RAGEL="$RAGEL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RAGEL="ragel"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RAGEL=$ac_cv_prog_RAGEL
+if test -n "$RAGEL"; then
+ { echo "$as_me:$LINENO: result: $RAGEL" >&5
+echo "${ECHO_T}$RAGEL" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+if test -z "$RAGEL"; then
+ echo
+ echo "error: ragel is required to build the parsers"
+ echo
+ exit 1
+fi
+
+# Extract the first word of "kelbt", so it can be a program name with args.
+set dummy kelbt; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_KELBT+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$KELBT"; then
+ ac_cv_prog_KELBT="$KELBT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_KELBT="kelbt"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+KELBT=$ac_cv_prog_KELBT
+if test -n "$KELBT"; then
+ { echo "$as_me:$LINENO: result: $KELBT" >&5
+echo "${ECHO_T}$KELBT" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+if test -z "$KELBT"; then
+ echo
+ echo "error: kelbt is required to build the parsers"
+ echo
+ exit 1
+fi
+
+fi # BUILD_PARSERS
+
+ac_config_files="$ac_config_files Makefile colm/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "colm/config.h") CONFIG_HEADERS="$CONFIG_HEADERS colm/config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "colm/Makefile") CONFIG_FILES="$CONFIG_FILES colm/Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+BUILD_PARSERS!$BUILD_PARSERS$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+RAGEL!$RAGEL$ac_delim
+KELBT!$KELBT$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 53; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+echo "configuration of colm complete"
diff --git a/configure.in b/configure.in
new file mode 100644
index 00000000..94fb7ba2
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,75 @@
+dnl
+dnl Copyright 2001-2008 Adrian Thurston <thurston@complang.org>
+dnl
+
+dnl This file is part of Colm.
+dnl
+dnl Colm is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl Colm is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with Colm; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+AC_INIT(colm/main.cpp)
+AC_CONFIG_HEADER(colm/config.h)
+
+dnl Set to true if build system should generate parsers from ragel, kelbt, and
+dnl gperf sources. Set to false if generated files are included and not to be
+dnl built (production).
+AC_SUBST(BUILD_PARSERS,true)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_DEFINE_UNQUOTED(CC,$CC)
+
+dnl Checks for programs.
+AC_PROG_CXX
+AC_DEFINE_UNQUOTED(CXX,$CXX)
+
+dnl Set test on c++ compiler.
+AC_LANG_CPLUSPLUS
+
+dnl Check for definition of MAKE.
+AC_PROG_MAKE_SET
+
+# Logging features
+# AC_ARG_ENABLE(log, "turn on logging", AC_DEFINE(COLM_LOG))
+# AC_ARG_ENABLE(log-bytecode, "turns on bytecode logging", AC_DEFINE(COLM_LOG_BYTECODE))
+# AC_ARG_ENABLE(log-parse, "turns on parse logging", AC_DEFINE(COLM_LOG_PARSE))
+# AC_ARG_ENABLE(log-match, "turns on match logging", AC_DEFINE(COLM_LOG_MATCH))
+# AC_ARG_ENABLE(log-compile, "turns on compile logging", AC_DEFINE(COLM_LOG_COMPILE))
+
+if test $BUILD_PARSERS = true; then
+
+dnl Check for Ragel
+AC_CHECK_PROG(RAGEL, ragel, ragel)
+if test -z "$RAGEL"; then
+ echo
+ echo "error: ragel is required to build the parsers"
+ echo
+ exit 1
+fi
+
+dnl Check for Kelbt
+AC_CHECK_PROG(KELBT, kelbt, kelbt)
+if test -z "$KELBT"; then
+ echo
+ echo "error: kelbt is required to build the parsers"
+ echo
+ exit 1
+fi
+
+fi # BUILD_PARSERS
+
+dnl write output files
+AC_OUTPUT(Makefile colm/Makefile)
+
+echo "configuration of colm complete"
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 00000000..492bfaf2
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright 2002-2006 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+SUBDIRS = xml python http dns diff html cxx ruby mediawiki
+
+all: $(BIN) $(SUBDIRS)
+
+.PHONY: $(SUBDIRS)
+
+$(SUBDIRS):
+ @cd $@ && $(MAKE)
+
+$(BIN): %.bin: %.lm
+ ../colm/colm $<
+
+# clean targets
+
+CLEAN_SUBDIRS = $(SUBDIRS:%=%-clean)
+
+.PHONY: $(CLEAN_SUBDIRS)
+
+$(CLEAN_SUBDIRS):
+ @cd $(@:%-clean=%) && $(MAKE) clean
+
+clean: $(CLEAN_SUBDIRS)
+ rm -f *.cpp *.bin
diff --git a/test/backtrack1.lm b/test/backtrack1.lm
new file mode 100644
index 00000000..0f3d8e88
--- /dev/null
+++ b/test/backtrack1.lm
@@ -0,0 +1,24 @@
+# Token names.
+
+lex start
+{
+ literal '+', '*'
+ token number /[0-9]+/
+ ignore ws / [ \t\n]+ /
+}
+
+def F
+ [number '+']
+| [number]
+| [F '*' number]
+
+def E
+ [E '+' F]
+| [F]
+
+def start
+ [E]
+
+start S = parse start( stdin )
+start R = match S ~ 9 + 9
+print_xml( R )
diff --git a/test/backtrack2.lm b/test/backtrack2.lm
new file mode 100644
index 00000000..fc63c7a6
--- /dev/null
+++ b/test/backtrack2.lm
@@ -0,0 +1,24 @@
+
+# Token names.
+lex start
+{
+ token id /[a-z]+/
+ ignore ws /[ \t\n]+/
+}
+
+token bang1 /'!'/
+token bang2 /'!'/
+
+def one [bang1 id id id]
+
+def two [bang2 id id id id]
+
+def prods
+ [one]
+| [two]
+
+def start
+ [prods]
+
+start S = parse start( stdin )
+match S "!aa bb cc dd"
diff --git a/test/backtrack3.lm b/test/backtrack3.lm
new file mode 100644
index 00000000..1f5e6e81
--- /dev/null
+++ b/test/backtrack3.lm
@@ -0,0 +1,27 @@
+
+# Token names.
+lex start
+{
+ token number /[0-9]+/
+ token id /[a-z]+/
+ token string /'"' [^"]* '"'/
+ ignore ws / [ \t\n]+ /
+}
+
+def prefix [id]
+
+def choice1
+ [number number]
+| [number]
+
+def choice2
+ [string id]
+| [number number]
+| [id number]
+| [number]
+
+def start
+ [prefix choice1 choice2 string id id]
+ {
+ match lhs "id 77 88 \"hello\" dude dude"
+ }
diff --git a/test/btscan.in b/test/btscan.in
new file mode 100644
index 00000000..88cec9d5
--- /dev/null
+++ b/test/btscan.in
@@ -0,0 +1,2 @@
+!abb !abba !aab
+
diff --git a/test/btscan.lm b/test/btscan.lm
new file mode 100644
index 00000000..ac7914c2
--- /dev/null
+++ b/test/btscan.lm
@@ -0,0 +1,34 @@
+namespace r1
+{
+ lex r1
+ {
+ literal '!', 'a', 'b'
+ ignore /[ \n\t]+/
+ }
+
+ def line [ '!' 'a' 'b' 'b' 'a']
+}
+
+namespace r2
+{
+ lex r2
+ {
+ literal '!'
+ token id /[a-zA-Z_]+/
+ ignore /[ \n\t]+/
+ }
+
+ def line [ '!' id ]
+}
+
+def item
+ [r1::line]
+| [r2::line]
+
+def btscan
+ [item*]
+
+btscan P = parse btscan( stdin )
+
+match P ~!abb !abba !aab
+print_xml(P)
diff --git a/test/commitbt.in b/test/commitbt.in
new file mode 100644
index 00000000..24a7dece
--- /dev/null
+++ b/test/commitbt.in
@@ -0,0 +1 @@
+1 2 3 * \ No newline at end of file
diff --git a/test/commitbt.lm b/test/commitbt.lm
new file mode 100644
index 00000000..75172b4b
--- /dev/null
+++ b/test/commitbt.lm
@@ -0,0 +1,110 @@
+#
+# Local commit:
+# -clears reparse flags underneath
+# -must be possible to backtrack after
+# Global commit (revertOn)
+# -clears all reparse flags
+# -must be possible to backtrack after
+# Global commit (!revertOn)
+# -clears all reparse flags
+# -clears all 'parsed' reverse code
+# -clears all reverse code
+# -clears all alg structures
+#
+
+# This test shows that a global commit with revertOn cannot clear 'parsed'
+# items because it must entertain the possibility of backtracking.
+
+lex start
+{
+ ignore /[\t\n ]+/
+ literal '^', '|', '-', ',', ':', '!', '?', '.'
+ literal '(', ')', '{', '}', '*', '&', '+'
+
+ literal '--', ':>', ':>>', '<:', '->', '**'
+
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ token uint /[0-9]+/
+}
+
+
+def expression [term expression_op*]
+
+def expression_op
+ ['|' term]
+| ['&' term]
+| ['-' term]
+| ['--' term]
+
+def term [factor_rep term_rest]
+
+# This list is done manually to get shortest match.
+def term_rest
+ []
+| [term_op term_rest]
+
+def term_op
+ [factor_rep]
+| ['.' factor_rep]
+| [':>' factor_rep]
+| [':>>' factor_rep]
+| ['<:' factor_rep]
+
+def factor_rep
+ [factor_neg factor_rep_op*]
+
+def factor_rep_op
+ ['*']
+| ['**']
+| ['?']
+| ['+']
+| ['{' factor_rep_num '}']
+| ['{' ',' factor_rep_num '}']
+| ['{' factor_rep_num ',' '}']
+| ['{' factor_rep_num ',' factor_rep_num '}']
+
+def factor_rep_num [uint]
+
+def factor_neg
+ ['!' factor_neg]
+| ['^' factor_neg]
+| [factor]
+
+def factor
+ [alphabet_num]
+| [word]
+| ['(' expression ')']
+
+def alphabet_num
+ [uint]
+
+global int i
+
+def suint
+ int i
+ [uint]
+ {
+ lhs.i = 0
+ i = 1
+ lhs = construct suint "1"
+ }
+
+def sub
+ [suint* '*']
+
+token item
+ sub S
+ /[0-9]+/
+ {
+ str M = pull(stdin, match_length)
+ sub S = parse sub(stdin)
+ send( make_token( typeid item, M, S ) )
+ }
+
+def stuff
+ [item* '!']
+| [sub]
+
+stuff S = parse stuff(stdin)
+
+print_xml( S )
diff --git a/test/constructex.in b/test/constructex.in
new file mode 100644
index 00000000..f458f2ad
--- /dev/null
+++ b/test/constructex.in
@@ -0,0 +1,3 @@
+<person name=adrian hometown=kingston>
+ <t1 foo=bar2 e=f></t2>
+</person> \ No newline at end of file
diff --git a/test/constructex.lm b/test/constructex.lm
new file mode 100644
index 00000000..01d71f37
--- /dev/null
+++ b/test/constructex.lm
@@ -0,0 +1,37 @@
+lex start
+{
+ token id /[a-zA-Z_][a-zA-Z0-9_]*/
+ literal '=', '<', '>', '/'
+ ignore /[ \t\n\r\v]+/
+}
+
+def attr
+ [id '=' id]
+
+def open_tag
+ ['<' id attr* '>']
+
+def close_tag
+ ['<' '/' id '>']
+
+def tag
+ [open_tag item* close_tag]
+
+def item
+ [tag]
+| [id]
+
+tag PersonTag = parse tag( stdin )
+
+match PersonTag
+ ["<person name=" Val:id attr*">" item* "</person>"]
+
+tag NameTag1 = construct tag
+ ["<name type=person>" Val "</name>"]
+
+tag NameTag2 = construct tag
+ "<name type=person>[Val]</name>"
+
+print( NameTag1, '\n' )
+print( NameTag2, '\n' )
+
diff --git a/test/counting1.in b/test/counting1.in
new file mode 100644
index 00000000..45eeecde
--- /dev/null
+++ b/test/counting1.in
@@ -0,0 +1 @@
+3 1 b c 1 1 0 3 a b c
diff --git a/test/counting1.lm b/test/counting1.lm
new file mode 100644
index 00000000..bd0154ec
--- /dev/null
+++ b/test/counting1.lm
@@ -0,0 +1,91 @@
+
+#
+# Regular Definitions
+#
+rl rl_ws /[ \t\n\r\v]+/
+rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/
+rl rl_num /[0-9]+/
+
+#
+# Tokens
+#
+
+lex start
+{
+ # Ignore whitespace.
+ ignore /rl_ws/
+
+ # Tokens.
+ token id /rl_id/
+ token number /rl_num/
+}
+
+#
+# Global Data
+#
+
+global int target
+
+#
+# Productions
+#
+
+
+def get_target
+ [number]
+ {
+ match lhs [Number:number]
+ target = Number.data.atoi()
+ }
+
+# Arbitrary item.
+def item
+ [number]
+| [id]
+
+# Type definition for the count_items nonterminal.
+def count_items
+ int count
+
+ # List production one. The condition stops the
+ # greedy list when it has gone too far.
+ [count_items item]
+ {
+ # Pass up the data
+ lhs.count = r1.count + 1
+ if lhs.count > target {
+ reject
+ }
+ }
+
+ # List production two, the base.
+| []
+ {
+ lhs.count = 0
+ }
+
+# Wrapper which prevents short lists from getting through if the parser
+# encounters an error and needs to backtrack over counted list.
+def counted_list
+ [get_target count_items]
+ {
+ if r2.count < target {
+ reject
+ }
+ }
+
+
+def start
+ [counted_list*]
+ {
+ for List:counted_list in lhs {
+ match List [Count:number Items:count_items]
+ print( 'num items: ', Count.data.atoi(), '\n' )
+
+ int i = 1
+ for Item:item in Items {
+ print( ' item ', i, ': ', Item, '\n' )
+ i = i + 1
+ }
+ }
+ }
diff --git a/test/counting2.lm b/test/counting2.lm
new file mode 100644
index 00000000..1044e5cb
--- /dev/null
+++ b/test/counting2.lm
@@ -0,0 +1,82 @@
+
+#
+# Regular Definitions
+#
+
+rl rl_ws /[ \t\n\r\v]+/
+rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/
+rl rl_num /[0-9]+/
+
+#
+# Tokens
+#
+
+lex start
+{
+ # Ignore whitespace.
+ ignore /rl_ws/
+
+ # Tokens.
+ token id /rl_id/
+ token number /rl_num/
+}
+
+#
+# Productions
+#
+
+# Arbitrary item.
+def item
+ [id]
+| [number]
+
+# List production one. The condition stops the
+# greedy list when it has gone too far.
+def count_items
+ int target
+ int count
+
+ [count_items item]
+ {
+ # Pass up the data
+ lhs.target = r1.target
+ lhs.count = r1.count + 1
+
+ if lhs.count > lhs.target {
+ reject
+ }
+ }
+
+ # List production two, the base.
+| [number]
+ {
+ match lhs [Number:number]
+ lhs.target = Number.data.atoi()
+ lhs.count = 0
+ }
+
+
+# Wrapper which prevents short lists from getting through if the parser
+# encounters an error and needs to backtrack over counted list.
+def counted_list
+ [count_items]
+ {
+ if r1.count < r1.target {
+ reject
+ }
+ }
+
+def start
+ [counted_list*]
+ {
+ for List:counted_list in lhs {
+ match List [CountItems:count_items]
+ print( 'num items: ', CountItems.target, '\n' )
+
+ int i = 1
+ for Item:item in CountItems {
+ print( ' item ', i, ': ', Item, '\n' )
+ i = i + 1
+ }
+ }
+ }
diff --git a/test/counting3.lm b/test/counting3.lm
new file mode 100644
index 00000000..d925b732
--- /dev/null
+++ b/test/counting3.lm
@@ -0,0 +1,92 @@
+
+#
+# Regular Definitions
+#
+rl rl_ws /[ \t\n\r\v]+/
+rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/
+rl rl_num /[0-9]+/
+
+#
+# Tokens
+#
+
+lex start
+{
+ # Ignore whitespace.
+ ignore /rl_ws/
+
+ literal ';'
+
+ # Tokens.
+ token id /rl_id/
+ token number /rl_num/
+}
+
+#
+# Global Data
+#
+
+global int target
+global int count
+
+#
+# Productions
+#
+
+
+def get_target
+ [number]
+ {
+ count = 0
+ target = r1.data.atoi()
+ print( 'target: ', target, '\n' )
+ }
+
+# Arbitrary item.
+def item
+ [number]
+| [id]
+
+def count_items
+ [one_item count_items]
+| []
+
+def one_item
+ [item]
+ {
+ count = count + 1
+ if count > target {
+ reject
+ }
+ print( 'ITEM\n' )
+ }
+
+
+# Wrapper which prevents short lists from getting through if the parser
+# encounters an error and needs to backtrack over counted list.
+def counted_list
+ [get_target count_items]
+ {
+ print( 'trying: ', count, ' for: ', target, '\n' )
+ if count < target {
+ reject
+ }
+ }
+
+
+def start
+ [counted_list*]
+ {
+
+ for List:counted_list in lhs {
+ match List [Count:number Items:count_items]
+ print( 'num items: ', Count.data.atoi(), '\n' )
+
+ int i = 1
+ for Item:item in Items {
+ print( ' item ', i, ': ', Item, '\n' )
+ i = i + 1
+ }
+ }
+ print( '*** SUCCESS ***\n' )
+ }
diff --git a/test/counting4.lm b/test/counting4.lm
new file mode 100644
index 00000000..b1a75130
--- /dev/null
+++ b/test/counting4.lm
@@ -0,0 +1,89 @@
+
+#
+# Regular Definitions
+#
+rl rl_ws /[ \t\n\r\v]+/
+rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/
+rl rl_num /[0-9]+/
+
+#
+# Tokens
+#
+
+lex start
+{
+ # Ignore whitespace.
+ ignore /rl_ws/
+
+ literal ';'
+
+ # Tokens.
+ token id /rl_id/
+ token number /rl_num/
+}
+
+#
+# Global Data
+#
+
+global int target
+global int count
+
+#
+# Productions
+#
+
+
+def get_target
+ [number]
+ {
+ count = 0
+ target = r1.data.atoi()
+ print( 'target: ', target, '\n' )
+ }
+
+# Arbitrary item.
+def item
+ [number]
+| [id]
+
+def count_items
+ [count_inc item count_items]
+| [count_end]
+
+def count_inc
+ []
+ {
+ if count < target
+ count = count + 1
+ else
+ reject
+ }
+
+def count_end
+ []
+ {
+ if count < target
+ reject
+ }
+
+def counted_list
+ [get_target count_items]
+
+def start
+ [counted_list*]
+ {
+ for List:counted_list in lhs {
+ match List [Count:number Items:count_items]
+ print( 'num items: ', Count.data.atoi(), '\n' )
+
+ int i = 1
+ for Item:item in Items {
+ print( ' item ', i, ': ', Item, '\n' )
+ i = i + 1
+ }
+ }
+ print( '*** SUCCESS ***\n' )
+ }
+
+parse start(stdin)
diff --git a/test/cxx/Makefile b/test/cxx/Makefile
new file mode 100644
index 00000000..9fb58795
--- /dev/null
+++ b/test/cxx/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright 2002-2006 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f cxx.cpp *.bin
diff --git a/test/cxx/cxx.lm b/test/cxx/cxx.lm
new file mode 100644
index 00000000..31fcc92e
--- /dev/null
+++ b/test/cxx/cxx.lm
@@ -0,0 +1,2168 @@
+#
+# Data types for global data.
+#
+
+# Map definition
+map object_map [str object_list]
+
+# Language objects.
+def lang_object
+ int typeId
+ str name
+
+ # If the object is a typedef, this points to the real object.
+ ptr lang_object typedefOf
+
+ object_map objectMap
+ object_list inherited
+ ptr lang_object lookupParent
+ ptr lang_object specializationOf
+ []
+
+# This structure is used to keep track of information necessary to make a
+# declaration. While parsing a declaration it records the declaration's
+# attributes.
+def declaration_data
+ int isTypedef
+ int isFriend
+ int isTemplate
+
+ ptr lang_object typeObj
+ []
+
+def declarator_data
+ ptr lang_object qualObj
+ ptr lang_object pdcScope
+ ptr lang_object lookupObj
+ []
+
+list declaration_data_list [declaration_data]
+list declarator_data_list [declarator_data]
+
+# Constants for language object types.
+global int NamespaceType = typeid namespace_id
+global int ClassType = typeid class_id
+global int TemplateClassType = typeid templ_class_id
+global int EnumType = typeid enum_id
+global int IdType = typeid identifier
+global int TypedefType = typeid typedef_id
+global int TemplateIdType = typeid template_id
+
+# Object stack definition. Uses references to objects.
+list object_list [ptr lang_object]
+
+# Stack of integers.
+list int_stack [int]
+
+#
+# Global data declarations
+#
+
+# Object stacks.
+global object_list curNamespace = construct object_list []
+global object_list declNs = construct object_list []
+global object_list lookupNs = construct object_list []
+global object_list qualNs = construct object_list []
+global object_list templateParamNs = construct object_list []
+
+# Declaration, declarator data.
+global declaration_data_list declarationData = construct declaration_data_list []
+global declarator_data_list declaratorData = construct declarator_data_list []
+
+# Template declarations
+global int_stack templDecl = construct int_stack []
+
+# Root namespace object
+global ptr lang_object rootNamespace = createLangObject( NamespaceType,
+ '<root_namespace>', nil )
+
+# Initialize the namespace and declaration stacks with the root namespace
+curNamespace.push( rootNamespace )
+declNs.push( rootNamespace )
+lookupNs.push( rootNamespace )
+
+# Start with no qualification (note variables are initialized to zero)
+qualNs.push( nil )
+
+templDecl.push( 0 )
+declarationData.push( construct declaration_data(
+ isTypedef: 0, isFriend: 0, isTemplate: 0 ) [] )
+
+#
+# Identifier lookup.
+#
+
+# Lookup the token in the members of an object.
+ptr lang_object lookupInObject( ptr lang_object obj, str name )
+{
+ # LOG print( ' looking in ', obj->name, '\n' )
+
+ object_list ol = obj->objectMap.find( name )
+ if ol {
+ # LOG print( ' * found an object: ', ol.head, '\n' )
+ return ol.head
+ }
+
+ return nil
+}
+
+# Lookup in an object and all the objects beneath it in the inheritance
+# tree.
+ptr lang_object lookupWithInheritance( ptr lang_object obj, str name )
+{
+ ptr lang_object found = lookupInObject( obj, name )
+ if found
+ return found
+
+ object_list localObjInherited = obj->inherited
+ for II: ptr lang_object in localObjInherited {
+ ptr lang_object inh = II
+
+ # First check if the inherited object is the one we are after.
+ if inh->name == name && inh->typeId == ClassType {
+ # LOG print( ' * found a class name\n' )
+ return inh
+ }
+
+ # Otherwise look inside the inherited object.
+ found = lookupWithInheritance( inh, name )
+ if found
+ return found
+ }
+
+ return nil
+}
+
+ptr lang_object unqualifiedLookup( str name )
+{
+ ptr lang_object found
+
+ # Start with the objects in the templateParamNs.
+ object_list localTemplateParamNs = templateParamNs
+ for TemplParaObjIter: ptr lang_object in rev_child(localTemplateParamNs) {
+ found = lookupWithInheritance( TemplParaObjIter, name )
+ if found
+ break
+ }
+
+ if !found {
+ # Iterator over the objects starting at the head of the lookup stack
+ # and going up through the lookup parents.
+ ptr lang_object lookupIn = lookupNs.top
+ while lookupIn {
+ found = lookupWithInheritance( lookupIn, name )
+ if found
+ break
+ lookupIn = lookupIn->lookupParent
+ }
+ }
+
+ return found
+}
+
+# The C++ scanner.
+lex start
+{
+ rl fract_const / digit* '.' digit+ | digit+ '.' /
+ rl exponent / [eE] [+\-]? digit+ /
+ rl float_suffix / [flFL] /
+
+ # Single and double literals.
+ token TK_SingleLit /( 'L'? "'" ( [^'\\\n] | '\\' any )* "'" )/
+ token TK_DoubleLit /( 'L'? '"' ( [^"\\\n] | '\\' any )* '"' )/
+
+ literal 'extern', 'namespace', 'friend', 'typedef', 'auto', 'register',
+ 'static', 'mutable', 'inline', 'virtual', 'explicit', 'const',
+ 'volatile', 'restrict', 'class', 'struct', 'union', 'template',
+ 'private', 'protected', 'public', 'using', 'void', 'char',
+ 'wchar_t', 'bool', 'int', 'float', 'double', 'short', 'long',
+ 'signed', 'unsigned', 'enum', 'new', 'delete', 'operator',
+ 'typename', 'export', 'throw', 'try', 'catch', 'sizeof',
+ 'dynamic_cast', 'static_cast', 'reinterpret_cast', 'const_cast',
+ 'typeid', 'this', 'true', 'false', 'switch', 'case', 'default',
+ 'if', 'else', 'while', 'do', 'for', 'break', 'continue',
+ 'return', 'goto'
+
+ literal '__typeof'
+
+ literal '{', '}', ';', ',', '=', '(', ')', ':', '&', '*', '[', ']', '~', '+', '-',
+ '/', '<', '>', '|', '^', '%', '!', '?', '.'
+
+ literal '::', '==', '!=', '&&', '||', '*=', '/=', '%=', '+=', '-=', '&=',
+ '^=', '|=', '++', '--', '->', '->*', '.*', '...', '<<=', '>>='
+
+ # Token translation targets.
+ def unknown_id [lookup_id]
+ def class_id [lookup_id]
+ def namespace_id [lookup_id]
+ def templ_class_id [lookup_id]
+ def enum_id [lookup_id]
+ def typedef_id [lookup_id]
+ def identifier [lookup_id]
+ def template_id [lookup_id]
+
+ # Identifiers
+ token lookup_id
+ ptr lang_object obj
+ ptr lang_object qualObj
+
+ /( [a-zA-Z_] [a-zA-Z0-9_]* )/
+ {
+ str name = match_text
+ ptr lang_object found = nil
+ ptr lang_object qualObj = nil
+ if qualNs.top {
+ # LOG print( 'qualified lookup of ', name, '\n' )
+
+ # Transfer the qualification to the token and reset it.
+ qualObj = qualNs.top
+ qualNs.top = nil
+
+ # Lookup using the qualification.
+ found = lookupWithInheritance( qualObj, name )
+ }
+ else {
+ # No qualification, full search.
+ # LOG print( 'unqualified lookup of ', name, '\n' )
+ found = unqualifiedLookup( name )
+ }
+
+ # If no match, return an Unknown ID
+ int id = typeid unknown_id
+ if found
+ id = found->typeId
+
+ any LookupId = make_token( typeid lookup_id,
+ pull(stdin, match_length), found, qualObj )
+ send( make_tree( id, LookupId ) )
+
+ }
+
+ # Floats.
+ token TK_Float /( fract_const exponent? float_suffix? |
+ digit+ exponent float_suffix? )/
+
+ # Integer decimal. Leading part buffered by float.
+ token TK_IntegerDecimal /( ( '0' | [1-9] [0-9]* ) [ulUL]{0,3} )/
+
+ # Integer octal. Leading part buffered by float.
+ token TK_IntegerOctal /( '0' [0-9]+ [ulUL]{0,2} )/
+
+ # Integer hex. Leading 0 buffered by float.
+ token TK_IntegerHex /( '0x' [0-9a-fA-F]+ [ulUL]{0,2} )/
+
+ # Preprocessor line.
+ ignore /'#' [^\n]* '\n'/
+
+ # Comments and whitespace.
+ ignore /( '/*' (any | '\n')* :>> '*/' )/
+ ignore /( '//' any* :> '\n' )/
+ ignore /( any - 33..126 )+/
+}
+
+#
+# Support functions
+#
+
+ptr lang_object createLangObject( int typeId, str name, ptr lang_object lookupParent )
+{
+ ptr lang_object obj = new construct lang_object(
+ typeId: typeId,
+ name: name,
+ objectMap: construct object_map [],
+ inherited: construct object_list [],
+ lookupParent: lookupParent ) []
+ return obj
+}
+
+# Building the language object tree.
+int insertObject( ptr lang_object definedIn, str name, ptr lang_object obj )
+{
+ object_list ol = definedIn->objectMap.find( name )
+ if !ol {
+ # Element not in the map already
+ ol = construct object_list []
+ }
+ ol.append( obj )
+ definedIn->objectMap.store( name, ol )
+}
+
+ptr lang_object findClass( ptr lang_object inObj, str name )
+{
+ object_list ol = inObj->objectMap.find( name )
+ if ol {
+ for ObjIter: ptr lang_object in ol {
+ ptr lang_object obj = ObjIter
+ if obj->typeId == ClassType {
+ return obj
+ }
+ }
+ }
+ return nil
+}
+
+ptr lang_object findTemplateClass( ptr lang_object inObj, str name )
+{
+ object_list ol = inObj->objectMap.find( name )
+ if ol {
+ for ObjIter: ptr lang_object in ol {
+ ptr lang_object obj = ObjIter
+ if obj->typeId == TemplateClassType
+ return obj
+ }
+ }
+ return nil
+}
+
+def root_qual_opt
+ []
+| ['::']
+
+def nested_name_specifier_opt
+ [nested_name_specifier_opt qualifying_name '::' designated_qualifying_name '::']
+| [nested_name_specifier_opt qualifying_name '::']
+| []
+
+def nested_name_specifier
+ [nested_name_specifier designated_qualifying_name '::']
+| [nested_name_specifier qualifying_name '::']
+| [qualifying_name '::']
+
+def qualifying_name
+ [class_name]
+ {
+ qualNs.top = r1.lookupId.obj
+ }
+
+| [namespace_id]
+ {
+ match r1 [Id: lookup_id]
+ qualNs.top = Id.obj
+ }
+
+| [typedef_id]
+ {
+ match r1 [Id: lookup_id]
+ qualNs.top = Id.obj->typedefOf
+ }
+
+def designated_qualifying_name
+ ['template' any_id]
+ {
+ # FIXME: nulling qualNs is not the right thing to do here.
+ qualNs.top = nil
+ }
+
+| ['template' any_id
+ templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ # FIXME: nulling qualNs is not the right thing to do here.
+ qualNs.top = nil
+ }
+
+#
+# Id Expression
+#
+
+def id_expression
+ lookup_id lookupId
+
+ [root_qual_opt nested_name_specifier_opt unknown_id]
+ {
+ lhs.lookupId = lookup_id in r3
+ }
+
+| [root_qual_opt nested_name_specifier_opt identifier]
+ {
+ lhs.lookupId = lookup_id in r3
+ }
+
+| [root_qual_opt nested_name_specifier_opt operator_function_id]
+ {
+ # Normally the token translation transfers the qualification. Since
+ # the operator_function_id does not end in a lookup we must do it ourselves.
+ ptr lang_object qualObj = qualNs.top
+ qualNs.top = nil
+
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<operator_function_id>'
+ lhs.lookupId.qualObj = qualObj
+ }
+
+| [root_qual_opt nested_name_specifier_opt conversion_function_id]
+ {
+ # Normally the token translation transfers the qualification. Since
+ # the operator_function_id does not } in a lookup we must do it ourselves.
+ ptr lang_object qualObj = qualNs.top
+ qualNs.top = nil
+
+ # Do we need qual reset here becauase operator_function_id does not do it?
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<conversion_function_id>'
+ lhs.lookupId.qualObj = qualObj
+ }
+
+| [root_qual_opt nested_name_specifier_opt '~' class_name]
+ {
+ lhs.lookupId = r4.lookupId
+ }
+
+| [root_qual_opt nested_name_specifier_opt template_name]
+ {
+ lhs.lookupId = r3.lookupId
+ }
+
+def template_name
+ lookup_id lookupId
+
+ [template_id templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+| [template_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+
+#
+# Class Names
+#
+
+def class_name
+ lookup_id lookupId
+
+ [class_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+| [templ_class_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+| [templ_class_id templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ # TODO: Look for a specialization.
+ lhs.lookupId = lookup_id in r1
+ }
+
+def templ_arg_open
+ ['<']
+ {
+ qualNs.push( nil )
+ }
+
+def templ_arg_close
+ ['>']
+ {
+ qualNs.pop()
+ }
+
+def declaration
+ [block_declaration] commit
+| [function_definition] commit
+| [template_declaration] commit
+| [explicit_instantiation] commit
+| [explicit_specialization] commit
+| [linkage_specification] commit
+| [namespace_definition] commit
+
+#
+# Declarations
+#
+
+def block_declaration
+ [simple_declaration]
+| [using_declaration]
+| [using_directive]
+
+def simple_declaration
+ [declaration_start simple_declaration_forms declaration_end ';']
+
+# Ordering is important for optimization. The form with the optional
+# decl_specifier_sing should go second.
+def simple_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing
+ decl_specifier_mult_seq_opt init_declarator_list_opt]
+
+| [decl_specifier_mult_seq_opt init_declarator_list_opt]
+
+def declaration_start
+ []
+ {
+ # LOG print( 'opening new declaration_data with templDecl: ', templDecl.top, '\n' )
+ declarationData.push( construct declaration_data (
+ isTypedef: 0, isFriend: 0, isTemplate: 0 ) [] )
+
+ # Transfer the template flag and reset it.
+ declarationData.top.isTemplate = templDecl.top
+ templDecl.push( 0 )
+ }
+
+def declaration_end
+ []
+ {
+ # LOG print( 'closing declaration_data\n' )
+ declarationData.pop()
+ templDecl.pop()
+ }
+
+def decl_specifier_sing
+ [type_specifier_sing]
+ {
+ # Store the object type of the declaration (if any) for use
+ # by typedefs.
+ declarationData.top.typeObj = r1.lookupId.obj
+ }
+
+def type_specifier_seq
+ lookup_id lookupId
+
+ [type_specifier_mult_seq_opt type_specifier_sing type_specifier_mult_seq_opt]
+ {
+ lhs.lookupId = r2.lookupId
+ }
+
+def type_specifier_sing
+ lookup_id lookupId
+
+ [simple_type_specifier]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+| [class_specifier]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<class_specifier>'
+ }
+
+| [enum_specifier]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<enum_specifier>'
+ }
+
+| [elaborated_type_specifier]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<elaborated_type_specifier>'
+ }
+
+# Type specifier sequence without enum specifier or class specifier.
+def necs_type_specifier_seq
+ [type_specifier_mult_seq_opt necs_type_specifier_sing type_specifier_mult_seq_opt]
+
+# Type specifier singular without enum specifier or class specifier.
+def necs_type_specifier_sing
+ [simple_type_specifier]
+| [elaborated_type_specifier]
+
+def type_specifier_mult_seq_opt
+ [type_specifier_mult_seq_opt type_specifier_mult]
+| []
+
+def type_specifier_mult_seq
+ [type_specifier_mult_seq type_specifier_mult]
+| [type_specifier_mult]
+
+def simple_type_specifier
+ lookup_id lookupId
+
+ [simple_type_specifier_name]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+| [simple_type_specifier_kw_seq]
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<simple_type_specifier_kw_seq>'
+ }
+
+| ['typename' root_qual_opt nested_name_specifier type_name]
+ {
+ lhs.lookupId = r4.lookupId
+ }
+
+| ['typename' root_qual_opt nested_name_specifier identifier]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+| ['typename' root_qual_opt nested_name_specifier unknown_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+ # Extension.
+| ['__typeof' '(' identifier ')']
+ {
+ lhs.lookupId = construct lookup_id ["x"]
+ lhs.lookupId.data = '<simple_type_specifier_kw_seq>'
+ }
+
+def simple_type_specifier_name
+ lookup_id lookupId
+
+ [qual_type_name]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+def simple_type_specifier_kw_seq
+ [simple_type_specifier_kw_seq simple_type_specifier_kw]
+| [simple_type_specifier_kw]
+
+def simple_type_specifier_kw
+ ['void']
+| ['char']
+| ['wchar_t']
+| ['bool']
+| ['int']
+| ['float']
+| ['double']
+| ['short']
+| ['long']
+| ['signed']
+| ['unsigned']
+
+def qual_type_name
+ lookup_id lookupId
+
+ [root_qual_opt nested_name_specifier_opt type_name]
+ {
+ lhs.lookupId = r3.lookupId
+ }
+
+def type_name
+ lookup_id lookupId
+
+ [class_name]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+| [enum_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+| [typedef_id]
+ {
+ lhs.lookupId = lookup_id in r1
+ }
+
+# NOTE: the typename case is moved to simple type specifier
+# to take advantage of its conflict resolution.
+def elaborated_type_specifier
+ [class_key nested_name_specifier_opt class_head_name]
+ {
+ lookup_id Id = lookup_id in r3
+ str name = Id.data
+
+ # Get the ns the class is declared in.
+ ptr lang_object parentObj = declNs.top
+ if Id.qualObj
+ parentObj = Id.qualObj
+
+ # Look for the class in the given scope.
+ ptr lang_object declaredClass = findClass( parentObj, name )
+ if !declaredClass
+ declaredClass = findTemplateClass( parentObj, name )
+
+ if !declaredClass {
+ # LOG print( 'creating new class: ', name, '\n' )
+
+ # Class does not exist in the parent scope, create it.
+ int nsType = declaredClassType()
+
+ declaredClass = createLangObject( nsType, name, lookupNs.top )
+
+ # FIXME: handle friends. Make the class visible only if we are NOT
+ # in a friend declaration. The new class object is necessary to
+ # properly process the body of the class.
+ if declarationData.top.isFriend == 0
+ insertObject( parentObj, name, declaredClass )
+ }
+ }
+
+ # TODO: Lookup type specialization.
+| [class_key nested_name_specifier_opt templ_class_id
+ templ_arg_open template_argument_list_opt templ_arg_close]
+
+| ['enum' nested_name_specifier_opt enum_head_name]
+ {
+ # TODO: should look for existing enums of the same name.
+ lookup_id Id = lookup_id in r3
+ # LOG print( 'creating enumeration ', Id.data, '\n' )
+ ptr lang_object enum = createLangObject( EnumType, Id.data, lookupNs.top )
+ insertObject( declNs.top, Id.data, enum )
+ }
+
+def decl_specifier_mult_seq_opt
+ [decl_specifier_mult_seq_opt decl_specifier_mult]
+| []
+
+def decl_specifier_mult_seq
+ [decl_specifier_mult_seq decl_specifier_mult]
+| [decl_specifier_mult]
+
+def decl_specifier_mult
+ [type_specifier_mult]
+| [storage_class_specifier]
+| [function_specifier]
+
+| ['friend']
+ {
+ declarationData.top.isFriend = 1
+ }
+
+| ['typedef']
+ {
+ declarationData.top.isTypedef = 1
+ }
+
+def storage_class_specifier
+ ['auto']
+| ['register']
+| ['static']
+| ['extern']
+| ['mutable']
+
+def function_specifier
+ ['inline']
+| ['virtual']
+| ['explicit']
+
+def type_specifier_mult
+ [cv_qualifier]
+
+def cv_qualifier
+ ['const']
+| ['volatile']
+| ['restrict']
+
+def cv_qualifier_rep
+ [cv_qualifier_rep cv_qualifier]
+| []
+
+def namespace_definition
+ [named_namespace_definition]
+| [unnamed_namespace_definition]
+
+def named_namespace_definition
+ [original_namespace_definition]
+| [extension_namespace_definition]
+
+#
+# Enumerations
+#
+
+def enum_specifier
+ ['enum' nested_name_specifier_opt
+ enum_head_name '{' enumerator_list_opt '}']
+ {
+ # TODO: should look for existing enums of the same name.
+ lookup_id Id = lookup_id in r3
+ # LOG print( 'creating enumeration ', Id.data, '\n' )
+ ptr lang_object enum = createLangObject( EnumType, Id.data, lookupNs.top )
+ insertObject( declNs.top, Id.data, enum )
+ }
+
+| ['enum' '{' enumerator_list_opt '}']
+
+def enum_head_name
+ [class_id]
+| [templ_class_id]
+| [namespace_id]
+| [typedef_id]
+| [enum_id]
+| [identifier]
+| [template_id]
+| [unknown_id]
+
+def enumerator_list_opt
+ [enumerator_list]
+| [enumerator_list ',']
+| []
+
+def enumerator_list
+ [enumerator_list ',' enumerator_definition]
+| [enumerator_definition]
+
+def enumerator_definition
+ [enumerator_id]
+ {
+ lookup_id Id = lookup_id in r1
+ ptr lang_object enumId = createLangObject( IdType, Id.data, lookupNs.top )
+ insertObject( declNs.top, Id.data, enumId )
+ }
+
+| [enumerator_id '=' constant_expression]
+ {
+ lookup_id Id = lookup_id in r1
+ ptr lang_object enumId = createLangObject( IdType, Id.data, lookupNs.top )
+ insertObject( declNs.top, Id.data, enumId )
+ }
+
+def enumerator_id
+ [namespace_id]
+| [typedef_id]
+| [enum_id]
+| [class_id]
+| [templ_class_id]
+| [template_id]
+| [identifier]
+| [unknown_id]
+
+#
+# Declarators
+#
+
+def init_declarator_list_opt
+ [init_declarator_list]
+| []
+
+def init_declarator_list
+ [init_declarator_list ',' init_declarator]
+| [init_declarator]
+
+def init_declarator
+ [declarator initializer_opt]
+
+def initializer_opt
+ ['=' initializer_clause]
+| ['(' expression ')']
+| []
+
+def initializer_clause
+ [assignment_expression]
+| ['{' initializer_list '}']
+| ['{' initializer_list ',' '}']
+| ['{' '}']
+
+def initializer_list
+ [initializer_list ',' initializer_clause]
+| [initializer_clause]
+
+#
+# Expressions
+#
+
+def expression
+ [expression ',' assignment_expression]
+| [assignment_expression]
+
+def expression_opt
+ [expression]
+| []
+
+def constant_expression
+ [conditional_expression]
+
+def constant_expression_opt
+ [constant_expression]
+| []
+
+def assignment_expression
+ [conditional_expression]
+| [logical_or_expression assignment_op assignment_expression]
+| [throw_expression]
+
+def assignment_op
+ ['=']
+| ['*=']
+| ['/=']
+| ['%=']
+| ['+=']
+| ['-=']
+| ['>>=']
+| ['<<=']
+| ['&=']
+| ['^=']
+| ['|=']
+
+def conditional_expression
+ [logical_or_expression]
+| [logical_or_expression '?' expression ':' assignment_expression]
+
+def logical_or_expression
+ [logical_or_expression '||' logical_and_expression]
+| [logical_and_expression]
+
+def logical_and_expression
+ [logical_and_expression '&&' inclusive_or_expression]
+| [inclusive_or_expression]
+
+def inclusive_or_expression
+ [inclusive_or_expression '|' exclusive_or_expression]
+| [exclusive_or_expression]
+
+def exclusive_or_expression
+ [exclusive_or_expression '^' and_expression]
+| [and_expression]
+
+def and_expression
+ [and_expression '&' equality_expression]
+| [equality_expression]
+
+def equality_expression
+ [equality_expression '==' relational_expression]
+| [equality_expression '!=' relational_expression]
+| [relational_expression]
+
+def relational_expression
+ [relational_expression '<' shift_expression]
+| [relational_expression '>' shift_expression]
+| [relational_expression lt_eq shift_expression]
+| [relational_expression gt_eq shift_expression]
+| [shift_expression]
+
+def shift_expression
+ [shift_expression shift_left additive_expression]
+| [shift_expression shift_right additive_expression]
+| [additive_expression]
+
+def additive_expression
+ [additive_expression '+' multiplicative_expression]
+| [additive_expression '-' multiplicative_expression]
+| [multiplicative_expression]
+
+def multiplicative_expression
+ [multiplicative_expression '*' pm_expression]
+| [multiplicative_expression '/' pm_expression]
+| [multiplicative_expression '%' pm_expression]
+| [pm_expression]
+
+def pm_expression
+ [pm_expression '->*' cast_expression]
+| [pm_expression '.*' cast_expression]
+| [cast_expression]
+
+def cast_expression
+ [unary_expression]
+| ['(' type_id ')' cast_expression]
+
+def delete_expression
+ [root_qual_opt 'delete' cast_expression]
+| [root_qual_opt 'delete' '[' ']' cast_expression]
+
+def new_initializer_opt
+ [new_initializer]
+| []
+
+def new_initializer
+ ['(' expression_opt ')']
+
+def direct_new_declarator
+ ['[' expression ']']
+| [direct_new_declarator '[' constant_expression ']']
+
+def new_declarator_opt
+ [new_declarator]
+| []
+
+def new_declarator
+ [direct_new_declarator]
+| [ptr_operator_seq direct_new_declarator]
+| [ptr_operator_seq]
+
+def new_type_id
+ [necs_type_specifier_seq new_declarator_opt]
+
+def new_placement
+ ['(' expression ')']
+
+def new_expression
+ [root_qual_opt 'new' new_type_id new_initializer_opt]
+| [root_qual_opt 'new' new_placement new_type_id new_initializer_opt]
+| [root_qual_opt 'new' '(' type_id ')' new_initializer_opt]
+| [root_qual_opt 'new' new_placement '(' type_id ')' new_initializer_opt]
+
+def unary_operator
+ ['*']
+| ['&']
+| ['+']
+| ['-']
+| ['!']
+| ['~']
+
+def unary_expression
+ [postfix_expression]
+| ['++' cast_expression]
+| ['--' cast_expression]
+| [unary_operator cast_expression]
+| ['sizeof' '(' type_id ')']
+| ['sizeof' unary_expression]
+| [new_expression]
+| [delete_expression]
+
+def function_style_type_conv
+ [simple_type_specifier]
+
+
+def postfix_expression
+ [primary_expression]
+| [postfix_expression '[' expression ']']
+| [postfix_expression '(' expression_opt ')']
+| [function_style_type_conv '(' expression_opt ')']
+| [member_request_expr dot_arrow id_expression]
+| [member_request_expr dot_arrow pseudo_destructor_call]
+| [postfix_expression '++']
+| [postfix_expression '--']
+| ['dynamic_cast' templ_arg_open type_id templ_arg_close '(' expression ')']
+| ['static_cast' templ_arg_open type_id templ_arg_close '(' expression ')']
+| ['reinterpret_cast' templ_arg_open type_id templ_arg_close '(' expression ')']
+| ['const_cast' templ_arg_open type_id templ_arg_close '(' expression ')']
+| ['typeid' '(' expression ')']
+| ['typeid' '(' type_id ')']
+
+def pseudo_destructor_call
+ [root_qual_opt nested_name_specifier_opt '~' pdc_type_name]
+
+def primary_expression
+ [expr_lit]
+| ['this']
+| ['(' expression ')']
+| [id_expression]
+# This is an GNU extension.
+| ['(' '{' statement_rep '}' ')']
+
+def expr_lit
+ [TK_IntegerDecimal]
+| [TK_IntegerOctal]
+| [TK_IntegerHex]
+| [TK_SingleLit]
+| [TK_Float]
+| [double_lit_list]
+| ['true']
+| ['false']
+
+def double_lit_list
+ [TK_DoubleLit double_lit_list]
+| [TK_DoubleLit]
+
+def member_request_expr
+ [postfix_expression]
+# {
+# # FIXME: If no proper type is found, we must fail.
+# # LOG print( 'setting member request scope\n' )
+# # qualNs.set( $1->type != 0 ? $1->type->getObject() : 0 );
+# }
+
+def dot_arrow
+ ['->']
+| ['.']
+
+def pdc_type_name
+ [enum_id]
+| [typedef_id]
+
+#
+# Statements
+#
+
+def statement_rep
+ [statement_rep statement]
+| []
+
+def statement
+ [declaration_statement]
+| [labeled_statement]
+| [expression_statement]
+| [compound_statement]
+| [selection_statement]
+| [iteration_statement]
+| [jump_statement]
+| [try_block]
+
+def labeled_statement
+ [label_id ':' statement]
+| ['case' constant_expression ':' statement]
+| ['default' ':' statement]
+
+def label_id
+ [unknown_id]
+| [identifier]
+| [class_id]
+| [templ_class_id]
+| [namespace_id]
+| [typedef_id]
+| [enum_id]
+| [template_id]
+
+def compound_statement
+ ['{' compound_begin statement_rep compound_end '}']
+
+def compound_begin
+ []
+ {
+ ptr lang_object newCompound = createLangObject( 0, '<compound_begin>', lookupNs.top )
+ lookupNs.push( newCompound )
+ declNs.push( newCompound )
+ # LOG print( 'opening <compound>\n' )
+ }
+
+def compound_end
+ []
+ {
+ lookupNs.pop()
+ declNs.pop()
+ # LOG print( 'closing <compound>\n' )
+ }
+
+def selection_statement
+ ['if' '(' condition ')' statement elseif_clauses else_clause]
+| ['switch' '(' condition ')' statement]
+
+def elseif_clauses
+ [elseif_clauses 'else' 'if' '(' condition ')' statement]
+| []
+
+def else_clause
+ ['else' statement]
+| []
+
+def iteration_statement
+ ['while' '(' condition ')' statement]
+| ['do' statement 'while' '(' expression ')' ';']
+| ['for' '(' for_init_statement condition_opt ';' expression_opt ')' statement]
+
+def jump_statement
+ ['break' ';']
+| ['continue' ';']
+| ['return' expression_opt ';']
+| ['goto' any_id ';']
+
+def any_id
+ [unknown_id]
+| [class_id]
+| [namespace_id]
+| [templ_class_id]
+| [enum_id]
+| [typedef_id]
+| [identifier]
+| [template_id]
+
+
+def for_init_statement
+ [expression_statement]
+| [stmt_block_declaration_forms ';']
+
+def condition
+ [expression]
+| [type_specifier_seq declarator '=' assignment_expression]
+
+def condition_opt
+ [condition]
+| []
+
+def expression_statement
+ [expression ';']
+| [';']
+
+def declaration_statement
+ [stmt_block_declaration]
+
+def stmt_block_declaration
+ [declaration_start stmt_block_declaration_forms declaration_end ';']
+| [using_declaration]
+| [using_directive]
+
+def stmt_block_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing decl_specifier_mult_seq_opt
+ init_declarator_list_opt]
+| [decl_specifier_mult_seq init_declarator_list_opt]
+
+#
+# Declarators
+#
+
+def declarator
+ ptr lang_object lookupObj
+
+ [ptr_operator_seq_opt declarator_id decl_array_or_param_rep declarator_end]
+ {
+ lhs.lookupObj = r4.lookupObj
+ }
+
+| [ptr_operator_seq_opt '(' sub_declarator ')' decl_array_or_param_rep declarator_end]
+ {
+ lhs.lookupObj = r6.lookupObj
+ }
+
+def sub_declarator
+ [ptr_operator_seq declarator_id decl_array_or_param_rep]
+| [ptr_operator_seq '(' sub_declarator ')' decl_array_or_param_rep]
+| ['(' sub_declarator ')' decl_array_or_param_rep]
+| [declarator_id decl_array_or_param_rep]
+
+def decl_array_or_param_rep
+ [decl_array_or_param_rep decl_array_or_param]
+| []
+
+def decl_array_or_param
+ ['[' constant_expression_opt ']']
+| ['(' parameter_declaration_clause ')' cv_qualifier_rep exception_specification_opt]
+
+def declarator_id
+ [declarator_id_forms]
+ {
+ str name = r1.lookupId.data
+ ptr lang_object qualObj = r1.lookupId.qualObj
+
+ ptr lang_object parentObj = declNs.top
+ if qualObj {
+ parentObj = qualObj
+ }
+
+ # Decide if we are declaring a constructor/destructor.
+ bool isConstructor
+ if parentObj == r1.lookupId.obj {
+ isConstructor = true
+ # LOG print( 'making declarator ', name, ' a constructor/destructor\n' )
+ }
+
+ if parentObj->specializationOf &&
+ parentObj->specializationOf == r1.lookupId.obj
+ {
+ isConstructor = true
+ # LOG print( 'making declarator ', name, ' a constructor/destructor\n' )
+ }
+
+ ptr lang_object obj = nil
+ if name && !isConstructor && declarationData.top.isFriend == 0 {
+ if declarationData.top.isTypedef {
+ obj = createLangObject( TypedefType, name, lookupNs.top )
+ obj->typedefOf = declarationData.top.typeObj
+ insertObject( parentObj, name, obj )
+
+ # LOG print( 'making declarator ', name, ' a typedef\n' )
+ }
+ else {
+ if !qualObj {
+ if declarationData.top.isTemplate {
+ # If in a template declaration and the name is not qualified then
+ # create the template id.
+ obj = createLangObject( TemplateIdType, name, lookupNs.top )
+ #object->objType = declarationData.top.type
+ insertObject( declNs.top, name, obj )
+
+ # LOG print( 'making declarator ', name, ' a template id\n' )
+ }
+ else {
+ obj = createLangObject( IdType, name, lookupNs.top )
+ #object->objType = declarationData.top().type;
+ insertObject( declNs.top, name, obj )
+
+ # LOG print( 'making declarator ', name, ' an id\n' )
+ }
+ }
+ }
+ }
+
+ declaratorData.push( construct declarator_data (
+ qualObj: qualObj, lookupObj: lookupNs.top ) [] )
+
+ # If the declarator is qualified, push the qualification to the lookup
+ # stack. Also save it in the declarator data so it can be passed to a
+ # function body if needed.
+ if qualObj {
+ lookupNs.push( qualObj )
+ declaratorData.top.lookupObj = qualObj
+ }
+
+ # LOG print( 'reduced declarator_id: ', name, '\n' )
+ }
+
+# Undoes the setup done by declarator_id and pdc_start.
+def declarator_end
+ ptr lang_object lookupObj
+
+ []
+ {
+ # Get the lookupObject from the scope and pass it up. If we are about to
+ # parse a function body it will be needed.
+ lhs.lookupObj = declaratorData.top.lookupObj
+
+ ptr lang_object pdcScope = declaratorData.top.pdcScope
+ ptr lang_object qualObj = declaratorData.top.qualObj
+
+ declaratorData.pop()
+
+ if pdcScope {
+ # LOG print( 'closing <pdc_scope>\n' )
+ lookupNs.pop()
+ declNs.pop()
+ }
+
+ if qualObj {
+ # LOG print( 'popping lookupNs\n' )
+ lookupNs.pop()
+ }
+ }
+
+def declarator_id_forms
+ lookup_id lookupId
+
+ [id_expression]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+| [root_qual_opt nested_name_specifier_opt type_name]
+ {
+ lhs.lookupId = r3.lookupId
+ }
+
+| [root_qual_opt nested_name_specifier_opt '~' class_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+| [root_qual_opt nested_name_specifier_opt '~' templ_class_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+| [root_qual_opt nested_name_specifier_opt '~' unknown_id]
+ {
+ lhs.lookupId = lookup_id in r4
+ }
+
+def type_id
+ lookup_id lookupId
+
+ [type_specifier_seq abstract_declarator_opt]
+ {
+ lhs.lookupId = r1.lookupId
+ }
+
+def abstract_declarator_opt
+ [abstract_declarator]
+| []
+
+def abstract_declarator
+ [ptr_operator_seq abstract_noid abstract_decl_array_or_param_seq_opt declarator_end]
+| [ptr_operator_seq '(' sub_abstract_declarator ')'
+ abstract_decl_array_or_param_seq_opt declarator_end]
+| [abstract_noid abstract_decl_array_or_param_seq declarator_end]
+| ['(' sub_abstract_declarator ')' abstract_decl_array_or_param_seq_opt declarator_end]
+
+def sub_abstract_declarator
+ [ptr_operator_seq abstract_noid abstract_decl_array_or_param_seq_opt]
+
+| [ptr_operator_seq '(' sub_abstract_declarator ')'
+ abstract_decl_array_or_param_seq_opt]
+
+| ['(' sub_abstract_declarator ')' abstract_decl_array_or_param_seq_opt]
+
+def abstract_noid
+ []
+ {
+ # Make scope for declarator.
+ declaratorData.push( construct declarator_data [] )
+ }
+
+def abstract_decl_array_or_param_seq_opt
+ [abstract_decl_array_or_param_seq_opt abstract_decl_array_or_param]
+| []
+
+def abstract_decl_array_or_param_seq
+ [abstract_decl_array_or_param_seq abstract_decl_array_or_param]
+| [abstract_decl_array_or_param]
+
+def abstract_decl_array_or_param
+ ['[' constant_expression_opt ']']
+| ['(' parameter_declaration_clause ')' cv_qualifier_rep
+ exception_specification_opt]
+
+def parameter_declaration_clause
+ [pdc_start parameter_declaration_list]
+| [pdc_start parameter_declaration_list '...']
+| [pdc_start parameter_declaration_list ',' '...']
+| [pdc_start '...']
+| [pdc_start]
+
+def pdc_start
+ []
+ {
+ if !declaratorData.top.pdcScope {
+ # We are going to need a scope for the declarator.
+ ptr lang_object pdcScope = createLangObject( 0, '<pdc_scope>', lookupNs.top )
+ lookupNs.push( pdcScope )
+ declNs.push( pdcScope )
+
+ declaratorData.top.pdcScope = pdcScope
+ declaratorData.top.lookupObj = pdcScope
+ # LOG print( 'opening <pdc_scope>\n' )
+ }
+ }
+
+def parameter_declaration_list
+ [parameter_declaration_list ',' parameter_declaration]
+| [parameter_declaration]
+
+def parameter_declaration
+ [declaration_start parameter_declaration_forms declaration_end]
+
+# Ordering the productions such that decl_specifier_sing is tried first is good
+# for performance.
+def parameter_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing decl_specifier_mult_seq_opt
+ param_maybe_declarator maybe_parameter_init]
+
+| [decl_specifier_mult_seq param_maybe_declarator maybe_parameter_init]
+
+def param_maybe_declarator
+ [abstract_declarator]
+| [declarator]
+| []
+
+def maybe_parameter_init
+ ['=' constant_expression]
+| []
+
+def ptr_operator
+ ['&']
+| [root_qual_opt nested_name_specifier_opt '*' cv_qualifier_rep]
+
+def ptr_operator_seq
+ [ptr_operator_seq ptr_operator]
+| [ptr_operator]
+
+def ptr_operator_seq_opt
+ [ptr_operator_seq_opt ptr_operator]
+| []
+
+#
+# Functions
+#
+
+def function_definition
+ [function_def_declaration ctor_initializer_opt function_body function_def_end]
+
+def function_def_declaration
+ [declaration_start function_def_declaration_forms declaration_end]
+
+def function_def_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing
+ decl_specifier_mult_seq_opt function_def_declarator]
+| [decl_specifier_mult_seq function_def_declarator]
+| [function_def_declarator]
+
+def function_def_declarator
+ [declarator]
+ {
+ # The lookupObj from the declarator is the deepest lookup object found
+ # while parsing the declarator. Make it visible in the function body.
+ # This could be the args, the qualObj, or the parent to the function.
+ lookupNs.push( r1.lookupObj )
+ }
+
+def function_def_end
+ []
+ {
+ # Pop the lookup object.
+ lookupNs.pop()
+ }
+
+def function_body
+ [function_body_begin '{' statement_rep function_body_end '}']
+
+def function_body_begin
+ []
+ {
+ ptr lang_object newFunctionBody = createLangObject( 0,
+ '<function_body_begin>', lookupNs.top )
+ lookupNs.push( newFunctionBody )
+ declNs.push( newFunctionBody )
+ templDecl.push( 0 )
+ # LOG print( 'opening <function_body>\n' )
+ }
+
+def function_body_end
+ []
+ {
+ # First undoes the function body begin work. Then undoes the setup in
+ # function_def_declarator.
+ declNs.pop()
+ lookupNs.pop()
+ templDecl.pop()
+ # LOG print( 'closing <function_body>\n' )
+ }
+
+
+
+#
+# Classs
+#
+
+int declaredClassType()
+{
+ if declarationData.top.isTemplate {
+ return TemplateClassType
+ } else {
+ return ClassType
+ }
+}
+
+def class_specifier
+ [class_head base_clause_opt '{' class_member_rep class_body_end '}']
+ {
+# FIXME: reparse not implemented yet
+# # Visit class function bodies, but skip nested classes.
+# for CFB: class_function_body in lhs {
+# skipping class_specifier
+#
+# # Reparse the text of the class function body as a function body
+# function_body FB = reparse function_body( CFB )
+#
+# # Replace the class function body with the parsed function body.
+# CFB = construct class_function_body
+# [FB]
+# }
+ }
+
+def class_head
+ [class_key]
+ {
+ int nsType = declaredClassType()
+
+ # LOG print( 'creating new anonymous class\n' )
+ ptr lang_object newClass = createLangObject( nsType,
+ '<anon_class>', lookupNs.top )
+ lookupNs.push( newClass )
+ declNs.push( newClass )
+ }
+
+| [class_key nested_name_specifier_opt class_head_name]
+ {
+ lookup_id Id = lookup_id in r3
+ str name = Id.data
+
+ # Get the ns the class is declared in.
+ ptr lang_object parentObj = declNs.top
+ if Id.qualObj
+ parentObj = Id.qualObj
+
+ # Look for the class in the given scope.
+ ptr lang_object declaredClass = findClass( parentObj, name )
+ if !declaredClass
+ declaredClass = findTemplateClass( parentObj, name )
+
+ if !declaredClass {
+ # LOG print( 'creating new class: ', name, '\n' )
+
+ # Class does not exist in the parent scope, create it.
+ int nsType = declaredClassType()
+
+ declaredClass = createLangObject( nsType, name, lookupNs.top )
+
+ # FIXME: handle friends. Make the class visible only if we are NOT
+ # in a friend declaration. The new class object is necessary to
+ # properly process the body of the class.
+ if declarationData.top.isFriend == 0
+ insertObject( parentObj, name, declaredClass )
+ }
+
+ # Push the found/new class.
+ lookupNs.push( declaredClass )
+ declNs.push( declaredClass )
+ }
+
+| [class_key nested_name_specifier_opt templ_class_id
+ templ_arg_open template_argument_list_opt templ_arg_close]
+ {
+ match r3 [Id: lookup_id]
+ str id = Id.data
+ ptr lang_object classObj = Id.obj
+
+ # TODO: Try to find the specializaition in the template class object.
+ # TypeList typeList;
+ # makeTypeList( typeList, $6->last );
+
+ ptr lang_object declaredClass
+ #declaredClass = classObj->findSpecExact( typeList );
+ if !declaredClass {
+ # LOG print( 'making new template specialization\n' )
+ int nsType = declaredClassType()
+ declaredClass = createLangObject( nsType, id, lookupNs.top )
+ # LOG print( 'declaredClass: ', declaredClass, '\n' )
+ declaredClass->specializationOf = classObj
+ # $$->typeListMapEl = classObj->typeListMap.insert( typeList, declaredClass );
+ }
+
+ # Push the found/new class.
+ lookupNs.push( declaredClass )
+ declNs.push( declaredClass )
+ }
+
+def class_body_end
+ []
+ {
+ # Pop the class ns.
+ lookupNs.pop()
+ declNs.pop()
+
+ # LOG print( 'closing off class\n' )
+ }
+
+def class_head_name
+ [class_id]
+| [templ_class_id]
+| [namespace_id]
+| [typedef_id]
+| [enum_id]
+| [unknown_id]
+| [identifier]
+| [template_id]
+
+def class_key
+ ['class']
+| ['struct']
+| ['union']
+
+def class_member_rep
+ [class_member_rep class_member]
+| []
+
+def class_member
+ [member_declaration]
+| [access_specifier ':']
+
+def member_declaration
+ [declaration_start member_declaration_forms declaration_end ';']
+| [class_function_definition]
+| [using_declaration]
+| [template_declaration]
+
+def class_function_definition
+ [function_def_declaration ctor_initializer_opt class_function_body function_def_end]
+
+lex cfb_conts
+{
+ token cfb_open /'{'/
+ token cfb_close /'}'/
+ token cfb_string /
+ "'" ( [^'\\\n] | '\\' any )* "'" |
+ '"' ( [^"\\\n] | '\\' any )* '"'/
+ token cfb_comment /
+ ( '/*' (any | '\n')* :>> '*/' ) |
+ ( '//' any* :> '\n' )/
+ token cfb_data /[^{}'"/]+ | '/'/
+}
+
+def cfb_item
+ [cfb_data]
+| [cfb_string]
+| [cfb_comment]
+| [cfb_open cfb_item* cfb_close]
+
+def cfb_conts
+ [cfb_item* cfb_close]
+
+
+
+def class_function_body
+# ['{' cfb_conts]
+#| [function_body]
+ [function_body]
+
+# Get better performance if the form with decl_specifier_sing comes first.
+def member_declaration_forms
+ [decl_specifier_mult_seq_opt decl_specifier_sing
+ decl_specifier_mult_seq_opt member_declarator_list_opt]
+| [decl_specifier_mult_seq_opt member_declarator_list_opt]
+
+def member_declarator_list_opt
+ [member_declarator_list]
+| []
+
+def member_declarator_list
+ [member_declarator_list ',' member_declarator]
+| [member_declarator]
+
+def member_declarator
+ [declarator]
+| [declarator '=' constant_expression]
+| [declarator ':' constant_expression]
+| [':' constant_expression]
+
+def access_specifier
+ ['private']
+| ['protected']
+| ['public']
+
+def access_specifier_opt
+ [access_specifier]
+| []
+
+def using_declaration
+ ['using' id_expression ';']
+ {
+ ptr lang_object obj = r2.lookupId.obj
+ if obj
+ insertObject( declNs.top, obj->name, obj )
+ }
+
+| ['using' type_id ';']
+ {
+ ptr lang_object obj = r2.lookupId.obj
+ if obj
+ insertObject( declNs.top, obj->name, obj )
+ }
+
+def using_directive
+ ['using' 'namespace' root_qual_opt nested_name_specifier_opt
+ namespace_id ';']
+ {
+ # This uses a simple, incomplete guard against cycles in the graph of
+ # using namespaces. A more sophisticated and complete guard would look
+ # for longer cycles as well. Note that even gcc 3.3.5 does not bother.
+ match r5 [Id: lookup_id]
+ ptr lang_object usingObject = Id.obj
+ ptr lang_object inObject = declNs.top
+ if usingObject != inObject
+ inObject->inherited.append( usingObject )
+ }
+
+
+#
+# Derived classes
+#
+
+def base_clause_opt
+ [base_clause]
+| []
+
+def base_clause
+ [':' base_specifier_list]
+
+def base_specifier_list
+ [base_specifier_list ',' base_specifier]
+| [base_specifier]
+
+int addBaseSpecifier( ptr lang_object inObject, ptr lang_object inheritedObject )
+{
+ # Resolve typedefs.
+ if inheritedObject->typeId == TypedefType
+ inheritedObject = inheritedObject->typedefOf
+
+ inObject->inherited.append( inheritedObject )
+}
+
+def base_specifier
+ [root_qual_opt nested_name_specifier_opt type_name]
+ {
+ addBaseSpecifier( declNs.top, r3.lookupId.obj )
+ }
+
+| ['virtual' access_specifier_opt root_qual_opt nested_name_specifier_opt type_name]
+ {
+ addBaseSpecifier( declNs.top, r5.lookupId.obj )
+ }
+
+| [access_specifier virtual_opt root_qual_opt nested_name_specifier_opt type_name]
+ {
+ addBaseSpecifier( declNs.top, r5.lookupId.obj )
+ }
+
+def virtual_opt
+ ['virtual']
+| []
+
+#
+# Special member functions
+#
+
+def conversion_function_id
+ ['operator' conversion_type_id]
+
+def conversion_type_id
+ [necs_type_specifier_seq ptr_operator_seq_opt]
+
+def ctor_initializer_opt
+ [ctor_initializer]
+| []
+
+def ctor_initializer
+ [':' mem_initializer_list]
+
+def mem_initializer_list
+ [mem_initializer_list ',' mem_initializer]
+| [mem_initializer]
+
+def mem_initializer
+ [mem_initializer_id '(' expression_opt ')']
+
+def mem_initializer_id
+ [root_qual_opt nested_name_specifier_opt unknown_id]
+| [root_qual_opt nested_name_specifier_opt identifier]
+| [root_qual_opt nested_name_specifier_opt type_name]
+| [root_qual_opt nested_name_specifier_opt template_name]
+
+
+#
+# Overloading
+#
+def operator_function_id
+ ['operator' operator]
+
+def operator
+ ['+'] | ['-'] | ['*'] | ['/'] | ['='] | ['<'] | ['>'] | ['&'] | ['|'] |
+ ['^'] | ['%'] | ['~'] | ['!'] | ['(' ')'] | ['[' ']'] | ['new'] |
+ ['delete'] | ['->'] | ['++'] | ['--'] | ['*='] | ['/='] | ['%='] |
+ ['+='] | ['-='] | ['>>='] | ['<<='] | ['&='] | ['^='] | ['|='] | ['=='] |
+ ['!='] | ['&&'] | ['||'] | [lt_eq] | [gt_eq] | [shift_left] | [shift_right]
+
+def lt_eq
+ ['<' '=']
+# try {
+# if ( $2->leader != 0 ) {
+# #ifdef LOG_REDUCE
+# cerr << "rejecting less-than equals-to" << endl;
+# #endif
+# reject();
+# }
+# };
+
+def gt_eq
+ ['>' '=']
+# try {
+# if ( $2->leader != 0 ) {
+# #ifdef LOG_REDUCE
+# cerr << "rejecting greater-than equals-to" << endl;
+# #endif
+# reject();
+# }
+# };
+
+def shift_left
+ ['<' '<']
+# try {
+# if ( $2->leader != 0 ) {
+# #ifdef LOG_REDUCE
+# cerr << "rejecting shift left" << endl;
+# #endif
+# reject();
+# }
+# };
+
+def shift_right
+ ['>' '>']
+# try {
+# if ( $2->leader != 0 ) {
+# #ifdef LOG_REDUCE
+# cerr << "rejecting shift right" << endl;
+# #endif
+# reject();
+# }
+# };
+
+#
+# Templates
+#
+
+def template_declaration
+ [template_declaration_params declaration]
+ {
+ templDecl.pop()
+ templateParamNs.pop()
+ }
+
+def template_declaration_params
+ ['template' '<' tpl_start template_parameter_list '>']
+ {
+ templDecl.push( 1 )
+ }
+
+| ['export' 'template' '<' tpl_start template_parameter_list '>']
+ {
+ templDecl.push( 1 )
+ }
+
+def tpl_start
+ []
+ {
+ # Create a new scope for the template parameters.
+ ptr lang_object newTemplateParamScope =
+ createLangObject( 0, '<tpl_start>', lookupNs.top )
+ templateParamNs.push( newTemplateParamScope )
+ }
+
+def template_parameter_list
+ [template_parameter_list ',' template_parameter]
+| [template_parameter]
+
+def template_parameter
+ [type_parameter]
+| [template_parameter_declaration]
+
+def template_parameter_declaration
+ [declaration_start template_parameter_declaration_forms declaration_end]
+
+def template_parameter_declaration_forms
+ [decl_specifier_mult_seq param_maybe_declarator maybe_parameter_init]
+
+| [temp_param_decl_specifier_sing decl_specifier_mult_seq_opt
+ param_maybe_declarator maybe_parameter_init]
+
+| [decl_specifier_mult_seq temp_param_decl_specifier_sing
+ decl_specifier_mult_seq_opt param_maybe_declarator maybe_parameter_init]
+
+def temp_param_decl_specifier_sing
+ [temp_param_type_specifier_sing]
+
+# Template parameters cannot support elaborated type specifer or class specifier.
+def temp_param_type_specifier_sing
+ [templ_simple_type_specifier]
+| [enum_specifier]
+
+def templ_simple_type_specifier
+ [simple_type_specifier_name]
+| [simple_type_specifier_kw_seq]
+
+def type_parameter
+ ['class' type_param_id type_param_init_opt]
+ {
+ lookup_id Id = lookup_id in r2
+ if Id {
+ # The lookup ns should be a template param scope.
+ ptr lang_object newClass =
+ createLangObject( ClassType, Id.data, lookupNs.top )
+ insertObject( templateParamNs.top, Id.data, newClass )
+ }
+ }
+
+| ['typename' type_param_id type_param_init_opt]
+ {
+ lookup_id Id = lookup_id in r2
+ if Id {
+ # The lookup ns should be a template param scope.
+ ptr lang_object newClass =
+ createLangObject( ClassType, Id.data, lookupNs.top )
+ insertObject( templateParamNs.top, Id.data, newClass )
+ }
+ }
+
+| ['template' '<' tpl_start template_parameter_list '>'
+ 'class' type_param_id templ_type_param_init_opt]
+ {
+ lookup_id Id = lookup_id in r7
+ if Id {
+ ptr lang_object newClass =
+ createLangObject( TemplateClassType, Id.data, lookupNs.top )
+ insertObject( templateParamNs.top, Id.data, newClass )
+ }
+ }
+
+def templ_type_param_init_opt
+ ['=' id_expression]
+| []
+
+def type_param_init_opt
+ ['=' type_id]
+| []
+
+def type_param_id
+ [namespace_id]
+| [typedef_id]
+| [enum_id]
+| [class_id]
+| [templ_class_id]
+| [identifier]
+| [template_id]
+| [unknown_id]
+| []
+
+def template_argument_list_opt
+ [template_argument_list]
+| []
+
+def template_argument_list
+ [template_argument_list ',' template_argument]
+| [template_argument]
+
+def template_argument
+ [type_id]
+| [assignment_expression]
+
+def explicit_instantiation
+ ['template' declaration]
+| [declaration_start decl_specifier_mult_seq 'template' declaration declaration_end]
+
+def explicit_specialization
+ ['template' '<' '>' declaration]
+
+## Not sure what this one is about?
+#explicit_specialization:
+# declaration_start decl_specifier_mult_seq KW_Template '<' '>'
+# declaration declaration_end;
+
+
+#
+# Original namespace definition
+#
+
+def original_namespace_definition
+ [orig_namespace_def_name '{' declaration* namespace_end '}']
+
+def orig_namespace_def_name ['namespace' unknown_id]
+ {
+ match r2 [Id: lookup_id]
+ ptr lang_object nspace = createLangObject(
+ NamespaceType, Id.data, lookupNs.top )
+
+ # Insert the new object into the dictionary of the parent.
+ insertObject( curNamespace.top, Id.data, nspace )
+
+ # Push the namespace
+ curNamespace.push( nspace )
+ declNs.push( nspace )
+ lookupNs.push( nspace )
+
+ # LOG print( 'created original namespace: ', Id.data, '\n' )
+ }
+
+def namespace_end []
+ {
+ # Pop the namespace.
+ curNamespace.pop()
+ declNs.pop()
+ lookupNs.pop()
+
+ # LOG print( 'closed namespace\n' )
+ }
+
+#
+# Extension namespace definition
+#
+
+def extension_namespace_definition
+ [ext_namespace_def_name '{' declaration* namespace_end '}']
+
+def ext_namespace_def_name ['namespace' namespace_id]
+ {
+ match r2 [Id: lookup_id]
+ ptr lang_object nspace = Id.obj
+
+ # Push the namespace
+ curNamespace.push( nspace )
+ declNs.push( nspace )
+ lookupNs.push( nspace )
+
+ # LOG print( 'found extended namespace: ', Id.data, '\n' )
+ }
+
+#
+# Unnamed namespace definition
+#
+def unnamed_namespace_definition
+ [unnamed_namespace_def_name '{' declaration* namespace_end '}']
+
+def unnamed_namespace_def_name ['namespace']
+ {
+ ptr lang_object nspace = createLangObject(
+ NamespaceType, '<unnamed_namespace>',
+ lookupNs.top )
+
+ # Push the namespace
+ curNamespace.push( nspace )
+ declNs.push( nspace )
+ lookupNs.push( nspace )
+
+ # LOG print( 'parsed unnamed namespace\n' )
+ }
+
+#
+# linkage_specification
+#
+def linkage_specification
+ ['extern' TK_DoubleLit '{' declaration* '}']
+| ['extern' TK_DoubleLit declaration]
+
+#
+# Exception Handling.
+#
+
+def try_block
+ ['try' compound_statement handler_seq]
+
+def handler_seq
+ [handler_seq handler]
+| [handler]
+
+def handler
+ ['catch' '(' exception_declaration ')' compound_statement]
+
+def exception_declaration
+ [type_specifier_seq declarator]
+| [type_specifier_seq abstract_declarator]
+| [type_specifier_seq]
+| ['...']
+
+def throw_expression
+ ['throw' assignment_expression]
+| ['throw']
+
+def exception_specification_opt
+ [exception_specification]
+| []
+
+def exception_specification
+ ['throw' '(' type_id_list_opt ')']
+
+def type_id_list_opt
+ [type_id_list]
+| []
+
+def type_id_list
+ [type_id_list ',' type_id]
+| [type_id]
+
+def start
+ [declaration*]
+
+#
+# Grammar done.
+#
+
+int printObject( str indent, ptr lang_object obj )
+{
+ print( indent, obj->name )
+
+ if obj->objectMap.length > 0
+ print( ' {\n' )
+
+ object_map ChildNames = obj->objectMap
+ for MapEl: object_list in child( ChildNames ) {
+ for Obj: ptr lang_object in MapEl
+ printObject( indent + ' ', Obj )
+ }
+
+ if obj->objectMap.length > 0
+ print( indent, '}' )
+
+ print( '\n' )
+}
+
+int printNamespace()
+{
+ printObject( '', rootNamespace )
+}
+
+start S = parse start( stdin )
+#printNamespace()
+#print( '***** SUCCESS *****\n' )
+#print_xml( S )
+#for DI: declarator_id in S {
+# if match DI
+# [root_qual_opt nested_name_specifier_opt '~' UID:unknown_id]
+# {
+# print( UID, '\n' )
+# }
+#}
diff --git a/test/cxx/input01.cpp b/test/cxx/input01.cpp
new file mode 100644
index 00000000..e2b125f4
--- /dev/null
+++ b/test/cxx/input01.cpp
@@ -0,0 +1,17 @@
+namespace ns1
+{
+ namespace sub1 { class A {}; }
+ namespace sub2 { class B {}; }
+}
+
+namespace ns2
+{
+// int i = b;
+ class C
+ {
+ };
+
+ using namespace ns1;
+}
+
+ns2::sub1::A a;
diff --git a/test/cxx/input02.cpp b/test/cxx/input02.cpp
new file mode 100644
index 00000000..65ebe0db
--- /dev/null
+++ b/test/cxx/input02.cpp
@@ -0,0 +1,16 @@
+
+struct A
+{
+ struct B {};
+};
+
+struct C
+{
+ struct D : virtual public A {};
+};
+
+C::D::A d;
+
+C c;
+
+
diff --git a/test/cxx/input03.cpp b/test/cxx/input03.cpp
new file mode 100644
index 00000000..bccfbf0e
--- /dev/null
+++ b/test/cxx/input03.cpp
@@ -0,0 +1,19 @@
+
+struct C
+{
+
+};
+
+enum E
+{
+ C,
+ b
+};
+
+E e;
+
+enum E
+{
+ C,
+ b
+};
diff --git a/test/cxx/input04.cpp b/test/cxx/input04.cpp
new file mode 100644
index 00000000..9741a82b
--- /dev/null
+++ b/test/cxx/input04.cpp
@@ -0,0 +1,17 @@
+
+
+int i;
+class C
+{
+ int j;
+};
+
+class D
+{
+ int ~D();
+};
+
+int C::k;
+int C::~C;
+
+typedef int Int;
diff --git a/test/cxx/input05.cpp b/test/cxx/input05.cpp
new file mode 100644
index 00000000..7936ce09
--- /dev/null
+++ b/test/cxx/input05.cpp
@@ -0,0 +1,8 @@
+
+class C {};
+void ~C( );
+void C::operator +( int i );
+
+int i;
+
+//void operator C( void k );
diff --git a/test/cxx/input06.cpp b/test/cxx/input06.cpp
new file mode 100644
index 00000000..008edd4b
--- /dev/null
+++ b/test/cxx/input06.cpp
@@ -0,0 +1,7 @@
+
+class C
+{
+
+};
+
+int C::f( int i, int j( void v ) );
diff --git a/test/cxx/input07.cpp b/test/cxx/input07.cpp
new file mode 100644
index 00000000..474ba9a1
--- /dev/null
+++ b/test/cxx/input07.cpp
@@ -0,0 +1,18 @@
+class C
+{
+ class D {};
+
+ typedef C I;
+
+ I::D i;
+};
+
+C c;
+
+void function( int i, int j );
+{
+ asdlkf
+}
+
+
+
diff --git a/test/cxx/input08.cpp b/test/cxx/input08.cpp
new file mode 100644
index 00000000..2e9ec7a0
--- /dev/null
+++ b/test/cxx/input08.cpp
@@ -0,0 +1,13 @@
+class B { class Find {}; };
+
+typedef B T;
+
+class C : public T
+{
+ Find find;
+};
+
+
+
+
+
diff --git a/test/cxx/input09.cpp b/test/cxx/input09.cpp
new file mode 100644
index 00000000..373f4373
--- /dev/null
+++ b/test/cxx/input09.cpp
@@ -0,0 +1,7 @@
+template <class X> struct C
+{
+ X t;
+ void f();
+};
+
+template <class X> void C<X>::f();
diff --git a/test/cxx/input10.cpp b/test/cxx/input10.cpp
new file mode 100644
index 00000000..98b6a96a
--- /dev/null
+++ b/test/cxx/input10.cpp
@@ -0,0 +1,11 @@
+template <class X> struct C
+{
+ class Y {};
+};
+
+class C<int>
+{
+ int i;
+};
+
+//void f( class C<int> i, int j );
diff --git a/test/cxx/input11.cpp b/test/cxx/input11.cpp
new file mode 100644
index 00000000..d9714571
--- /dev/null
+++ b/test/cxx/input11.cpp
@@ -0,0 +1,2 @@
+
+int f( int (*) [](), void );
diff --git a/test/cxx/input12.cpp b/test/cxx/input12.cpp
new file mode 100644
index 00000000..c135c8da
--- /dev/null
+++ b/test/cxx/input12.cpp
@@ -0,0 +1,8 @@
+void f();
+class C
+{
+ class D {};
+ void g();
+};
+
+typename C c;
diff --git a/test/cxx/input13.cpp b/test/cxx/input13.cpp
new file mode 100644
index 00000000..67fd42fd
--- /dev/null
+++ b/test/cxx/input13.cpp
@@ -0,0 +1,14 @@
+
+class C
+{
+ class D {};
+ int f();
+};
+
+int f()
+{
+}
+int C::f()
+{
+ D d;
+}
diff --git a/test/cxx/preproc b/test/cxx/preproc
new file mode 100755
index 00000000..2661a197
--- /dev/null
+++ b/test/cxx/preproc
@@ -0,0 +1,5 @@
+#!/bin/bash
+#
+
+echo 'struct __builtin_va_list {};'
+g++ -E -undef -D'__attribute__(xyz)=' "$@" | sed 's/#.*$//' | grep -v '^[ \t]*$'
diff --git a/test/diff/Makefile b/test/diff/Makefile
new file mode 100644
index 00000000..d647261a
--- /dev/null
+++ b/test/diff/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright 2002-2006 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f *.cpp *.bin
diff --git a/test/diff/diff.lm b/test/diff/diff.lm
new file mode 100644
index 00000000..37232025
--- /dev/null
+++ b/test/diff/diff.lm
@@ -0,0 +1,84 @@
+
+
+token newline / '\n' /
+token index / 'Index:' [ \t]* /
+token consume_line / [^\n]* /
+
+
+def index_stmt [index consume_line newline]
+
+token separator_line / '='+ '\n' /
+
+# Whitespace separated word list
+lex word_list
+{
+ token word /[^\t \n]+/
+ ignore /[\t ]+/
+
+ def word_list
+ [word word_list]
+ | []
+}
+
+token old_file_start / '---' [\t ]+ /
+token new_file_start / '+++' [\t ]+ /
+
+def old_file
+ [old_file_start word_list newline]
+
+def new_file
+ [new_file_start word_list newline]
+
+def file_header
+ [index_stmt separator_line old_file new_file]
+
+token hunk_header / '@@' any* :>> '@@' '\n' /
+token hunk_line / ( ' ' | '-' | '+' ) [^\n]* '\n' /
+
+def hunk_body
+ [hunk_line*]
+
+def hunk
+ [hunk_header hunk_body]
+
+# diff of a single file: header followed by a hunk list.
+def file_diff
+ [file_header hunk*]
+
+def start
+ [file_diff*]
+
+
+start S = parse start( stdin )
+
+for OF:old_file in S {
+ print( 'old file: ', OF )
+ # Get the first word and check if it is
+ # the file we are interested in.
+ if match OF [
+ "--- fsmrun.cpp"
+ Rest: word_list
+ "\n"
+ ]
+ {
+ OF = construct old_file
+ ["--- newfilename.cpp" Rest "\n"]
+ print_xml( OF )
+ }
+}
+
+print( S )
+
+# for Header: file_header in lhs {
+# old_file OF = old_file in Header
+# if match OF
+# [old_file_start "lmparse.kl" word_list newline]
+# {
+# Header = construct file_header
+# ~Index: rewritten
+# ~===================================================================
+# ~--- this is the file (asldkfj)
+# ~+++ this is the file (ewir)
+# }
+# }
+
diff --git a/test/diff/input1.diff b/test/diff/input1.diff
new file mode 100644
index 00000000..b0021f67
--- /dev/null
+++ b/test/diff/input1.diff
@@ -0,0 +1,86 @@
+Index: fsmrun.cpp
+===================================================================
+--- fsmrun.cpp (revision 4555)
++++ fsmrun.cpp (working copy)
+@@ -150,7 +150,7 @@
+ peof = 0;
+ if ( parser != 0 ) {
+ region = parser->getNextRegion();
+- cs = getStateFromNextRegion();
++ cs = tables->entryByRegion[region];
+ }
+ else {
+ region = 0;
+@@ -189,7 +189,7 @@
+
+ tokstart = 0;
+ region = parser->getNextRegion();
+- cs = getStateFromNextRegion();
++ cs = tables->entryByRegion[region];
+ }
+
+ void FsmRun::sendToken( int id )
+@@ -222,7 +222,7 @@
+ parser = newParser;
+
+ region = parser->getNextRegion();
+- cs = getStateFromNextRegion();
++ cs = tables->entryByRegion[region];
+ }
+ else {
+ #ifdef LOG_ACTIONS
+@@ -355,7 +355,7 @@
+
+ /* Set the current state from the next region. */
+ region = parser->getNextRegion();
+- cs = getStateFromNextRegion();
++ cs = tables->entryByRegion[region];
+ }
+ }
+
+@@ -452,7 +452,7 @@
+ /* First thing check for error. */
+ if ( cs == tables->errorState ) {
+ if ( parser != 0 ) {
+- if ( getStateFromNextRegion( 1 ) != 0 ) {
++ if ( parser->getNextRegion( 1 ) != 0 ) {
+ #ifdef LOG_BACKTRACK
+ cerr << "scanner failed, trying next region" << endl;
+ #endif
+@@ -462,7 +462,7 @@
+
+ parser->nextRegionInd += 1;
+ region = parser->getNextRegion();
+- cs = getStateFromNextRegion();
++ cs = tables->entryByRegion[region];
+ cerr << "new token region: " <<
+ parser->tables->gbl->regionInfo[region].name << endl;
+ continue;
+@@ -495,7 +495,7 @@
+ }
+ else {
+ region = parser->getNextRegion();
+- cs = getStateFromNextRegion();
++ cs = tables->entryByRegion[region];
+ cerr << "new token region: " <<
+ parser->tables->gbl->regionInfo[region].name << endl;
+ continue;
+Index: junk.cpp
+===================================================================
+---
++++ junk.cpp (working copy)
+Index: fsmrun.h
+===================================================================
+--- fsmrun.h (revision 4557)
++++ fsmrun.h (working copy)
+@@ -197,10 +197,6 @@
+ void runOnInputStream( PdaRun *parser, InputStream &in );
+ void execute();
+
+- /* Offset can be used to look at the next nextRegionInd. */
+- int getStateFromNextRegion( int offset = 0 )
+- { return tables->entryByRegion[parser->getNextRegion(offset)]; }
+-
+ FsmTables *tables;
+ PdaRun *parser;
+ InputStream *inputStream;
diff --git a/test/dns/Makefile b/test/dns/Makefile
new file mode 100644
index 00000000..86e11071
--- /dev/null
+++ b/test/dns/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright 2007 Adrian Thurston <thurston@complang.org>
+#
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+extract: extract.c
+ gcc -Wall -o extract extract.c -lpcap
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f dns.cpp dns.bin extract
diff --git a/test/dns/dns.lm b/test/dns/dns.lm
new file mode 100644
index 00000000..29f0cdbe
--- /dev/null
+++ b/test/dns/dns.lm
@@ -0,0 +1,488 @@
+
+# Used for most of the grammar.
+token octet /any/
+
+# Filled in during the parsing of resource records. Determine what RR_UNKNOWN
+# translates to.
+global int rr_type_value
+global int rr_class_value
+
+# Tokens generated from RR_UNKNOWN. Used to pick the kind
+# of resource record to attempt to parse.
+token RR_A // # 1 a host address
+token RR_NS // # 2 an authoritative name server
+token RR_MD // # 3 a mail destination (Obsolete - use MX)
+token RR_MF // # 4 a mail forwarder (Obsolete - use MX)
+token RR_CNAME // # 5 the canonical name for an alias
+token RR_SOA // # 6 marks the start of a zone of authority
+token RR_MB // # 7 a mailbox domain name (EXPERIMENTAL)
+token RR_MG // # 8 a mail group member (EXPERIMENTAL)
+token RR_MR // # 9 a mail rename domain name (EXPERIMENTAL)
+token RR_NULL // # 10 a null RR (EXPERIMENTAL)
+token RR_WKS // # 11 a well known service description
+token RR_PTR // # 12 a domain name pointer
+token RR_HINFO // # 13 host information
+token RR_MINFO // # 14 mailbox or mail list information
+token RR_MX // # 15 mail exchange
+token RR_TXT // # 16 text strings
+
+token RR_UNKNOWN
+ /''/
+ {
+ int id = typeid RR_UNKNOWN
+ if rr_type_value == 1
+ id = typeid RR_A
+ elsif rr_type_value == 2
+ id = typeid RR_NS
+ elsif rr_type_value == 5
+ id = typeid RR_CNAME
+ elsif rr_type_value == 12
+ id = typeid RR_PTR
+ elsif rr_type_value == 15
+ id = typeid RR_MX
+ elsif rr_type_value == 16
+ id = typeid RR_TXT
+
+ send( make_token( id, '' ) )
+ }
+
+# Convert two octets in network order into an unsigned 16 bit value.
+int network_uord16( octet o1, octet o2 )
+{
+ return o1.data.uord8() * 256 + o2.data.uord8()
+}
+
+
+def message
+ [header questions answers authorities additionals]
+
+global int question_count
+global int answer_count
+global int authority_count
+global int additional_count
+
+# Message Header
+#
+# 1 1 1 1 1 1
+# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | ID |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | QDCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | ANCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | NSCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | ARCOUNT |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+def header
+ [header_id header_fields count count count count]
+ {
+ question_count = r3.count
+ answer_count = r4.count
+ authority_count = r5.count
+ additional_count = r6.count
+ }
+
+def header_id
+ [octet octet]
+
+def header_fields
+ [octet octet]
+
+def count
+ int count
+
+ [octet octet]
+ {
+ lhs.count = network_uord16( r1, r2 )
+ }
+
+#
+# Counting Primitives
+#
+# Uses a global stack of lengths. Using a stack allows for counted lists to be
+# nested. As the list is consumed it brings the count down to zero. To use it,
+# push a new count value to the list and include it in a right-recursive list
+# like so:
+#
+# def LIST
+# [count_inc ITEM LIST]
+# [count_end]
+# end
+#
+
+list count_stack [int]
+global count_stack CL = construct count_stack []
+
+int start_list( int count )
+{
+ CL.push( count )
+}
+
+def count_inc
+ []
+ {
+ if CL.top == 0 {
+ reject
+ } else {
+ CL.top = CL.top - 1
+ }
+ }
+
+def count_end
+ []
+ {
+ if CL.top != 0 {
+ reject
+ } else {
+ CL.pop()
+ }
+ }
+
+#
+# Octet List
+#
+
+# General octet list. Length must be set to use this.
+def octet_list
+ [count_inc octet octet_list]
+| [count_end]
+
+
+#
+# Names
+#
+
+def name
+ [name_part* name_end]
+
+# Name part lists are terminated by a zero length or a pointer.
+def name_end
+ # Zero length ending
+ [octet]
+ {
+ int val = r1.data.uord8()
+ if val != 0 {
+ reject
+ }
+ }
+
+ # Pointer ending
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ # | 1 1| OFFSET |
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+| [octet octet]
+ {
+ int val = r1.data.uord8()
+ if val < 64 {
+ reject
+ }
+ }
+
+#
+# Get some number of bytes.
+#
+
+# How many to get
+global int nbytes
+
+# We use this token to eliminate the lookahead that would be needed to cause a
+# reduce of part_len. This forces whatever comes before nbytes to be reduced before
+# nbytes_data token is fetched from the scanner. We need this because nbytes_data
+# depends on the nbytes global and we need to ensure that it is set.
+token nb_empty /''/
+
+# Fetch nbytes bytes.
+token nbytes_data
+ /''/
+ {
+ send( make_token( typeid nbytes_data, pull(stdin, nbytes) ) )
+ }
+
+def nbytes
+ [nb_empty nbytes_data]
+
+def name_part
+ [part_len nbytes]
+
+
+def part_len
+ [octet]
+ {
+ # A name part list is terminated either by a zero length or a pointer,
+ # which must have the two high bits set.
+ int count = r1.data.uord8()
+ if count == 0 || count >= 64 {
+ reject
+ } else {
+ # Set the number of bytes to get for the name part.
+ nbytes = count
+ }
+ }
+
+#
+# Resource Records
+#
+
+# 1 1 1 1 1 1
+# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | |
+# / /
+# / NAME /
+# | |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | TYPE |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | CLASS |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | TTL |
+# | |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | RDLENGTH |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+# / RDATA /
+# / /
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+def resource_record
+ [name rr_type rr_class ttl rdlength rdata]
+
+def rr_type
+ [octet octet]
+ {
+ rr_type_value = network_uord16( r1, r2 )
+ }
+
+def rr_class
+ int value
+ [octet octet]
+ {
+ rr_class_value = network_uord16( r1, r2 )
+ }
+
+def ttl
+ [octet octet octet octet]
+
+token rdata_bytes
+ /''/
+ {
+ send( make_token( typeid rdata_bytes, pull(stdin, rdata_length) ) )
+ }
+
+def rdlength
+ [octet octet]
+ {
+ rdata_length = network_uord16( r1, r2 )
+ }
+
+global int rdata_length
+
+def rdata
+ [RR_UNKNOWN rdata_bytes]
+| [RR_A address]
+| [RR_NS name]
+| [RR_CNAME name]
+| [RR_PTR name]
+| [RR_MX octet octet name]
+| [RR_TXT rdata_bytes]
+
+
+#
+# Address
+#
+def address [octet octet octet octet]
+
+#
+# List of Questions
+#
+
+def questions
+ [load_question_count question_list]
+
+def load_question_count
+ []
+ {
+ start_list( question_count )
+ }
+
+def question_list
+ [count_inc question question_list]
+| [count_end]
+
+#
+# Question
+#
+
+# 1 1 1 1 1 1
+# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | |
+# / QNAME /
+# / /
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | QTYPE |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | QCLASS |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+def question
+ [name qtype qclass]
+
+def qtype
+ [octet octet]
+
+def qclass
+ [octet octet]
+
+#
+# List of Answers
+#
+
+def answers
+ [load_answer_count answer_list]
+
+def load_answer_count
+ []
+ {
+ start_list( answer_count )
+ }
+
+def answer_list
+ [count_inc answer answer_list]
+| [count_end]
+
+#
+# Answer
+#
+
+def answer
+ [resource_record]
+
+#
+# List of Authorities
+#
+
+def authorities
+ [load_authority_count authority_list]
+
+def load_authority_count
+ []
+ {
+ start_list( authority_count )
+ }
+
+def authority_list
+ [count_inc authority authority_list]
+| [count_end]
+
+#
+# Authority
+#
+
+def authority
+ [resource_record]
+
+#
+# List of Additionals
+#
+
+def additionals
+ [load_additional_count additional_list]
+
+def load_additional_count
+ []
+ {
+ start_list( additional_count )
+ }
+
+def additional_list
+ [count_inc additional additional_list]
+| [count_end]
+
+#
+# Additional
+#
+
+def additional
+ [resource_record]
+
+
+def start
+ [message*]
+
+#
+# Grammar End.
+#
+
+int print_RR_UNKNOWN( start s )
+{
+ for I:rdata in s {
+ if match I [u:RR_UNKNOWN rdata_bytes] {
+ print( 'UNKNOWN TYPE\n' )
+ }
+ }
+}
+
+int print_RR_A( start s )
+{
+ for I:rdata in s {
+ if match I [RR_A o1:octet o2:octet o3:octet o4:octet] {
+ print( 'RR_A: ', o1.data.uord8(), '.', o2.data.uord8(), '.',
+ o3.data.uord8(), '.', o4.data.uord8(), '\n' )
+ }
+ }
+}
+
+map name_map [int name]
+
+int print_name( name n, name_map m )
+{
+ for P: name_part in n {
+ match P [part_len D:nbytes]
+ print( D, '.' )
+ }
+
+ for E:name_end in n {
+ if match E [o1:octet o2:octet] {
+ int val = (o1.data.uord8() - 192) * 256 + o2.data.uord8()
+ print( '[', val, ']' )
+ name nameInMap = m.find( val )
+ print_name( nameInMap, m )
+ }
+ }
+}
+
+int print_all_names( start s )
+{
+ for M:message in s {
+ name_map m = construct name_map []
+
+ octet O = octet in M
+
+ for N:name in M {
+ match N [name_part* E:name_end]
+
+ for NP: name_part* in N {
+ if match NP [L:octet nbytes name_part*] {
+ int messageOffset = L.pos - O.pos
+ name n = construct name [NP E]
+ m.insert( messageOffset, n )
+ }
+ }
+ }
+
+ for I:name in M {
+ print_name( I, m )
+ print( '\n' )
+ }
+ }
+}
+
+start S = parse start( stdin )
+print_all_names( S )
+print( '*** SUCCESS ***\n' )
diff --git a/test/dns/dumpdns b/test/dns/dumpdns
new file mode 100644
index 00000000..3409afee
--- /dev/null
+++ b/test/dns/dumpdns
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+
+# Use this script to capture dns packets to a dump file. Then use extract to
+# break up the packets and strip the headers, leaving just dns packets.
+#
+# usage: bash dumpdns <dumpfile>
+
+[ -z "$1" ] && exit
+
+tcpdump -s 0 -w $1 udp port 53
diff --git a/test/dns/extract.c b/test/dns/extract.c
new file mode 100644
index 00000000..8af026a3
--- /dev/null
+++ b/test/dns/extract.c
@@ -0,0 +1,48 @@
+#include <pcap.h>
+
+/*
+ * Break up a dump file and strip headers, leaving just
+ * the dns portion of packets.
+ */
+
+char outname[1024];
+char errbuf[PCAP_ERRBUF_SIZE];
+
+int main( int argc, char **argv )
+{
+ int packet;
+ pcap_t *p;
+ if ( argc != 3 ) {
+ fprintf( stderr, "usage: get <dumpfile> <rootname>\n" );
+ return 1;
+ }
+
+ p = pcap_open_offline( argv[1], errbuf );
+
+ for ( packet = 0; ; packet++ ) {
+ FILE *file;
+ unsigned long len;
+ struct pcap_pkthdr h;
+ const u_char *data;
+
+ data = pcap_next( p, &h );
+ if ( data == 0 )
+ break;
+
+ if ( h.caplen < h.len )
+ fprintf( stderr, "warning: packet number %02d is short\n", packet );
+
+ /* The magic number is the size of the headers we want to strip. */
+ data += 42;
+ len = h.caplen - 42;
+
+ sprintf( outname, "%s-%04d", argv[2], packet );
+ file = fopen( outname, "wb" );
+ fwrite( data, 1, len, file );
+ fclose( file );
+ }
+
+ pcap_close( p );
+
+ return 0;
+}
diff --git a/test/heredoc.in b/test/heredoc.in
new file mode 100644
index 00000000..c9638ca9
--- /dev/null
+++ b/test/heredoc.in
@@ -0,0 +1,3 @@
+hello
+random 9392af j9 stuff
+hello
diff --git a/test/heredoc.lm b/test/heredoc.lm
new file mode 100644
index 00000000..54dcc33d
--- /dev/null
+++ b/test/heredoc.lm
@@ -0,0 +1,45 @@
+rl ident_char /[a-zA-Z_]/
+
+lex start
+{
+ # Tokens
+ token other /(^(ident_char|0|'\n'))+/
+
+ token here_close //
+ token id
+ /ident_char+/
+ {
+ if HereId && HereId == match_text {
+ send( make_token(
+ typeid here_close,
+ pull(stdin, match_length - 1) ) )
+ } else {
+ send( make_token( typeid id, pull(stdin, match_length) ) )
+ }
+ }
+
+ token nl /'\n'/
+}
+
+def here_name
+ [id]
+ {
+ HereId = r1.data
+ }
+
+global str HereId
+
+def here_data
+ [here_data_item*]
+
+def here_data_item
+ [id]
+| [other]
+| [nl]
+
+def heredoc
+ [here_name here_data here_close id nl]
+
+
+heredoc S = parse heredoc( stdin )
+print_xml(S)
diff --git a/test/html/Makefile b/test/html/Makefile
new file mode 100644
index 00000000..d647261a
--- /dev/null
+++ b/test/html/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright 2002-2006 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f *.cpp *.bin
diff --git a/test/html/html-lextag.lm b/test/html/html-lextag.lm
new file mode 100644
index 00000000..0869538c
--- /dev/null
+++ b/test/html/html-lextag.lm
@@ -0,0 +1,324 @@
+#
+# Regular Definitions
+#
+rl def_name_char /[\-A-Za-z0-9._:?]/
+rl def_name /[A-Za-z_:] def_name_char*/
+rl def_system_literal /'"' [^"]* '"' | "'" [^']* "'"/
+
+#
+# Scanner for tag names.
+#
+lex TAG_NAME
+{
+ ignore /space+/
+ token tag_id /def_name/
+}
+
+#
+# Scanner for attributes names
+#
+lex ATTR_NAME
+{
+ ignore /space+/
+ token attr_name /def_name_char+/
+ literal '='
+}
+
+# Scanner for attribute values.
+lex ATTR_VAL
+{
+ ignore /space+/
+ literal '>', '/>'
+ token dquote_val /'"' ([^"] | '\\' any)* '"'/
+ token squote_val /"'" ([^'] | '\\' any)* "'"/
+ token unq_val /[^ \t\r\n<>"'] [^ \t\r\n<>]*/
+}
+
+#
+# Tokens
+#
+
+lex START
+{
+ ignore /space+/
+
+ literal '<', '</', '<!DOCTYPE'
+ token close_tag
+ /'</' [\t ]* id: [a-zA-Z]+ '>'/
+
+ token doc_data /[^<]+/
+ token comment /'<!--' any* :>> '-->'/
+}
+
+#
+# Tags
+#
+
+bool inTagStack( str id )
+{
+ tag_stack LocalTagStack = TagStack
+ for Tag:tag_id in LocalTagStack {
+ if id == Tag.data
+ return true
+ }
+ return false
+}
+
+# This scanner is just for the id in close tags. The id needs to be looked up
+# in the tag stack so we can determine if it is a stray.
+lex close_id
+{
+ # Ignore whitespace.
+ ignore /space+/
+
+ token stray_close_id //
+ token missing_close_id //
+
+ token close_id /def_name/
+ {
+ # If it is in the tag stack then it is a close_id. If not then it's a
+ # stray_close_id.
+ int send_id = typeid stray_close_id
+
+ if ( inTagStack( match_text ) ) {
+ print( 'CLOSE \'', match_text, '\' IN TAG STACK\n' )
+
+ # The tag is in the stack, send missing close tags until we get to it.
+ match TagStack [Top:tag_id Rest:tag_stack]
+ TagStack = Rest
+ while ( Top.data != match_text ) {
+ print( 'SENDING missing close\n' )
+ send( make_token( typeid missing_close_id, '' ) )
+ match TagStack [Top2:tag_id Rest2:tag_stack]
+ Top = Top2
+ TagStack = Rest2
+ }
+
+ print( 'SENDING close\n' )
+ send( make_token( typeid close_id, pull( stdin, match_length ) ) )
+ }
+ else {
+ print( 'CLOSE \'', match_text, '\' NOT IN TAG STACK\n' )
+ # The tag is not in the tag stack so send the id as a stray close.
+ send( make_token( typeid stray_close, pull( stdin, match_length ) ) )
+ }
+ }
+}
+
+#
+# Tag Stack
+#
+
+def tag_stack
+ [tag_id tag_stack]
+| []
+
+global tag_stack TagStack = construct tag_stack []
+
+#
+# Document Type
+#
+# This scanner handles inside DOCTYPE tags (except keywords).
+lex DOCTYPE
+{
+ ignore /space+/
+ token dt_name /def_name/
+ token dt_literal /def_system_literal/
+ token dt_bl /"[" [^\]]* "]"/
+ token dt_close /'>'/
+}
+
+# Using a separate scanner for the keywords in DOCTYPE prevents them from
+# covering dt_name
+lex DOCTYPE_KW
+{
+ ignore /space+/
+ literal 'SYSTEM', 'PUBLIC'
+}
+
+def DOCTYPE ['<!DOCTYPE' dt_name external_id dt_bl? dt_close]
+
+def external_id
+ ['SYSTEM' dt_literal?]
+| ['PUBLIC' dt_literal dt_literal?]
+
+#
+# Tags, with optionanal close.
+#
+
+def tag
+ [open_tag item* close_tag]
+
+def unclosed_tag
+ [open_tag item* missing_close_id]
+
+def open_tag
+ ['<' tag_id attr* '>']
+ {
+ TagStack = construct tag_stack
+ [r2 TagStack]
+ }
+
+#
+# Empty tags
+#
+def empty_tag
+ ['<' tag_id attr* '/>']
+
+#
+# Stray close tags
+#
+def stray_close
+ [close_tag]
+
+
+#
+# Attributes
+#
+
+def attr
+ [attr_name eql_attr_val?]
+
+def eql_attr_val ['=' attr_val]
+
+def attr_val
+ [squote_val]
+| [dquote_val]
+| [unq_val]
+| []
+
+#
+# Items
+#
+
+def item
+ [DOCTYPE]
+| [tag]
+| [unclosed_tag]
+| [empty_tag]
+| [stray_close]
+| [doc_data]
+| [comment]
+
+
+token trailing /any*/
+
+def start
+ [item* trailing]
+
+#
+# END GRAMMAR
+#
+
+int addDefaultAltTags( ref start Start )
+{
+ for T: open_tag in Start {
+ require T
+ ["<img" AttrList: attr* '>']
+
+ bool haveAlt = false
+ for A: attr in T {
+ if match A ["alt=" attr_val]
+ haveAlt = true
+ }
+
+ if !haveAlt {
+ for AL: attr* in T {
+ if match AL [] {
+ AL = construct attr*
+ [" alt=\"default alt\""]
+ break
+ }
+ }
+ }
+ }
+}
+
+int printLinks( start Start )
+{
+ for A:tag in Start {
+ require A
+ ["<a" AttrList: attr* ">" I: item* "</a>"]
+
+ for Attr: attr in AttrList {
+ if match Attr ["href = " AttrVal: attr_val]
+ print( 'link: ', I, '\ntarget: ', AttrVal, '\n\n' )
+ }
+ }
+}
+
+
+bool should_close( tag_id TI )
+{
+ return true
+}
+
+bool should_flatten( tag_id TI )
+{
+ return true
+}
+
+# Finds unclosed tags and puts the content after the tag. Afterwards
+# all unclosed tags will be empty 'inside'.
+#int flatten( ref start Start )
+#{
+# for TL: item* in Start {
+# require TL
+# [OT: open_tag Inside: item* Trailing: item*]
+#
+# match OT
+# ['<' TagId: tag_id attr* '>']
+#
+# if should_flatten( TagId )
+# {
+# require Inside
+# [item item*]
+#
+# # Put Trailing at the end of inside.
+# for END: item* in Inside {
+# if match END [] {
+# END = Trailing
+# break
+# }
+# }
+#
+# str empty = ''
+# missing_close_id Missing = construct missing_close_id [empty]
+# opt_close_tag EmptyCloseTag =
+# construct opt_close_tag [Missing]
+#
+# # Close the tag and put inside after it.
+# TL = construct item*
+# [OT EmptyCloseTag Inside]
+# }
+# }
+#}
+#
+#int close( ref start Start )
+#{
+# for TL: item in Start {
+# require TL
+# [OpenTag: open_tag Inside: item*]
+#
+# match OpenTag
+# ['<' TagId: tag_id attr* '>']
+#
+# if should_close( TagId )
+# {
+# close_id CloseId = construct close_id
+# [TagId.data]
+#
+# opt_close_tag CloseTag =
+# construct opt_close_tag ['</' CloseId '>']
+#
+# # Close the tag and put inside after it.
+# TL = construct item
+# [OpenTag Inside CloseTag]
+# }
+# }
+#}
+
+start HTML = parse start( stdin )
+print_xml( HTML )
+for C: close_tag in HTML
+ print( C.id, '\n' )
diff --git a/test/html/html.lm b/test/html/html.lm
new file mode 100644
index 00000000..98573f2e
--- /dev/null
+++ b/test/html/html.lm
@@ -0,0 +1,307 @@
+#
+# Regular Definitions
+#
+rl def_name_char /[\-A-Za-z0-9._:?]/
+rl def_name /[A-Za-z_:] def_name_char*/
+rl def_system_literal /'"' [^"]* '"' | "'" [^']* "'"/
+
+#
+# Scanner for tag names.
+#
+lex TAG_NAME
+{
+ ignore /space+/
+ token tag_id /def_name/
+}
+
+#
+# Scanner for attributes names
+#
+lex ATTR_NAME
+{
+ ignore /space+/
+ token attr_name /def_name_char+/
+ literal '='
+}
+
+# Scanner for attribute values.
+lex ATTR_VAL
+{
+ ignore /space+/
+ literal '>', '/>'
+ token dquote_val /'"' ([^"] | '\\' any)* '"'/
+ token squote_val /"'" ([^'] | '\\' any)* "'"/
+ token unq_val /[^ \t\r\n<>"'] [^ \t\r\n<>]*/
+}
+
+#
+# Tokens
+#
+
+lex START
+{
+ ignore /space+/
+ literal '<', '</', '<!DOCTYPE'
+ token doc_data /[^<]+/
+ token comment /"<!--" any* :>> "-->"/
+}
+
+#
+# Tags
+#
+
+# This scanner is just for the id in close tags. The id needs to be looked up
+# in the tag stack so we can determine if it is a stray.
+lex close_id
+{
+ # Ignore whitespace.
+ ignore /space+/
+
+ token stray_close_id //
+ token close_id /def_name/
+ {
+ # If it is in the tag stack then it is a close_id. If not then it's a
+ # stray_close_id.
+ int send_id = typeid stray_close_id
+
+ tag_stack LocalTagStack = TagStack
+ for Tag:tag_id in LocalTagStack {
+ tag_id T = Tag
+ if match_text == T.data {
+ send_id = typeid close_id
+ break
+ }
+ }
+
+ send( make_token( send_id, pull(stdin, match_length) ) )
+ }
+}
+
+#
+# Tag Stack
+#
+
+def tag_stack
+ [tag_id tag_stack]
+| []
+
+global tag_stack TagStack = construct tag_stack []
+
+#
+# Document Type
+#
+# This scanner handles inside DOCTYPE tags (except keywords).
+lex DOCTYPE
+{
+ ignore /space+/
+ token dt_name /def_name/
+ token dt_literal /def_system_literal/
+ token dt_bl /"[" [^\]]* "]"/
+ token dt_close /'>'/
+}
+
+# Using a separate scanner for the keywords in DOCTYPE prevents them from
+# covering dt_name
+lex DOCTYPE_KW
+{
+ ignore /space+/
+ literal 'SYSTEM', 'PUBLIC'
+}
+
+def DOCTYPE ['<!DOCTYPE' dt_name external_id dt_bl? dt_close]
+
+def external_id
+ ['SYSTEM' dt_literal?]
+| ['PUBLIC' dt_literal dt_literal?]
+
+#
+# Tags, with optionanal close.
+#
+
+def tag
+ [open_tag item* opt_close_tag]
+
+def open_tag
+ ['<' tag_id attr* '>']
+ {
+ TagStack = construct tag_stack
+ [r2 TagStack]
+ }
+
+def opt_close_tag
+ ['</' close_id '>']
+ {
+ match TagStack [Top:tag_id Rest:tag_stack]
+ if r2.data == Top.data
+ TagStack = Rest
+ else
+ reject
+ }
+
+| []
+ {
+ match TagStack [Top:tag_id Rest:tag_stack]
+ TagStack = Rest
+ }
+
+#
+# Empty tags
+#
+def empty_tag
+ ['<' tag_id attr* '/>']
+
+#
+# Stray close tags
+#
+def stray_close
+ ['</' stray_close_id '>']
+
+
+#
+# Attributes
+#
+
+def attr
+ [attr_name eql_attr_val?]
+
+def eql_attr_val ['=' attr_val]
+
+def attr_val
+ [squote_val]
+| [dquote_val]
+| [unq_val]
+| []
+
+#
+# Items
+#
+
+def item
+ [DOCTYPE]
+| [tag]
+| [empty_tag]
+| [stray_close]
+| [doc_data]
+| [comment]
+
+
+token trailing /any*/
+
+def start
+ [item* trailing]
+
+#
+# END GRAMMAR
+#
+
+int addDefaultAltTags( ref start Start )
+{
+ for T: open_tag in Start {
+ require T
+ ["<img" AttrList: attr* '>']
+
+ bool haveAlt = false
+ for A: attr in T {
+ if match A ["alt=" attr_val]
+ haveAlt = true
+ }
+
+ if !haveAlt {
+ for AL: attr* in T {
+ if match AL [] {
+ AL = construct attr*
+ [" alt=\"default alt\""]
+ break
+ }
+ }
+ }
+ }
+}
+
+int printLinks( start Start )
+{
+ for A:tag in Start {
+ require A
+ ["<a" AttrList: attr* ">" I: item* "</a>"]
+
+ for Attr: attr in AttrList {
+ if match Attr ["href = " AttrVal: attr_val]
+ print( 'link: ', I, '\ntarget: ', AttrVal, '\n\n' )
+ }
+ }
+}
+
+
+bool should_close( tag_id TI )
+{
+ return true
+}
+
+bool should_flatten( tag_id TI )
+{
+ return true
+}
+
+# Finds unclosed tags and puts the content after the tag. Afterwards
+# all unclosed tags will be empty 'inside'.
+int flatten( ref start Start )
+{
+ for TL: item* in Start {
+ require TL
+ [OT: open_tag Inside: item* Trailing: item*]
+
+ match OT
+ ['<' TagId: tag_id attr* '>']
+
+ if should_flatten( TagId )
+ {
+ require Inside
+ [item item*]
+
+ # Put Trailing at the end of inside.
+ for END: item* in Inside {
+ if match END [] {
+ END = Trailing
+ break
+ }
+ }
+
+ opt_close_tag EmptyCloseTag =
+ construct opt_close_tag []
+
+ # Close the tag and put inside after it.
+ TL = construct item*
+ [OT EmptyCloseTag Inside]
+ }
+ }
+}
+
+int close( ref start Start )
+{
+ for TL: item in Start {
+ require TL
+ [OpenTag: open_tag Inside: item*]
+
+ match OpenTag
+ ['<' TagId: tag_id attr* '>']
+
+ if should_close( TagId )
+ {
+ close_id CloseId = construct close_id
+ [TagId.data]
+
+ opt_close_tag CloseTag =
+ construct opt_close_tag ['</' CloseId '>']
+
+ # Close the tag and put inside after it.
+ TL = construct item
+ [OpenTag Inside CloseTag]
+ }
+ }
+}
+
+start HTML = parse start( stdin )
+flatten( HTML )
+#print_xml( HTML )
+printLinks( HTML )
+
diff --git a/test/html/input01.html b/test/html/input01.html
new file mode 100644
index 00000000..cf783d63
--- /dev/null
+++ b/test/html/input01.html
@@ -0,0 +1,8 @@
+<t1>
+
+ <t2>
+ <a href="foo">FOO</a>
+ <t3>
+ </t3>
+
+</t1>
diff --git a/test/http/Makefile b/test/http/Makefile
new file mode 100644
index 00000000..d647261a
--- /dev/null
+++ b/test/http/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright 2002-2006 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f *.cpp *.bin
diff --git a/test/http/http.lm b/test/http/http.lm
new file mode 100644
index 00000000..d914ab6f
--- /dev/null
+++ b/test/http/http.lm
@@ -0,0 +1,68 @@
+#
+# Character classes
+#
+rl CTL /0..31 | 127/
+rl CR /13/
+rl LF /10/
+rl SP /32/
+rl HT /9/
+rl CHAR /0..127/
+
+rl separators / '(' | ')' | '<' | '>'
+ | '@' | ',' | ';' | ':' | '\\'
+ | '"' | '/' | '[' | ']' | '?'
+ | '=' | '{' | '}' | SP | HT /
+
+rl token_char /CHAR - CTL - separators/
+
+#
+# Literal tokens
+#
+
+literal 'HTTP/', ' ', ':'
+token CRLF /CR LF/
+
+#
+# Request Line
+#
+
+token method /token_char+/
+
+token request_uri /(^SP)+/
+
+token http_number /digit+ '.' digit+/
+
+def http_version
+ [ 'HTTP/' http_number ]
+
+def request_line
+ [method ' ' request_uri
+ ' ' http_version CRLF]
+
+#
+# Header
+#
+
+token field_name /token_char+/
+
+token field_value
+ /(^(CR|LF) | CR LF (SP|HT))* CR LF/
+
+def header
+ [field_name ':' field_value]
+
+#
+# Request
+#
+
+def request
+ [request_line header* CRLF]
+
+request R = parse_stop request( stdin )
+
+print( 'HTTP/1.0 200 OK\r\n' )
+print( 'Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n' )
+print( 'Content-Type: text/plain\r\n' )
+print( '\r\n' )
+print_xml( R )
+
diff --git a/test/http/input1 b/test/http/input1
new file mode 100644
index 00000000..c1416f84
--- /dev/null
+++ b/test/http/input1
@@ -0,0 +1,2 @@
+GET /hi/there/ HTTP/1.1
+
diff --git a/test/http/input2 b/test/http/input2
new file mode 100644
index 00000000..076222d5
--- /dev/null
+++ b/test/http/input2
@@ -0,0 +1,13 @@
+GET /hithere/ HTTP/1.1
+Host: localhost:3535
+User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12
+Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip,deflate
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
+Keep-Alive: 300
+Connection: keep-alive
+Cache-Control: max-age=0
+
+adslfkj
+alkfj
diff --git a/test/http/input3 b/test/http/input3
new file mode 100644
index 00000000..16b817f1
--- /dev/null
+++ b/test/http/input3
@@ -0,0 +1,8 @@
+GET foo HTTP/1.1
+hello: foo
+hi: there
+ my
+ friend
+
+ from outter space
+
diff --git a/test/http/xinetd.conf b/test/http/xinetd.conf
new file mode 100644
index 00000000..5c95545c
--- /dev/null
+++ b/test/http/xinetd.conf
@@ -0,0 +1,10 @@
+service colm_http
+{
+ type = unlisted
+ socket_type = stream
+ protocol = tcp
+ port = 3535
+ wait = no
+ user = thurston
+ server = /home/thurston/devel/colm/test/http/http.bin
+}
diff --git a/test/island.in b/test/island.in
new file mode 100644
index 00000000..d34467bb
--- /dev/null
+++ b/test/island.in
@@ -0,0 +1,19 @@
+class
+{
+ 1;
+ "string";
+ foo;
+ func()
+ {
+ func()
+ {
+ 1+{2}
+ }
+ }
+}
+
+func()
+{
+ "data"
+ {a}
+}
diff --git a/test/island.lm b/test/island.lm
new file mode 100644
index 00000000..c407aa28
--- /dev/null
+++ b/test/island.lm
@@ -0,0 +1,57 @@
+
+lex function_body
+{
+ token func_chr /[^{}]+/
+ token func_open /'{'/
+ token func_close /'}'/
+}
+
+def func_item
+ [func_chr]
+| [func_open func_body func_close]
+
+def func_body
+ [func_item*]
+
+def func
+ [ident '(' ')' '{' func_body func_close ]
+
+lex start
+{
+ token ident /[a-zA-Z_]+/
+ token number /[0-9]+/
+
+ rl s_string / "'" ([^'\\\n] | '\\' any )* "'" /
+ rl d_string / '"' ([^"\\\n] | '\\' any )* '"' /
+ token string /s_string | d_string/
+
+ literal '+', '*', ';', '(', ')', '{', '}'
+
+ ignore wp / [ \t\n]+ /
+}
+
+def class_item
+ [func]
+| [class]
+| [ident ';']
+| [number ';']
+| [string ';']
+
+def class_body
+ [class_item*]
+
+def class
+ [ident '{' class_body '}' ]
+
+def top_item
+ [func]
+| [class]
+
+def start
+ [top_item*]
+ {
+ print_xml(lhs)
+ }
+
+#pattern start
+# ~class { func() { func() { 1+{2}} } } func() {{a}}
diff --git a/test/liftattrs.in b/test/liftattrs.in
new file mode 100644
index 00000000..5a50f377
--- /dev/null
+++ b/test/liftattrs.in
@@ -0,0 +1,3 @@
+<t1 a=b foo=bar1 c=d>
+ <t2 foo=bar2 e=f></t2>
+</t1>
diff --git a/test/liftattrs.lm b/test/liftattrs.lm
new file mode 100644
index 00000000..305a805b
--- /dev/null
+++ b/test/liftattrs.lm
@@ -0,0 +1,74 @@
+
+#
+# Regular Definitions
+#
+rl rl_ws /[ \t\n\r\v]+/
+rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/
+
+#
+# Tokens
+#
+
+lex start
+{
+ literal '=', '<', '>', '/'
+
+ # Ignore whitespace.
+ ignore /rl_ws/
+
+ # Open and close id
+ token id /rl_id/
+}
+
+#
+# Productions
+#
+
+def attr [id '=' id]
+
+def attr_list
+ [attr_list attr]
+| []
+
+def open_tag
+ ['<' id attr_list '>']
+
+def close_tag
+ ['<' '/' id '>']
+
+def tag
+ [open_tag item_list close_tag]
+
+def item_list
+ [item_list tag]
+| []
+
+item_list IL = parse item_list(stdin)
+
+# Get the item list
+match IL [RootItemList: item_list]
+
+# List for collecting the attrs we pull out.
+attr_list CollectedAttrs = construct attr_list []
+
+# Iterate through all attributes
+for AttrListIter:attr_list in RootItemList {
+ # If the name of the attr is foo, remove it.
+ if match AttrListIter
+ [SubAttrList:attr_list "foo=" Val:id]
+ {
+ # Remove the attribute
+ AttrListIter = construct attr_list
+ [SubAttrList]
+
+ # Add it to the colection
+ CollectedAttrs = construct attr_list
+ [CollectedAttrs " foo=" Val]
+ }
+}
+
+# Reconstruct the left hand side with the
+IL = construct item_list
+ ["<wrapper" CollectedAttrs ">" RootItemList "</wrapper>"]
+
+print( IL, '\n' )
diff --git a/test/mailbox.in b/test/mailbox.in
new file mode 100644
index 00000000..412f8bed
--- /dev/null
+++ b/test/mailbox.in
@@ -0,0 +1,29 @@
+From thurston Tue Jan 2 21:16:50 2007
+Return-Path: <unknown>
+X-Spam-Level: *
+Received: from [109.111.71.111] (helo=twfmtr)
+ by zifreax with smtp (Exim 4.43)
+ id 1H1vfs-0005LN-HW; Tue, 2 Jan 2007 21:16:16 -0500
+Message-ID: <459B113F.8050903@immoarthabitatge.com>
+X-Keywords:
+X-UID: 1
+
+Content-Type: text/html; charset=ISO-8859-1
+</body>
+</html>
+
+From thurston Wed Jan 3 02:35:48 2007
+Return-Path: <unknown>
+X-Spam-Checker-Version: SpamAssassin 3.1.1 (2006-03-10) on mambo.cs.queensu.ca
+X-Spam-Level: **
+X-Spam-Status: No, score=2.9 required=5.0 tests=BAYES_20,EXTRA_MPART_TYPE,
+ HTML_40_50,HTML_IMAGE_ONLY_16,HTML_MESSAGE,RCVD_IN_BL_SPAMCOP_NET
+ autolearn=no version=3.1.1
+X-Bogosity: Unsure, tests=bogofilter, spamicity=0.971708, version=1.0.2
+Status: RO
+X-UID: 2
+
+------=_NextPart_000_0010_01C72F11.F137BD60
+ charset="windows-1252"
+Content-Transfer-Encoding: quoted-printable
+
diff --git a/test/mailbox.lm b/test/mailbox.lm
new file mode 100644
index 00000000..3387fcff
--- /dev/null
+++ b/test/mailbox.lm
@@ -0,0 +1,44 @@
+
+# lines, and fromlines
+lex lines
+{
+ rl day /[A-Z][a-z][a-z]/
+ rl month /[A-Z][a-z][a-z]/
+ rl year /[0-9][0-9][0-9][0-9]/
+ rl time /[0-9][0-9] ':' [0-9][0-9] ( ':' [0-9][0-9] )? /
+ rl letterZone /[A-Z][A-Z][A-Z]/
+ rl numZone /[+\-][0-9][0-9][0-9][0-9]/
+ rl zone / letterZone | numZone/
+ rl dayNum /[0-9 ][0-9]/
+
+ # These are the different formats of the date minus an obscure
+ # type that has a funny string 'remote from xxx' on the end. Taken
+ # from c-client in the imap-2000 distribution.
+ rl date / day ' ' month ' ' dayNum ' ' time ' '
+ ( year | year ' ' zone | zone ' ' year ) /
+
+ # From lines separate messages. We will exclude from_line from a message
+ # body line. This will cause us to stay in message line up until an
+ # entirely correct from line is matched.
+ token from_line / 'From ' (any-'\n')* ' ' date '\n' /
+ token simple_line / [^\n]* '\n' /
+}
+
+rl hchar /print - [ :]/
+token header_name /hchar+/
+
+token colon /':' ' '*/
+token header_content / ([^\n] | '\n' [ \t])* '\n'/
+token blank_line / '\n' /
+
+def header
+ [header_name colon header_content]
+
+def message
+ [from_line header* blank_line simple_line*]
+
+def start
+ [message*]
+ {
+ print_xml( lhs )
+ }
diff --git a/test/matchex.in b/test/matchex.in
new file mode 100644
index 00000000..f458f2ad
--- /dev/null
+++ b/test/matchex.in
@@ -0,0 +1,3 @@
+<person name=adrian hometown=kingston>
+ <t1 foo=bar2 e=f></t2>
+</person> \ No newline at end of file
diff --git a/test/matchex.lm b/test/matchex.lm
new file mode 100644
index 00000000..67b69238
--- /dev/null
+++ b/test/matchex.lm
@@ -0,0 +1,34 @@
+lex start
+{
+ token id /[a-zA-Z_][a-zA-Z0-9_]*/
+ literal '=', '<', '>', '/'
+ ignore /[ \t\n\r\v]+/
+}
+
+def attr
+ [id '=' id]
+
+def open_tag
+ ['<' id attr* '>']
+
+def close_tag
+ ['<' '/' id '>']
+
+def tag
+ [open_tag item* close_tag]
+
+def item
+ [tag]
+| [id]
+
+tag Tag = parse tag( stdin )
+
+# Style: List of literal text and types.
+match Tag ["<person name=" Val1:id attr*">" item* "</person>"]
+
+# Style: Literal text with embedded lists of types.
+match Tag "<person name=[Val2:id attr*]>[item*]</person>"
+
+print( Val1, '\n' )
+print( Val2, '\n' )
+
diff --git a/test/maxlen.lm b/test/maxlen.lm
new file mode 100644
index 00000000..19869634
--- /dev/null
+++ b/test/maxlen.lm
@@ -0,0 +1,44 @@
+
+#
+# Regular Definitions
+#
+rl rl_ws /[ \t\n\r\v]+/
+rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/
+
+#
+# Tokens
+#
+
+lex start
+{
+ ignore /rl_ws/
+ token id /rl_id/
+}
+
+global int num
+global int allow = 3
+
+def item
+ [id]
+ {
+ num = num + 1
+ int toomuch = allow+1
+ if num == toomuch {
+ reject
+ }
+ }
+
+def open
+ []
+ {
+ num = 0
+ }
+
+def close []
+
+def restricted_list
+ [open item*]
+
+def start
+ [restricted_list id*]
+
diff --git a/test/mediawiki/Makefile b/test/mediawiki/Makefile
new file mode 100644
index 00000000..3e6bf661
--- /dev/null
+++ b/test/mediawiki/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright 2008 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: pdump garticle mediawiki.bin
+
+pdump.cpp: pdump.rl
+ ragel -G2 -o pdump.cpp pdump.rl
+
+pdump: pdump.cpp
+ g++ -O3 -Wall -o pdump pdump.cpp
+
+garticle.cpp: garticle.rl
+ ragel -G2 -o garticle.cpp garticle.rl
+
+garticle: garticle.cpp
+ g++ -O3 -Wall -o garticle garticle.cpp
+
+mediawiki.bin: mediawiki.lm
+ $(COLM) mediawiki.lm
+
+clean:
+ rm -f mediawiki.cpp *.bin garticle.cpp garticle pdump.cpp pdump
diff --git a/test/mediawiki/garticle.rl b/test/mediawiki/garticle.rl
new file mode 100644
index 00000000..cc101364
--- /dev/null
+++ b/test/mediawiki/garticle.rl
@@ -0,0 +1,135 @@
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <string.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::ifstream;
+using std::ofstream;
+
+%%{
+ machine garticle;
+ write data;
+}%%
+
+
+int main( int argc, char **argv )
+{
+ std::ios::sync_with_stdio(false);
+
+ if ( argc != 5 ) {
+ cerr << "usage: garticle <dump-file> <article-index> <section> <article>" << endl;
+ return -1;
+ }
+
+ char *dumpFile = argv[1];
+ char *articleIndex = argv[2];
+ char *section = argv[3];
+ char *article = argv[4];
+
+ ifstream dump( dumpFile );
+ if ( !dump.is_open() ) {
+ cerr << "error: unable to open " << dumpFile << " for reading" << endl;
+ return -1;
+ }
+
+ ifstream index( articleIndex );
+ if ( !index.is_open() ) {
+ cerr << "error: unable to open " << articleIndex << " for writing" << endl;
+ return -1;
+ }
+
+ long long articleNum = atoll(article);
+ index.seekg( articleNum * sizeof(long long) );
+
+ long long start, end;
+ index.read( (char*)&start, sizeof(long long) );
+ index.read( (char*)&end, sizeof(long long) );
+
+ long long len = end - start;
+ char *buf = new char[len];
+ dump.seekg( start-5 );
+ dump.read( buf, len );
+
+ char tn[2048];
+ long ptn = 0;
+ bool emit = false;
+
+ char *p = buf, *pe = buf+len;
+ int cs;
+
+ %%{
+ newline = '\n';
+ sp = [ \t\n\r];
+
+ name = [a-zA-Z:_0-9]+;
+
+ # Tag names.
+ tag_name = name
+ >{ ptn = 0; }
+ ${ tn[ptn++] = *p; }
+ %{ tn[ptn++] = 0; }
+ ;
+
+ attr_name = name;
+
+ # Attributes
+ attr_val = '"' ( [^"\\] | newline | ( '\\' any ) )* '"';
+ attr = attr_name '=' attr_val;
+ attrs = ( sp attr )*;
+
+ action maybe_open {
+ if ( strcmp( tn, section ) == 0 )
+ emit = true;
+ }
+
+ action maybe_close {
+ if ( strcmp( tn, section ) == 0 )
+ emit = false;
+ }
+
+ # Tags
+ tag = '<' tag_name %maybe_open attrs sp? ( '>' | '/>' );
+ close_tag = '</' tag_name %maybe_close '>';
+
+ # Character data, not spaces and not tag starts.
+ char_data_char = ^('<'|'&');
+ char_data = char_data_char+
+ ${
+ if ( emit )
+ cout << *p;
+ } ;
+
+ defined_entities =
+ 'quot' %{if (emit) cout << '"';} |
+ 'amp' %{if (emit) cout << '&';} |
+ 'apos' %{if (emit) cout << '\'';} |
+ 'lt' %{if (emit) cout << '<';} |
+ 'gt' %{if (emit) cout << '>';};
+
+ entity_ref = '&' defined_entities ';';
+
+ main := (
+ tag |
+ close_tag |
+ entity_ref |
+ char_data
+ )*
+ ;
+
+ write init;
+ write exec;
+ }%%
+
+ if ( cs < garticle_first_final ) {
+ cerr << endl << endl << "garticle: error parsing dump file" << endl;
+ return 1;
+ }
+
+ //cout.write( buf, len );
+ cout << endl;
+
+ return 0;
+}
diff --git a/test/mediawiki/mediawiki.lm b/test/mediawiki/mediawiki.lm
new file mode 100644
index 00000000..e8dd3a27
--- /dev/null
+++ b/test/mediawiki/mediawiki.lm
@@ -0,0 +1,196 @@
+def open_item
+ str type
+ int num
+ []
+
+list open_stack [open_item]
+global open_stack OpenStack = construct open_stack []
+open_item Sentinal = construct open_item( type: '** SENTINAL **', num: 1 ) []
+OpenStack.push( Sentinal )
+
+lex start
+{
+ token stray_close //
+
+ token ocurly /'{'+/
+ {
+ open_item OI = construct open_item( type: '{', num: match_length ) []
+ OpenStack.push( OI )
+ int i = 0
+ while ( i < match_length ) {
+ send( make_token( typeid ocurly, pull(stdin, 1 ) ) )
+ i = i + 1
+ }
+ }
+
+ token ccurly1 //
+ token ccurly2 //
+ token ccurly3 //
+ token missing_curly //
+
+ token tmp1 /'}'+/
+ {
+ if OpenStack.length > 0 && OpenStack.tail.type == '{' {
+ int length = 3
+ if ( length > match_length )
+ length = match_length
+
+ open_item Tail = OpenStack.pop()
+ if ( length > Tail.num )
+ length = Tail.num
+
+ if ( length == 1 )
+ send( make_token( typeid ccurly1, pull( stdin, 1 ) ) )
+ else if ( length == 2 )
+ send( make_token( typeid ccurly2, pull( stdin, 2 ) ) )
+ else if ( length == 3 )
+ send( make_token( typeid ccurly3, pull( stdin, 3 ) ) )
+
+ Tail.num = Tail.num - length
+
+ if ( Tail.num > 0 )
+ OpenStack.push( Tail )
+ }
+ else {
+ send( make_token( typeid stray_close, pull( stdin, match_length ) ) )
+ }
+ }
+
+ token osquare /'['+/
+ {
+ open_item OI = construct open_item( type: '[', num: match_length ) []
+ OpenStack.push( OI )
+ int i = 0
+ while ( i < match_length ) {
+ send( make_token( typeid osquare, pull(stdin, 1 ) ) )
+ i = i + 1
+ }
+ }
+
+ token csquare1 //
+ token csquare2 //
+ token missing_square //
+
+ token tmp2 /']'+/
+ {
+ if OpenStack.length > 0 && OpenStack.tail.type == '[' {
+ int length = 2
+ if ( length > match_length )
+ length = match_length
+
+ open_item Tail = OpenStack.pop()
+ if ( length > Tail.num )
+ length = Tail.num
+
+ if ( length == 1 )
+ send( make_token( typeid csquare1, pull( stdin, 1 ) ) )
+ else if ( length == 2 )
+ send( make_token( typeid csquare2, pull( stdin, 2 ) ) )
+
+ Tail.num = Tail.num - length
+
+ if ( Tail.num > 0 )
+ OpenStack.push( Tail )
+ }
+ else {
+ send( make_token( typeid stray_close, pull( stdin, match_length ) ) )
+ }
+ }
+
+ literal '|'
+ token char /any/
+
+ preeof {
+ while ( OpenStack.length > 0 ) {
+ open_item Tail = OpenStack.pop()
+ int i
+ if ( Tail.type == '{' ) {
+ i = 0
+ while ( i < Tail.num ) {
+ send( make_token( typeid missing_curly, '}' ) )
+ i = i + 1
+ }
+ }
+ else if ( Tail.type == '[' ) {
+ i = 0
+ while ( i < Tail.num ) {
+ send( make_token( typeid missing_square, ']' ) )
+ i = i + 1
+ }
+ }
+ }
+ }
+}
+
+#
+# Internal Links
+#
+
+
+lex el_prefix
+{
+ literal 'http:'
+ literal 'ftp:'
+ literal 'mailto:'
+}
+
+def el_prefix
+ ['http:']
+| ['ftp:']
+| ['mailto:']
+
+def external_link
+ [osquare item* csquare1]
+
+def internal_link
+ [osquare osquare item* csquare2]
+
+def unclosed_square
+ [osquare item* missing_square]
+
+#
+# Templates
+#
+
+def sing_template
+ [ocurly item* ccurly1]
+
+def template
+ [ocurly ocurly item* ccurly2]
+
+def parameter
+ [ocurly ocurly ocurly item* ccurly3]
+
+def unclosed_curly
+ [ocurly item* missing_curly]
+
+#
+# Template Parameters
+#
+
+
+def U1 []
+def U2 []
+def U3 []
+
+def item
+ [external_link]
+| [internal_link]
+| [unclosed_curly]
+| [sing_template]
+| [template]
+| [parameter]
+| [unclosed_curly]
+| [stray_close]
+| [osquare]
+| ['|']
+| [char]
+
+def start
+ [item*]
+
+start S = parse start(stdin)
+for I: internal_link in S
+ print( I, '\n' )
+print_xml( S )
+#print_xml( OpenStack )
diff --git a/test/mediawiki/pdump.rl b/test/mediawiki/pdump.rl
new file mode 100644
index 00000000..8b19bf37
--- /dev/null
+++ b/test/mediawiki/pdump.rl
@@ -0,0 +1,115 @@
+#include <iostream>
+#include <fstream>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::ifstream;
+using std::ofstream;
+
+
+#define RBS 65536
+
+%%{
+ machine pdump;
+ write data;
+}%%
+
+int main( int argc, char **argv )
+{
+ std::ios::sync_with_stdio(false);
+
+ if ( argc != 3 ) {
+ cerr << "usage: pdump <dump-file> <article-index>" << endl;
+ return -1;
+ }
+
+ ifstream input( argv[1] );
+ if ( !input.is_open() ) {
+ cerr << "error: unable to open " << argv[1] << " for reading" << endl;
+ return -1;
+ }
+
+ ofstream output( argv[2] );
+ if ( !output.is_open() ) {
+ cerr << "error: unable to open " << argv[2] << " for writing" << endl;
+ return -1;
+ }
+
+ long cs;
+ %% write init;
+
+ long long line = 1;
+ long long total = 0;
+ static char buf[RBS];
+ while ( true ) {
+ if ( input.eof() )
+ break;
+
+ input.read( buf, RBS );
+ long ss = input.gcount();
+
+ char *p = buf, *pe = buf + ss;
+
+ %%{
+
+ action newline { line++; }
+ newline = '\n'@newline;
+ any_nl = any | newline;
+
+ sp_char = [ \t\n\r];
+ sp = sp_char | newline;
+
+ # Tag names.
+ any_tag_name = [a-zA-Z:0-9]+ ;
+
+ page_tag_name = 'page'
+ %{
+ long inbuf = p - buf;
+ long long pos = total + inbuf;
+ output.write( (char*)&pos, sizeof(long long) );
+ };
+
+ tag_name = any_tag_name | page_tag_name;
+
+ attr_name = [a-zA-Z:0-9]+;
+
+ # Attributes
+ attr_val = '"' ( [^"\\] | newline | ( '\\' any_nl ) )* '"';
+ attr = attr_name '=' attr_val;
+ attrs = ( sp attr )*;
+
+ # Tags
+ tag = '<' tag_name attrs sp? ( '>' | '/>' );
+ close_tag = '</' any_tag_name '>';
+
+ # Character data, not spaces and not tag starts.
+ char_data_char = ^(sp_char | '<');
+ char_data = char_data_char+;
+
+ main := (
+ tag |
+ close_tag |
+ newline |
+ sp |
+ char_data
+ )*
+ ;
+
+ write exec;
+
+ }%%
+
+ if ( cs == pdump_error ) {
+ cerr << "error:" << line << ": parse error" << endl;
+ return -1;
+ }
+
+ total += ss;
+ }
+
+ input.close();
+ output.close();
+
+ return 0;
+}
diff --git a/test/nestedcomm.in b/test/nestedcomm.in
new file mode 100644
index 00000000..11789576
--- /dev/null
+++ b/test/nestedcomm.in
@@ -0,0 +1 @@
+hello there ( (this is a nested comment /*sdf;asd_++_stuff) ) and this is not
diff --git a/test/nestedcomm.lm b/test/nestedcomm.lm
new file mode 100644
index 00000000..cc28726e
--- /dev/null
+++ b/test/nestedcomm.lm
@@ -0,0 +1,41 @@
+#
+# Tokens
+#
+
+# Any single character can be a literal
+lex start
+{
+ # Ignore whitespace.
+ ignore /[ \t\n\r\v]+/
+
+ # Open and close id
+ token id /[a-zA-Z_][a-zA-Z0-9_]*/
+
+ token open_paren /'('/
+ {
+ send_ignore( parse_stop nested_comment( stdin ) )
+ }
+}
+
+#
+# Token translation
+#
+
+lex nc_scan
+{
+ literal '(', ')'
+ token nc_data /[^()]+/
+}
+
+def nc_item
+ [nc_data]
+| [nested_comment]
+
+def nested_comment
+ ['(' nc_item* ')']
+
+def nested [id*]
+
+nested P = parse nested( stdin )
+print_xml( P )
+print( P, '\n' )
diff --git a/test/python/Makefile b/test/python/Makefile
new file mode 100644
index 00000000..6ee0fde1
--- /dev/null
+++ b/test/python/Makefile
@@ -0,0 +1,33 @@
+#
+# Copyright 2007 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f *.cpp *.bin
diff --git a/test/python/input1.py b/test/python/input1.py
new file mode 100644
index 00000000..22ffd2e1
--- /dev/null
+++ b/test/python/input1.py
@@ -0,0 +1,18 @@
+
+# dude, this is a comment
+ # some more
+hello
+def dude():
+ yes
+ awesome;
+
+ # Here we have a comment
+ def realy_awesome(): # hi there
+ in_more
+
+ same_level
+ def one_liner(): first; second # both inside one_liner
+
+ back_down
+
+last_statement
diff --git a/test/python/input2.py b/test/python/input2.py
new file mode 100644
index 00000000..063825e1
--- /dev/null
+++ b/test/python/input2.py
@@ -0,0 +1,20 @@
+
+# dude, this is a comment
+ # some more
+hello
+if 1:
+ yes
+ awesome;
+
+ # Here we have a comment
+ if ('hello'): # hi there
+ in_more
+
+ same_level
+ if ['dude', 'dudess'].horsie(): first; second # both inside one_liner
+ 1
+
+ back_down
+
+last_statement
+
diff --git a/test/python/input3.py b/test/python/input3.py
new file mode 100644
index 00000000..90ecf3f9
--- /dev/null
+++ b/test/python/input3.py
@@ -0,0 +1 @@
+hello = 1.1(20);
diff --git a/test/python/input4.py b/test/python/input4.py
new file mode 100644
index 00000000..1a281c46
--- /dev/null
+++ b/test/python/input4.py
@@ -0,0 +1,10 @@
+
+# subscription
+a[1] = b[2];
+
+# simple slicing
+a[1:1] = b[2:2];
+
+# simple slicing
+a[1:1, 2:2] = b[3:3, 4:4];
+
diff --git a/test/python/python.lm b/test/python/python.lm
new file mode 100644
index 00000000..d4e8a692
--- /dev/null
+++ b/test/python/python.lm
@@ -0,0 +1,727 @@
+# Regular definitions
+rl ident_char /[a-zA-Z_]/
+
+# List used as a stack of indentations.
+list indent_stack [int]
+global indent_stack IndentStack = construct indent_stack []
+IndentStack.push( 0 )
+
+# Has a newline been sent for this '\n' .. whitespace match.
+global int newline_sent = 0
+
+# Tokens.
+lex start
+{
+ # Python keywords.
+ literal 'and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or',
+ 'with', 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except',
+ 'import', 'print', 'class', 'exec', 'in', 'raise', 'continue',
+ 'finally', 'is', 'return', 'def', 'for', 'lambda', 'try'
+
+ # Identifiers
+ rl lowercase /'a'..'z'/
+ rl uppercase /'A'..'Z'/
+ rl letter /lowercase | uppercase/
+ token identifier /(letter|'_') (letter | digit | '_')*/
+
+ # Literals
+ rl escapeseq /'\\' any /
+ rl longstringchar /[^\\]/
+ rl shortstringchar_s /[^\\\n']/
+ rl shortstringchar_d /[^\\\n"]/
+ rl longstringitem /longstringchar | escapeseq/
+ rl shortstringitem_s /shortstringchar_s | escapeseq/
+ rl shortstringitem_d /shortstringchar_d | escapeseq/
+ rl longstring /"'''" longstringitem* :>> "'''" | '"""' longstringitem* :>> '"""'/
+ rl shortstring /"'" shortstringitem_s* "'" | '"' shortstringitem_d* '"'/
+ rl stringprefix /"r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"/
+ token stringliteral /stringprefix? (shortstring | longstring)/
+
+ # Integers
+ rl hexdigit /digit | 'a'..'f' | 'A'..'F'/
+ rl octdigit /'0'..'7'/
+ rl nonzerodigit /'1'..'9'/
+ rl hexinteger /'0' ('x' | 'X') hexdigit+/
+ rl octinteger /'0' octdigit+/
+ rl decimalinteger /nonzerodigit digit* | '0'/
+ token integer /decimalinteger | octinteger | hexinteger/
+ token longinteger /integer ('l' | 'L')/
+
+ # Floats.
+ rl exponent /('e' | 'E') ('+' | '-')? digit+/
+ rl fraction /'.' digit+/
+ rl intpart /digit+/
+ rl pointfloat /intpart? fraction | intpart '.'/
+ rl exponentfloat /(intpart | pointfloat) exponent/
+ token floatnumber /pointfloat | exponentfloat/
+
+ # Imaginaries.
+ token imagnumber /(floatnumber | intpart) ("j" | "J")/
+
+ # Operators.
+ literal '+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&', '|', '^',
+ '~', '<', '>', '<=', '>=', '==', '!=', '<>'
+
+ # Delimiters
+ literal '(', ')', '[', ']', '{', '}', '@', ',', ':', '.', '`', '=', ';',
+ '+=', '-=', '*=', '/=', '//=', '%=', '&=', '|=', '^=', '>>=', '<<=',
+ '**='
+
+ literal '...'
+
+ # In general whitespace is ignored.
+ ignore WS /' '+/
+
+ # Find and ignore entire blank lines.
+ token BLANK_LINE
+ / '\n' [ \t]* ('#' [^\n]*)? '\n' /
+ {
+ # Need to shorten to take off the newline.
+ # Turn it into ignore.
+ send_ignore( make_token( typeid WS, pull(stdin, match_length - 1) ) )
+ }
+
+ # Find and ignore comments.
+ token COMMENT
+ / '#' [^\n]* '\n' /
+ {
+ # Need to shorten to take off the newline. Turn it into ignore.
+ send_ignore( make_token( typeid WS, pull(stdin, match_length - 1) ) )
+ }
+
+ # These tokens are generated
+ token INDENT //
+ token DEDENT //
+ token NEWLINE //
+ ignore IND_WS //
+
+ token INDENTATION
+ /'\n' [ \t]*/
+ {
+ # First the newline.
+ send( make_token( typeid NEWLINE, '' ) )
+
+ # We have already sent the newline, compute the indentation level.
+ int data_length = match_length - 1
+
+ if data_length > IndentStack.top {
+ # The indentation level is more than the level on the top
+ # of the stack. This is an indent event. Send as an INDENT.
+ send( make_token( typeid INDENT, '' ) )
+
+ # Push to the stack as per python manual.
+ IndentStack.push( data_length )
+ } else {
+ while data_length < IndentStack.top {
+ # The indentation level is less than the level on the top of
+ # the stack. Pop the level and send one dedent. This flow of
+ # control will execute until we find the right indentation level
+ # to match up with.
+ IndentStack.pop()
+
+ # Send as a DEDENT
+ send( make_token( typeid DEDENT, '' ) )
+ }
+ }
+
+ # FIXME: if data.length is now > top of stack then error. This
+ # means the outdent does not match anything.
+
+ # We have squared up INDENTs and DEDENTs. Ignore the entire match.
+ send_ignore( make_token( typeid WS, pull(stdin, match_length) ) )
+ }
+}
+
+# Blank lines or comment lines at the beginning of the file.
+token LEADER / ( [ \t]* ('#' [^\n]*)? '\n' )* /
+
+int print_target_subscriptions_and_slicings( start Start )
+{
+ for TI: target_ext in Start {
+ if match TI [subscription] {
+ print( 'TARGET SUBSCRIPTION: ', TI, '\n' )
+ }
+
+ if match TI [simple_slicing] {
+ print( 'TARGET SIMPLE SLICING: ', TI, '\n' )
+ }
+
+ if match TI [extended_slicing] {
+ print( 'TARGET EXTENDED SLICING: ', TI, '\n' )
+ }
+ }
+
+}
+
+int print_primary_subscriptions_and_slicings( start Start )
+{
+ for PI:primary_ext in Start {
+ if match PI [subscription] {
+ print( 'PRIMARY SUBSCRIPTION: ', PI, '\n' )
+ }
+
+ if match PI [simple_slicing] {
+ print( 'PRIMARY SIMPLE SLICING: ', PI, '\n' )
+ }
+
+ if match PI [extended_slicing] {
+ print( 'PRIMARY EXTENDED SLICING: ', PI, '\n' )
+ }
+ }
+}
+
+def start
+ [file_input]
+
+def file_input
+ [file_input_forms*]
+
+def file_input_forms
+ [statement]
+| [NEWLINE]
+
+def statement
+ [stmt_list NEWLINE]
+| [compound_stmt]
+
+def stmt_list
+ [simple_stmt another_stmt* opt_semi]
+
+def another_stmt
+ [';' simple_stmt]
+
+def opt_semi
+ [';']
+| []
+
+def suite
+ [stmt_list NEWLINE]
+| [NEWLINE INDENT statement_seq DEDENT]
+
+def statement_seq
+ [statement_seq statement]
+| [statement]
+
+def compound_stmt
+ [if_stmt]
+| [while_stmt]
+| [for_stmt]
+| [try_stmt]
+| [with_stmt]
+| [funcdef]
+| [classdef]
+
+def if_stmt
+ ['if' expression ':' suite elif_part* opt_else_part]
+
+def elif_part
+ ['elif' expression ':' suite]
+
+def opt_else_part
+ ['else' ':' suite]
+| []
+
+def while_stmt
+ ['while' expression ':' suite opt_else_part]
+
+def for_stmt
+ ['for' target_list 'in' expression_list ':' suite opt_else_part]
+
+def try_stmt
+ ['try' ':' suite except_list opt_else_part opt_finally_part]
+| ['try' ':' suite 'finally' ':' suite]
+
+def except_list
+ [except_list except_part]
+| [except_part]
+
+def except_part
+ ['except' ':' suite]
+| ['except' expression ':' suite]
+| ['except' expression ',' target ':' suite]
+
+def opt_finally_part
+ ['finally' ':' suite]
+| []
+
+def with_stmt
+ ['with' expression ':' suite]
+| ['with' expression 'as' target ':' suite]
+
+def funcdef
+ [decorators 'def' funcname '(' opt_parameter_list ')' ':' suite]
+
+def funcname
+ [identifier]
+
+def decorators
+ [decorators decorator]
+| []
+
+def decorator
+ ['@' dotted_name opt_decorator_pal NEWLINE]
+
+def opt_decorator_pal
+ []
+| ['(' ')']
+| ['(' argument_list ')']
+| ['(' argument_list ',' ')']
+
+def dotted_name
+ [dotted_name '.' identifier]
+| [identifier]
+
+def opt_parameter_list
+ [parameter_list]
+| []
+
+def parameter_list
+ [defparameter_list defparameter opt_comma]
+| [defparameter_list '*' identifier]
+| [defparameter_list '*' identifier '**' identifier]
+| [defparameter_list '**' identifier]
+
+def defparameter_list
+ [defparameter_list defparameter ',']
+| []
+
+def defparameter
+ [parameter]
+| [parameter '=' expression]
+
+def sublist
+ [sublist_pl opt_comma]
+
+def sublist_pl
+ [sublist_pl ',' parameter]
+| [parameter]
+
+def parameter
+ [identifier]
+| ['(' sublist ')']
+
+def classdef
+ ['class' classname opt_inheritance ':' suite]
+
+def classname
+ [identifier]
+
+def opt_inheritance
+ ['(' ')']
+| ['(' expression_list ')']
+| []
+
+def simple_stmt
+ [expression_stmt]
+| [assert_stmt]
+| [assignment_stmt]
+| [augmented_assignment_stmt]
+| [pass_stmt]
+| [del_stmt]
+| [print_stmt]
+| [return_stmt]
+| [yield_stmt]
+| [raise_stmt]
+| [break_stmt]
+| [continue_stmt]
+| [import_stmt]
+| [global_stmt]
+| [exec_stmt]
+
+def expression_stmt
+ [expression_list]
+
+def assert_stmt
+ ['assert' expression_list_core]
+
+def assignment_stmt
+ [target_equals_list expression_list]
+
+def target_equals_list
+ [target_equals_list target_equals]
+| [target_equals]
+
+def target_equals
+ [target_list '=']
+
+def target_list
+ [target_list_core opt_comma]
+
+def target_list_core
+ [target_list_core ',' target]
+| [target]
+
+def target
+ [target_atom target_ext_rep]
+
+def target_atom
+ [identifier]
+| ['(' target_list ')']
+| ['[' target_list ']']
+
+def target_ext_rep
+ [target_ext target_ext_rep]
+| []
+
+def target_ext
+ [attributeref]
+| [subscription]
+| [slicing]
+
+def augmented_assignment_stmt
+ [target augop expression_list]
+
+def augop
+ ['+='] | ['-='] | ['*='] | ['/=']
+| ['\%='] | ['**='] | ['>>='] | ['<<='] | ['\&=']
+| ['^'] | ['|=']
+
+def pass_stmt
+ ['pass']
+
+def del_stmt
+ ['del' target_list]
+
+def print_stmt
+ ['print' opt_expression_list]
+| ['print' '>>' expression_list]
+
+def return_stmt
+ ['return' opt_expression_list]
+
+def yield_stmt
+ ['yield' expression_list]
+
+def raise_stmt
+ ['raise']
+| ['raise' expression]
+| ['raise' expression ',' expression]
+| ['raise' expression ',' expression ',' expression]
+
+def break_stmt
+ ['break']
+
+def continue_stmt
+ ['continue']
+
+def import_stmt
+ ['import' module opt_as_name more_imports]
+| ['from' module 'import' identifier opt_as_name more_imports]
+| ['from' module 'import' '(' identifier opt_as_name more_imports opt_comma ')']
+| ['from' module 'import' '*']
+
+def more_imports
+ [more_imports ',' identifier opt_as_name]
+| []
+
+def module
+ [module '.' identifier]
+| [identifier]
+
+def opt_as_name
+ ['as' identifier]
+| []
+
+def global_stmt
+ ['global' identifer_list]
+
+def identifer_list
+ [identifer_list ',' identifier]
+| [identifier]
+
+def exec_stmt
+ ['exec' expression]
+| ['exec' expression 'in' expression]
+| ['exec' expression 'in' expression ',' expression]
+
+def opt_expression_list
+ [expression_list]
+| []
+
+def expression_list
+ [expression_list_core opt_comma]
+
+def expression_list_core
+ [expression_list_core ',' expression]
+| [expression]
+
+def opt_comma
+ [',']
+| []
+
+def expression
+ [or_test 'if' or_test 'else' test]
+| [or_test]
+| [lambda_form]
+
+def or_test
+ [or_test 'or' and_test]
+| [and_test]
+
+def and_test
+ [and_test 'and' not_test]
+| [not_test]
+
+def not_test
+ [comparison]
+| ['not' not_test]
+
+def lambda_form
+ ['lambda' opt_parameter_list ':' expression]
+
+def test
+ [or_test]
+| [lambda_form]
+
+def comparison
+ [or_expr comparison_part*]
+
+def comparison_part
+ [comp_operator or_expr]
+
+def comp_operator
+ ['<'] | ['>'] | ['=='] | ['>='] | ['<='] | ['<>'] | ['!='] | ['is'] |
+ ['is' 'not'] | ['in'] | ['not' 'in']
+
+def or_expr
+ [or_expr '|' xor_expr]
+| [xor_expr]
+
+def xor_expr
+ [xor_expr '^' and_expr]
+| [and_expr]
+
+def and_expr
+ [and_expr '&' shift_expr]
+| [shift_expr]
+
+def shift_expr
+ [shift_expr '<<' a_expr]
+| [shift_expr '>>' a_expr]
+| [a_expr]
+
+def a_expr
+ [a_expr '+' m_expr]
+| [a_expr '-' m_expr]
+| [m_expr]
+
+def m_expr
+ [m_expr '*' u_expr]
+| [m_expr '//' u_expr]
+| [m_expr '/' u_expr]
+| [m_expr '\%' u_expr]
+| [u_expr]
+
+def u_expr
+ [power]
+| ['-' u_expr]
+| ['+' u_expr]
+| ['\~' u_expr]
+
+def power
+ [primary '**' u_expr]
+| [primary]
+
+def primary
+ [atom primary_ext_rep]
+
+def atom
+ [identifier]
+| [pyliteral]
+| [enclosure]
+
+def primary_ext_rep
+ [primary_ext primary_ext_rep]
+| []
+
+def primary_ext
+ [attributeref]
+| [subscription]
+| [slicing]
+| [call]
+
+def pyliteral
+ [stringliteral]
+| [integer]
+| [longinteger]
+| [floatnumber]
+| [imagnumber]
+
+def enclosure
+ [parenth_form]
+| [list_display]
+| [generator_expression]
+| [dict_display]
+| [string_conversion]
+
+def parenth_form
+ ['(' opt_expression_list ')']
+
+def list_display
+ ['[' opt_listmaker ']']
+
+def opt_listmaker
+ [listmaker]
+| []
+
+def listmaker
+ [expression list_for]
+| [expression listmaker_ext* opt_comma]
+
+def listmaker_ext
+ [',' expression]
+
+def opt_list_iter
+ [list_iter]
+| []
+
+def list_iter
+ [list_for]
+| [list_if]
+
+def list_if
+ ['if' test opt_list_iter]
+
+def list_for
+ ['for' expression_list 'in' testlist opt_list_iter]
+
+def testlist
+ [test testlist_ext* opt_comma]
+
+def testlist_ext
+ [',' test ]
+
+def generator_expression
+ ['(' test genexpr_for ')']
+
+def genexpr_for
+ ['for' expression_list 'in' test opt_genexpr_iter]
+
+def opt_genexpr_iter
+ [genexpr_iter]
+| []
+
+def genexpr_iter
+ [genexpr_for]
+| [genexpr_if]
+
+def genexpr_if
+ ['if' test opt_genexpr_iter]
+
+def dict_display
+ ['\{' opt_key_datum_list '\}']
+
+def opt_key_datum_list
+ [key_datum_list]
+| []
+
+def key_datum_list
+ [key_datum key_datum_list_ext* opt_comma]
+
+def key_datum_list_ext
+ [',' key_datum]
+
+def key_datum
+ [expression ':' expression]
+
+def string_conversion
+ ['`' expression_list '`']
+
+def attributeref
+ ['.' identifier]
+
+def subscription
+ ['[' expression_list ']']
+
+# The natural ordered choice does not suffice here. Must force it.
+
+def slicing
+ [simple_slicing]
+| [extended_slicing]
+
+def simple_slicing
+ ['[' short_slice ']']
+
+def extended_slicing
+ ['[' slice_list ']']
+
+def slice_list
+ [slice_item slice_list_ext* opt_comma]
+
+def slice_list_ext
+ [',' slice_item]
+
+def slice_item
+ [expression]
+| [proper_slice]
+| [ellipsis]
+
+def proper_slice
+ [short_slice]
+| [long_slice]
+
+def short_slice
+ [':']
+| [':' upper_bound]
+| [lower_bound ':']
+| [lower_bound ':' upper_bound]
+
+def long_slice
+ [short_slice ':' stride]
+| [short_slice ':']
+
+def lower_bound
+ [expression]
+
+def upper_bound
+ [expression]
+
+def stride
+ [expression]
+
+def ellipsis
+ ['...']
+
+def call
+ ['(' opt_argument_list ')']
+
+def opt_argument_list
+ [argument_list opt_comma]
+| []
+
+def argument_list
+ [positional_arguments opt_comma_keyword_arguments
+ opt_comma_star_expr opt_comma_dstar_expr]
+| [keyword_arguments opt_comma_star_expr opt_comma_dstar_expr]
+| ['*' expression opt_comma_dstar_expr]
+| ['**' expression]
+
+def opt_comma_star_expr
+ [',' '*' expression]
+| []
+
+def opt_comma_dstar_expr
+ [',' '**' expression]
+| []
+
+def positional_arguments
+ [positional_arguments ',' expression]
+| [expression]
+
+def opt_comma_keyword_arguments
+ [',' keyword_arguments]
+| []
+
+def keyword_arguments
+ [keyword_arguments ',' keyword_item]
+| [keyword_item]
+
+def keyword_item
+ [identifier '=' expression]
+
+
+start S = parse start( stdin )
+#print_xml( S )
+print_target_subscriptions_and_slicings( S )
+print_primary_subscriptions_and_slicings( S )
+print( '*** SUCCESS ***\n' )
diff --git a/test/ragelambig.in b/test/ragelambig.in
new file mode 100644
index 00000000..0b4439e5
--- /dev/null
+++ b/test/ragelambig.in
@@ -0,0 +1 @@
+1 - 1
diff --git a/test/ragelambig1.lm b/test/ragelambig1.lm
new file mode 100644
index 00000000..1c292fd1
--- /dev/null
+++ b/test/ragelambig1.lm
@@ -0,0 +1,65 @@
+lex start
+{
+ ignore /[\t\n ]+/
+ literal '^', '|', '-', ',', ':', '!', '?', '.'
+ literal '(', ')', '{', '}', '*', '&', '+'
+
+ literal '--', ':>', ':>>', '<:', '->', '**'
+
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ token uint /[0-9]+/
+}
+
+
+def start
+ [expression]
+ {
+ print_xml( lhs )
+ }
+
+def expression
+ [expression '|' term]
+| [expression '&' term]
+| [expression '-' term]
+| [expression '--' term]
+| [term]
+
+def term
+ [term factor_with_rep]
+ {
+ if match lhs [term '-' uint] {
+ reject
+ }
+ }
+| [term '.' factor_with_rep]
+| [term ':>' factor_with_rep]
+| [term ':>>' factor_with_rep]
+| [term '<:' factor_with_rep]
+| [factor_with_rep]
+
+def factor_with_rep
+ [factor_with_rep '*']
+| [factor_with_rep '**']
+| [factor_with_rep '?']
+| [factor_with_rep '+']
+| [factor_with_rep '{' factor_rep_num '}']
+| [factor_with_rep '{' ',' factor_rep_num '}']
+| [factor_with_rep '{' factor_rep_num ',' '}']
+| [factor_with_rep '{' factor_rep_num ',' factor_rep_num '}']
+| [factor_with_neg]
+
+def factor_rep_num [uint]
+
+def factor_with_neg
+ ['!' factor_with_neg]
+| ['^' factor_with_neg]
+| [factor]
+
+def factor
+ [alphabet_num]
+| [word]
+| ['(' expression ')']
+
+def alphabet_num
+ [uint]
+| ['-' uint]
diff --git a/test/ragelambig2.lm b/test/ragelambig2.lm
new file mode 100644
index 00000000..70e97c66
--- /dev/null
+++ b/test/ragelambig2.lm
@@ -0,0 +1,65 @@
+lex start
+{
+ ignore /[\t\n ]+/
+ literal '^', '|', '-', ',', ':', '!', '?', '.'
+ literal '(', ')', '{', '}', '*', '&', '+'
+
+ literal '--', ':>', ':>>', '<:', '->', '**'
+
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ token uint /[0-9]+/
+}
+
+
+def start
+ [expression]
+ {
+ print_xml( lhs )
+ }
+
+def expression
+ [expression '|' term]
+| [expression '&' term]
+| [expression '-' term]
+| [expression '--' term]
+| [term]
+
+def term
+ [factor_with_rep more_term]
+
+# Can resolve the ambiguity by making more_term shortest match.
+def more_term
+ []
+| [factor_with_rep more_term]
+| ['.' factor_with_rep more_term]
+| [':>' factor_with_rep more_term]
+| [':>>' factor_with_rep more_term]
+| ['<:' factor_with_rep more_term]
+
+def factor_with_rep
+ [factor_with_rep '*']
+| [factor_with_rep '**']
+| [factor_with_rep '?']
+| [factor_with_rep '+']
+| [factor_with_rep '{' factor_rep_num '}']
+| [factor_with_rep '{' ',' factor_rep_num '}']
+| [factor_with_rep '{' factor_rep_num ',' '}']
+| [factor_with_rep '{' factor_rep_num ',' factor_rep_num '}']
+| [factor_with_neg]
+
+def factor_rep_num
+ [uint]
+
+def factor_with_neg
+ ['!' factor_with_neg]
+| ['^' factor_with_neg]
+| [factor]
+
+def factor
+ [alphabet_num]
+| [word]
+| ['(' expression ')']
+
+def alphabet_num
+ [uint]
+| ['-' uint]
diff --git a/test/ragelambig3.lm b/test/ragelambig3.lm
new file mode 100644
index 00000000..649038e5
--- /dev/null
+++ b/test/ragelambig3.lm
@@ -0,0 +1,64 @@
+lex start
+{
+ ignore /[\t\n ]+/
+ literal '^', '|', '-', ',', ':', '!', '?', '.'
+ literal '(', ')', '{', '}', '*', '&', '+'
+
+ literal '--', ':>', ':>>', '<:', '->', '**'
+
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ token uint /[0-9]+/
+}
+
+
+def start
+ [expression]
+ {
+ print_xml( lhs )
+ }
+
+def expression
+ [expression '|' term_short]
+| [expression '&' term_short]
+| [expression '-' term_short]
+| [expression '--' term_short]
+| [term_short]
+
+def term_short
+ reducefirst
+ [term]
+
+def term
+ [term factor_with_rep]
+| [term '.' factor_with_rep]
+| [term ':>' factor_with_rep]
+| [term ':>>' factor_with_rep]
+| [term '<:' factor_with_rep]
+| [factor_with_rep]
+
+def factor_with_rep
+ [factor_with_rep '*']
+| [factor_with_rep '**']
+| [factor_with_rep '?']
+| [factor_with_rep '+']
+| [factor_with_rep '{' factor_rep_num '}']
+| [factor_with_rep '{' ',' factor_rep_num '}']
+| [factor_with_rep '{' factor_rep_num ',' '}']
+| [factor_with_rep '{' factor_rep_num ',' factor_rep_num '}']
+| [factor_with_neg]
+
+def factor_rep_num [uint]
+
+def factor_with_neg
+ ['!' factor_with_neg]
+| ['^' factor_with_neg]
+| [factor]
+
+def factor
+ [alphabet_num]
+| [word]
+| ['(' expression ')']
+
+def alphabet_num
+ [uint]
+| ['-' uint]
diff --git a/test/ragelambig4.lm b/test/ragelambig4.lm
new file mode 100644
index 00000000..d489bca3
--- /dev/null
+++ b/test/ragelambig4.lm
@@ -0,0 +1,69 @@
+lex start
+{
+ ignore /[\t\n ]+/
+ literal '^', '|', '-', ',', ':', '!', '?', '.'
+ literal '(', ')', '{', '}', '*', '&', '+'
+
+ literal '--', ':>', ':>>', '<:', '->', '**'
+
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ token uint /[0-9]+/
+}
+
+
+def start
+ [expression]
+ {
+ print_xml( lhs )
+ }
+
+def expression [term expression_op*]
+
+def expression_op
+ ['|' term]
+| ['&' term]
+| ['-' term]
+| ['--' term]
+
+def term [factor_rep term_op_list_short]
+
+# This list is done manually to get shortest match.
+def term_op_list_short
+ []
+| [term_op term_op_list_short]
+
+def term_op
+ [factor_rep]
+| ['.' factor_rep]
+| [':>' factor_rep]
+| [':>>' factor_rep]
+| ['<:' factor_rep]
+
+def factor_rep
+ [factor_neg factor_rep_op*]
+
+def factor_rep_op
+ ['*']
+| ['**']
+| ['?']
+| ['+']
+| ['{' factor_rep_num '}']
+| ['{' ',' factor_rep_num '}']
+| ['{' factor_rep_num ',' '}']
+| ['{' factor_rep_num ',' factor_rep_num '}']
+
+def factor_rep_num [uint]
+
+def factor_neg
+ ['!' factor_neg]
+| ['^' factor_neg]
+| [factor]
+
+def factor
+ [alphabet_num]
+| [word]
+| ['(' expression ')']
+
+def alphabet_num
+ [uint]
+| ['-' uint]
diff --git a/test/rediv.in b/test/rediv.in
new file mode 100644
index 00000000..f1ef2a38
--- /dev/null
+++ b/test/rediv.in
@@ -0,0 +1 @@
+2 / /[^gu-zy].*o[\d-xa]*/;
diff --git a/test/rediv.lm b/test/rediv.lm
new file mode 100644
index 00000000..c3750351
--- /dev/null
+++ b/test/rediv.lm
@@ -0,0 +1,92 @@
+# Or-literal scanner
+lex orlit
+{
+ token orlit_dash /'-' /
+ token orlit_close /']'/
+
+ rl orlit_specials /[\-\]]/
+ token orlit_chr /^orlit_specials | '\\' any/
+}
+
+def orlit_item
+ [orlit_chr]
+| [orlit_chr orlit_dash orlit_chr]
+
+def orlit
+ [orlit_item*]
+
+# Regex scanner
+lex regex
+{
+ token orlit_open /'['/
+ token orlit_neg_open /'[^'/
+ token regex_dot /'.'/
+ token regex_star /'*'/
+ token regex_close /'/'/
+
+ rl regex_specials /[\[\.\*\/\\]/
+ token regex_chr /(^regex_specials)* | '\\' any/
+}
+
+def regex_rep
+ [regex_star]
+| []
+
+def regex_base
+ [regex_chr]
+| [regex_dot]
+| [orlit_open orlit orlit_close]
+| [orlit_neg_open orlit orlit_close]
+
+def regex_item
+ [regex_base regex_rep]
+
+def regex_body
+ [regex_item*]
+
+rl s_string /"'" ([^'\\\n] | '\\' any )* "'"/
+rl d_string /'"' ([^"\\\n] | '\\' any )* '"'/
+
+# Root scanner
+lex start
+{
+ token ident /[a-zA-Z_]+/
+ token number /[0-9]+/
+ token string /s_string | d_string/
+
+ literal '+', '-', '*', ';', '/'
+ token slash /'/'/
+ token semi /';'/
+
+ ignore wp /[ \t\n]+/
+}
+
+def factor
+ [ident]
+| [number]
+| [string]
+| ['/' regex_body regex_close]
+
+def term
+ [term '*' factor]
+| [term '/' factor]
+| [factor]
+
+def expr
+ [expr '+' term]
+| [expr '-' term]
+| [term]
+
+def statement
+ [expr ';']
+
+def start
+ [statement*]
+ {
+ for I:orlit_item in lhs {
+ if match I [orlit_chr] {
+ print( I, '\n' )
+ }
+ }
+ print_xml( lhs )
+ }
diff --git a/test/ruby/Makefile b/test/ruby/Makefile
new file mode 100644
index 00000000..16285a0a
--- /dev/null
+++ b/test/ruby/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright 2008 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f *.cpp *.bin
diff --git a/test/ruby/ruby.lm b/test/ruby/ruby.lm
new file mode 100644
index 00000000..ec35fae4
--- /dev/null
+++ b/test/ruby/ruby.lm
@@ -0,0 +1,606 @@
+#
+# Grammar
+#
+
+# The items in this scanner may have newline in front of them.
+lex start
+{
+ # Reserved Words.
+ literal '__LINE__', '__FILE__', '__ENCODING__', 'BEGIN', 'END', 'alias',
+ 'and', 'begin', 'break', 'case', 'class', 'def', 'defined?', 'do',
+ 'else', 'elsif', 'end', 'ensure', 'false', 'for', 'in', 'module',
+ 'next', 'nil', 'not', 'or', 'redo', 'rescue', 'retry', 'return',
+ 'self', 'super', 'then', 'true', 'undef', 'when', 'yield', 'if',
+ 'unless', 'while', 'until'
+
+ token tNTH_REF /'$' [0-9]+/
+ token tBACK_REF /'$' ( '&' | '`' | '\'' | '+' ) /
+
+ literal ')', ',', ']'
+ literal '{', '}', ':'
+ literal '.', '::'
+ literal '->'
+
+ # Unary operators.
+ literal '!', '~'
+ token tUPLUS /'+'/
+ token tUMINUS /'-'/
+
+ token tLBRACK /'['/
+ token tLPAREN /'('/
+ token tSTAR /'*'/
+ token tBAR /'|'/
+ token tAMPER /'&'/
+
+ token tIDENTIFIER /[a-z][a-zA-Z_]*/
+ token tFID /[a-z][a-zA-Z_]* ('!'|'?')/
+ token tCONSTANT /[A-Z][a-zA-Z_]*/
+ token tGVAR /'$' [a-zA-Z_]+/
+ token tIVAR /'@' [a-zA-Z_]+/
+ token tCVAR /'@@' [a-zA-Z_]+/
+
+ token tINTEGER /[0-9]+/
+ token tFLOAT /[0-9]+ '.' [0-9]+/
+
+ token tDSTRING_BEG /'"'/
+ token tSSTRING_BEG /'\''/
+ token tXSTRING_BEG /'`'/
+
+ ignore /[ \t\n]+/
+ ignore comment /'#' [^\n]* '\n'/
+}
+
+# These items cannot appear at the beginning of a line (except maybe the first).
+lex expr_cont_ops
+{
+ ignore /[\t ]+/
+
+ literal '+', '-', '*', '**', '/', '%', '^'
+ literal '|', '&', '||', '&&'
+ literal '[', '('
+ literal '='
+ literal '<<', '>>'
+ literal '?'
+ literal '<=>'
+ literal '=>'
+ literal '[]', '[]='
+ literal '=~', '!~'
+ literal '<', '>', '>=', '<='
+ literal '!=', '==', '==='
+ literal '..', '...'
+}
+lex terms
+{
+ ignore /[\t ]+/
+ ignore /'#' [^\n]*/
+ literal ';'
+ literal '\n'
+}
+
+
+lex dstring_contents
+{
+ token dstring_contents /[^"]+/
+ token tDSTRING_END /'"'/
+}
+
+lex sstring_contents
+{
+ token sstring_contents /[^']+/
+ token tSSTRING_END /'\''/
+}
+
+lex xstring_contents
+{
+ token xstring_contents /[^`]+/
+ token tXSTRING_END /'`'/
+}
+
+def ruby
+ [compstmt]
+
+def compstmt
+ [stmts opt_terms]
+
+def bodystmt
+ [compstmt opt_rescue opt_else opt_ensure]
+
+def opt_rescue
+# ['rescue' exc_list exc_var then compstmt opt_rescue] |
+ []
+
+def then
+ [term]
+| ['then']
+| [term 'then']
+
+def do
+ [term]
+| ['do']
+
+def if_tail
+ [opt_else]
+| ['elsif' expr_value then compstmt if_tail]
+
+def opt_else
+ ['else' compstmt]
+| []
+
+def opt_ensure
+ ['ensure' compstmt]
+| []
+
+def stmts
+ [stmts terms stmt]
+| [stmt]
+| []
+
+def opt_terms
+ [terms]
+| []
+
+def terms
+ [term]
+| [terms ';']
+
+def term
+ [';']
+| ['\n']
+
+def stmt
+ ['alias' fitem fitem]
+| ['undef' undef_list]
+| [stmt 'if' expr_value]
+| [stmt 'unless' expr_value]
+| [stmt 'while' expr_value]
+| [stmt 'until' expr_value]
+| [stmt 'rescue' stmt]
+| ['BEGIN' '{' compstmt '}']
+| ['END' '{' compstmt '}']
+| [lhs '=' mrhs]
+| [mlhs '=' arg_value]
+| [mlhs '=' mrhs]
+| [expr]
+
+def mlhs
+ [mlhs_basic]
+| [tLPAREN mlhs ')']
+
+def mlhs_basic
+ [mlhs_head]
+
+def mlhs_head
+ [mlhs_item ',' mlhs_head]
+| [mlhs_item]
+
+def mlhs_item
+ [variable]
+| ['*' mlhs_item]
+| ['*']
+| [primary_value '[' opt_call_args ']']
+| [primary_value '.' tIDENTIFIER]
+| [primary_value '.' tCONSTANT]
+| [primary_value '::' tIDENTIFIER]
+| [primary_value '::' tCONSTANT]
+| ['::' tCONSTANT]
+| [backref]
+| [tLPAREN mlhs ')']
+
+def lhs
+ [variable]
+| [primary_value '[' opt_call_args ']']
+| [primary_value '.' tIDENTIFIER]
+| [primary_value '.' tCONSTANT]
+| [primary_value '::' tIDENTIFIER]
+| [primary_value '::' tCONSTANT]
+| ['::' tCONSTANT]
+| [backref]
+
+def mrhs
+ [args ',' arg_value]
+| [args ',' '*' arg_value]
+| ['*' arg_value]
+
+def expr
+ [expr 'and' expr]
+| [expr 'or' expr]
+| ['not' expr]
+| [arg]
+
+def expr_value
+ [expr]
+
+def opt_brace_block
+ [brace_block]
+| []
+
+def block_param_def
+ [tBAR opt_bv_decl tBAR]
+| [tBAR block_param opt_bv_decl tBAR]
+
+def block_param
+ [block_arg_list]
+| []
+
+def block_arg_list
+ [block_arg_list ',' block_arg_item]
+| [block_arg_item]
+
+def block_arg_item
+ [f_norm_arg]
+| [f_rest_arg]
+| [f_block_arg]
+| ['(' f_args ')']
+
+def opt_bv_decl
+ [';' bv_decls]
+| []
+
+def bv_decls
+ [bvar]
+| [bv_decls ',' bvar]
+
+def bvar
+ [tIDENTIFIER]
+
+def opt_block_param
+ [block_param_def]
+| []
+
+def operation
+ [tIDENTIFIER]
+| [tCONSTANT]
+| [tFID]
+
+def operation2
+ [tIDENTIFIER]
+| [tCONSTANT]
+| [tFID]
+| [op]
+
+def operation3
+ [tIDENTIFIER]
+| [tFID]
+| [op]
+
+def op
+ ['|'] | ['^'] | ['&'] | ['<=>'] | ['=='] | ['==='] | ['=~'] | ['!~'] |
+ ['>'] | ['>='] | ['<'] | ['<='] | ['!='] | ['<<'] | ['>>'] | ['+'] |
+ ['-'] | ['*'] | ['/'] | ['%'] | ['**'] | ['!'] | ['~'] | ['[]'] | ['[]='] |
+ [tXSTRING_BEG]
+
+def opt_call_args
+ [call_args]
+| []
+
+def call_args
+ [args opt_block_arg]
+| [assocs opt_block_arg]
+| [args ',' assocs opt_block_arg]
+| [block_arg]
+
+def args
+ [arg_value]
+| ['*' arg_value]
+| [args ',' arg_value]
+| [args ',' '*' arg_value]
+
+def arg_value
+ [arg]
+
+def opt_block_arg
+ [',' block_arg]
+| []
+
+def block_arg
+ [tAMPER arg_value]
+
+right '='
+left 'rescue'
+right '?', ':'
+nonassoc '..', '...'
+left '||'
+left '&&'
+nonassoc '<=>', '==', '===', '!=', '=~', '!~'
+left '>', '>=', '<', '<='
+left '|', '^'
+left '&'
+left '<<', '>>'
+left '+', '-'
+left '*', '/', '%'
+#right tUMINUS_NUM tUMINUS
+right tUMINUS
+right '**'
+right '!', '~', tUPLUS
+
+def arg
+ [lhs '=' arg]
+| [lhs '=' arg 'rescue' arg]
+| [arg '?' arg ':' arg]
+| [arg '..' arg]
+| [arg '...' arg]
+| [arg '||' arg]
+| [arg '&&' arg]
+| [arg '<=>' arg]
+| [arg '==' arg]
+| [arg '===' arg]
+| [arg '!=' arg]
+| [arg '=~' arg]
+| [arg '!~' arg]
+| [arg '>' arg]
+| [arg '>=' arg]
+| [arg '<' arg]
+| [arg '<=' arg]
+| [arg '|' arg]
+| [arg '^' arg]
+| [arg '&' arg]
+| [arg '<<' arg]
+| [arg '>>' arg]
+| [arg '+' arg]
+| [arg '-' arg]
+| [arg '*' arg]
+| [arg '/' arg]
+| [arg '%' arg]
+| [arg '**' arg]
+| ['!' primary]
+| ['~' primary]
+| [tUMINUS primary]
+| [tUPLUS primary]
+| ['defined?' arg]
+| [primary]
+
+def primary_value
+ [primary]
+
+def primary
+ [pliteral]
+| [strings]
+| [xstring]
+#| [regexp]
+#| [words]
+#| [qwords]
+| [var_ref]
+| [backref]
+| [tFID]
+| ['begin' bodystmt 'end']
+| [tLPAREN compstmt ')']
+| [primary_value '::' tCONSTANT]
+| ['::' tCONSTANT]
+| [tLBRACK aref_args ']']
+| ['{' assoc_list '}']
+| ['defined?' '(' expr ')']
+| [operation brace_block]
+| [method_call]
+| [method_call brace_block]
+| ['->' lambda]
+| ['if' expr_value then compstmt if_tail 'end']
+| ['unless' expr_value then compstmt opt_else 'end']
+| ['while' expr_value do compstmt 'end']
+| ['until' expr_value do compstmt 'end']
+#| ['case' expr_value opt_terms case_body 'end']
+#| ['case' opt_terms case_body 'end']
+| ['for' for_var 'in' expr_value do compstmt 'end']
+| ['class' cpath superclass bodystmt 'end']
+| ['class' '<<' expr term bodystmt 'end']
+| ['module' cpath bodystmt 'end']
+| ['def' fname f_arglist bodystmt 'end']
+| ['def' singleton dot_or_colon fname f_arglist bodystmt 'end']
+| ['break']
+| ['next']
+| ['redo']
+| ['retry']
+
+def for_var
+ [lhs]
+| [mlhs]
+
+def lambda
+ [f_larglist lambda_body]
+
+def f_larglist
+ ['(' f_args opt_bv_decl ')']
+| [f_args opt_bv_decl]
+
+def lambda_body
+ ['{' compstmt '}']
+| ['do' compstmt 'end']
+
+def assoc_list
+ [assocs trailer]
+| []
+
+def assocs
+ [assocs ',' assoc]
+| [assoc]
+
+def assoc
+ [arg_value '=>' arg_value]
+| [':' arg_value]
+
+def singleton
+ [var_ref]
+| ['(' expr ')']
+
+def dot_or_colon
+ ['.']
+| ['::']
+
+def aref_args
+ [args trailer]
+| [args ',' assocs trailer]
+| [assocs trailer]
+| []
+
+def trailer
+ [',']
+| []
+
+def brace_block
+ ['{' opt_block_param compstmt '}']
+| ['do' opt_block_param compstmt 'end']
+
+def f_arglist
+ ['(' f_args ')']
+| [f_args term]
+
+def f_args
+ [f_arg_list]
+| []
+
+def f_arg_list
+ [f_arg_list ',' f_arg_item]
+| [f_arg_item]
+
+def f_arg_item
+ [f_norm_arg]
+| [f_opt]
+| [f_rest_arg]
+| [f_block_arg]
+| ['(' f_args ')']
+
+def f_opt
+ [tIDENTIFIER '=' arg_value]
+
+def f_rest_arg
+ ['*' tIDENTIFIER]
+| ['*']
+
+def f_block_arg
+ [tAMPER tIDENTIFIER]
+
+def f_norm_arg
+ [tIDENTIFIER]
+
+def backref
+ [tNTH_REF] | [tBACK_REF]
+
+def superclass
+ [term]
+| ['<' expr_value term]
+
+def cpath
+ ['::' cname]
+| [cname]
+| [primary_value '::' cname]
+
+def fname
+ [tIDENTIFIER]
+| [tCONSTANT]
+| [tFID]
+| [op]
+| [reswords]
+
+def reswords
+ ['__LINE__'] | ['__FILE__'] | ['__ENCODING__'] | ['BEGIN'] | ['END'] |
+ ['alias'] | ['and'] | ['begin'] | ['break'] | ['case'] | ['class'] |
+ ['def'] | ['defined?'] | ['do'] | ['else'] | ['elsif'] | ['end'] |
+ ['ensure'] | ['false'] | ['for'] | ['in'] | ['module'] |
+ ['next'] | ['nil'] | ['not'] | ['or'] | ['redo'] | ['rescue'] |
+ ['retry'] | ['return'] | ['self'] | ['super'] | ['then'] | ['true'] |
+ ['undef'] | ['when'] | ['yield'] | ['if'] | ['unless'] | ['while'] |
+ ['until']
+
+def cname
+ [tIDENTIFIER]
+| [tCONSTANT]
+
+def pliteral
+ [numeric]
+| [symbol]
+#| [dsym]
+
+def strings
+ [string]
+
+def string
+# [tCHAR]
+ [string1]
+| [string string1]
+
+def string1
+ [tSSTRING_BEG sstring_contents? tSSTRING_END]
+| [tDSTRING_BEG dstring_contents? tDSTRING_END]
+
+def xstring
+ [tXSTRING_BEG xstring_contents? tXSTRING_END]
+
+def numeric
+ [tINTEGER]
+| [tFLOAT]
+
+def symbol
+ [':' sym]
+
+def sym
+ [fname]
+| [tIVAR]
+| [tGVAR]
+| [tCVAR]
+
+def fitem
+ [fsym]
+#| [dsym]
+
+def undef_list
+ [fitem]
+| [undef_list ',' fitem]
+
+def fsym
+ [fname]
+| [symbol]
+
+#def dsym
+# [':' xstring_contents tDSTRING_END]
+
+def var_ref
+ [variable]
+
+def variable
+ [tIDENTIFIER] | [tIVAR] | [tGVAR] | [tCONSTANT] | [tCVAR] | ['nil'] |
+ ['self'] | ['true'] | ['false'] | ['__FILE__'] | ['__LINE__'] |
+ ['__ENCODING__']
+
+
+# Required whitespace, but newline is not allowed.
+token ws_no_nl
+ /[ \t]+[^ \t\n]/
+ {
+ send( make_token( typeid ws_no_nl, pull(stdin, match_length-1) ) )
+ }
+
+def method_call
+ [operation paren_args]
+| [operation ws_no_nl call_args]
+| [primary_value '.' operation2 opt_paren_args]
+| [primary_value '.' operation2 ws_no_nl call_args]
+| [primary_value '::' operation2 opt_paren_args]
+| [primary_value '::' operation2 ws_no_nl call_args]
+| [primary_value '.' paren_args]
+| [primary_value '::' paren_args]
+| ['super' paren_args]
+| ['super' ws_no_nl call_args]
+| ['super']
+| ['yield' paren_args]
+| ['yield' ws_no_nl call_args]
+| ['yield']
+| ['return' call_args]
+| ['return']
+| [primary_value '[' opt_call_args ']']
+
+def opt_paren_args
+ [paren_args]
+| []
+
+def paren_args
+ ['(' opt_call_args ')']
+
+#
+# Grammar finished
+#
+
+ruby R = parse ruby(stdin)
+
+print_xml( R )
+
+#for T: primary in R
+# print_xml( T, '\n\n' )
diff --git a/test/rubyhere.in b/test/rubyhere.in
new file mode 100644
index 00000000..a23dfead
--- /dev/null
+++ b/test/rubyhere.in
@@ -0,0 +1,8 @@
+print( <<DATA1, more, <<DATA2, 99 )
+"&^#(@ almost
+!arbitrary text!
+DATA1
+hello
+world
+DATA2
+. error here
diff --git a/test/rubyhere.lm b/test/rubyhere.lm
new file mode 100644
index 00000000..33fff4b7
--- /dev/null
+++ b/test/rubyhere.lm
@@ -0,0 +1,89 @@
+rl ident_pattern /[a-zA-Z_][a-zA-Z_0-9]*/
+rl number_pattern /[0-9]+/
+
+lex start
+{
+ ignore /[ \t\n]+/
+ token id /ident_pattern/
+ token number /number_pattern/
+ literal '<<', '*', ',', '(', ')'
+}
+
+global str HereId
+
+token rest_of_line /[^\n]*'\n'/
+
+lex here_start
+{
+ ignore /[ \t\n]+/
+ token here_id
+ here_data HereData
+ /ident_pattern/
+ {
+ # Take the text of the here_id from the input stream.
+ HereId = pull( stdin, match_length )
+
+ # Get the data up to the rest of the line.
+ rest_of_line ROL = parse_stop rest_of_line( stdin )
+
+ # Parse the heredoc data.
+ here_data HereData = parse_stop here_data( stdin )
+
+ # Push the rest-of-line data back to the input stream.
+ push( stdin, ROL )
+
+ # Send the here_id token. Attach the heredoc data as an attribute.
+ send( make_token( typeid here_id, HereId, HereData ) )
+ }
+}
+
+lex here_data
+{
+ token here_close_id
+ / ident_pattern '\n' /
+ {
+ if match_text == HereId + '\n' {
+ send( make_token(
+ typeid here_close_id,
+ pull(stdin, match_length) ) )
+ }
+ else
+ send( make_token( typeid here_line, pull(stdin, match_length) ) )
+ }
+
+ token here_line
+ / [^\n]* '\n' /
+}
+
+def here_data
+ [here_line* here_close_id]
+
+def heredoc
+ ['<<' here_id]
+
+def primary
+ [id]
+| [number]
+| [heredoc]
+
+def arglist
+ [primary arglist_more*]
+
+def arglist_more
+ [',' primary]
+
+def call
+ [id '(' arglist? ')']
+
+def statement
+ [primary]
+| [call]
+
+token foobar /any*/
+
+def start
+ [statement*]
+| [foobar]
+
+start S = parse start( stdin )
+print_xml(S)
diff --git a/test/string.in b/test/string.in
new file mode 100644
index 00000000..8aef536f
--- /dev/null
+++ b/test/string.in
@@ -0,0 +1,2 @@
+a + "%{{"; 1 * 2;
+
diff --git a/test/string.lm b/test/string.lm
new file mode 100644
index 00000000..7da88215
--- /dev/null
+++ b/test/string.lm
@@ -0,0 +1,54 @@
+lex string
+{
+ token str_escape /'\\' any/
+ token str_chr /[^\\"]+/
+}
+
+def str_item
+ [str_escape]
+| [str_chr]
+
+def string
+ ['"' str_item* '"']
+
+lex start
+{
+ token ident /[a-zA-Z_]+/
+ token number /[0-9]+/
+
+ literal '+', '*', ';', '"', '\'', '(', ')'
+ literal '+=', '-=', '*='
+
+ ignore wp /[ \t\n]+/
+}
+
+def expr
+ [expr '+' term]
+| [term]
+
+def term
+ [term '*' primary]
+| [primary]
+
+def primary
+ [number]
+| [ident]
+| [string]
+| ['(' expr ')']
+
+def expr_list
+ [expr_list expr ';']
+| []
+
+def start
+ [expr_list]
+ {
+ if match lhs
+ ~a + "%{{"; 1 * 2;
+ {
+ print( 'yes\n' )
+ }
+ }
+
+start S = parse start(stdin)
+print_xml( S )
diff --git a/test/superid.in b/test/superid.in
new file mode 100644
index 00000000..4002630f
--- /dev/null
+++ b/test/superid.in
@@ -0,0 +1 @@
+!a b b a;
diff --git a/test/superid.lm b/test/superid.lm
new file mode 100644
index 00000000..3a3eef59
--- /dev/null
+++ b/test/superid.lm
@@ -0,0 +1,59 @@
+
+lex start
+{
+ literal '!', 'a', ';\n'
+
+ token id /'a'|'b'/
+ {
+ #tok.id = trans_id_to
+ }
+
+ token super_id //
+ token foo //
+
+ ignore ws / [ \n\t]+ /
+}
+
+global int trans_id_to
+
+def e1
+ []
+ {
+ print( 'old_id = ', trans_id_to, '\n' )
+ #trans_id_to = type_id foo
+ print( 'new_id = ', trans_id_to, '\n' )
+ }
+
+def item1
+ str msg
+
+ [ e1 '!' 'a' super_id super_id 'a']
+ {
+ lhs.msg = 'this is item1\n'
+ }
+
+def e2
+ []
+ {
+ print( 'old_id = ', trans_id_to, '\n' )
+ #trans_id_to = type_id super_id
+ print( 'new_id = ', trans_id_to, '\n' )
+ }
+
+def item2
+ str msg
+
+ [ e2 '!' 'a' super_id super_id 'a']
+ {
+ lhs.msg = 'this is item2\n'
+ }
+
+
+def start
+ [item1 ';\n']
+| [item2 ';\n']
+ {
+ match lhs [Item2:item2 ';\n']
+ print( Item2.msg )
+ }
+
diff --git a/test/tags.in b/test/tags.in
new file mode 100644
index 00000000..939f9b48
--- /dev/null
+++ b/test/tags.in
@@ -0,0 +1 @@
+a b b a;
diff --git a/test/tags.lm b/test/tags.lm
new file mode 100644
index 00000000..9e13ddd8
--- /dev/null
+++ b/test/tags.lm
@@ -0,0 +1,82 @@
+# Open and close tags by rewriting to generic close tags. Won't work if
+# interested in unclosed tags because a token can start as not close_id, but
+# then become a close id during the course of parsing.
+
+#
+# Regular Definitions
+#
+rl rl_ws /[ \t\n\r\v]+/
+rl rl_id /[a-zA-Z_][a-zA-Z0-9_]*/
+
+#
+# Tokens
+#
+
+# Any single character can be a literal
+lex start
+{
+ literal '!\n', ';\n'
+
+ # Ignore whitespace.
+ ignore /rl_ws/
+
+ # Open and close id
+ token id /rl_id/
+}
+
+#
+# Global Data
+#
+
+def tag_stack
+ [id tag_stack]
+| []
+
+global tag_stack TS = construct tag_stack ["sentinal"]
+
+#
+# Productions
+#
+
+def open_tag
+ [id]
+ {
+ match lhs [Id:id]
+ match TS [Top:id Rest:tag_stack]
+ if Id.data == Top.data {
+ reject
+ } else {
+ TS = construct tag_stack [Id TS]
+ }
+ }
+
+def close_tag
+ [id]
+ {
+ match lhs [Id:id]
+ match TS [Top:id Rest:tag_stack]
+
+ if Id.data == Top.data {
+ TS = construct tag_stack [Rest]
+ } else {
+ reject
+ }
+ }
+
+def tag
+ [open_tag tag* close_tag]
+
+def start
+ [tag* ';\n']
+ {
+ print_xml( TS )
+ print_xml( lhs )
+ print( 'got structure\n' )
+ }
+
+| [id* ';\n']
+ {
+ print_xml( TS )
+ print_xml( lhs )
+ print( 'failed\n' )
+ }
diff --git a/test/til.in b/test/til.in
new file mode 100644
index 00000000..19b7bb19
--- /dev/null
+++ b/test/til.in
@@ -0,0 +1,14 @@
+
+var a;
+a := 1;
+
+head:
+
+a := a + 1;
+c := d;
+
+if a = 10 then
+ goto head;
+end
+
+hi := there;
diff --git a/test/til.lm b/test/til.lm
new file mode 100644
index 00000000..24acd4e3
--- /dev/null
+++ b/test/til.lm
@@ -0,0 +1,168 @@
+lex start
+{
+ literal 'var', 'if', 'then', 'else', 'while', 'do', 'for', 'read', 'write',
+ 'end', 'to', 'goto'
+ literal ':=', '!=', ';', '+', '-', '*', '/', '=', '(', ')', ':'
+
+ ignore /'//' [^\n]* '\n'/
+ ignore /[\n\t ]+/
+ token id /[a-zA-Z_]+/
+ token integernumber /[0-9]+/
+ token stringlit /'"' [^"]* '"'/
+}
+
+def program
+ [statement*]
+
+def statement
+ [declaration]
+| [assignment_statement]
+| [if_statement]
+| [while_statement]
+| [do_statement]
+| [for_statement]
+| [read_statement]
+| [write_statement]
+| [labelled_statement]
+| [goto_statement]
+
+def declaration
+ ['var' id ';']
+
+def assignment_statement
+ [id ':=' expression ';']
+
+def if_statement
+ ['if' expression 'then' statement* opt_else_statement 'end']
+
+def opt_else_statement
+ ['else' statement*]
+| []
+
+def while_statement
+ ['while' expression 'do' statement* 'end']
+
+def do_statement
+ ['do' statement* 'while' expression ';']
+
+def for_statement
+ ['for' id ':=' expression 'to' expression 'do' statement* 'end']
+
+def read_statement
+ ['read' id ';']
+
+def write_statement
+ ['write' expression ';']
+
+def expression
+ [term]
+| [expression eqop term]
+
+def eqop ['='] | ['!=']
+
+def term
+ [factor]
+| [term addop factor]
+
+def addop ['+'] | ['-']
+
+def factor
+ [primary]
+| [factor mulop primary]
+
+def mulop ['*'] | ['/']
+
+def primary
+ [id]
+| [lit]
+| ['(' expression ')']
+
+def lit
+ [integernumber]
+| [stringlit]
+
+def labelled_statement
+ [id ':' statement]
+
+def goto_statement
+ ['goto' id ';']
+
+program P = parse program(stdin)
+
+#for S:statement* in P
+#{
+# if match S [L0: id ':'
+# First: statement
+# Rest: statement*]
+# {
+# for Check: statement* in Rest
+# {
+# if match Check
+# ['if' E: expression 'then'
+# 'goto' Targ: id ';'
+# 'end'
+# T: statement*]
+# {
+# # This truncates Rest
+# Check = construct statement* []
+#
+# # Replace the labeled statement through to the goto with a
+# # do ... while.
+# S = construct statement*
+# ['do'
+# First
+# Rest
+# 'while' E ';'
+# T]
+# break
+# }
+# }
+# }
+#}
+
+for S: statement* in P
+{
+ if match S [Label: id ':'
+ First: statement
+ Rest: statement*]
+ {
+ expression Expr
+ statement* Following
+
+ # Look though the remaining statements for a goto back to the label.
+ # The repeat iterator yields only top-level statement lists. It
+ # restricts our search to the same nesting depth as the label.
+ for Check: statement* in Rest
+ {
+ if match Check
+ ['if' E: expression 'then'
+ 'goto' L:id ';'
+ 'end'
+ SL: statement*]
+ {
+ Expr = E
+ Following = SL
+
+ # Check iterates over tails of Rest. Assigning an empty list
+ # to check truncates the Rest list. What we cut off is saved in
+ # Following (excluding the if statement).
+ Check = construct statement* []
+ }
+ }
+
+ # If a goto was found, then perform the rewrite.
+ if ( Expr )
+ {
+ # Replace the labelled statement through to the goto
+ # with a do ... while.
+ S = construct statement*
+ ['do'
+ First
+ Rest
+ 'while' Expr ';'
+ Following]
+ }
+ }
+}
+
+print(P, '\n')
diff --git a/test/travs1.in b/test/travs1.in
new file mode 100644
index 00000000..e6cf5020
--- /dev/null
+++ b/test/travs1.in
@@ -0,0 +1 @@
+1 | 2 3
diff --git a/test/travs1.lm b/test/travs1.lm
new file mode 100644
index 00000000..e5820d8f
--- /dev/null
+++ b/test/travs1.lm
@@ -0,0 +1,144 @@
+lex start
+{
+ ignore /[\t\n ]+/
+ literal '^', '|', '-', ',', ':', '!', '?', '.'
+ literal '(', ')', '{', '}', '*', '&', '+'
+
+ literal '--', ':>', ':>>', '<:', '->', '**'
+
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ token uint /[0-9]+/
+}
+
+
+def start [expression]
+
+def expression [term expression_op*]
+
+def expression_op
+ ['|' term]
+| ['&' term]
+| ['-' term]
+| ['--' term]
+
+def term [factor_rep term_rest]
+
+# This list is done manually to get shortest match.
+def term_rest
+ []
+| [term_op term_rest]
+
+def term_op
+ [factor_rep]
+| ['.' factor_rep]
+| [':>' factor_rep]
+| [':>>' factor_rep]
+| ['<:' factor_rep]
+
+def factor_rep
+ [factor_neg factor_rep_op*]
+
+def factor_rep_op
+ ['*']
+| ['**']
+| ['?']
+| ['+']
+| ['{' factor_rep_num '}']
+| ['{' ',' factor_rep_num '}']
+| ['{' factor_rep_num ',' '}']
+| ['{' factor_rep_num ',' factor_rep_num '}']
+
+def factor_rep_num [uint]
+
+def factor_neg
+ ['!' factor_neg]
+| ['^' factor_neg]
+| [factor]
+
+def factor
+ [alphabet_num]
+| [word]
+| ['(' expression ')']
+
+def alphabet_num
+ [uint]
+
+start S = parse start(stdin)
+
+#
+# Top-Down, Left-Right
+#
+
+int do_topdown_leftright( ref any T )
+{
+ for C:any in child(T) {
+ yield C
+ do_topdown_leftright( C )
+ }
+}
+
+iter topdown_leftright( ref any T )
+{
+ do_topdown_leftright( T )
+}
+
+#
+# Bottom-Up, Left-Right
+#
+
+int do_bottomup_leftright( ref any T )
+{
+ for C:any in child(T) {
+ do_bottomup_leftright( C )
+ yield C
+ }
+}
+
+iter bottomup_leftright( ref any T )
+{
+ do_bottomup_leftright( T )
+}
+
+
+#
+# Top-Down, Right-Left
+#
+
+int do_topdown_rightleft( ref any T )
+{
+ for C:any in rev_child(T) {
+ yield C
+ do_topdown_rightleft( C )
+ }
+}
+
+iter topdown_rightleft( ref any T )
+{
+ do_topdown_rightleft( T )
+}
+
+#
+# Bottom-Up, Right-Left
+#
+
+int do_bottomup_rightleft( ref any T )
+{
+ for C:any in rev_child(T) {
+ do_bottomup_rightleft( C )
+ yield C
+ }
+}
+
+iter bottomup_rightleft( ref any T )
+{
+ do_bottomup_rightleft( T )
+}
+
+#
+# Testing
+#
+
+for C: expression in bottomup_leftright( S )
+{
+ print_xml( C )
+}
diff --git a/test/travs2.in b/test/travs2.in
new file mode 100644
index 00000000..81d197f3
--- /dev/null
+++ b/test/travs2.in
@@ -0,0 +1 @@
+1 2 | 3 4
diff --git a/test/travs2.lm b/test/travs2.lm
new file mode 100644
index 00000000..06facf3b
--- /dev/null
+++ b/test/travs2.lm
@@ -0,0 +1,93 @@
+lex start
+{
+ ignore /[\t\n ]+/
+ literal '^', '|', '-', ',', ':', '!', '?', '.'
+ literal '(', ')', '{', '}', '*', '&', '+'
+
+ literal '--', ':>', ':>>', '<:', '->', '**'
+
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ token uint /[0-9]+/
+}
+
+
+def start
+ [expression]
+
+def expression [term expression_op*]
+
+def expression_op
+ ['|' term]
+| ['&' term]
+| ['-' term]
+| ['--' term]
+
+def term [factor_rep term_rest]
+
+# This list is done manually to get shortest match.
+def term_rest
+ []
+| [term_op term_rest]
+
+def term_op
+ [factor_rep]
+| ['.' factor_rep]
+| [':>' factor_rep]
+| [':>>' factor_rep]
+| ['<:' factor_rep]
+
+def factor_rep
+ [factor_neg factor_rep_op*]
+
+def factor_rep_op
+ ['*']
+| ['**']
+| ['?']
+| ['+']
+| ['{' factor_rep_num '}']
+| ['{' ',' factor_rep_num '}']
+| ['{' factor_rep_num ',' '}']
+| ['{' factor_rep_num ',' factor_rep_num '}']
+
+def factor_rep_num [uint]
+
+def factor_neg
+ ['!' factor_neg]
+| ['^' factor_neg]
+| [factor]
+
+def factor
+ [alphabet_num]
+| [word]
+| ['(' expression ')']
+
+def alphabet_num
+ [uint]
+
+start S = parse start(stdin)
+
+#
+# Fixed point iteration
+#
+
+bool this_iter_modified()
+ { return true }
+
+iter fixed_point( ref any T )
+{
+ bool modified = true
+ while modified {
+ modified = false
+ for S:any in T {
+ yield S
+
+ if this_iter_modified() {
+ modified = true
+ break
+ }
+ }
+ }
+}
+
+print( S, '\n' )
+
diff --git a/test/xml/Makefile b/test/xml/Makefile
new file mode 100644
index 00000000..d647261a
--- /dev/null
+++ b/test/xml/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright 2002-2006 Adrian Thurston <thurston@complang.org>
+#
+
+# This file is part of Colm.
+#
+# Colm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Colm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Colm; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+SRC = $(wildcard *.lm)
+BIN = $(SRC:%.lm=%.bin)
+COLM = ../../colm/colm
+
+all: $(BIN)
+
+$(BIN): $(COLM)
+
+$(BIN): %.bin: %.lm
+ $(COLM) $<
+
+clean:
+ rm -f *.cpp *.bin
diff --git a/test/xml/xml.in b/test/xml/xml.in
new file mode 100644
index 00000000..22882c95
--- /dev/null
+++ b/test/xml/xml.in
@@ -0,0 +1,3962 @@
+<ragel version="5.24" filename="../colm/lmscan.rl" lang="C">
+<ragel_def name="rlscan">
+ <alphtype>char</alphtype>
+ <machine>
+ <action_list length="166">
+ <action id="0" name="inc_nl" line="217" col="16"><text>
+ lastnl = p;
+ column = 0;
+ line++;
+ </text></action>
+ <action id="1" name="initts" line="1" col="1"><init_tokstart></init_tokstart></action>
+ <action id="2" name="tokstart" line="1" col="1"><set_tokstart></set_tokstart></action>
+ <action id="3" name="tokend" line="1" col="1"><set_tokend>1</set_tokend></action>
+ <action id="4" name="last1" line="238" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\0' ); </text></sub_action></action>
+ <action id="5" name="last2" line="239" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\a' ); </text></sub_action></action>
+ <action id="6" name="last3" line="240" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\b' ); </text></sub_action></action>
+ <action id="7" name="last4" line="241" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\t' ); </text></sub_action></action>
+ <action id="8" name="last5" line="242" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\n' ); </text></sub_action></action>
+ <action id="9" name="last6" line="243" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\v' ); </text></sub_action></action>
+ <action id="10" name="last7" line="244" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\f' ); </text></sub_action></action>
+ <action id="11" name="last8" line="245" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, '\r' ); </text></sub_action></action>
+ <action id="12" name="last9" line="246" col="13"><set_tokend>1</set_tokend><sub_action><text> updateCol(); </text></sub_action></action>
+ <action id="13" name="last10" line="247" col="15"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, tokstart+1, tokend ); </text></sub_action></action>
+ <action id="14" name="last11" line="250" col="10"><set_tokend>1</set_tokend><sub_action><text> token( RE_Dash, 0, 0 ); </text></sub_action></action>
+ <action id="15" name="last12" line="253" col="10"><set_tokend>1</set_tokend><sub_action><text> token( RE_SqClose ); </text><ret></ret><text> </text></sub_action></action>
+ <action id="16" name="last13" line="255" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ scan_error() &lt;&lt; "unterminated OR literal" &lt;&lt; endl;
+ </text></sub_action></action>
+ <action id="17" name="last14" line="260" col="12"><set_tokend>1</set_tokend><sub_action><text> token( RE_Char, tokstart, tokend ); </text></sub_action></action>
+ <action id="18" name="store15" line="265" col="13"><set_act>15</set_act></action>
+ <action id="19" name="store16" line="266" col="12"><set_act>16</set_act></action>
+ <action id="20" name="store17" line="267" col="12"><set_act>17</set_act></action>
+ <action id="21" name="store18" line="268" col="13"><set_act>18</set_act></action>
+ <action id="22" name="store19" line="269" col="11"><set_act>19</set_act></action>
+ <action id="23" name="store20" line="270" col="13"><set_act>20</set_act></action>
+ <action id="24" name="store21" line="273" col="12"><set_act>21</set_act></action>
+ <action id="25" name="last24" line="281" col="7"><set_tokend>1</set_tokend><sub_action><text> token( TK_Literal, tokstart, tokend ); </text></sub_action></action>
+ <action id="26" name="last26" line="284" col="11"><set_tokend>1</set_tokend><sub_action><text> token( RE_SqOpenNeg ); </text><call>166</call><text> </text></sub_action></action>
+ <action id="27" name="last27" line="286" col="10"><set_tokend>1</set_tokend><sub_action><text> token( '/'); </text><ret></ret><text> </text></sub_action></action>
+ <action id="28" name="last28" line="289" col="20"><set_tokend>1</set_tokend><sub_action><text> updateCol(); </text></sub_action></action>
+ <action id="29" name="last29" line="291" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_ColonEquals ); </text></sub_action></action>
+ <action id="30" name="last30" line="294" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_StartToState ); </text></sub_action></action>
+ <action id="31" name="last31" line="295" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_AllToState ); </text></sub_action></action>
+ <action id="32" name="last32" line="296" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_FinalToState ); </text></sub_action></action>
+ <action id="33" name="last33" line="297" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotStartToState ); </text></sub_action></action>
+ <action id="34" name="last34" line="298" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotFinalToState ); </text></sub_action></action>
+ <action id="35" name="last35" line="299" col="12"><set_tokend>1</set_tokend><sub_action><text> token( TK_MiddleToState ); </text></sub_action></action>
+ <action id="36" name="last36" line="302" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_StartFromState ); </text></sub_action></action>
+ <action id="37" name="last37" line="303" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_AllFromState ); </text></sub_action></action>
+ <action id="38" name="last38" line="304" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_FinalFromState ); </text></sub_action></action>
+ <action id="39" name="last39" line="305" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotStartFromState ); </text></sub_action></action>
+ <action id="40" name="last40" line="306" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotFinalFromState ); </text></sub_action></action>
+ <action id="41" name="last41" line="307" col="12"><set_tokend>1</set_tokend><sub_action><text> token( TK_MiddleFromState ); </text></sub_action></action>
+ <action id="42" name="last42" line="310" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_StartEOF ); </text></sub_action></action>
+ <action id="43" name="last43" line="311" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_AllEOF ); </text></sub_action></action>
+ <action id="44" name="last44" line="312" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_FinalEOF ); </text></sub_action></action>
+ <action id="45" name="last45" line="313" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotStartEOF ); </text></sub_action></action>
+ <action id="46" name="last46" line="314" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotFinalEOF ); </text></sub_action></action>
+ <action id="47" name="last47" line="315" col="12"><set_tokend>1</set_tokend><sub_action><text> token( TK_MiddleEOF ); </text></sub_action></action>
+ <action id="48" name="last48" line="318" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_StartGblError ); </text></sub_action></action>
+ <action id="49" name="last49" line="319" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_AllGblError ); </text></sub_action></action>
+ <action id="50" name="last50" line="320" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_FinalGblError ); </text></sub_action></action>
+ <action id="51" name="last51" line="321" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotStartGblError ); </text></sub_action></action>
+ <action id="52" name="last52" line="322" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotFinalGblError ); </text></sub_action></action>
+ <action id="53" name="last53" line="323" col="12"><set_tokend>1</set_tokend><sub_action><text> token( TK_MiddleGblError ); </text></sub_action></action>
+ <action id="54" name="last54" line="326" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_StartLocalError ); </text></sub_action></action>
+ <action id="55" name="last55" line="327" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_AllLocalError ); </text></sub_action></action>
+ <action id="56" name="last56" line="328" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_FinalLocalError ); </text></sub_action></action>
+ <action id="57" name="last57" line="329" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotStartLocalError ); </text></sub_action></action>
+ <action id="58" name="last58" line="330" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotFinalLocalError ); </text></sub_action></action>
+ <action id="59" name="last59" line="331" col="12"><set_tokend>1</set_tokend><sub_action><text> token( TK_MiddleLocalError ); </text></sub_action></action>
+ <action id="60" name="last61" line="337" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_StartCond ); </text></sub_action></action>
+ <action id="61" name="last62" line="338" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_AllCond ); </text></sub_action></action>
+ <action id="62" name="last63" line="339" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_LeavingCond ); </text></sub_action></action>
+ <action id="63" name="last64" line="341" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_DotDot ); </text></sub_action></action>
+ <action id="64" name="last65" line="342" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_StarStar ); </text></sub_action></action>
+ <action id="65" name="last66" line="343" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_DashDash ); </text></sub_action></action>
+ <action id="66" name="last67" line="344" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_Arrow ); </text></sub_action></action>
+ <action id="67" name="last69" line="347" col="12"><set_tokend>1</set_tokend><sub_action><text> token( TK_ColonGtGt ); </text></sub_action></action>
+ <action id="68" name="last70" line="348" col="12"><set_tokend>1</set_tokend><sub_action><text> token( TK_LtColon ); </text></sub_action></action>
+ <action id="69" name="last72" line="354" col="9"><set_tokend>1</set_tokend><sub_action><text> updateCol(); </text></sub_action></action>
+ <action id="70" name="last73" line="357" col="6"><set_tokend>1</set_tokend></action>
+ <action id="71" name="last74" line="359" col="10"><set_tokend>1</set_tokend><sub_action><text> token( *tokstart ); </text></sub_action></action>
+ <action id="72" name="next21" line="273" col="12"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_Word, tokstart, tokend ); </text></sub_action></action>
+ <action id="73" name="next22" line="276" col="13"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_UInt, tokstart, tokend ); </text></sub_action></action>
+ <action id="74" name="next23" line="277" col="17"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_Hex, tokstart, tokend ); </text></sub_action></action>
+ <action id="75" name="next24" line="281" col="7"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_Literal, tokstart, tokend ); </text></sub_action></action>
+ <action id="76" name="next25" line="283" col="10"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( RE_SqOpen ); </text><call>166</call><text> </text></sub_action></action>
+ <action id="77" name="next60" line="334" col="11"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_Middle ); </text></sub_action></action>
+ <action id="78" name="next68" line="346" col="12"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_ColonGt ); </text></sub_action></action>
+ <action id="79" name="next71" line="351" col="15"><set_tokend>0</set_tokend><hold></hold><sub_action><text> updateCol(); </text></sub_action></action>
+ <action id="80" name="next74" line="359" col="10"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( *tokstart ); </text></sub_action></action>
+ <action id="81" name="lag22" line="276" col="13"><exec><get_tokend></get_tokend></exec><sub_action><text> token( TK_UInt, tokstart, tokend ); </text></sub_action></action>
+ <action id="82" name="switch" line="1" col="1"><lm_switch>
+ <sub_action id="15"><exec><get_tokend></get_tokend></exec><text> token( KW_When ); </text></sub_action>
+ <sub_action id="16"><exec><get_tokend></get_tokend></exec><text> token( KW_Eof ); </text></sub_action>
+ <sub_action id="17"><exec><get_tokend></get_tokend></exec><text> token( KW_Err ); </text></sub_action>
+ <sub_action id="18"><exec><get_tokend></get_tokend></exec><text> token( KW_Lerr ); </text></sub_action>
+ <sub_action id="19"><exec><get_tokend></get_tokend></exec><text> token( KW_To ); </text></sub_action>
+ <sub_action id="20"><exec><get_tokend></get_tokend></exec><text> token( KW_From ); </text></sub_action>
+ <sub_action id="21"><exec><get_tokend></get_tokend></exec><text> token( TK_Word, tokstart, tokend ); </text></sub_action>
+ </lm_switch></action>
+ <action id="83" name="last75" line="363" col="12"><set_tokend>1</set_tokend><sub_action><text> litBuf.append( '\a' ); </text></sub_action></action>
+ <action id="84" name="last76" line="364" col="12"><set_tokend>1</set_tokend><sub_action><text> litBuf.append( '\b' ); </text></sub_action></action>
+ <action id="85" name="last77" line="365" col="12"><set_tokend>1</set_tokend><sub_action><text> litBuf.append( '\t' ); </text></sub_action></action>
+ <action id="86" name="last78" line="366" col="12"><set_tokend>1</set_tokend><sub_action><text> litBuf.append( '\n' ); </text></sub_action></action>
+ <action id="87" name="last79" line="367" col="12"><set_tokend>1</set_tokend><sub_action><text> litBuf.append( '\v' ); </text></sub_action></action>
+ <action id="88" name="last80" line="368" col="12"><set_tokend>1</set_tokend><sub_action><text> litBuf.append( '\f' ); </text></sub_action></action>
+ <action id="89" name="last81" line="369" col="12"><set_tokend>1</set_tokend><sub_action><text> litBuf.append( '\r' ); </text></sub_action></action>
+ <action id="90" name="last82" line="371" col="12"><set_tokend>1</set_tokend><sub_action><text>
+ litBuf.append( tokstart[1] );
+ </text></sub_action></action>
+ <action id="91" name="last83" line="374" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ if ( litBuf.length &gt; 0 ) {
+ token( TK_LitPat, litBuf.data, litBuf.data+litBuf.length );
+ litBuf.clear();
+ }
+ token( '"' );
+ </text><ret></ret><text>
+ </text></sub_action></action>
+ <action id="92" name="last84" line="382" col="9"><set_tokend>1</set_tokend><sub_action><text>
+ if ( litBuf.length &gt; 0 ) {
+ litBuf.append( '\n' );
+ token( TK_LitPat, litBuf.data, litBuf.data+litBuf.length );
+ litBuf.clear();
+ }
+ token( '"' );
+ </text><ret></ret><text>
+ </text></sub_action></action>
+ <action id="93" name="last85" line="391" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ if ( litBuf.length &gt; 0 ) {
+ token( TK_LitPat, litBuf.data, litBuf.data+litBuf.length );
+ litBuf.clear();
+ }
+ token( '[' );
+ </text><call>10</call><text>
+ </text></sub_action></action>
+ <action id="94" name="last86" line="399" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ litBuf.append( *tokstart );
+ </text></sub_action></action>
+ <action id="95" name="store87" line="406" col="12"><set_act>87</set_act></action>
+ <action id="96" name="store88" line="407" col="15"><set_act>88</set_act></action>
+ <action id="97" name="store89" line="408" col="17"><set_act>89</set_act></action>
+ <action id="98" name="store90" line="409" col="15"><set_act>90</set_act></action>
+ <action id="99" name="store91" line="410" col="13"><set_act>91</set_act></action>
+ <action id="100" name="store92" line="411" col="14"><set_act>92</set_act></action>
+ <action id="101" name="store93" line="412" col="18"><set_act>93</set_act></action>
+ <action id="102" name="store94" line="413" col="14"><set_act>94</set_act></action>
+ <action id="103" name="store95" line="414" col="16"><set_act>95</set_act></action>
+ <action id="104" name="store96" line="415" col="16"><set_act>96</set_act></action>
+ <action id="105" name="store97" line="416" col="13"><set_act>97</set_act></action>
+ <action id="106" name="store98" line="417" col="15"><set_act>98</set_act></action>
+ <action id="107" name="store99" line="418" col="16"><set_act>99</set_act></action>
+ <action id="108" name="store101" line="420" col="14"><set_act>101</set_act></action>
+ <action id="109" name="store102" line="421" col="12"><set_act>102</set_act></action>
+ <action id="110" name="store103" line="422" col="12"><set_act>103</set_act></action>
+ <action id="111" name="store104" line="424" col="11"><set_act>104</set_act></action>
+ <action id="112" name="store105" line="425" col="12"><set_act>105</set_act></action>
+ <action id="113" name="store106" line="426" col="15"><set_act>106</set_act></action>
+ <action id="114" name="store107" line="427" col="12"><set_act>107</set_act></action>
+ <action id="115" name="store108" line="428" col="16"><set_act>108</set_act></action>
+ <action id="116" name="store109" line="429" col="18"><set_act>109</set_act></action>
+ <action id="117" name="store110" line="430" col="12"><set_act>110</set_act></action>
+ <action id="118" name="store112" line="432" col="16"><set_act>112</set_act></action>
+ <action id="119" name="store113" line="433" col="17"><set_act>113</set_act></action>
+ <action id="120" name="store114" line="434" col="11"><set_act>114</set_act></action>
+ <action id="121" name="store115" line="435" col="13"><set_act>115</set_act></action>
+ <action id="122" name="store116" line="436" col="15"><set_act>116</set_act></action>
+ <action id="123" name="store117" line="437" col="14"><set_act>117</set_act></action>
+ <action id="124" name="store118" line="438" col="13"><set_act>118</set_act></action>
+ <action id="125" name="store119" line="439" col="18"><set_act>119</set_act></action>
+ <action id="126" name="store120" line="440" col="13"><set_act>120</set_act></action>
+ <action id="127" name="store121" line="441" col="14"><set_act>121</set_act></action>
+ <action id="128" name="store122" line="442" col="12"><set_act>122</set_act></action>
+ <action id="129" name="store123" line="443" col="13"><set_act>123</set_act></action>
+ <action id="130" name="store124" line="444" col="13"><set_act>124</set_act></action>
+ <action id="131" name="store125" line="445" col="13"><set_act>125</set_act></action>
+ <action id="132" name="store126" line="446" col="18"><set_act>126</set_act></action>
+ <action id="133" name="store127" line="447" col="13"><set_act>127</set_act></action>
+ <action id="134" name="store128" line="448" col="11"><set_act>128</set_act></action>
+ <action id="135" name="store129" line="449" col="18"><set_act>129</set_act></action>
+ <action id="136" name="store130" line="450" col="16"><set_act>130</set_act></action>
+ <action id="137" name="store131" line="453" col="12"><set_act>131</set_act></action>
+ <action id="138" name="last133" line="457" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ token( '/' );
+ </text><call>168</call><text>
+ </text></sub_action></action>
+ <action id="139" name="last134" line="462" col="20"><set_tokend>1</set_tokend><sub_action><text>
+ token( '"' );
+ token( TK_LitPat, tokstart+1, tokend );
+ token( '"' );
+ </text></sub_action></action>
+ <action id="140" name="last135" line="468" col="16"><set_tokend>1</set_tokend><sub_action><text>
+ token( TK_Literal, tokstart, tokend );
+ </text></sub_action></action>
+ <action id="141" name="last136" line="472" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ token( '"' );
+ litBuf.clear();
+ </text><call>203</call><text>
+ </text></sub_action></action>
+ <action id="142" name="last137" line="477" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ token( '[' );
+ </text><call>10</call><text>
+ </text></sub_action></action>
+ <action id="143" name="last138" line="482" col="10"><set_tokend>1</set_tokend><sub_action><text>
+ token( ']' );
+ if ( top &gt; 0 )
+ </text><ret></ret><text>
+ </text></sub_action></action>
+ <action id="144" name="last139" line="489" col="20"><set_tokend>1</set_tokend><sub_action><text> updateCol(); </text></sub_action></action>
+ <action id="145" name="last140" line="491" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_ColonEquals ); </text></sub_action></action>
+ <action id="146" name="last141" line="492" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_DoubleArrow ); </text></sub_action></action>
+ <action id="147" name="last142" line="493" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_DoubleEquals ); </text></sub_action></action>
+ <action id="148" name="last143" line="494" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_NotEquals ); </text></sub_action></action>
+ <action id="149" name="last144" line="495" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_DoubleColon ); </text></sub_action></action>
+ <action id="150" name="last145" line="496" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_LessEquals ); </text></sub_action></action>
+ <action id="151" name="last146" line="497" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_GreaterEquals ); </text></sub_action></action>
+ <action id="152" name="last147" line="498" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_LeftArrow ); </text></sub_action></action>
+ <action id="153" name="last148" line="499" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_AmpAmp ); </text></sub_action></action>
+ <action id="154" name="last149" line="500" col="11"><set_tokend>1</set_tokend><sub_action><text> token( TK_BarBar ); </text></sub_action></action>
+ <action id="155" name="last150" line="502" col="43"><set_tokend>1</set_tokend><sub_action><text> token( *tokstart ); </text></sub_action></action>
+ <action id="156" name="last152" line="509" col="9"><set_tokend>1</set_tokend><sub_action><text> updateCol(); </text></sub_action></action>
+ <action id="157" name="last153" line="512" col="6"><set_tokend>1</set_tokend></action>
+ <action id="158" name="last154" line="514" col="10"><set_tokend>1</set_tokend><sub_action><text> token( *tokstart ); </text></sub_action></action>
+ <action id="159" name="next100" line="419" col="12"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( KW_Pri ); </text></sub_action></action>
+ <action id="160" name="next111" line="431" col="14"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( KW_Print ); </text></sub_action></action>
+ <action id="161" name="next131" line="453" col="12"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_Word, tokstart, tokend ); </text></sub_action></action>
+ <action id="162" name="next132" line="455" col="13"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( TK_Number, tokstart, tokend ); </text></sub_action></action>
+ <action id="163" name="next151" line="506" col="15"><set_tokend>0</set_tokend><hold></hold><sub_action><text> updateCol(); </text></sub_action></action>
+ <action id="164" name="next154" line="514" col="10"><set_tokend>0</set_tokend><hold></hold><sub_action><text> token( *tokstart ); </text></sub_action></action>
+ <action id="165" name="switch" line="1" col="1"><lm_switch>
+ <sub_action id="87"><exec><get_tokend></get_tokend></exec><text> token( KW_Lex ); </text></sub_action>
+ <sub_action id="88"><exec><get_tokend></get_tokend></exec><text> token( KW_Action ); </text></sub_action>
+ <sub_action id="89"><exec><get_tokend></get_tokend></exec><text> token( KW_AlphType ); </text></sub_action>
+ <sub_action id="90"><exec><get_tokend></get_tokend></exec><text> token( KW_Commit ); </text></sub_action>
+ <sub_action id="91"><exec><get_tokend></get_tokend></exec><text> token( KW_Undo ); </text></sub_action>
+ <sub_action id="92"><exec><get_tokend></get_tokend></exec><text> token( KW_Final ); </text></sub_action>
+ <sub_action id="93"><exec><get_tokend></get_tokend></exec><text> token( KW_Translate ); </text></sub_action>
+ <sub_action id="94"><exec><get_tokend></get_tokend></exec><text> token( KW_Token ); </text></sub_action>
+ <sub_action id="95"><exec><get_tokend></get_tokend></exec><text> token( KW_Literal ); </text></sub_action>
+ <sub_action id="96"><exec><get_tokend></get_tokend></exec><text> token( KW_NonTerm ); </text></sub_action>
+ <sub_action id="97"><exec><get_tokend></get_tokend></exec><text> token( KW_Uses ); </text></sub_action>
+ <sub_action id="98"><exec><get_tokend></get_tokend></exec><text> token( KW_Parser ); </text></sub_action>
+ <sub_action id="99"><exec><get_tokend></get_tokend></exec><text> token( KW_Include ); </text></sub_action>
+ <sub_action id="101"><exec><get_tokend></get_tokend></exec><text> token( KW_Write ); </text></sub_action>
+ <sub_action id="102"><exec><get_tokend></get_tokend></exec><text> token( KW_Nfa ); </text></sub_action>
+ <sub_action id="103"><exec><get_tokend></get_tokend></exec><text> token( KW_Pda ); </text></sub_action>
+ <sub_action id="104"><exec><get_tokend></get_tokend></exec><text> token( KW_Rl ); </text></sub_action>
+ <sub_action id="105"><exec><get_tokend></get_tokend></exec><text> token( KW_Cfl ); </text></sub_action>
+ <sub_action id="106"><exec><get_tokend></get_tokend></exec><text> token( KW_Ignore ); </text></sub_action>
+ <sub_action id="107"><exec><get_tokend></get_tokend></exec><text> token( KW_End ); </text></sub_action>
+ <sub_action id="108"><exec><get_tokend></get_tokend></exec><text> token( KW_Pattern ); </text></sub_action>
+ <sub_action id="109"><exec><get_tokend></get_tokend></exec><text> token( KW_Construct ); </text></sub_action>
+ <sub_action id="110"><exec><get_tokend></get_tokend></exec><text> token( KW_Red ); </text></sub_action>
+ <sub_action id="112"><exec><get_tokend></get_tokend></exec><text> token( KW_TypeId ); </text></sub_action>
+ <sub_action id="113"><exec><get_tokend></get_tokend></exec><text> token( KW_TypeDef ); </text></sub_action>
+ <sub_action id="114"><exec><get_tokend></get_tokend></exec><text> token( KW_If ); </text></sub_action>
+ <sub_action id="115"><exec><get_tokend></get_tokend></exec><text> token( KW_Init ); </text></sub_action>
+ <sub_action id="116"><exec><get_tokend></get_tokend></exec><text> token( KW_Reject ); </text></sub_action>
+ <sub_action id="117"><exec><get_tokend></get_tokend></exec><text> token( KW_While ); </text></sub_action>
+ <sub_action id="118"><exec><get_tokend></get_tokend></exec><text> token( KW_Else ); </text></sub_action>
+ <sub_action id="119"><exec><get_tokend></get_tokend></exec><text> token( KW_SubParser ); </text></sub_action>
+ <sub_action id="120"><exec><get_tokend></get_tokend></exec><text> token( KW_Next ); </text></sub_action>
+ <sub_action id="121"><exec><get_tokend></get_tokend></exec><text> token( KW_Match ); </text></sub_action>
+ <sub_action id="122"><exec><get_tokend></get_tokend></exec><text> token( KW_For ); </text></sub_action>
+ <sub_action id="123"><exec><get_tokend></get_tokend></exec><text> token( KW_Iter ); </text></sub_action>
+ <sub_action id="124"><exec><get_tokend></get_tokend></exec><text> token( KW_Find ); </text></sub_action>
+ <sub_action id="125"><exec><get_tokend></get_tokend></exec><text> token( KW_Root ); </text></sub_action>
+ <sub_action id="126"><exec><get_tokend></get_tokend></exec><text> token( KW_PrintXML ); </text></sub_action>
+ <sub_action id="127"><exec><get_tokend></get_tokend></exec><text> token( KW_Then ); </text></sub_action>
+ <sub_action id="128"><exec><get_tokend></get_tokend></exec><text> token( KW_Do ); </text></sub_action>
+ <sub_action id="129"><exec><get_tokend></get_tokend></exec><text> token( KW_Namespace ); </text></sub_action>
+ <sub_action id="130"><exec><get_tokend></get_tokend></exec><text> token( KW_Scanner ); </text></sub_action>
+ <sub_action id="131"><exec><get_tokend></get_tokend></exec><text> token( TK_Word, tokstart, tokend ); </text></sub_action>
+ </lm_switch></action>
+ </action_list>
+ <action_table_list length="166">
+ <action_table id="0" length="2">0 144</action_table>
+ <action_table id="1" length="1">0</action_table>
+ <action_table id="2" length="1">140</action_table>
+ <action_table id="3" length="2">0 139</action_table>
+ <action_table id="4" length="2">0 28</action_table>
+ <action_table id="5" length="1">81</action_table>
+ <action_table id="6" length="1">1</action_table>
+ <action_table id="7" length="1">2</action_table>
+ <action_table id="8" length="1">158</action_table>
+ <action_table id="9" length="1">157</action_table>
+ <action_table id="10" length="2">0 156</action_table>
+ <action_table id="11" length="1">141</action_table>
+ <action_table id="12" length="1">3</action_table>
+ <action_table id="13" length="1">155</action_table>
+ <action_table id="14" length="1">138</action_table>
+ <action_table id="15" length="2">3 137</action_table>
+ <action_table id="16" length="1">142</action_table>
+ <action_table id="17" length="1">143</action_table>
+ <action_table id="18" length="1">163</action_table>
+ <action_table id="19" length="1">164</action_table>
+ <action_table id="20" length="1">148</action_table>
+ <action_table id="21" length="1">153</action_table>
+ <action_table id="22" length="1">162</action_table>
+ <action_table id="23" length="1">149</action_table>
+ <action_table id="24" length="1">145</action_table>
+ <action_table id="25" length="1">152</action_table>
+ <action_table id="26" length="1">150</action_table>
+ <action_table id="27" length="1">147</action_table>
+ <action_table id="28" length="1">146</action_table>
+ <action_table id="29" length="1">151</action_table>
+ <action_table id="30" length="1">165</action_table>
+ <action_table id="31" length="1">161</action_table>
+ <action_table id="32" length="2">3 96</action_table>
+ <action_table id="33" length="2">3 97</action_table>
+ <action_table id="34" length="2">3 112</action_table>
+ <action_table id="35" length="2">3 98</action_table>
+ <action_table id="36" length="2">3 116</action_table>
+ <action_table id="37" length="2">3 134</action_table>
+ <action_table id="38" length="2">3 124</action_table>
+ <action_table id="39" length="2">3 114</action_table>
+ <action_table id="40" length="2">3 130</action_table>
+ <action_table id="41" length="2">3 100</action_table>
+ <action_table id="42" length="2">3 128</action_table>
+ <action_table id="43" length="2">3 120</action_table>
+ <action_table id="44" length="2">3 113</action_table>
+ <action_table id="45" length="2">3 107</action_table>
+ <action_table id="46" length="2">3 121</action_table>
+ <action_table id="47" length="2">3 129</action_table>
+ <action_table id="48" length="2">3 95</action_table>
+ <action_table id="49" length="2">3 103</action_table>
+ <action_table id="50" length="2">3 127</action_table>
+ <action_table id="51" length="2">3 135</action_table>
+ <action_table id="52" length="2">3 126</action_table>
+ <action_table id="53" length="2">3 109</action_table>
+ <action_table id="54" length="2">3 104</action_table>
+ <action_table id="55" length="2">3 106</action_table>
+ <action_table id="56" length="2">3 115</action_table>
+ <action_table id="57" length="2">3 110</action_table>
+ <action_table id="58" length="1">159</action_table>
+ <action_table id="59" length="1">160</action_table>
+ <action_table id="60" length="2">3 132</action_table>
+ <action_table id="61" length="2">3 111</action_table>
+ <action_table id="62" length="2">3 117</action_table>
+ <action_table id="63" length="2">3 122</action_table>
+ <action_table id="64" length="2">3 131</action_table>
+ <action_table id="65" length="2">3 136</action_table>
+ <action_table id="66" length="2">3 125</action_table>
+ <action_table id="67" length="2">3 133</action_table>
+ <action_table id="68" length="2">3 102</action_table>
+ <action_table id="69" length="2">3 101</action_table>
+ <action_table id="70" length="2">3 119</action_table>
+ <action_table id="71" length="2">3 118</action_table>
+ <action_table id="72" length="2">3 99</action_table>
+ <action_table id="73" length="2">3 105</action_table>
+ <action_table id="74" length="2">3 123</action_table>
+ <action_table id="75" length="2">3 108</action_table>
+ <action_table id="76" length="1">154</action_table>
+ <action_table id="77" length="1">17</action_table>
+ <action_table id="78" length="1">16</action_table>
+ <action_table id="79" length="1">14</action_table>
+ <action_table id="80" length="1">15</action_table>
+ <action_table id="81" length="1">13</action_table>
+ <action_table id="82" length="1">12</action_table>
+ <action_table id="83" length="1">4</action_table>
+ <action_table id="84" length="1">5</action_table>
+ <action_table id="85" length="1">6</action_table>
+ <action_table id="86" length="1">10</action_table>
+ <action_table id="87" length="1">8</action_table>
+ <action_table id="88" length="1">11</action_table>
+ <action_table id="89" length="1">7</action_table>
+ <action_table id="90" length="1">9</action_table>
+ <action_table id="91" length="1">71</action_table>
+ <action_table id="92" length="1">70</action_table>
+ <action_table id="93" length="2">0 69</action_table>
+ <action_table id="94" length="1">27</action_table>
+ <action_table id="95" length="2">3 24</action_table>
+ <action_table id="96" length="1">79</action_table>
+ <action_table id="97" length="1">75</action_table>
+ <action_table id="98" length="1">25</action_table>
+ <action_table id="99" length="1">80</action_table>
+ <action_table id="100" length="1">49</action_table>
+ <action_table id="101" length="1">37</action_table>
+ <action_table id="102" length="1">43</action_table>
+ <action_table id="103" length="1">61</action_table>
+ <action_table id="104" length="1">55</action_table>
+ <action_table id="105" length="1">31</action_table>
+ <action_table id="106" length="1">50</action_table>
+ <action_table id="107" length="1">38</action_table>
+ <action_table id="108" length="1">44</action_table>
+ <action_table id="109" length="1">62</action_table>
+ <action_table id="110" length="1">56</action_table>
+ <action_table id="111" length="1">32</action_table>
+ <action_table id="112" length="1">64</action_table>
+ <action_table id="113" length="1">65</action_table>
+ <action_table id="114" length="1">66</action_table>
+ <action_table id="115" length="1">63</action_table>
+ <action_table id="116" length="1">73</action_table>
+ <action_table id="117" length="1">74</action_table>
+ <action_table id="118" length="1">29</action_table>
+ <action_table id="119" length="1">78</action_table>
+ <action_table id="120" length="1">67</action_table>
+ <action_table id="121" length="1">51</action_table>
+ <action_table id="122" length="1">39</action_table>
+ <action_table id="123" length="1">45</action_table>
+ <action_table id="124" length="1">68</action_table>
+ <action_table id="125" length="1">57</action_table>
+ <action_table id="126" length="1">33</action_table>
+ <action_table id="127" length="1">77</action_table>
+ <action_table id="128" length="1">53</action_table>
+ <action_table id="129" length="1">41</action_table>
+ <action_table id="130" length="1">47</action_table>
+ <action_table id="131" length="1">59</action_table>
+ <action_table id="132" length="1">35</action_table>
+ <action_table id="133" length="1">48</action_table>
+ <action_table id="134" length="1">36</action_table>
+ <action_table id="135" length="1">42</action_table>
+ <action_table id="136" length="1">60</action_table>
+ <action_table id="137" length="1">54</action_table>
+ <action_table id="138" length="1">30</action_table>
+ <action_table id="139" length="1">52</action_table>
+ <action_table id="140" length="1">40</action_table>
+ <action_table id="141" length="1">46</action_table>
+ <action_table id="142" length="1">58</action_table>
+ <action_table id="143" length="1">34</action_table>
+ <action_table id="144" length="1">82</action_table>
+ <action_table id="145" length="1">76</action_table>
+ <action_table id="146" length="1">26</action_table>
+ <action_table id="147" length="1">72</action_table>
+ <action_table id="148" length="2">3 19</action_table>
+ <action_table id="149" length="2">3 20</action_table>
+ <action_table id="150" length="2">3 23</action_table>
+ <action_table id="151" length="2">3 21</action_table>
+ <action_table id="152" length="2">3 22</action_table>
+ <action_table id="153" length="2">3 18</action_table>
+ <action_table id="154" length="1">94</action_table>
+ <action_table id="155" length="2">0 92</action_table>
+ <action_table id="156" length="1">91</action_table>
+ <action_table id="157" length="1">93</action_table>
+ <action_table id="158" length="1">90</action_table>
+ <action_table id="159" length="1">83</action_table>
+ <action_table id="160" length="1">84</action_table>
+ <action_table id="161" length="1">88</action_table>
+ <action_table id="162" length="1">86</action_table>
+ <action_table id="163" length="1">89</action_table>
+ <action_table id="164" length="1">85</action_table>
+ <action_table id="165" length="1">87</action_table>
+ </action_table_list>
+ <start_state>10</start_state>
+ <entry_points>
+ <entry name="or_literal">166</entry>
+ <entry name="regular_type">168</entry>
+ <entry name="literal_pattern">203</entry>
+ <entry name="main">10</entry>
+ </entry_points>
+ <state_list length="205">
+ <state id="0">
+ <trans_list length="3">
+ <t>-128 9 0 x</t>
+ <t>10 10 10 0</t>
+ <t>11 127 0 x</t>
+ </trans_list>
+ </state>
+
+ <state id="1">
+ <trans_list length="7">
+ <t>-128 9 1 x</t>
+ <t>10 10 1 1</t>
+ <t>11 38 1 x</t>
+ <t>39 39 10 2</t>
+ <t>40 91 1 x</t>
+ <t>92 92 2 x</t>
+ <t>93 127 1 x</t>
+ </trans_list>
+ </state>
+
+ <state id="2">
+ <trans_list length="3">
+ <t>-128 9 1 x</t>
+ <t>10 10 1 1</t>
+ <t>11 127 1 x</t>
+ </trans_list>
+ </state>
+
+ <state id="3">
+ <trans_list length="3">
+ <t>-128 9 3 x</t>
+ <t>10 10 10 3</t>
+ <t>11 127 3 x</t>
+ </trans_list>
+ </state>
+
+ <state id="4">
+ <trans_list length="7">
+ <t>-128 9 4 x</t>
+ <t>10 10 4 1</t>
+ <t>11 33 4 x</t>
+ <t>34 34 171 x</t>
+ <t>35 91 4 x</t>
+ <t>92 92 5 x</t>
+ <t>93 127 4 x</t>
+ </trans_list>
+ </state>
+
+ <state id="5">
+ <trans_list length="3">
+ <t>-128 9 4 x</t>
+ <t>10 10 4 1</t>
+ <t>11 127 4 x</t>
+ </trans_list>
+ </state>
+
+ <state id="6">
+ <trans_list length="3">
+ <t>-128 9 6 x</t>
+ <t>10 10 168 4</t>
+ <t>11 127 6 x</t>
+ </trans_list>
+ </state>
+
+ <state id="7">
+ <trans_list length="7">
+ <t>-128 9 7 x</t>
+ <t>10 10 7 1</t>
+ <t>11 38 7 x</t>
+ <t>39 39 171 x</t>
+ <t>40 91 7 x</t>
+ <t>92 92 8 x</t>
+ <t>93 127 7 x</t>
+ </trans_list>
+ </state>
+
+ <state id="8">
+ <trans_list length="3">
+ <t>-128 9 7 x</t>
+ <t>10 10 7 1</t>
+ <t>11 127 7 x</t>
+ </trans_list>
+ </state>
+
+ <state id="9">
+ <trans_list length="7">
+ <t>-128 47 168 5</t>
+ <t>48 57 181 x</t>
+ <t>58 64 168 5</t>
+ <t>65 70 181 x</t>
+ <t>71 96 168 5</t>
+ <t>97 102 181 x</t>
+ <t>103 127 168 5</t>
+ </trans_list>
+ </state>
+
+ <state id="10" final="t">
+ <state_actions>6 7 x</state_actions>
+ <trans_list length="61">
+ <t>-128 -1 10 8</t>
+ <t>0 0 10 9</t>
+ <t>1 8 10 8</t>
+ <t>9 9 11 x</t>
+ <t>10 10 10 10</t>
+ <t>11 12 10 8</t>
+ <t>13 13 11 x</t>
+ <t>14 31 10 8</t>
+ <t>32 32 11 x</t>
+ <t>33 33 12 x</t>
+ <t>34 34 10 11</t>
+ <t>35 35 13 12</t>
+ <t>36 37 10 8</t>
+ <t>38 38 14 x</t>
+ <t>39 39 15 12</t>
+ <t>40 43 10 13</t>
+ <t>44 44 10 8</t>
+ <t>45 45 10 13</t>
+ <t>46 46 10 8</t>
+ <t>47 47 10 14</t>
+ <t>48 57 16 x</t>
+ <t>58 58 17 x</t>
+ <t>59 59 10 8</t>
+ <t>60 60 18 x</t>
+ <t>61 61 19 x</t>
+ <t>62 62 20 x</t>
+ <t>63 64 10 8</t>
+ <t>65 90 21 15</t>
+ <t>91 91 10 16</t>
+ <t>92 92 10 8</t>
+ <t>93 93 10 17</t>
+ <t>94 94 10 8</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 8</t>
+ <t>97 97 22 x</t>
+ <t>98 98 21 15</t>
+ <t>99 99 33 x</t>
+ <t>100 100 45 x</t>
+ <t>101 101 46 x</t>
+ <t>102 102 50 x</t>
+ <t>103 104 21 15</t>
+ <t>105 105 55 x</t>
+ <t>106 107 21 15</t>
+ <t>108 108 68 x</t>
+ <t>109 109 75 x</t>
+ <t>110 110 79 x</t>
+ <t>111 111 21 15</t>
+ <t>112 112 95 x</t>
+ <t>113 113 21 15</t>
+ <t>114 114 112 x</t>
+ <t>115 115 119 x</t>
+ <t>116 116 132 x</t>
+ <t>117 117 152 x</t>
+ <t>118 118 21 15</t>
+ <t>119 119 157 x</t>
+ <t>120 122 21 15</t>
+ <t>123 123 10 8</t>
+ <t>124 124 164 x</t>
+ <t>125 125 10 8</t>
+ <t>126 126 165 12</t>
+ <t>127 127 10 8</t>
+ </trans_list>
+ </state>
+
+ <state id="11" final="t">
+ <trans_list length="7">
+ <t>-128 8 10 18</t>
+ <t>9 9 11 x</t>
+ <t>10 12 10 18</t>
+ <t>13 13 11 x</t>
+ <t>14 31 10 18</t>
+ <t>32 32 11 x</t>
+ <t>33 127 10 18</t>
+ </trans_list>
+ </state>
+
+ <state id="12" final="t">
+ <trans_list length="3">
+ <t>-128 60 10 19</t>
+ <t>61 61 10 20</t>
+ <t>62 127 10 19</t>
+ </trans_list>
+ </state>
+
+ <state id="13" final="t">
+ <trans_list length="3">
+ <t>-128 9 0 x</t>
+ <t>10 10 10 0</t>
+ <t>11 127 0 x</t>
+ </trans_list>
+ </state>
+
+ <state id="14" final="t">
+ <trans_list length="3">
+ <t>-128 37 10 19</t>
+ <t>38 38 10 21</t>
+ <t>39 127 10 19</t>
+ </trans_list>
+ </state>
+
+ <state id="15" final="t">
+ <trans_list length="7">
+ <t>-128 9 1 x</t>
+ <t>10 10 1 1</t>
+ <t>11 38 1 x</t>
+ <t>39 39 10 2</t>
+ <t>40 91 1 x</t>
+ <t>92 92 2 x</t>
+ <t>93 127 1 x</t>
+ </trans_list>
+ </state>
+
+ <state id="16" final="t">
+ <trans_list length="3">
+ <t>-128 47 10 22</t>
+ <t>48 57 16 x</t>
+ <t>58 127 10 22</t>
+ </trans_list>
+ </state>
+
+ <state id="17" final="t">
+ <trans_list length="5">
+ <t>-128 57 10 19</t>
+ <t>58 58 10 23</t>
+ <t>59 60 10 19</t>
+ <t>61 61 10 24</t>
+ <t>62 127 10 19</t>
+ </trans_list>
+ </state>
+
+ <state id="18" final="t">
+ <trans_list length="5">
+ <t>-128 44 10 19</t>
+ <t>45 45 10 25</t>
+ <t>46 60 10 19</t>
+ <t>61 61 10 26</t>
+ <t>62 127 10 19</t>
+ </trans_list>
+ </state>
+
+ <state id="19" final="t">
+ <trans_list length="4">
+ <t>-128 60 10 19</t>
+ <t>61 61 10 27</t>
+ <t>62 62 10 28</t>
+ <t>63 127 10 19</t>
+ </trans_list>
+ </state>
+
+ <state id="20" final="t">
+ <trans_list length="3">
+ <t>-128 60 10 19</t>
+ <t>61 61 10 29</t>
+ <t>62 127 10 19</t>
+ </trans_list>
+ </state>
+
+ <state id="21" final="t">
+ <trans_list length="9">
+ <t>-128 47 10 30</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 30</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 30</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 30</t>
+ <t>97 122 21 15</t>
+ <t>123 127 10 30</t>
+ </trans_list>
+ </state>
+
+ <state id="22" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 98 21 15</t>
+ <t>99 99 23 x</t>
+ <t>100 107 21 15</t>
+ <t>108 108 27 x</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="23" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 24 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="24" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 104 21 15</t>
+ <t>105 105 25 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="25" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 110 21 15</t>
+ <t>111 111 26 x</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="26" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 21 32</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="27" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 111 21 15</t>
+ <t>112 112 28 x</t>
+ <t>113 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="28" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 103 21 15</t>
+ <t>104 104 29 x</t>
+ <t>105 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="29" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 30 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="30" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 120 21 15</t>
+ <t>121 121 31 x</t>
+ <t>122 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="31" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 111 21 15</t>
+ <t>112 112 32 x</t>
+ <t>113 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="32" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 33</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="33" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 101 21 15</t>
+ <t>102 102 34 x</t>
+ <t>103 110 21 15</t>
+ <t>111 111 35 x</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="34" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 21 34</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="35" final="t">
+ <trans_list length="12">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 108 21 15</t>
+ <t>109 109 36 x</t>
+ <t>110 110 39 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="36" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 108 21 15</t>
+ <t>109 109 37 x</t>
+ <t>110 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="37" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 104 21 15</t>
+ <t>105 105 38 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="38" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 21 35</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="39" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 114 21 15</t>
+ <t>115 115 40 x</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="40" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 41 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="41" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 42 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="42" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 116 21 15</t>
+ <t>117 117 43 x</t>
+ <t>118 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="43" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 98 21 15</t>
+ <t>99 99 44 x</t>
+ <t>100 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="44" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 21 36</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="45" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 110 21 15</t>
+ <t>111 111 21 37</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="46" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 47 x</t>
+ <t>109 109 21 15</t>
+ <t>110 110 49 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="47" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 114 21 15</t>
+ <t>115 115 48 x</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="48" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 38</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="49" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 99 21 15</t>
+ <t>100 100 21 39</t>
+ <t>101 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="50" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 104 21 15</t>
+ <t>105 105 51 x</t>
+ <t>106 110 21 15</t>
+ <t>111 111 54 x</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="51" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 52 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="52" final="t">
+ <trans_list length="12">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 53 x</t>
+ <t>98 99 21 15</t>
+ <t>100 100 21 40</t>
+ <t>101 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="53" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 21 41</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="54" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 21 42</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="55" final="t">
+ <trans_list length="16">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 101 21 15</t>
+ <t>102 102 21 43</t>
+ <t>103 103 56 x</t>
+ <t>104 109 21 15</t>
+ <t>110 110 60 x</t>
+ <t>111 115 21 15</t>
+ <t>116 116 66 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="56" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 57 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="57" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 110 21 15</t>
+ <t>111 111 58 x</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="58" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 59 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="59" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 44</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="60" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 98 21 15</t>
+ <t>99 99 61 x</t>
+ <t>100 104 21 15</t>
+ <t>105 105 65 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="61" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 62 x</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="62" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 116 21 15</t>
+ <t>117 117 63 x</t>
+ <t>118 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="63" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 99 21 15</t>
+ <t>100 100 64 x</t>
+ <t>101 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="64" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 45</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="65" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 21 46</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="66" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 67 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="67" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 21 47</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="68" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 69 x</t>
+ <t>102 104 21 15</t>
+ <t>105 105 70 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="69" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 119 21 15</t>
+ <t>120 120 21 48</t>
+ <t>121 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="70" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 71 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="71" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 72 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="72" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 73 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="73" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 74 x</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="74" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 21 49</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="75" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 76 x</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="76" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 77 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="77" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 98 21 15</t>
+ <t>99 99 78 x</t>
+ <t>100 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="78" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 103 21 15</t>
+ <t>104 104 21 50</t>
+ <t>105 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="79" final="t">
+ <trans_list length="15">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 80 x</t>
+ <t>98 100 21 15</t>
+ <t>101 101 87 x</t>
+ <t>102 102 89 x</t>
+ <t>103 110 21 15</t>
+ <t>111 111 90 x</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="80" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 108 21 15</t>
+ <t>109 109 81 x</t>
+ <t>110 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="81" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 82 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="82" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 114 21 15</t>
+ <t>115 115 83 x</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="83" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 111 21 15</t>
+ <t>112 112 84 x</t>
+ <t>113 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="84" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 85 x</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="85" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 98 21 15</t>
+ <t>99 99 86 x</t>
+ <t>100 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="86" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 51</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="87" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 119 21 15</t>
+ <t>120 120 88 x</t>
+ <t>121 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="88" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 21 52</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="89" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 21 53</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="90" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 91 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="91" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 92 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="92" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 93 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="93" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 94 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="94" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 108 21 15</t>
+ <t>109 109 21 54</t>
+ <t>110 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="95" final="t">
+ <trans_list length="14">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 96 x</t>
+ <t>98 99 21 15</t>
+ <t>100 100 104 x</t>
+ <t>101 113 21 15</t>
+ <t>114 114 105 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="96" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 97 x</t>
+ <t>115 115 21 15</t>
+ <t>116 116 100 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="97" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 114 21 15</t>
+ <t>115 115 98 x</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="98" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 99 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="99" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 21 55</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="100" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 101 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="101" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 102 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="102" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 103 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="103" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 21 56</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="104" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 21 57</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="105" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 104 21 15</t>
+ <t>105 105 106 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="106" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 58</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 58</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 58</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 58</t>
+ <t>97 109 21 15</t>
+ <t>110 110 107 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 58</t>
+ </trans_list>
+ </state>
+
+ <state id="107" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 108 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="108" final="t">
+ <trans_list length="9">
+ <t>-128 47 10 59</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 59</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 59</t>
+ <t>95 95 109 x</t>
+ <t>96 96 10 59</t>
+ <t>97 122 21 15</t>
+ <t>123 127 10 59</t>
+ </trans_list>
+ </state>
+
+ <state id="109" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 119 21 15</t>
+ <t>120 120 110 x</t>
+ <t>121 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="110" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 108 21 15</t>
+ <t>109 109 111 x</t>
+ <t>110 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="111" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 21 60</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="112" final="t">
+ <trans_list length="15">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 113 x</t>
+ <t>102 107 21 15</t>
+ <t>108 108 21 61</t>
+ <t>109 110 21 15</t>
+ <t>111 111 117 x</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="113" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 99 21 15</t>
+ <t>100 100 21 62</t>
+ <t>101 105 21 15</t>
+ <t>106 106 114 x</t>
+ <t>107 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="114" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 115 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="115" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 98 21 15</t>
+ <t>99 99 116 x</t>
+ <t>100 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="116" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 21 63</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="117" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 110 21 15</t>
+ <t>111 111 118 x</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="118" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 21 64</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="119" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 98 21 15</t>
+ <t>99 99 120 x</t>
+ <t>100 116 21 15</t>
+ <t>117 117 125 x</t>
+ <t>118 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="120" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 121 x</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="121" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 122 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="122" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 123 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="123" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 124 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="124" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 21 65</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="125" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 21 15</t>
+ <t>98 98 126 x</t>
+ <t>99 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="126" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 111 21 15</t>
+ <t>112 112 127 x</t>
+ <t>113 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="127" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 128 x</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="128" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 129 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="129" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 114 21 15</t>
+ <t>115 115 130 x</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="130" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 131 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="131" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 113 21 15</t>
+ <t>114 114 21 66</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="132" final="t">
+ <trans_list length="17">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 103 21 15</t>
+ <t>104 104 133 x</t>
+ <t>105 110 21 15</t>
+ <t>111 111 135 x</t>
+ <t>112 113 21 15</t>
+ <t>114 114 138 x</t>
+ <t>115 120 21 15</t>
+ <t>121 121 145 x</t>
+ <t>122 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="133" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 134 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="134" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 21 67</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="135" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 106 21 15</t>
+ <t>107 107 136 x</t>
+ <t>108 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="136" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 137 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="137" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 21 68</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="138" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 139 x</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="139" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 140 x</t>
+ <t>111 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="140" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 114 21 15</t>
+ <t>115 115 141 x</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="141" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 142 x</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="142" final="t">
+ <trans_list length="10">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 97 143 x</t>
+ <t>98 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="143" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 144 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="144" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 69</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="145" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 111 21 15</t>
+ <t>112 112 146 x</t>
+ <t>113 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="146" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 147 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="147" final="t">
+ <trans_list length="9">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 148 x</t>
+ <t>96 96 10 31</t>
+ <t>97 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="148" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 99 21 15</t>
+ <t>100 100 149 x</t>
+ <t>101 104 21 15</t>
+ <t>105 105 151 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="149" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 150 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="150" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 101 21 15</t>
+ <t>102 102 21 70</t>
+ <t>103 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="151" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 99 21 15</t>
+ <t>100 100 21 71</t>
+ <t>101 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="152" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 109 21 15</t>
+ <t>110 110 153 x</t>
+ <t>111 114 21 15</t>
+ <t>115 115 155 x</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="153" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 99 21 15</t>
+ <t>100 100 154 x</t>
+ <t>101 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="154" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 110 21 15</t>
+ <t>111 111 21 72</t>
+ <t>112 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="155" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 156 x</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="156" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 114 21 15</t>
+ <t>115 115 21 73</t>
+ <t>116 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="157" final="t">
+ <trans_list length="13">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 103 21 15</t>
+ <t>104 104 158 x</t>
+ <t>105 113 21 15</t>
+ <t>114 114 161 x</t>
+ <t>115 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="158" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 104 21 15</t>
+ <t>105 105 159 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="159" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 107 21 15</t>
+ <t>108 108 160 x</t>
+ <t>109 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="160" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 74</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="161" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 104 21 15</t>
+ <t>105 105 162 x</t>
+ <t>106 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="162" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 115 21 15</t>
+ <t>116 116 163 x</t>
+ <t>117 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="163" final="t">
+ <trans_list length="11">
+ <t>-128 47 10 31</t>
+ <t>48 57 21 15</t>
+ <t>58 64 10 31</t>
+ <t>65 90 21 15</t>
+ <t>91 94 10 31</t>
+ <t>95 95 21 15</t>
+ <t>96 96 10 31</t>
+ <t>97 100 21 15</t>
+ <t>101 101 21 75</t>
+ <t>102 122 21 15</t>
+ <t>123 127 10 31</t>
+ </trans_list>
+ </state>
+
+ <state id="164" final="t">
+ <trans_list length="3">
+ <t>-128 123 10 19</t>
+ <t>124 124 10 76</t>
+ <t>125 127 10 19</t>
+ </trans_list>
+ </state>
+
+ <state id="165" final="t">
+ <trans_list length="3">
+ <t>-128 9 3 x</t>
+ <t>10 10 10 3</t>
+ <t>11 127 3 x</t>
+ </trans_list>
+ </state>
+
+ <state id="166" final="t">
+ <state_actions>6 7 x</state_actions>
+ <trans_list length="8">
+ <t>-128 -1 166 77</t>
+ <t>0 0 166 78</t>
+ <t>1 44 166 77</t>
+ <t>45 45 166 79</t>
+ <t>46 91 166 77</t>
+ <t>92 92 167 x</t>
+ <t>93 93 166 80</t>
+ <t>94 127 166 77</t>
+ </trans_list>
+ </state>
+
+ <state id="167" final="t">
+ <trans_list length="18">
+ <t>-128 9 166 81</t>
+ <t>10 10 166 82</t>
+ <t>11 47 166 81</t>
+ <t>48 48 166 83</t>
+ <t>49 96 166 81</t>
+ <t>97 97 166 84</t>
+ <t>98 98 166 85</t>
+ <t>99 101 166 81</t>
+ <t>102 102 166 86</t>
+ <t>103 109 166 81</t>
+ <t>110 110 166 87</t>
+ <t>111 113 166 81</t>
+ <t>114 114 166 88</t>
+ <t>115 115 166 81</t>
+ <t>116 116 166 89</t>
+ <t>117 117 166 81</t>
+ <t>118 118 166 90</t>
+ <t>119 127 166 81</t>
+ </trans_list>
+ </state>
+
+ <state id="168" final="t">
+ <state_actions>6 7 x</state_actions>
+ <trans_list length="47">
+ <t>-128 -1 168 91</t>
+ <t>0 0 168 92</t>
+ <t>1 8 168 91</t>
+ <t>9 9 169 x</t>
+ <t>10 10 168 93</t>
+ <t>11 12 168 91</t>
+ <t>13 13 169 x</t>
+ <t>14 31 168 91</t>
+ <t>32 32 169 x</t>
+ <t>33 33 168 91</t>
+ <t>34 34 170 12</t>
+ <t>35 35 172 12</t>
+ <t>36 36 173 x</t>
+ <t>37 37 174 x</t>
+ <t>38 38 168 91</t>
+ <t>39 39 175 12</t>
+ <t>40 41 168 91</t>
+ <t>42 42 176 x</t>
+ <t>43 44 168 91</t>
+ <t>45 45 177 x</t>
+ <t>46 46 178 x</t>
+ <t>47 47 168 94</t>
+ <t>48 48 179 12</t>
+ <t>49 57 180 x</t>
+ <t>58 58 182 x</t>
+ <t>59 59 168 91</t>
+ <t>60 60 184 x</t>
+ <t>61 61 168 91</t>
+ <t>62 62 186 x</t>
+ <t>63 63 168 91</t>
+ <t>64 64 187 x</t>
+ <t>65 90 188 95</t>
+ <t>91 91 189 x</t>
+ <t>92 94 168 91</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 91</t>
+ <t>97 100 188 95</t>
+ <t>101 101 190 x</t>
+ <t>102 102 193 x</t>
+ <t>103 107 188 95</t>
+ <t>108 108 196 x</t>
+ <t>109 115 188 95</t>
+ <t>116 116 199 x</t>
+ <t>117 118 188 95</t>
+ <t>119 119 200 x</t>
+ <t>120 122 188 95</t>
+ <t>123 127 168 91</t>
+ </trans_list>
+ </state>
+
+ <state id="169" final="t">
+ <trans_list length="7">
+ <t>-128 8 168 96</t>
+ <t>9 9 169 x</t>
+ <t>10 12 168 96</t>
+ <t>13 13 169 x</t>
+ <t>14 31 168 96</t>
+ <t>32 32 169 x</t>
+ <t>33 127 168 96</t>
+ </trans_list>
+ </state>
+
+ <state id="170" final="t">
+ <trans_list length="7">
+ <t>-128 9 4 x</t>
+ <t>10 10 4 1</t>
+ <t>11 33 4 x</t>
+ <t>34 34 171 x</t>
+ <t>35 91 4 x</t>
+ <t>92 92 5 x</t>
+ <t>93 127 4 x</t>
+ </trans_list>
+ </state>
+
+ <state id="171" final="t">
+ <trans_list length="3">
+ <t>-128 104 168 97</t>
+ <t>105 105 168 98</t>
+ <t>106 127 168 97</t>
+ </trans_list>
+ </state>
+
+ <state id="172" final="t">
+ <trans_list length="3">
+ <t>-128 9 6 x</t>
+ <t>10 10 168 4</t>
+ <t>11 127 6 x</t>
+ </trans_list>
+ </state>
+
+ <state id="173" final="t">
+ <trans_list length="13">
+ <t>-128 32 168 99</t>
+ <t>33 33 168 100</t>
+ <t>34 41 168 99</t>
+ <t>42 42 168 101</t>
+ <t>43 46 168 99</t>
+ <t>47 47 168 102</t>
+ <t>48 62 168 99</t>
+ <t>63 63 168 103</t>
+ <t>64 93 168 99</t>
+ <t>94 94 168 104</t>
+ <t>95 125 168 99</t>
+ <t>126 126 168 105</t>
+ <t>127 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="174" final="t">
+ <trans_list length="13">
+ <t>-128 32 168 99</t>
+ <t>33 33 168 106</t>
+ <t>34 41 168 99</t>
+ <t>42 42 168 107</t>
+ <t>43 46 168 99</t>
+ <t>47 47 168 108</t>
+ <t>48 62 168 99</t>
+ <t>63 63 168 109</t>
+ <t>64 93 168 99</t>
+ <t>94 94 168 110</t>
+ <t>95 125 168 99</t>
+ <t>126 126 168 111</t>
+ <t>127 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="175" final="t">
+ <trans_list length="7">
+ <t>-128 9 7 x</t>
+ <t>10 10 7 1</t>
+ <t>11 38 7 x</t>
+ <t>39 39 171 x</t>
+ <t>40 91 7 x</t>
+ <t>92 92 8 x</t>
+ <t>93 127 7 x</t>
+ </trans_list>
+ </state>
+
+ <state id="176" final="t">
+ <trans_list length="3">
+ <t>-128 41 168 99</t>
+ <t>42 42 168 112</t>
+ <t>43 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="177" final="t">
+ <trans_list length="5">
+ <t>-128 44 168 99</t>
+ <t>45 45 168 113</t>
+ <t>46 61 168 99</t>
+ <t>62 62 168 114</t>
+ <t>63 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="178" final="t">
+ <trans_list length="3">
+ <t>-128 45 168 99</t>
+ <t>46 46 168 115</t>
+ <t>47 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="179" final="t">
+ <trans_list length="5">
+ <t>-128 47 168 116</t>
+ <t>48 57 180 x</t>
+ <t>58 119 168 116</t>
+ <t>120 120 9 x</t>
+ <t>121 127 168 116</t>
+ </trans_list>
+ </state>
+
+ <state id="180" final="t">
+ <trans_list length="3">
+ <t>-128 47 168 116</t>
+ <t>48 57 180 x</t>
+ <t>58 127 168 116</t>
+ </trans_list>
+ </state>
+
+ <state id="181" final="t">
+ <trans_list length="7">
+ <t>-128 47 168 117</t>
+ <t>48 57 181 x</t>
+ <t>58 64 168 117</t>
+ <t>65 70 181 x</t>
+ <t>71 96 168 117</t>
+ <t>97 102 181 x</t>
+ <t>103 127 168 117</t>
+ </trans_list>
+ </state>
+
+ <state id="182" final="t">
+ <trans_list length="4">
+ <t>-128 60 168 99</t>
+ <t>61 61 168 118</t>
+ <t>62 62 183 x</t>
+ <t>63 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="183" final="t">
+ <trans_list length="3">
+ <t>-128 61 168 119</t>
+ <t>62 62 168 120</t>
+ <t>63 127 168 119</t>
+ </trans_list>
+ </state>
+
+ <state id="184" final="t">
+ <trans_list length="15">
+ <t>-128 32 168 99</t>
+ <t>33 33 168 121</t>
+ <t>34 41 168 99</t>
+ <t>42 42 168 122</t>
+ <t>43 46 168 99</t>
+ <t>47 47 168 123</t>
+ <t>48 57 168 99</t>
+ <t>58 58 168 124</t>
+ <t>59 61 168 99</t>
+ <t>62 62 185 x</t>
+ <t>63 93 168 99</t>
+ <t>94 94 168 125</t>
+ <t>95 125 168 99</t>
+ <t>126 126 168 126</t>
+ <t>127 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="185" final="t">
+ <trans_list length="11">
+ <t>-128 32 168 127</t>
+ <t>33 33 168 128</t>
+ <t>34 41 168 127</t>
+ <t>42 42 168 129</t>
+ <t>43 46 168 127</t>
+ <t>47 47 168 130</t>
+ <t>48 93 168 127</t>
+ <t>94 94 168 131</t>
+ <t>95 125 168 127</t>
+ <t>126 126 168 132</t>
+ <t>127 127 168 127</t>
+ </trans_list>
+ </state>
+
+ <state id="186" final="t">
+ <trans_list length="13">
+ <t>-128 32 168 99</t>
+ <t>33 33 168 133</t>
+ <t>34 41 168 99</t>
+ <t>42 42 168 134</t>
+ <t>43 46 168 99</t>
+ <t>47 47 168 135</t>
+ <t>48 62 168 99</t>
+ <t>63 63 168 136</t>
+ <t>64 93 168 99</t>
+ <t>94 94 168 137</t>
+ <t>95 125 168 99</t>
+ <t>126 126 168 138</t>
+ <t>127 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="187" final="t">
+ <trans_list length="11">
+ <t>-128 32 168 99</t>
+ <t>33 33 168 139</t>
+ <t>34 41 168 99</t>
+ <t>42 42 168 140</t>
+ <t>43 46 168 99</t>
+ <t>47 47 168 141</t>
+ <t>48 93 168 99</t>
+ <t>94 94 168 142</t>
+ <t>95 125 168 99</t>
+ <t>126 126 168 143</t>
+ <t>127 127 168 99</t>
+ </trans_list>
+ </state>
+
+ <state id="188" final="t">
+ <trans_list length="9">
+ <t>-128 47 168 144</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 144</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 144</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 144</t>
+ <t>97 122 188 95</t>
+ <t>123 127 168 144</t>
+ </trans_list>
+ </state>
+
+ <state id="189" final="t">
+ <trans_list length="3">
+ <t>-128 93 168 145</t>
+ <t>94 94 168 146</t>
+ <t>95 127 168 145</t>
+ </trans_list>
+ </state>
+
+ <state id="190" final="t">
+ <trans_list length="13">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 110 188 95</t>
+ <t>111 111 191 x</t>
+ <t>112 113 188 95</t>
+ <t>114 114 192 x</t>
+ <t>115 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="191" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 101 188 95</t>
+ <t>102 102 188 148</t>
+ <t>103 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="192" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 113 188 95</t>
+ <t>114 114 188 149</t>
+ <t>115 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="193" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 113 188 95</t>
+ <t>114 114 194 x</t>
+ <t>115 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="194" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 110 188 95</t>
+ <t>111 111 195 x</t>
+ <t>112 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="195" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 108 188 95</t>
+ <t>109 109 188 150</t>
+ <t>110 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="196" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 100 188 95</t>
+ <t>101 101 197 x</t>
+ <t>102 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="197" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 113 188 95</t>
+ <t>114 114 198 x</t>
+ <t>115 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="198" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 113 188 95</t>
+ <t>114 114 188 151</t>
+ <t>115 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="199" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 110 188 95</t>
+ <t>111 111 188 152</t>
+ <t>112 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="200" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 103 188 95</t>
+ <t>104 104 201 x</t>
+ <t>105 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="201" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 100 188 95</t>
+ <t>101 101 202 x</t>
+ <t>102 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="202" final="t">
+ <trans_list length="11">
+ <t>-128 47 168 147</t>
+ <t>48 57 188 95</t>
+ <t>58 64 168 147</t>
+ <t>65 90 188 95</t>
+ <t>91 94 168 147</t>
+ <t>95 95 188 95</t>
+ <t>96 96 168 147</t>
+ <t>97 109 188 95</t>
+ <t>110 110 188 153</t>
+ <t>111 122 188 95</t>
+ <t>123 127 168 147</t>
+ </trans_list>
+ </state>
+
+ <state id="203" final="t">
+ <state_actions>6 7 x</state_actions>
+ <trans_list length="8">
+ <t>-128 9 203 154</t>
+ <t>10 10 203 155</t>
+ <t>11 33 203 154</t>
+ <t>34 34 203 156</t>
+ <t>35 90 203 154</t>
+ <t>91 91 203 157</t>
+ <t>92 92 204 x</t>
+ <t>93 127 203 154</t>
+ </trans_list>
+ </state>
+
+ <state id="204" final="t">
+ <trans_list length="14">
+ <t>-128 96 203 158</t>
+ <t>97 97 203 159</t>
+ <t>98 98 203 160</t>
+ <t>99 101 203 158</t>
+ <t>102 102 203 161</t>
+ <t>103 109 203 158</t>
+ <t>110 110 203 162</t>
+ <t>111 113 203 158</t>
+ <t>114 114 203 163</t>
+ <t>115 115 203 158</t>
+ <t>116 116 203 164</t>
+ <t>117 117 203 158</t>
+ <t>118 118 203 165</t>
+ <t>119 127 203 158</t>
+ </trans_list>
+ </state>
+ </state_list>
+ </machine>
+</ragel_def>
+<ragel_def name="section_parse">
+ <alphtype>int</alphtype>
+ <machine>
+ <action_list length="5">
+ <action id="0" name="clear_words" line="97" col="21"><text> word = lit = 0; word_len = lit_len = 0; </text></action>
+ <action id="1" name="store_lit" line="98" col="19"><text> lit = tokdata; lit_len = toklen; </text></action>
+ <action id="2" name="incl_err" line="101" col="18"><text> scan_error() &lt;&lt; "bad include statement" &lt;&lt; endl; </text></action>
+ <action id="3" name="handle_include" line="105" col="2"><text>
+ #if 0
+ char *inclSectionName = word;
+ char *inclFileName = 0;
+
+ /* Implement defaults for the input file and section name. */
+ if ( inclSectionName == 0 )
+ inclSectionName = parser-&gt;sectionName;
+
+ if ( lit != 0 )
+ inclFileName = prepareFileName( lit, lit_len );
+ else
+ inclFileName = fileName;
+
+ /* Check for a recursive include structure. Add the current file/section
+ * name then check if what we are including is already in the stack. */
+ includeStack.append( IncludeStackItem( fileName, parser-&gt;sectionName ) );
+
+ if ( recursiveInclude( inclFileName, inclSectionName ) )
+ scan_error() &lt;&lt; "include: this is a recursive include operation" &lt;&lt; endl;
+ else {
+ /* Open the input file for reading. */
+ ifstream *inFile = new ifstream( inclFileName );
+ if ( ! inFile-&gt;is_open() ) {
+ scan_error() &lt;&lt; "include: could not open " &lt;&lt;
+ inclFileName &lt;&lt; " for reading" &lt;&lt; endl;
+ }
+
+ Scanner scanner( inclFileName, *inFile, output, parser,
+ inclSectionName, includeDepth+1 );
+ scanner.do_scan( );
+ delete inFile;
+ }
+
+ /* Remove the last element (len-1) */
+ includeStack.remove( -1 );
+ #endif
+ </text></action>
+ <action id="4" name="handle_token" line="152" col="2"><text>
+ InputLoc loc;
+
+ #ifdef PRINT_TOKENS
+ cerr &lt;&lt; "scanner:" &lt;&lt; line &lt;&lt; ":" &lt;&lt; column &lt;&lt;
+ ": sending token to the parser " &lt;&lt; Parser_lelNames[*p];
+ cerr &lt;&lt; " " &lt;&lt; toklen;
+ if ( tokdata != 0 )
+ cerr &lt;&lt; " " &lt;&lt; tokdata;
+ cerr &lt;&lt; endl;
+ #endif
+
+ loc.fileName = fileName;
+ loc.line = line;
+ loc.col = column;
+
+ parser-&gt;token( loc, type, tokdata, toklen );
+ </text></action>
+ </action_list>
+ <action_table_list length="4">
+ <action_table id="0" length="1">2</action_table>
+ <action_table id="1" length="2">0 1</action_table>
+ <action_table id="2" length="1">3</action_table>
+ <action_table id="3" length="1">4</action_table>
+ </action_table_list>
+ <start_state>3</start_state>
+ <error_state>0</error_state>
+ <entry_points>
+ <entry name="main">3</entry>
+ </entry_points>
+ <state_list length="4">
+ <state id="0">
+ <trans_list length="0">
+ </trans_list>
+ </state>
+
+ <state id="1">
+ <state_actions>x x 0</state_actions>
+ <trans_list length="3">
+ <t>-2147483648 131 x 0</t>
+ <t>132 132 2 1</t>
+ <t>133 2147483647 x 0</t>
+ </trans_list>
+ </state>
+
+ <state id="2">
+ <state_actions>x x 0</state_actions>
+ <trans_list length="3">
+ <t>-2147483648 58 x 0</t>
+ <t>59 59 3 2</t>
+ <t>60 2147483647 x 0</t>
+ </trans_list>
+ </state>
+
+ <state id="3" final="t">
+ <trans_list length="3">
+ <t>-2147483648 128 3 3</t>
+ <t>129 129 1 x</t>
+ <t>130 2147483647 3 3</t>
+ </trans_list>
+ </state>
+ </state_list>
+ </machine>
+</ragel_def>
+<host line="1" col="1">/*
+ * Copyright 2006-2007 Adrian Thurston &lt;thurston@complang.org&gt;
+ */
+
+/* This file is part of Ragel.
+ *
+ * Ragel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Ragel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Ragel; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include &lt;iostream&gt;
+#include &lt;fstream&gt;
+#include &lt;string.h&gt;
+
+#include "colm.h"
+#include "lmscan.h"
+#include "lmparse.h"
+#include "parsedata.h"
+#include "avltree.h"
+#include "vector.h"
+
+//#define PRINT_TOKENS
+
+using std::ifstream;
+using std::istream;
+using std::ostream;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+</host>
+<write def_name="section_parse" line="45" col="2"><arg>data</arg></write>
+<host line="46">
+
+void Scanner::sectionParseInit()
+{
+ </host>
+<write def_name="section_parse" line="50" col="5"><arg>init</arg></write>
+<host line="51">}
+
+ostream &amp;Scanner::scan_error()
+{
+ /* Maintain the error count. */
+ gblErrorCount += 1;
+ cerr &lt;&lt; fileName &lt;&lt; ":" &lt;&lt; line &lt;&lt; ":" &lt;&lt; column &lt;&lt; ": ";
+ return cerr;
+}
+
+bool Scanner::recursiveInclude( char *inclFileName, char *inclSectionName )
+{
+ for ( IncludeStack::Iter si = includeStack; si.lte(); si++ ) {
+ if ( strcmp( si-&gt;fileName, inclFileName ) == 0 &amp;&amp;
+ strcmp( si-&gt;sectionName, inclSectionName ) == 0 )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Scanner::updateCol()
+{
+ char *from = lastnl;
+ if ( from == 0 )
+ from = tokstart;
+ //cerr &lt;&lt; "adding " &lt;&lt; tokend - from &lt;&lt; " to column" &lt;&lt; endl;
+ column += tokend - from;
+ lastnl = 0;
+}
+
+void Scanner::token( int type, char c )
+{
+ token( type, &amp;c, &amp;c + 1 );
+}
+
+void Scanner::token( int type )
+{
+ token( type, 0, 0 );
+}
+
+</host>
+<host line="178">
+
+void Scanner::token( int type, char *start, char *end )
+{
+ char *tokdata = 0;
+ int toklen = 0;
+ int *p = &amp;type;
+ int *pe = &amp;type + 1;
+
+ if ( start != 0 ) {
+ toklen = end-start;
+ tokdata = new char[toklen+1];
+ memcpy( tokdata, start, toklen );
+ tokdata[toklen] = 0;
+ }
+
+ </host>
+<write def_name="section_parse" line="196" col="3"><arg>exec</arg></write>
+<host line="197">
+
+ updateCol();
+}
+
+void Scanner::endSection( )
+{
+ /* Execute the eof actions for the section parser. */
+ </host>
+<write def_name="section_parse" line="207" col="3"><arg>eof</arg></write>
+<host line="208">
+}
+
+</host>
+<host line="516">
+
+</host>
+<write def_name="rlscan" line="518" col="4"><arg>data</arg></write>
+<host line="519">
+void Scanner::do_scan()
+{
+ int bufsize = 8;
+ char *buf = new char[bufsize];
+ const char last_char = 0;
+ int cs, act, have = 0;
+ int top, stack[32];
+ bool execute = true;
+
+ sectionParseInit();
+ </host>
+<write def_name="rlscan" line="530" col="5"><arg>init</arg></write>
+<host line="531">
+ while ( execute ) {
+ char *p = buf + have;
+ int space = bufsize - have;
+
+ if ( space == 0 ) {
+ /* We filled up the buffer trying to scan a token. Grow it. */
+ bufsize = bufsize * 2;
+ char *newbuf = new char[bufsize];
+
+ /* Recompute p and space. */
+ p = newbuf + have;
+ space = bufsize - have;
+
+ /* Patch up pointers possibly in use. */
+ if ( tokstart != 0 )
+ tokstart = newbuf + ( tokstart - buf );
+ tokend = newbuf + ( tokend - buf );
+
+ /* Copy the new buffer in. */
+ memcpy( newbuf, buf, have );
+ delete[] buf;
+ buf = newbuf;
+ }
+
+ input.read( p, space );
+ int len = input.gcount();
+
+ /* If we see eof then append the EOF char. */
+ if ( len == 0 ) {
+ p[0] = last_char, len = 1;
+ execute = false;
+ }
+
+ char *pe = p + len;
+ </host>
+<write def_name="rlscan" line="566" col="6"><arg>exec</arg></write>
+<host line="567">
+ /* Check if we failed. */
+ if ( cs == rlscan_error ) {
+ /* Machine failed before finding a token. I'm not yet sure if this
+ * is reachable. */
+ scan_error() &lt;&lt; "scanner error" &lt;&lt; endl;
+ exit(1);
+ }
+
+ /* Decide if we need to preserve anything. */
+ char *preserve = tokstart;
+
+ /* Now set up the prefix. */
+ if ( preserve == 0 )
+ have = 0;
+ else {
+ /* There is data that needs to be shifted over. */
+ have = pe - preserve;
+ memmove( buf, preserve, have );
+ unsigned int shiftback = preserve - buf;
+ if ( tokstart != 0 )
+ tokstart -= shiftback;
+ tokend -= shiftback;
+
+ preserve = buf;
+ }
+ }
+ delete[] buf;
+
+ InputLoc loc;
+ loc.fileName = "&lt;EOF&gt;";
+ loc.line = line;
+ loc.col = 1;
+ parser-&gt;token( loc, _eof, 0, 0 );
+}
+
+void scan( char *fileName, istream &amp;input, ostream &amp;output )
+{
+ Scanner scanner( fileName, input, output, 0, 0, 0 );
+}
+</host>
+</ragel>
diff --git a/test/xml/xml.lm b/test/xml/xml.lm
new file mode 100644
index 00000000..803d4a5d
--- /dev/null
+++ b/test/xml/xml.lm
@@ -0,0 +1,168 @@
+#
+# Definitions
+#
+
+rl xml_digit / (0x30..0x39) /
+
+rl base_char / 0x41..0x5A | 0x61..0x7A /
+
+rl char / 0x9 | 0xA | 0xD | 0x20..0x7f /
+
+rl letter / base_char /
+
+rl name_char / letter | digit | '.' | '-' | '_' | ':' | 0xb7 /
+
+rl name / (letter | '_' | ':') name_char* /
+
+#
+# Reference definitions. These appear in the
+# top level and also in strings.
+#
+
+rl entity_ref_pat / '&' name ';' /
+
+rl char_ref_pat / '&#' [0-9]+ ';' | '&0x' [0-9a-fA-F]+ ';' /
+
+#
+# Single quotes.
+#
+lex sq
+{
+ token sq_close /'\''/
+
+ # References in single quotes
+ token sq_entity_ref /entity_ref_pat/
+ token sq_char_ref /char_ref_pat/
+
+ token sq_data / [^<&']+ /
+
+ def sq_item
+ [ sq_data ]
+ | [ sq_entity_ref ]
+ | [ sq_char_ref ]
+
+ # The opening quote belongs to the tag region.
+ def sq_string
+ [ '\'' sq_item* sq_close ]
+}
+
+#
+# Double quotes.
+#
+lex dq
+{
+ token dq_close /'"'/
+
+ # References in double quotes
+ token dq_entity_ref /entity_ref_pat/
+ token dq_char_ref /char_ref_pat/
+
+ token dq_data / [^<&"]+ /
+
+ def dq_item
+ [ dq_data ]
+ | [ dq_entity_ref ]
+ | [ dq_char_ref ]
+
+ # The opening quote belongs to the tag region.
+ def dq_string
+ [ '"' dq_item* dq_close ]
+}
+
+#
+# Tag elements.
+#
+lex tag
+{
+ literal '\'', '\"', '=', '\/', '>'
+
+ # Within this region whitespace is not significant.
+ ignore xml_space / (0x20 | 0x9 | 0xD | 0xA)+ /
+
+ #
+ # Attributes
+ #
+ token attr_name / name /
+}
+
+#
+# Top Level
+#
+lex start
+{
+ #
+ # Comments
+ #
+
+ # Cannot contain '--'
+ rl char_no_dash / char - '-' /
+ token comment / '<!--' ( char_no_dash | '-' char_no_dash )* '-->' /
+
+
+ # Opening a tag.
+ literal '<'
+
+ #
+ # Character Data
+ #
+
+ token cdata / '<![CDATA[' char* :> ']]>'/
+ token char_data / [^<&]+ /
+ token entity_ref /entity_ref_pat/
+ token char_ref /char_ref_pat/
+}
+
+
+def attribute_value
+ [ sq_string ]
+| [ dq_string ]
+
+def attribute
+ [ attr_name '=' attribute_value ]
+
+def empty_tag
+ [ '<' attr_name attribute* '/' '>' ]
+
+def close_tag
+ [ '<' '/' attr_name '>' ]
+
+def open_tag
+ [ '<' attr_name attribute* '>' ]
+
+def tag
+ [open_tag content close_tag]
+
+def content_item
+ [tag]
+| [empty_tag]
+| [char_data]
+| [entity_ref]
+| [char_ref]
+| [cdata]
+| [comment]
+
+def content
+ [content_item*]
+
+def document
+ [content]
+
+def start
+ [document]
+
+start S = parse start(stdin)
+
+for Switch:tag in S {
+ if match Switch
+ ["<lm_switch>" SwitchContent:content "</lm_switch>"]
+ {
+ print( 'SWITCH\n' )
+ for Text:tag in SwitchContent {
+ if match Text
+ ["<text>" TextContent:content "</text>"]
+ {
+ print( ' ', TextContent, '\n' )
+ }
+ }
+ }
+}
diff --git a/version.mk b/version.mk
new file mode 100644
index 00000000..8272a624
--- /dev/null
+++ b/version.mk
@@ -0,0 +1,2 @@
+VERSION = 0.1.0
+PUBDATE = June 2008