[llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/treecc/.cvsignore AUTHORS COPYING ChangeLog INSTALL Makefile NEWS README config.h context.c errors.c errors.h gen.c gen.h gen_c.c gen_cpp.c gen_cs.c gen_java.c gen_php.c gen_ruby.c info.h input.c input.h literal.c main.c node.c oper.c options.c options.h parse.c parse.h skeleton.c skels.c stream.c stream.h system.h

John Criswell criswell at cs.uiuc.edu
Tue Apr 6 12:54:04 PDT 2004


Changes in directory llvm/test/Programs/MultiSource/Applications/treecc:

.cvsignore added (r1.1)
AUTHORS added (r1.1)
COPYING added (r1.1)
ChangeLog added (r1.1)
INSTALL added (r1.1)
Makefile added (r1.1)
NEWS added (r1.1)
README added (r1.1)
config.h added (r1.1)
context.c added (r1.1)
errors.c added (r1.1)
errors.h added (r1.1)
gen.c added (r1.1)
gen.h added (r1.1)
gen_c.c added (r1.1)
gen_cpp.c added (r1.1)
gen_cs.c added (r1.1)
gen_java.c added (r1.1)
gen_php.c added (r1.1)
gen_ruby.c added (r1.1)
info.h added (r1.1)
input.c added (r1.1)
input.h added (r1.1)
literal.c added (r1.1)
main.c added (r1.1)
node.c added (r1.1)
oper.c added (r1.1)
options.c added (r1.1)
options.h added (r1.1)
parse.c added (r1.1)
parse.h added (r1.1)
skeleton.c added (r1.1)
skels.c added (r1.1)
stream.c added (r1.1)
stream.h added (r1.1)
system.h added (r1.1)

---
Log message:

Initial commit of treecc test program.



---
Diffs of the changes:  (+17512 -0)

Index: llvm/test/Programs/MultiSource/Applications/treecc/.cvsignore
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/.cvsignore:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/.cvsignore	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,13 ----
+ Makefile
+ Makefile.in
+ .deps
+ configure
+ config.log
+ config.cache
+ config.status
+ config.h
+ stamp-h
+ treecc
+ aclocal.m4
+ config.h.in
+ skels.c


Index: llvm/test/Programs/MultiSource/Applications/treecc/AUTHORS
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/AUTHORS:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/AUTHORS	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1 ----
+ Southern Storm Software, Pty Ltd


Index: llvm/test/Programs/MultiSource/Applications/treecc/COPYING
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/COPYING:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/COPYING	Tue Apr  6 12:53:30 2004
***************
*** 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.


Index: llvm/test/Programs/MultiSource/Applications/treecc/ChangeLog
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/ChangeLog:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/ChangeLog	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,378 ----
+ 
+ 2004-01-03  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* configure.in, NEWS: update version for the 0.2.8 release.
+ 
+ 2003-12-03  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* gen_c.c, tests/output15.out, tests/output7.out, tests/output8.out:
+ 	don't put a trailing comma on "enum" definitions, because strict ANSI
+ 	C compilers don't like them (thanks to Miroslaw Dobrzanski-Neumann).
+ 
+ 2003-11-20  Gopal.V  <gopalv82 at symonds.net>
+ 
+ 	* context.c, gen_cpp.c, gen_cs.c, gen_java.c, info.h, options.c,
+ 	doc/treecc.texi: add the "base_type" option.
+ 
+ 2003-07-17  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* configure.in, NEWS: update version for the 0.2.6 release.
+ 
+ 	* configure.in: update working version to "0.2.7".
+ 
+ 2003-07-05  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* gen_c.c, gen_cpp.c: fix some incorrect variable declarations
+ 	that gcc allowed through when it shouldn't have.
+ 
+ 2003-07-04  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* README: minor change to the treecc README file.
+ 
+ 	* Makefile.am, context.c, gen_c.c, gen_cpp.c, info.h, options.c,
+ 	doc/treecc.texi, etc/Makefile.am, etc/c_gc_skel.c, etc/c_gc_skel.h,
+ 	etc/cpp_gc_skel.cc, etc/cpp_gc_skel.h, tests/output17.out,
+ 	tests/output17.tst, tests/output18.out, tests/output18.tst,
+ 	tests/test_list: add the "gc_allocator" option to treecc,
+ 	to make the node allocator use libgc.
+ 
+ 2003-02-29  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* tests/output5.out, tests/output6.out, tests/output9.out:
+ 	update test output files for one of jeyk's fixes.
+ 
+ 	* configure.in, NEWS: update version for the 0.2.4 release.
+ 
+ 	* configure.in: update working version to "0.2.5".
+ 
+ 2003-02-29  Jeyasankar Kottalam  <jeyk at cox.net>
+ 
+ 	* gen_cpp.cpp, etc/cpp_skel.cc: add namespace support for C++;
+ 	fix a bug in the C++ skeleton.
+ 
+ 2003-02-08  Stephen Compall  <s11 at member.fsf.org>
+ 
+ 	* treecc.spec.in: Removed $PREFIX/share/treecc from the install
+ 	search-path.
+ 
+ 2003-02-08  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* NEWS, configure.in: update version for the "0.2.2" release.
+ 
+ 	* configure.in: update working version to "0.2.3".
+ 
+ 2003-01-29  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* context.c, gen_c.c, gen_cpp.c, info.h, options.c, doc/treecc.texi,
+ 	etc/cpp_skel.cc, tests/output5.out, tests/output6.out,
+ 	tests/output9.out: add the "allocator" and "no_allocator" options,
+ 	which allow treecc's C/C++ node allocators to be replaced with
+ 	third party node allocators.
+ 
+ 	* main.c, doc/treecc.1, doc/treecc.texi: add the "-O" option to
+ 	the treecc command-line, which allows "%option" commands to
+ 	be issued directly from the command-line.
+ 
+ 	* tests/.cvsignore, tests/Makefile.am, tests/normalize.c,
+ 	tests/run_tests: replace the reference to "sed" in "run_tests"
+ 	with "normalize", to work around problems with CRLF's under cygwin.
+ 
+ 2003-01-27  James Michael DuPont  <mdupont777 at yahoo.com>
+ 
+ 	* context.c, info.h, options.c, stream.c: add the "print_lines"
+ 	and "no_print_lines" options to suppress #line directives.
+ 
+ 2003-01-27  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* doc/treecc.texi: minor adjustment to direntry tag; only include
+ 	treecc once in the info directory.
+ 
+ 	* doc/treecc.texi: document the "print_lines" and "no_print_lines"
+ 	options.
+ 
+ 2003-01-26  Stephen Compall  <s11 at member.fsf.org>
+ 
+ 	* doc/treecc.texi: Added info dir entries.
+ 
+ 2003-01-15  Gopal.V  <gopalv82 at symonds.net>
+ 
+ 	* gen_php.c: Merge patch #942 for Php output and make a few cosmetic
+ 	changes to the file.
+ 
+ 2003-01-11  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* NEWS, configure.in: update version for the "0.2.0" release.
+ 
+ 	* configure.in: update working version to "0.2.1".
+ 
+ 2003-01-11  Alan Knowles  <alan at akbkhome.com>
+ 
+ 	* Makefile.am, gen.c, gen.h, gen_php.c, info.h, options.c:
+ 	add support for PHP output.
+ 
+ 2003-01-09  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* stream.c (TreeCCStreamCreate): copy the "force" flag from
+ 	the configuration settings into newly created streams.
+ 
+ 2002-12-31  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* gen_cs.c, gen_java.c, info.h, options.c, doc/treecc.texi,
+ 	tests/output16.out, tests/output16.tst, tests/test_list:
+ 	add the "internal_access" and "public_access" options, so that
+ 	treecc can output assembly-private node definitions.
+ 
+ 2002-12-21  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* configure.in: remove AC_PROG_CXX from configure.in, because it
+ 	isn't necessary any more since expr_cpp was disabled.
+ 
+ 2002-12-16  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* tests/run_tests: perform end of line conversion on the expected
+ 	test output files to prevent problems when diff'ing on MS-DOS systems.
+ 
+ 	* configure.in: don't use "-mno-cygwin" with "mingw32" compilers.
+ 
+ 2002-12-15  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* mkskel-sh, .cvsignore, Makefile.am, info.h, main.c, skeleton.c,
+ 	doc/treecc.1, doc/treecc.texi, etc/Makefile.am, tests/output1.out,
+ 	tests/output12.out, tests/output13.out, tests/output14.out,
+ 	tests/output15.out, tests/output2.out, tests/output3.out,
+ 	tests/output4.out, tests/output5.out, tests/output6.out,
+ 	tests/output7.out, tests/output8.out, tests/output9.out,
+ 	tests/test_output.c: bind the skeleton files into the "treecc"
+ 	binary so that we don't have any more skeleton path search problems.
+ 
+ 	* README, configure.in: always turn off cygwin builds under Win32.
+ 
+ 	* configure.in, config.guess, config.sub: set up for a canonical
+ 	build system, so that cygwin/mingw32 detection works correctly.
+ 
+ 	* Makefile.am, configure.in, examples/Makefile.am, tests/Makefile.am:
+ 	remove TREECC_DATA_DIR and clean up the -Wall handling for gcc.
+ 
+ 	* examples/Makefile.am: remove the unnecessary skeleton directory
+ 	specification.
+ 
+ 	* make-zip.sh, doc/binary_readme.txt: add the "make-zip.sh"
+ 	script, to assist with building a Win32 binary .zip file package.
+ 
+ 	* errors.c, main.c, examples/Makefile.am, examples/expr_c.tc,
+ 	tests/Makefile.am, tests/run_tests, tests/test_input.c,
+ 	tests/test_output.c, tests/test_parse.c: changes to support
+ 	out of tree builds properly.
+ 
+ 2002-11-24  Gopal V  <gopalv82 at symonds.net>
+ 	
+ 	* treecc.spec, configure.in, treecc.spec.in: Fix RPM builds
+ 
+ 2002-11-23  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* NEWS, configure.in: update version for the "0.1.8" release.
+ 
+ 	* configure.in: update working version to "0.1.9".
+ 
+ 2002-11-16  Peter Minten  <silvernerd at users.sf.net>
+ 
+ 	* doc/treecc.texi: Added Ruby output documentation.
+ 
+ 2002-11-09  Peter Minten  <silvernerd at users.sf.net>
+ 
+ 	* gen_ruby.c: Modified to create code compliant with Ruby markup
+ 	conventions, also some little bug fixes.
+ 	
+ 	* examples/expr_ruby.tc: Improved example.
+ 	
+ 	* stream.h, stream.c: Overloaded TreeCCStreamCodeIndent
+ 	to support languages that don't use tabs for indenting.
+ 	
+ 2002-11-05  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* NEWS, configure.in: update version for the "0.1.6" release.
+ 
+ 	* configure.in: update working version to "0.1.7".
+ 
+ 2002-11-03  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* doc/extending.txt, README: add a "quick and dirty" guide for
+ 	people who want to extend treecc with new output languages.
+ 
+ 2002-10-26  Peter Minten  <silvernerd at users.sf.net>
+ 
+ 	* Makefile.am, gen.c, gen.h, gen_ruby.c, info.h, options.c,
+ 	examples/README, examples/expr_ruby.tc: add Ruby code generation
+ 	support to treecc.
+ 
+ 2002-09-12  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* gen_cpp.c: extra comma where there shouldn't be in the
+ 	declaration of C++ virtual operations.
+ 
+ 2002-09-02  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* NEWS, configure.in: update version for the "0.1.4" release.
+ 
+ 	* configure.in: update working version to "0.1.5".
+ 
+ 2002-08-13  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* auto_gen.sh: slightly smarter script that also runs "aclocal".
+ 
+ 	* aclocal.m4, config.h.in, missing, examples/Makefile.am,
+ 	examples/ylwrap: update build system to automake 1.6, and remove
+ 	"expr_cpp" from the build because cygwin's automake is busted.
+ 
+ 	* auto_gen.sh, config.h.in: remove config.h.in from the CVS
+ 	tree and generate it from "auto_gen.sh" instead.
+ 
+ 2002-06-27  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* NEWS, configure.in: update version for the "0.1.2" release.
+ 
+ 	* configure.in: update working version to "0.1.3".
+ 
+ 2002-06-14  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* auto_gen.sh, configure.in: make the system more friendly to
+ 	automake 1.5 systems.
+ 
+ 	* tests/run_tests: work-around versions of "sed" that do not
+ 	recognise "-" to mean standard input.
+ 
+ 2002-05-27  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* tests/Makefile.am, examples/Makefile.am: patches from
+ 	Stephen Compall to support out of tree builds.
+ 
+ 2002-04-20  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* configure.in, NEWS: update version for the "0.1.0" release.
+ 
+ 	* configure.in: update the working version to "0.1.1".
+ 
+ 2002-04-01  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* configure.in, aclocal.m4: use "AM_MAINTAINER_MODE" in the
+ 	configure.in file to work around automake issues under Cygwin.
+ 
+ 	* conf_fix.sh, README: remove "conf_fix.sh", as we don't
+ 	need it any more with maintainer mode.
+ 
+ 	* auto_gen.sh: pass the "-a" option to "automake".
+ 
+ 2002-03-27  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* conf_fix.sh, README: add a configuration script that can be
+ 	used to get around problems with automake 1.5 under Cygwin.
+ 
+ 	* configure.in, NEWS: update version for the "0.0.8" release.
+ 
+ 	* configure.in: update the working version to "0.0.9".
+ 
+ 2002-03-23  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* doc/essay.html, README: add the treecc essay to the "doc"
+ 	subdirectory.
+ 
+ 2002-03-17  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* context.c, gen_c.c, gen_cpp.c, gen_cs.c, gen_java.c, info.h,
+ 	options.c, skeleton.c, stream.c, stream.h, doc/treecc.texi:
+ 	implement the "strip_filenames" option to make it more likely
+ 	that treecc will generate constant output files regardless of
+ 	which directory it is executed in.
+ 
+ 	* auto_gen.sh, README: add the "auto_gen.sh" script and some
+ 	instructions on its use.
+ 
+ 2002-03-05  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* doc/treecc.texi: polish the text a little.
+ 
+ 	* etc/cpp_skel.cc: declare the argument to "alloc" as "size_t",
+ 	to match the declaration in the common header file.
+ 
+ 	* tests/output5.out, tests/output6.out, tests/output9.out:
+ 	modify test output files to match the change to "etc/cpp_skel.cc".
+ 
+ 2002-01-10  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* configure.in, examples/Makefile.am: only build "expr_cpp" if
+ 	bison is being used, because it uses features that are not
+ 	compatible with byacc.
+ 
+ 2002-01-07  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* input.c: add ';' after a goto label for correct ANSI C syntax.
+ 
+ 2001-12-28  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* gen_c.c (ImplementCreateFuncs): insert a '*' into the return
+ 	cast when creating a singleton.
+ 
+ 	* context.c, gen_c.c, info.h, options.c, doc/treecc.texi:
+ 	add the options "kind_in_vtable" and "kind_in_node".
+ 
+ 	* skeleton.c (TreeCCIncludeSkeleton): replace all instances of
+ 	"yy" in a skeleton with "context->yy_replacement".
+ 
+ 	* tests/output12.out, tests/output12.tst, tests/output13.out,
+ 	tests/output13.tst, tests/output14.out, tests/output14.tst,
+ 	tests/test_list: add new tests for singletons, vtable kinds, and
+ 	"yy" replacement.
+ 
+ 	* ChangeLog: adjust the ChangeLog format to make it Emacs-friendly.
+ 
+ 	* gen.c, gen.h, gen_c.c, gen_java.c, info.h, input.c, input.h,
+ 	parse.c, doc/treecc.texi, tests/output15.out, tests/output15.tst,
+ 	tests/test_input.c, tests/test_list: implement the "%split" flag
+ 	for non-virtual operations to split large "switch" statements
+ 	across multiple functions.
+ 
+ 	* configure.in, NEWS: update the release version to 0.0.6.
+ 
+ 	* configure.in: change the version to "0.0.7" for the new working
+ 	version.
+ 
+ 2001-12-16  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* main.c: bug fix - create the default output files correctly;
+ 	defaults weren't working when the input didn't have "%output"
+ 	specified.
+ 
+ 2001-12-11  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* etc/c_skel.c, etc/cpp_skel.cc: swap the order of "data__" and
+ 	"next__" in "YYNODESTATE_block" so that the start of the
+ 	"data__" buffer will be properly aligned on 64-bit platforms.
+ 
+ 	* tests/output1.out, tests/output2.out, tests/output3.out,
+ 	tests/output4.out, tests/output5.out, tests/output6.out,
+ 	tests/output7.out, tests/output8.out, tests/output9.out:
+ 	new test output files that were affected by the skeleton change.
+ 
+ 2001-11-08  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* etc/c_skel.c, etc/cpp_skel.cc: update the C and C++ skeleton
+ 	files with an alignment algorithm that should work better on
+ 	platforms such as 64-bit Solaris.
+ 
+ 	* tests/output1.out, tests/output2.out, tests/output3.out,
+ 	tests/output4.out, tests/output5.out, tests/output6.out,
+ 	tests/output7.out, tests/output8.out, tests/output9.out:
+ 	new test output files that were affected by the skeleton change.
+ 
+ 	* doc/treecc.texi: insert a "@page" command to force the index to
+ 	be formatted correctly when PDF documentation is generated.
+ 
+ 	* configure.in, NEWS: version and news updates for the "0.0.4" release.
+ 
+ 	* configure.in: change the version to "0.0.5" for the new working
+ 	version.
+ 
+ 2001-08-14  Rhys Weatherley  <rweather at southern-storm.com.au>
+ 
+ 	* treecc.spec: applied patch submitted by mdaniel to create
+ 	RPM spec file.


Index: llvm/test/Programs/MultiSource/Applications/treecc/INSTALL
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/INSTALL:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/INSTALL	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,182 ----
+ Basic Installation
+ ==================
+ 
+    These are generic installation instructions.
+ 
+    The `configure' shell script attempts to guess correct values for
+ various system-dependent variables used during compilation.  It uses
+ those values to create a `Makefile' in each directory of the package.
+ It may also create one or more `.h' files containing system-dependent
+ definitions.  Finally, it creates a shell script `config.status' that
+ you can run in the future to recreate the current configuration, a file
+ `config.cache' that saves the results of its tests to speed up
+ reconfiguring, and a file `config.log' containing compiler output
+ (useful mainly for debugging `configure').
+ 
+    If you need to do unusual things to compile the package, please try
+ to figure out how `configure' could check whether to do them, and mail
+ diffs or instructions to the address given in the `README' so they can
+ be considered for the next release.  If at some point `config.cache'
+ contains results you don't want to keep, you may remove or edit it.
+ 
+    The file `configure.in' is used to create `configure' by a program
+ called `autoconf'.  You only need `configure.in' if you want to change
+ it or regenerate `configure' using a newer version of `autoconf'.
+ 
+ The simplest way to compile this package is:
+ 
+   1. `cd' to the directory containing the package's source code and type
+      `./configure' to configure the package for your system.  If you're
+      using `csh' on an old version of System V, you might need to type
+      `sh ./configure' instead to prevent `csh' from trying to execute
+      `configure' itself.
+ 
+      Running `configure' takes awhile.  While running, it prints some
+      messages telling which features it is checking for.
+ 
+   2. Type `make' to compile the package.
+ 
+   3. Optionally, type `make check' to run any self-tests that come with
+      the package.
+ 
+   4. Type `make install' to install the programs and any data files and
+      documentation.
+ 
+   5. You can remove the program binaries and object files from the
+      source code directory by typing `make clean'.  To also remove the
+      files that `configure' created (so you can compile the package for
+      a different kind of computer), type `make distclean'.  There is
+      also a `make maintainer-clean' target, but that is intended mainly
+      for the package's developers.  If you use it, you may have to get
+      all sorts of other programs in order to regenerate files that came
+      with the distribution.
+ 
+ Compilers and Options
+ =====================
+ 
+    Some systems require unusual options for compilation or linking that
+ the `configure' script does not know about.  You can give `configure'
+ initial values for variables by setting them in the environment.  Using
+ a Bourne-compatible shell, you can do that on the command line like
+ this:
+      CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+ 
+ Or on systems that have the `env' program, you can do it like this:
+      env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+ 
+ Compiling For Multiple Architectures
+ ====================================
+ 
+    You can compile the package for more than one kind of computer at the
+ same time, by placing the object files for each architecture in their
+ own directory.  To do this, you must use a version of `make' that
+ supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+ directory where you want the object files and executables to go and run
+ the `configure' script.  `configure' automatically checks for the
+ source code in the directory that `configure' is in and in `..'.
+ 
+    If you have to use a `make' that does not supports the `VPATH'
+ variable, you have to compile the package for one architecture at a time
+ in the source code directory.  After you have installed the package for
+ one architecture, use `make distclean' before reconfiguring for another
+ architecture.
+ 
+ Installation Names
+ ==================
+ 
+    By default, `make install' will install the package's files in
+ `/usr/local/bin', `/usr/local/man', etc.  You can specify an
+ installation prefix other than `/usr/local' by giving `configure' the
+ option `--prefix=PATH'.
+ 
+    You can specify separate installation prefixes for
+ architecture-specific files and architecture-independent files.  If you
+ give `configure' the option `--exec-prefix=PATH', the package will use
+ PATH as the prefix for installing programs and libraries.
+ Documentation and other data files will still use the regular prefix.
+ 
+    In addition, if you use an unusual directory layout you can give
+ options like `--bindir=PATH' to specify different values for particular
+ kinds of files.  Run `configure --help' for a list of the directories
+ you can set and what kinds of files go in them.
+ 
+    If the package supports it, you can cause programs to be installed
+ with an extra prefix or suffix on their names by giving `configure' the
+ option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+ 
+ Optional Features
+ =================
+ 
+    Some packages pay attention to `--enable-FEATURE' options to
+ `configure', where FEATURE indicates an optional part of the package.
+ They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+ is something like `gnu-as' or `x' (for the X Window System).  The
+ `README' should mention any `--enable-' and `--with-' options that the
+ package recognizes.
+ 
+    For packages that use the X Window System, `configure' can usually
+ find the X include and library files automatically, but if it doesn't,
+ you can use the `configure' options `--x-includes=DIR' and
+ `--x-libraries=DIR' to specify their locations.
+ 
+ Specifying the System Type
+ ==========================
+ 
+    There may be some features `configure' can not figure out
+ automatically, but needs to determine by the type of host the package
+ will run on.  Usually `configure' can figure that out, but if it prints
+ a message saying it can not guess the host type, give it the
+ `--host=TYPE' option.  TYPE can either be a short name for the system
+ type, such as `sun4', or a canonical name with three fields:
+      CPU-COMPANY-SYSTEM
+ 
+ See the file `config.sub' for the possible values of each field.  If
+ `config.sub' isn't included in this package, then this package doesn't
+ need to know the host type.
+ 
+    If you are building compiler tools for cross-compiling, you can also
+ use the `--target=TYPE' option to select the type of system they will
+ produce code for and the `--build=TYPE' option to select the type of
+ system on which you are compiling the package.
+ 
+ Sharing Defaults
+ ================
+ 
+    If you want to set default values for `configure' scripts to share,
+ you can create a site shell script called `config.site' that gives
+ default values for variables like `CC', `cache_file', and `prefix'.
+ `configure' looks for `PREFIX/share/config.site' if it exists, then
+ `PREFIX/etc/config.site' if it exists.  Or, you can set the
+ `CONFIG_SITE' environment variable to the location of the site script.
+ A warning: not all `configure' scripts look for a site script.
+ 
+ Operation Controls
+ ==================
+ 
+    `configure' recognizes the following options to control how it
+ operates.
+ 
+ `--cache-file=FILE'
+      Use and save the results of the tests in FILE instead of
+      `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+      debugging `configure'.
+ 
+ `--help'
+      Print a summary of the options to `configure', and exit.
+ 
+ `--quiet'
+ `--silent'
+ `-q'
+      Do not print messages saying which checks are being made.  To
+      suppress all normal output, redirect it to `/dev/null' (any error
+      messages will still be shown).
+ 
+ `--srcdir=DIR'
+      Look for the package's source code in directory DIR.  Usually
+      `configure' can determine that directory automatically.
+ 
+ `--version'
+      Print the version of Autoconf used to generate the `configure'
+      script, and exit.
+ 
+ `configure' also accepts some other, not widely useful, options.


Index: llvm/test/Programs/MultiSource/Applications/treecc/Makefile
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/Makefile:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/Makefile	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,6 ----
+ LEVEL = ../../../../..
+ PROG = treecc
+ #LDFLAGS += -lstdc++
+ #LIBS += -lstdc++
+ STDIN_FILENAME=$(BUILD_SRC_DIR)/tests/input3.tst
+ include ../../Makefile.multisrc


Index: llvm/test/Programs/MultiSource/Applications/treecc/NEWS
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/NEWS:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/NEWS	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,105 ----
+ 
+ 0.2.8 (3 January 2004)
+ 
+ 	* Add the "base_type" option (Gopal V).
+ 	* Don't put trailing commas on enums because strict ANSI C
+ 	  does not allow trailing commas (Miroslaw Dobrzanski-Neumann).
+ 
+ 0.2.6 (17 July 2003)
+ 
+ 	* Add the "gc_allocator" option, so that node allocation can be
+ 	  done using "libgc" if the programmer chooses to do so.
+ 	* Fix some non-ANSI variable declarations.
+ 
+ 0.2.4 (29 March 2003)
+ 
+ 	* Fixes to treecc.spec.in for RPM generation (Stephen Compall).
+ 	* Add support for namespaces in C++ (Jeyasankar Kottalam).
+ 	* Change "new.h" to "new" to comply with C++ standards
+ 	  (Jeyasankar Kottalam).
+ 	* Fix the return type of YYNODESTATE::dealloc (Jeyasankar Kottalam).
+ 
+ 0.2.2 (8 February 2003)
+ 
+ 	* PHP back-end patches (Alan Knowles).
+ 	* Add directory entries to texinfo documentation (Stephen Compall).
+ 	* "print_lines" and "no_print_lines" options (James Michael DuPont).
+ 	* "allocator" and "no_allocator" options.
+ 	* Permit treecc "%name" options to be set from the command-line.
+ 	* Replace "sed" with "normalize" in "run_tests", to work around
+ 	  problems on systems with CRLF end of line markers (e.g. cygwin.
+ 
+ 0.2.0 (11 January 2003)
+ 
+ 	* Bind the skeleton files directly into the "treecc" binary,
+ 	  to solve problems with locating the skeletons at runtime.
+ 	* Always disable cygwin for Win32 builds.
+ 	* Better support for out of tree builds.
+ 	* Fix up end of line handling in the test suite so that the
+ 	  tests don't fail because of CRLF vs LF issues.
+ 	* Add the "interal_access" and "public_access" options to
+ 	  support creating private libraries of nodes in C#.
+ 	* Fix the "-f" (force) command-line flag.
+ 	* PHP back-end (Alan Knowles).
+ 
+ 0.1.8 (23 November 2002)
+ 
+ 	* Bug fixes and documentation for Ruby back-end (Peter Minten).
+ 	* Support languages that don't use tabs for indenting (Peter Minten).
+ 
+ 0.1.6 (5 November 2002)
+ 
+ 	* Fix C++ code generation in the declaration of virtual operations.
+ 	* Add Ruby code generation (Peter Minten).
+ 	* "Quick and Dirty" guide to extending treecc to new languages.
+ 
+ 0.1.4 (2 September 2002)
+ 
+ 	* Fixes to "auto_gen.sh" and autoconf/automake support scripts
+ 	  to better support automake 1.6 systems.
+ 
+ 0.1.2 (27 June 2002)
+ 
+ 	* Add some patches to support out of tree builds (Stephen Compall).
+ 	* Make the build system more automake 1.5 friendly.
+ 	* Work around versions of "sed" that don't support "-" for stdin.
+ 
+ 0.1.0 (20 April 2002)
+ 
+ 	* Add maintainer mode to the autoconf system to work around
+ 	  autotools version problems.
+ 
+ 0.0.8 (27 March 2002)
+ 
+ 	* ANSI C compatiblity fixes.
+ 	* Only build "expr_cpp" if bison is being used because "byacc"
+ 	  does not understand the options used in the C++ grammar.
+ 	* Polish the Texinfo documentation a little.
+ 	* Fix the C++ skeleton to use "size_t" in the declaration of "alloc".
+ 	* Implement the "strip_filenames" option to improve the predictability
+ 	  of code generation in Portable.NET's C# compiler.
+ 	* Add the "auto_gen.sh" and "conf_fix.sh" scripts.
+ 	* Add the "essay.html" file to the documentation directory.
+ 
+ 0.0.6 (28 December 2001)
+ 
+ 	* Swap the order of some fields in "YYNODESTATE" to align nodes
+ 	  better on 64-bit platforms.
+ 	* Fix a bug which prevented treecc from creating default output
+ 	  files if "%output" and "%header" were missing from the source.
+ 	* Bug fix in the singleton code: missing '*' in return case.
+ 	* Add an option for kind values in either the node or the vtable.
+ 	  Vtable kinds can help reduce memory requirements.
+ 	* Bug fix to the skeleton expansion code: "yy" was not being
+ 	  properly expanded to the specified prefix.
+ 	* Implement the "%split" flag for non-virtual operations to split
+ 	  large "switch" statements across multiple functions.  This should
+ 	  help alleviate optimisation problems when compiling Portable.NET's
+ 	  C# compiler with GCC 3.0.
+ 
+ 0.0.4 (8 November 2001)
+ 
+ 	* Modify the skeleton files so that tree nodes are aligned correctly
+ 	  on 64-bit Solaris systems.
+ 	* Slight documentation and GNU-compliance updates.
+ 	* New version numbering scheme.


Index: llvm/test/Programs/MultiSource/Applications/treecc/README
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/README:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/README	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,77 ----
+ Tree Compiler-Compiler
+ ======================
+ 
+ The treecc program is designed to assist in the development of compilers
+ and other language-based tools.  It manages the generation of code to handle
+ abstract syntax trees and operations upon the trees.
+ 
+ A fuller account of why treecc exists and what it can be used for can
+ be found in the Texinfo documentation within the "doc" subdirectory,
+ and in the introductory article "doc/essay.html".
+ 
+ Downloading and Building
+ ------------------------
+ 
+ The latest version of treecc can be obtained from the following Web site:
+ 
+     http://www.southern-storm.com.au/treecc/
+ 
+ To build and install, unpack the ".tar.gz" file into a temporary directory
+ and execute the following commands:
+ 
+     $ ./configure
+ 	$ make all
+ 	$ make check
+ 	$ make install
+ 
+ The "make check" runs the treecc test suite to check for any problems
+ on your system.  Report any such problems to the authors, together with
+ a script of the failed test output.
+ 
+ If you obtained the treecc sources via CVS, you will need to run the
+ following before "./configure":
+ 
+ 	$ ./auto_gen.sh
+ 
+ If you wish to install treecc somewhere other than the default prefix
+ ("/usr/local"), use the following configuration command instead:
+ 
+     $ ./configure --prefix=PREFIX
+ 
+ where "PREFIX" is the full pathname of the directory where you want to
+ install the program.
+ 
+ If you want to add a new output language, see "doc/extending.txt".
+ 
+ Copyright Considerations
+ ------------------------
+ 
+ Treecc is distributed under the terms of the GNU General Public License.
+ A copy of this can be found in the "COPYING" file.
+ 
+ However, it is not our intention to restrict the use of treecc to only
+ free software providers.  Use by commercial software vendors is welcome.
+ 
+ When you use treecc on your own input files to generate source code as
+ output, the resulting source code files are also owned by you.  You may
+ re-distribute unmodified copies of these output source files, and any
+ binaries derived from them, in any way you see fit.
+ 
+ If you modify treecc itself, and generate new output files as a result,
+ then you must release all modifications to treecc with your program so
+ that other users can benefit from your changes under the terms of the GPL.
+ 
+ Contact the authors if you have any questions regarding the above.
+ It is our intention to allow the same amount of access to treecc output
+ files as is currently available using the GNU Bison and Flex programs.
+ 
+ Contacting the Authors
+ ----------------------
+ 
+ The authors can be contacted via e-mail at the following address:
+ 
+     treecc at southern-storm.com.au
+ 
+ Also check our Web site for updates to treecc:
+ 
+     http://www.southern-storm.com.au/treecc/


Index: llvm/test/Programs/MultiSource/Applications/treecc/config.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/config.h:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/config.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,72 ----
+ /* config.h.  Generated automatically by configure.  */
+ /* config.h.in.  Generated automatically from configure.in by autoheader.  */
+ 
+ /* Define to empty if the keyword does not work.  */
+ /* #undef const */
+ 
+ /* Define if you have the ANSI C header files.  */
+ #define STDC_HEADERS 1
+ 
+ /* Define if lex declares yytext as a char * by default, not a char[].  */
+ #define YYTEXT_POINTER 1
+ 
+ /* Define if you have the _vsnprintf function.  */
+ /* #undef HAVE__VSNPRINTF */
+ 
+ /* Define if you have the access function.  */
+ #define HAVE_ACCESS 1
+ 
+ /* Define if you have the memcmp function.  */
+ #define HAVE_MEMCMP 1
+ 
+ /* Define if you have the memcpy function.  */
+ #define HAVE_MEMCPY 1
+ 
+ /* Define if you have the qsort function.  */
+ #define HAVE_QSORT 1
+ 
+ /* Define if you have the stat function.  */
+ #define HAVE_STAT 1
+ 
+ /* Define if you have the strchr function.  */
+ #define HAVE_STRCHR 1
+ 
+ /* Define if you have the vfprintf function.  */
+ #define HAVE_VFPRINTF 1
+ 
+ /* Define if you have the vsnprintf function.  */
+ #define HAVE_VSNPRINTF 1
+ 
+ /* Define if you have the vsprintf function.  */
+ #define HAVE_VSPRINTF 1
+ 
+ /* Define if you have the <stdarg.h> header file.  */
+ #define HAVE_STDARG_H 1
+ 
+ /* Define if you have the <stdlib.h> header file.  */
+ #define HAVE_STDLIB_H 1
+ 
+ /* Define if you have the <string.h> header file.  */
+ #define HAVE_STRING_H 1
+ 
+ /* Define if you have the <strings.h> header file.  */
+ #define HAVE_STRINGS_H 1
+ 
+ /* Define if you have the <sys/stat.h> header file.  */
+ #define HAVE_SYS_STAT_H 1
+ 
+ /* Define if you have the <sys/types.h> header file.  */
+ #define HAVE_SYS_TYPES_H 1
+ 
+ /* Define if you have the <unistd.h> header file.  */
+ #define HAVE_UNISTD_H 1
+ 
+ /* Define if you have the <varargs.h> header file.  */
+ /* #undef HAVE_VARARGS_H */
+ 
+ /* Name of package */
+ #define PACKAGE "treecc"
+ 
+ /* Version number of package */
+ #define VERSION "0.2.8"
+ 


Index: llvm/test/Programs/MultiSource/Applications/treecc/context.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/context.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/context.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,111 ----
+ /*
+  * context.c - Create or destroy "treecc" parsing contexts.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ TreeCCContext *TreeCCContextCreate(TreeCCInput *input)
+ {
+ 	TreeCCContext *context;
+ 
+ 	/* Allocate space for the context */
+ 	if((context = (TreeCCContext *)calloc(1, sizeof(TreeCCContext))) == 0)
+ 	{
+ 		TreeCCOutOfMemory(input);
+ 	}
+ 
+ 	/* Initialize and return the context */
+ 	context->input = input;
+ 	context->debugMode = 0;
+ 	context->track_lines = 1;
+ 	context->no_singletons = 0;
+ 	context->reentrant = 0;
+ 	context->force = 0;
+ 	context->virtual_factory = 0;
+ 	context->abstract_factory = 0;
+ 	context->kind_in_vtable = 0;
+ 	context->strip_filenames = 0;
+ 	context->print_lines = 1;
+ 	context->internal_access = 0;
+ 	context->use_allocator = 1;
+ 	context->use_gc_allocator = 0;
+ 	context->yy_replacement = "yy";
+ 	context->state_type = "YYNODESTATE";
+ 	context->namespace = 0;
+ 	context->language = TREECC_LANG_C;
+ 	context->block_size = 0;
+ 	context->nodeNumber = 1;
+ 	context->baseType = 0;
+ 	return context;
+ }
+ 
+ void TreeCCContextDestroy(TreeCCContext *context)
+ {
+ 	unsigned int hash;
+ 	TreeCCNode *node, *nextNode;
+ 	TreeCCOperation *oper, *nextOper;
+ 	TreeCCStream *stream, *nextStream;
+ 
+ 	/* Close the source streams */
+ 	stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		nextStream = stream->nextStream;
+ 		TreeCCStreamDestroy(stream);
+ 		stream = nextStream;
+ 	}
+ 
+ 	/* Free the contents of the node hash */
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		node = context->nodeHash[hash];
+ 		while(node != 0)
+ 		{
+ 			nextNode = node->nextHash;
+ 			TreeCCNodeFree(node);
+ 			node = nextNode;
+ 		}
+ 	}
+ 
+ 	/* Free the contents of the operation hash */
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		oper = context->operHash[hash];
+ 		while(oper != 0)
+ 		{
+ 			nextOper = oper->nextHash;
+ 			TreeCCOperationFree(oper);
+ 			oper = nextOper;
+ 		}
+ 	}
+ 
+ 	/* Free the context block itself */
+ 	free(context);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/errors.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/errors.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/errors.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,124 ----
+ /*
+  * errors.c - Error and message reporting for "treecc".
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ FILE *TreeCCErrorFile = NULL;
+ int TreeCCErrorStripPath = 0;
+ 
+ static void ReportError(char *filename, long linenum,
+ 						const char *format, VA_LIST va)
+ {
+ 	if(!TreeCCErrorFile)
+ 	{
+ 		TreeCCErrorFile = stderr;
+ 	}
+ 	if(filename)
+ 	{
+ 		if(TreeCCErrorStripPath)
+ 		{
+ 			int len = strlen(filename);
+ 			while(len > 0 && filename[len - 1] != '/' &&
+ 				  filename[len - 1] != '\\')
+ 			{
+ 				--len;
+ 			}
+ 			filename += len;
+ 		}
+ 		fputs(filename, TreeCCErrorFile);
+ 		putc(':', TreeCCErrorFile);
+ 	}
+ 	fprintf(TreeCCErrorFile, "%ld: ", linenum);
+ #ifdef HAVE_VFPRINTF
+ 	vfprintf(TreeCCErrorFile, format, va);
+ #else
+ 	fputs(format, TreeCCErrorFile);
+ #endif
+ 	putc('\n', TreeCCErrorFile);
+ 	fflush(TreeCCErrorFile);
+ }
+ 
+ void TreeCCError(TreeCCInput *input, const char *format, ...)
+ {
+ 	VA_START;
+ 	ReportError((input ? input->filename : 0),
+ 				(input ? input->linenum : 0), format, VA_GET_LIST);
+ 	VA_END;
+ 	if(input)
+ 	{
+ 		input->errors = 1;
+ 	}
+ }
+ 
+ void TreeCCErrorOnLine(TreeCCInput *input, char *filename, long linenum,
+ 					   const char *format, ...)
+ {
+ 	VA_START;
+ 	ReportError(filename, linenum, format, VA_GET_LIST);
+ 	VA_END;
+ 	if(input)
+ 	{
+ 		input->errors = 1;
+ 	}
+ }
+ 
+ void TreeCCAbort(TreeCCInput *input, const char *format, ...)
+ {
+ 	VA_START;
+ 	ReportError((input ? input->filename : 0),
+ 				(input ? input->linenum : 0), format, VA_GET_LIST);
+ 	VA_END;
+ 	exit(1);
+ }
+ 
+ void TreeCCDebug(long linenum, const char *format, ...)
+ {
+ 	VA_START;
+ 	printf("line %ld: ", linenum);
+ #ifdef HAVE_VFPRINTF
+ 	vfprintf(stdout, format, VA_GET_LIST);
+ #else
+ 	fputs(format, stdout);
+ #endif
+ 	putc('\n', stdout);
+ 	VA_END;
+ 	fflush(stdout);
+ }
+ 
+ void TreeCCOutOfMemory(TreeCCInput *input)
+ {
+ 	if(input && input->progname)
+ 	{
+ 		fputs(input->progname, stderr);
+ 		fputs(": ", stderr);
+ 	}
+ 	fputs("virtual memory exhausted\n", stderr);
+ 	exit(1);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/errors.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/errors.h:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/errors.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,73 ----
+ /*
+  * errors.h - Error and message reporting for "treecc".
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_ERRORS_H
+ #define	_TREECC_ERRORS_H
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * If we are using GCC, then make it perform some extra
+  * error checking for printf-style formats.
+  */
+ #ifdef __GNUC__
+ 	#define	TREECC_ERRFMT(n,m)	\
+      	__attribute__ ((__format__ (__printf__, n, m)))
+ #else
+ 	#define	TREECC_ERRFMT(n,m)
+ #endif
+ 
+ /*
+  * Report an error on the current line of input.
+  */
+ void TreeCCError(TreeCCInput *input, const char *format, ...)
+ 			TREECC_ERRFMT(2, 3);
+ 
+ /*
+  * Report an error on a particular line of input.
+  */
+ void TreeCCErrorOnLine(TreeCCInput *input, char *filename, long linenum,
+ 					   const char *format, ...)
+ 			TREECC_ERRFMT(4, 5);
+ 
+ /*
+  * Report an error on the current line of input and abort.
+  */
+ void TreeCCAbort(TreeCCInput *input, const char *format, ...)
+ 			TREECC_ERRFMT(2, 3);
+ 
+ /*
+  * Print a debugging message.
+  */
+ void TreeCCDebug(long linenum, const char *format, ...)
+ 			TREECC_ERRFMT(2, 3);
+ 
+ /*
+  * Abort the program due to out of memory.
+  */
+ void TreeCCOutOfMemory(TreeCCInput *input);
+ 
+ #ifdef	__cplusplus
+ };
+ #endif
+ 
+ #endif	/* _TREECC_ERRORS_H */


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,664 ----
+ /*
+  * gen.c - Generate code to "treecc" output files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "gen.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ void TreeCCGenerate(TreeCCContext *context)
+ {
+ 	switch(context->language)
+ 	{
+ 		case TREECC_LANG_C:
+ 		{
+ 			TreeCCGenerateC(context);
+ 		}
+ 		break;
+ 
+ 		case TREECC_LANG_CPP:
+ 		{
+ 			TreeCCGenerateCPP(context);
+ 		}
+ 		break;
+ 
+ 		case TREECC_LANG_JAVA:
+ 		{
+ 			TreeCCGenerateJava(context);
+ 		}
+ 		break;
+ 
+ 		case TREECC_LANG_CSHARP:
+ 		{
+ 			TreeCCGenerateCSharp(context);
+ 		}
+ 		break;
+ 
+ 		case TREECC_LANG_RUBY:
+ 		{
+ 			TreeCCGenerateRuby(context);
+ 		}
+ 		break;
+ 
+ 		case TREECC_LANG_PHP:
+ 		{
+ 			TreeCCGeneratePHP(context);
+ 		}
+ 		break;
+ 
+ 	}
+ }
+ 
+ /*
+  * Generate selectors for one case of a "switch" statement.
+  */
+ static int GenerateSelectors(TreeCCContext *context, TreeCCStream *stream,
+ 							 const TreeCCNonVirtual *nonVirt, TreeCCNode *node,
+ 							 int markBit, int triggerNum)
+ {
+ 	/* If the mark bit is already set, then we've already handled this case */
+ 	if((node->flags & markBit) != 0)
+ 	{
+ 		return 0;
+ 	}
+ 
+ 	/* Mark the node as already visited */
+ 	node->flags |= markBit;
+ 
+ 	/* Generate a selector for this node */
+ 	(*(nonVirt->genSelector))(context, stream, node, triggerNum);
+ 
+ 	/* Generate selectors for the children */
+ 	node = node->firstChild;
+ 	while(node != 0)
+ 	{
+ 		GenerateSelectors(context, stream, nonVirt, node, markBit, triggerNum);
+ 		node = node->nextSibling;
+ 	}
+ 
+ 	/* We have done something non-trivial */
+ 	return 1;
+ }
+ 
+ /*
+  * Determine if the outer trigger levels of two operation cases match.
+  */
+ static int LevelsMatch(TreeCCOperationCase *operCase1,
+ 					   TreeCCOperationCase *operCase2,
+ 					   int triggerNum)
+ {
+ 	TreeCCTrigger *trigger1 = operCase1->triggers;
+ 	TreeCCTrigger *trigger2 = operCase2->triggers;
+ 	while(triggerNum > 0)
+ 	{
+ 		if(trigger1->node != trigger2->node)
+ 		{
+ 			return 0;
+ 		}
+ 		trigger1 = trigger1->next;
+ 		trigger2 = trigger2->next;
+ 	}
+ 	return 1;
+ }
+ 
+ /*
+  * Generate code for a "switch" on a trigger.
+  */
+ static TreeCCOperationCase *GenerateSwitch
+ 			(TreeCCContext *context, TreeCCStream *stream,
+ 			 const TreeCCNonVirtual *nonVirt, TreeCCOperation *oper,
+ 			 TreeCCOperationCase *operCase, int triggerNum)
+ {
+ 	TreeCCParam *param;
+ 	int num, markBit;
+ 	int paramNum;
+ 	TreeCCOperationCase *firstCase;
+ 	TreeCCTrigger *trigger;
+ 	TreeCCNode *node;
+ 	int isEnum;
+ 
+ 	/* Generate the head of the switch for this level */
+ 	param = oper->params;
+ 	num = 0;
+ 	paramNum = 1;
+ 	while(param != 0)
+ 	{
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(num == triggerNum)
+ 			{
+ 				break;
+ 			}
+ 			++num;
+ 		}
+ 		if(!(param->name))
+ 		{
+ 			++paramNum;
+ 		}
+ 		param = param->next;
+ 	}
+ 	if(!param)
+ 	{
+ 		/* Output the code for the case */
+ 		if((oper->flags & TREECC_OPER_INLINE) != 0)
+ 		{
+ 			(*(nonVirt->genCaseInline))(context, stream, operCase,
+ 										triggerNum - 1);
+ 		}
+ 		else
+ 		{
+ 			(*(nonVirt->genCaseCall))(context, stream, operCase,
+ 									  operCase->number, triggerNum - 1);
+ 		}
+ 		return operCase->next;
+ 	}
+ 	node = TreeCCNodeFindByType(context, param->type);
+ 	isEnum = ((node->flags & TREECC_NODE_ENUM) != 0);
+ 	if(param->name)
+ 	{
+ 		(*(nonVirt->genSwitchHead))(context, stream, param->name,
+ 								    triggerNum, isEnum);
+ 	}
+ 	else
+ 	{
+ 		char paramName[64];
+ 		sprintf(paramName, "P%d__", paramNum);
+ 		(*(nonVirt->genSwitchHead))(context, stream, paramName,
+ 									triggerNum, isEnum);
+ 	}
+ 
+ 	/* Recurse to handle the next-inner level of switch statements */
+ 	markBit = TREECC_NODE_MARK(triggerNum);
+ 	TreeCCNodeClearMarking(context, markBit);
+ 	firstCase = operCase;
+ 	do
+ 	{
+ 		/* Output the "case" statements to match this operation case */
+ 		trigger = operCase->triggers;
+ 		num = 0;
+ 		while(trigger != 0 && num < triggerNum)
+ 		{
+ 			++num;
+ 			trigger = trigger->next;
+ 		}
+ 		if(trigger)
+ 		{
+ 			if(!GenerateSelectors(context, stream, nonVirt,
+ 							      trigger->node, markBit, triggerNum))
+ 			{
+ 				/* We already output code for this with another case */
+ 				TreeCCErrorOnLine(context->input, operCase->filename,
+ 								  operCase->linenum,
+ 								  "this operation case duplicates another");
+ 			}
+ 		}
+ 		(*(nonVirt->genEndSelectors))(context, stream, triggerNum);
+ 
+ 		/* Generate the next level of "switch"'s */
+ 		operCase = GenerateSwitch(context, stream, nonVirt,
+ 								  oper, operCase, triggerNum + 1);
+ 
+ 		/* Terminate the "case" statement */
+ 		(*(nonVirt->genEndCase))(context, stream, triggerNum);
+ 	}
+ 	while(operCase != 0 && LevelsMatch(firstCase, operCase, triggerNum));
+ 
+ 	/* Generate the end of the switch for this level */
+ 	(*(nonVirt->genEndSwitch))(context, stream, triggerNum);
+ 
+ 	/* Return the next case to be handled to the caller */
+ 	return operCase;
+ }
+ 
+ /*
+  * Assign positions to the node types in a non-virtual operation.
+  */
+ static void AssignTriggerPosns(TreeCCContext *context, TreeCCOperation *oper)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCNode *type;
+ 	param = oper->params;
+ 	while(param != 0)
+ 	{
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			type = TreeCCNodeFindByType(context, param->type);
+ 			if(type)
+ 			{
+ 				TreeCCNodeAssignPositions(type);
+ 			}
+ 		}
+ 		param = param->next;
+ 	}
+ }
+ 
+ /*
+  * Forward declaration.
+  */
+ static void GenerateMultiSwitch(TreeCCContext *context,
+ 								TreeCCStream *stream,
+ 							    const TreeCCNonVirtual *nonVirt,
+ 								TreeCCOperation *oper,
+ 								TreeCCOperationCase **sortedCases,
+ 								int base, int multiplier,
+ 								TreeCCParam *nextParam,
+ 								int triggerNum);
+ 
+ /*
+  * Scan down the hierarchy to generate cases for a multi-trigger operation.
+  */
+ static void GenerateMultiScan(TreeCCContext *context,
+ 							  TreeCCStream *stream,
+ 						      const TreeCCNonVirtual *nonVirt,
+ 							  TreeCCOperation *oper,
+ 							  TreeCCOperationCase **sortedCases,
+ 							  int base, int multiplier,
+ 							  TreeCCParam *nextParam,
+ 							  int triggerNum,
+ 							  TreeCCNode *node)
+ {
+ 	/* Ignore abstract node types */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) == 0)
+ 	{
+ 		/* Generate a selector for this node */
+ 		(*(nonVirt->genSelector))(context, stream, node, triggerNum);
+ 		(*(nonVirt->genEndSelectors))(context, stream, triggerNum);
+ 
+ 		/* Go in one level for this node */
+ 		GenerateMultiSwitch(context, stream, nonVirt, oper, sortedCases,
+ 						    base + node->position * multiplier,
+ 					  		multiplier * nextParam->size, nextParam->next,
+ 					  	    triggerNum + 1);
+ 
+ 		/* Terminate the case for the above selector */
+ 		(*(nonVirt->genEndCase))(context, stream, triggerNum);
+ 	}
+ 
+ 	/* Scan all of the children */
+ 	node = node->firstChild;
+ 	while(node != 0)
+ 	{
+ 		GenerateMultiScan(context, stream, nonVirt, oper, sortedCases,
+ 						  base, multiplier, nextParam, triggerNum, node);
+ 		node = node->nextSibling;
+ 	}
+ }
+ 
+ /*
+  * Generate code for a "switch" on a multi-trigger operation.
+  */
+ static void GenerateMultiSwitch(TreeCCContext *context,
+ 								TreeCCStream *stream,
+ 							    const TreeCCNonVirtual *nonVirt,
+ 								TreeCCOperation *oper,
+ 								TreeCCOperationCase **sortedCases,
+ 								int base, int multiplier,
+ 								TreeCCParam *nextParam,
+ 								int triggerNum)
+ {
+ 	TreeCCNode *type;
+ 	int isEnum;
+ 
+ 	/* Scan for the next trigger parameter */
+ 	while(nextParam != 0 && (nextParam->flags & TREECC_PARAM_TRIGGER) == 0)
+ 	{
+ 		nextParam = nextParam->next;
+ 	}
+ 
+ 	/* If we are out of triggers, then we need to output the case code */
+ 	if(!nextParam)
+ 	{
+ 		if((oper->flags & TREECC_OPER_INLINE) != 0)
+ 		{
+ 			(*(nonVirt->genCaseInline))(context, stream, sortedCases[base],
+ 										triggerNum - 1);
+ 		}
+ 		else
+ 		{
+ 			(*(nonVirt->genCaseCall))(context, stream, sortedCases[base],
+ 									  sortedCases[base]->number,
+ 									  triggerNum - 1);
+ 		}
+ 		return;
+ 	}
+ 
+ 	/* Generate the head of the switch for this level */
+ 	type = TreeCCNodeFindByType(context, nextParam->type);
+ 	isEnum = ((type->flags & TREECC_NODE_ENUM) != 0);
+ 	if(nextParam->name)
+ 	{
+ 		(*(nonVirt->genSwitchHead))(context, stream, nextParam->name,
+ 								    triggerNum, isEnum);
+ 	}
+ 	else
+ 	{
+ 		char paramName[64];
+ 		int paramNum = 0;
+ 		TreeCCParam *param = oper->params;
+ 		while(param != 0 && param != nextParam)
+ 		{
+ 			if(!(param->name))
+ 			{
+ 				++paramNum;
+ 			}
+ 			param = param->next;
+ 		}
+ 		sprintf(paramName, "P%d__", paramNum);
+ 		(*(nonVirt->genSwitchHead))(context, stream, paramName,
+ 									triggerNum, isEnum);
+ 	}
+ 
+ 	/* Scan down the node type hierarchy for this trigger level */
+ 	GenerateMultiScan(context, stream, nonVirt, oper, sortedCases,
+ 					  base, multiplier, nextParam, triggerNum, type);
+ 
+ 	/* Generate the end of the switch for this level */
+ 	(*(nonVirt->genEndSwitch))(context, stream, triggerNum);
+ }
+ 
+ /*
+  * Forward declaration.
+  */
+ static void GenerateSplitMultiSwitch(TreeCCContext *context,
+ 								     TreeCCStream *stream,
+ 							         const TreeCCNonVirtual *nonVirt,
+ 								     TreeCCOperation *oper,
+ 								     TreeCCOperationCase **sortedCases,
+ 								     int base, int multiplier,
+ 								     TreeCCParam *nextParam,
+ 								     int triggerNum);
+ 
+ /*
+  * Scan down the hierarchy to generate cases for a multi-trigger operation
+  * that is split across multiple functions.
+  */
+ static void GenerateSplitMultiScan(TreeCCContext *context,
+ 							       TreeCCStream *stream,
+ 						           const TreeCCNonVirtual *nonVirt,
+ 							       TreeCCOperation *oper,
+ 							       TreeCCOperationCase **sortedCases,
+ 							       int base, int multiplier,
+ 							       TreeCCParam *nextParam,
+ 							       int triggerNum,
+ 							       TreeCCNode *node)
+ {
+ 	int number;
+ 
+ 	/* Ignore abstract node types */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) == 0)
+ 	{
+ 		/* Generate a selector for this node */
+ 		(*(nonVirt->genSelector))(context, stream, node, 0);
+ 		(*(nonVirt->genEndSelectors))(context, stream, 0);
+ 
+ 		/* Generate the code for the case */
+ 		number = base + node->position * multiplier;
+ 		if(triggerNum == (oper->numTriggers - 1))
+ 		{
+ 			/* We are at the inner-most level, so insert the case's code */
+ 			if((oper->flags & TREECC_OPER_INLINE) != 0)
+ 			{
+ 				(*(nonVirt->genCaseInline))(context, stream,
+ 											sortedCases[number], 0);
+ 			}
+ 			else
+ 			{
+ 				(*(nonVirt->genCaseCall))(context, stream,
+ 										  sortedCases[number],
+ 										  sortedCases[number]->number, 0);
+ 			}
+ 		}
+ 		else
+ 		{
+ 			/* Generate a call to a split function */
+ 			(*(nonVirt->genCaseSplit))(context, stream,
+ 									   sortedCases[number], number, 0);
+ 		}
+ 
+ 		/* Terminate the case for the above selector */
+ 		(*(nonVirt->genEndCase))(context, stream, 0);
+ 	}
+ 
+ 	/* Scan all of the children */
+ 	node = node->firstChild;
+ 	while(node != 0)
+ 	{
+ 		GenerateSplitMultiScan(context, stream, nonVirt, oper, sortedCases,
+ 						       base, multiplier, nextParam, triggerNum, node);
+ 		node = node->nextSibling;
+ 	}
+ }
+ 
+ /*
+  * Scan down the hierarchy to generate split functions for
+  * a multi-trigger operation.
+  */
+ static void GenerateSplitMultiScanFunc(TreeCCContext *context,
+ 							           TreeCCStream *stream,
+ 						               const TreeCCNonVirtual *nonVirt,
+ 							           TreeCCOperation *oper,
+ 							           TreeCCOperationCase **sortedCases,
+ 							           int base, int multiplier,
+ 							           TreeCCParam *nextParam,
+ 							           int triggerNum,
+ 							           TreeCCNode *node)
+ {
+ 	/* Ignore abstract node types */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) == 0)
+ 	{
+ 		/* Go in one level for this node */
+ 		GenerateSplitMultiSwitch(context, stream, nonVirt, oper, sortedCases,
+ 						         base + node->position * multiplier,
+ 					  		     multiplier * nextParam->size, nextParam->next,
+ 					  	         triggerNum + 1);
+ 	}
+ 
+ 	/* Scan all of the children */
+ 	node = node->firstChild;
+ 	while(node != 0)
+ 	{
+ 		GenerateSplitMultiScanFunc(context, stream, nonVirt, oper,
+ 								   sortedCases, base, multiplier,
+ 								   nextParam, triggerNum, node);
+ 		node = node->nextSibling;
+ 	}
+ }
+ 
+ /*
+  * Generate code for a "switch" on a multi-trigger operation
+  * that is split across multiple functions.
+  */
+ static void GenerateSplitMultiSwitch(TreeCCContext *context,
+ 								     TreeCCStream *stream,
+ 							         const TreeCCNonVirtual *nonVirt,
+ 								     TreeCCOperation *oper,
+ 								     TreeCCOperationCase **sortedCases,
+ 								     int base, int multiplier,
+ 								     TreeCCParam *nextParam,
+ 								     int triggerNum)
+ {
+ 	TreeCCNode *type;
+ 	int isEnum;
+ 
+ 	/* Scan for the next trigger parameter */
+ 	while(nextParam != 0 && (nextParam->flags & TREECC_PARAM_TRIGGER) == 0)
+ 	{
+ 		nextParam = nextParam->next;
+ 	}
+ 
+ 	/* Generate the next level of split functions */
+ 	type = TreeCCNodeFindByType(context, nextParam->type);
+ 	if(triggerNum != (oper->numTriggers - 1))
+ 	{
+ 		GenerateSplitMultiScanFunc
+ 			(context, stream, nonVirt, oper, sortedCases,
+ 		     base, multiplier, nextParam, triggerNum, type);
+ 	}
+ 
+ 	/* Output the entry point for this switch function */
+ 	if(triggerNum != 0)
+ 	{
+ 		(*(nonVirt->genSplitEntry))(context, stream, oper, base);
+ 	}
+ 	else
+ 	{
+ 		(*(nonVirt->genEntry))(context, stream, oper);
+ 	}
+ 
+ 	/* Generate the head of the switch for this level */
+ 	isEnum = ((type->flags & TREECC_NODE_ENUM) != 0);
+ 	if(nextParam->name)
+ 	{
+ 		(*(nonVirt->genSwitchHead))(context, stream, nextParam->name,
+ 								    0, isEnum);
+ 	}
+ 	else
+ 	{
+ 		char paramName[64];
+ 		int paramNum = 0;
+ 		TreeCCParam *param = oper->params;
+ 		while(param != 0 && param != nextParam)
+ 		{
+ 			if(!(param->name))
+ 			{
+ 				++paramNum;
+ 			}
+ 			param = param->next;
+ 		}
+ 		sprintf(paramName, "P%d__", paramNum);
+ 		(*(nonVirt->genSwitchHead))(context, stream, paramName, 0, isEnum);
+ 	}
+ 
+ 	/* Scan down the node type hierarchy for this trigger level */
+ 	GenerateSplitMultiScan(context, stream, nonVirt, oper, sortedCases,
+ 					       base, multiplier, nextParam, triggerNum, type);
+ 
+ 	/* Generate the end of the switch for this level */
+ 	(*(nonVirt->genEndSwitch))(context, stream, 0);
+ 
+ 	/* Generate the exit point for this switch function */
+ 	(*(nonVirt->genExit))(context, stream, oper);
+ }
+ 
+ /*
+  * Generate code for a specific non-virtual operation.
+  */
+ static void GenerateNonVirtual(TreeCCContext *context,
+ 							   const TreeCCNonVirtual *nonVirt,
+ 							   TreeCCOperation *oper)
+ {
+ 	TreeCCStream *stream;
+ 	TreeCCOperationCase *operCase;
+ 	int number;
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->language == TREECC_LANG_JAVA)
+ 	{
+ 		if(oper->className)
+ 		{
+ 			stream = TreeCCStreamGetJava(context, oper->className);
+ 		}
+ 		else
+ 		{
+ 			stream = TreeCCStreamGetJava(context, oper->name);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		stream = oper->source;
+ 	}
+ 
+ 	/* Output start declarations for the operation */
+ 	(*(nonVirt->genStart))(context, stream, oper);
+ 
+ 	/* If the operation is not inline, then output functions for all cases */
+ 	if((oper->flags & TREECC_OPER_INLINE) == 0)
+ 	{
+ 		number = 1;
+ 		operCase = oper->firstCase;
+ 		while(operCase != 0)
+ 		{
+ 			(*(nonVirt->genCaseFunc))(context, stream, operCase, number);
+ 			operCase->number = number++;
+ 			operCase = operCase->next;
+ 		}
+ 	}
+ 
+ 	/* Process split non-virtuals */
+ 	if(oper->numTriggers > 1 && (oper->flags & TREECC_OPER_SPLIT) != 0)
+ 	{
+ 		/* Split the switch statement over multiple levels of functions,
+ 		   so that no single function grows too large */
+ 		AssignTriggerPosns(context, oper);
+ 		GenerateSplitMultiSwitch(context, stream, nonVirt, oper,
+ 							     oper->sortedCases, 0, 1, oper->params, 0);
+ 		(*(nonVirt->genEnd))(context, stream, oper);
+ 		return;
+ 	}
+ 
+ 	/* Output the entry point for the operation */
+ 	(*(nonVirt->genEntry))(context, stream, oper);
+ 
+ 	/* Generate the switch statement for the outer-most level */
+ 	if(oper->numTriggers <= 1)
+ 	{
+ 		GenerateSwitch(context, stream, nonVirt, oper, oper->firstCase, 0);
+ 	}
+ 	else
+ 	{
+ 		AssignTriggerPosns(context, oper);
+ 		GenerateMultiSwitch(context, stream, nonVirt, oper,
+ 							oper->sortedCases, 0, 1, oper->params, 0);
+ 	}
+ 
+ 	/* Output the exit point for the operation */
+ 	(*(nonVirt->genExit))(context, stream, oper);
+ 
+ 	/* Output the end declarations for the operation */
+ 	(*(nonVirt->genEnd))(context, stream, oper);
+ }
+ 
+ void TreeCCGenerateNonVirtuals(TreeCCContext *context,
+ 							   const TreeCCNonVirtual *nonVirt)
+ {
+ 	unsigned int hash;
+ 	TreeCCOperation *oper;
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		oper = context->operHash[hash];
+ 		while(oper != 0)
+ 		{
+ 			if((oper->flags & TREECC_OPER_VIRTUAL) == 0)
+ 			{
+ 				GenerateNonVirtual(context, nonVirt, oper);
+ 			}
+ 			oper = oper->nextHash;
+ 		}
+ 	}
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen.h:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,127 ----
+ /*
+  * gen.h - Generate code to "treecc" output files.
+  *
+  * Copyright (C) 2001, 2002  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_GEN_H
+ #define	_TREECC_GEN_H
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Generate the source code output.
+  */
+ void TreeCCGenerate(TreeCCContext *context);
+ 
+ /*
+  * Generate the source code output for specific languages.
+  */
+ void TreeCCGenerateC(TreeCCContext *context);
+ void TreeCCGenerateCPP(TreeCCContext *context);
+ void TreeCCGenerateJava(TreeCCContext *context);
+ void TreeCCGenerateCSharp(TreeCCContext *context);
+ void TreeCCGenerateRuby(TreeCCContext *context);
+ void TreeCCGeneratePHP(TreeCCContext *context);
+ 
+ /*
+  * Control structure for generating the code for
+  * non-virtual operations.
+  */
+ typedef struct
+ {
+ 	/* Generate the start declarations for a non-virtual operation */
+ 	void (*genStart)(TreeCCContext *context, TreeCCStream *stream,
+ 					 TreeCCOperation *oper);
+ 
+ 	/* Generate the entry point for a non-virtual operation */
+ 	void (*genEntry)(TreeCCContext *context, TreeCCStream *stream,
+ 					 TreeCCOperation *oper);
+ 
+ 	/* Generate the entry point for a split-out function */
+ 	void (*genSplitEntry)(TreeCCContext *context, TreeCCStream *stream,
+ 					      TreeCCOperation *oper, int number);
+ 
+ 	/* Generate the head of a "switch" statement */
+ 	void (*genSwitchHead)(TreeCCContext *context, TreeCCStream *stream,
+ 						  char *paramName, int level, int isEnum);
+ 
+ 	/* Generate a selector for a "switch" case */
+ 	void (*genSelector)(TreeCCContext *context, TreeCCStream *stream,
+ 					    TreeCCNode *node, int level);
+ 
+ 	/* Terminate the selectors and begin the body of a "switch" case */
+ 	void (*genEndSelectors)(TreeCCContext *context, TreeCCStream *stream,
+ 						    int level);
+ 
+ 	/* Generate the code for a case within a function */
+ 	void (*genCaseFunc)(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCOperationCase *operCase, int number);
+ 
+ 	/* Generate a call to a case function from within the "switch" */
+ 	void (*genCaseCall)(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCOperationCase *operCase, int number, int level);
+ 
+ 	/* Generate the code for a case inline within the "switch" */
+ 	void (*genCaseInline)(TreeCCContext *context, TreeCCStream *stream,
+ 						  TreeCCOperationCase *operCase, int level);
+ 
+ 	/* Generate the code for a call to a split function within the "switch" */
+ 	void (*genCaseSplit)(TreeCCContext *context, TreeCCStream *stream,
+ 						 TreeCCOperationCase *operCase, int number, int level);
+ 
+ 	/* Terminate a "switch" case */
+ 	void (*genEndCase)(TreeCCContext *context, TreeCCStream *stream,
+ 					   int level);
+ 
+ 	/* Terminate the "switch" statement */
+ 	void (*genEndSwitch)(TreeCCContext *context, TreeCCStream *stream,
+ 						 int level);
+ 
+ 	/* Generate the exit point for a non-virtual operation */
+ 	void (*genExit)(TreeCCContext *context, TreeCCStream *stream,
+ 					TreeCCOperation *oper);
+ 
+ 	/* Generate the end declarations for a non-virtual operation */
+ 	void (*genEnd)(TreeCCContext *context, TreeCCStream *stream,
+ 				   TreeCCOperation *oper);
+ 
+ } TreeCCNonVirtual;
+ 
+ /*
+  * Generate the code for the non-virtual operations.
+  */
+ void TreeCCGenerateNonVirtuals(TreeCCContext *context,
+ 							   const TreeCCNonVirtual *nonVirt);
+ 
+ /*
+  * Common non-virtual operations that are used for C and C++.
+  */
+ extern TreeCCNonVirtual const TreeCCNonVirtualFuncsC;
+ 
+ /*
+  * Common non-virtual operations that are used for Java and C#.
+  */
+ extern TreeCCNonVirtual const TreeCCNonVirtualFuncsJava;
+ 
+ #ifdef	__cplusplus
+ };
+ #endif
+ 
+ #endif	/* _TREECC_GEN_H */


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen_c.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen_c.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen_c.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,1754 ----
+ /*
+  * gen_c.c - Generate C source code from "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "gen.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Define the node numbers.
+  */
+ static void DefineNodeNumbers(TreeCCContext *context,
+ 							  TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->header;
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) == 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_kind %d\n",
+ 						  node->name, node->number);
+ 	}
+ }
+ 
+ /*
+  * Declare the fields for a node type.
+  */
+ static void DeclareFields(TreeCCContext *context,
+ 						  TreeCCStream *stream, TreeCCNode *node)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		DeclareFields(context, stream, node->parent);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t%s %s;\n",
+ 						  field->type, field->name);
+ 		field = field->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the virtuals for a node type.
+  */
+ static void DeclareVirtuals(TreeCCContext *context,
+ 							TreeCCStream *stream, TreeCCNode *node)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	int num;
+ 	if(node->parent)
+ 	{
+ 		DeclareVirtuals(context, stream, node->parent);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t%s (*%s_v__)(%s *this__",
+ 						  virt->returnType, virt->name, node->name);
+ 		param = virt->params;
+ 		num = 1;
+ 		while(param != 0)
+ 		{
+ 			if(param->name)
+ 			{
+ 				TreeCCStreamPrint(stream, ", %s %s",
+ 								  param->type, param->name);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ", %s P%d__",
+ 								  param->type, num);
+ 				++num;
+ 			}
+ 			param = param->next;
+ 		}
+ 		TreeCCStreamPrint(stream, ");\n");
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the macros for calling the virtuals for a node type.
+  */
+ static void DeclareVirtualMacros(TreeCCContext *context,
+ 								 TreeCCStream *stream, TreeCCNode *node)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	int num;
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s(this__", virt->name);
+ 		param = virt->params;
+ 		num = 1;
+ 		while(param != 0)
+ 		{
+ 			if(param->name)
+ 			{
+ 				TreeCCStreamPrint(stream, ",%s", param->name);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ",P%d__", num);
+ 				++num;
+ 			}
+ 			param = param->next;
+ 		}
+ 		TreeCCStreamPrint(stream, ") \\\n");
+ 		TreeCCStreamPrint(stream,
+ 			"\t((*(((struct %s_vtable__ *)((this__)->vtable__))->%s_v__)) \\\n",
+ 			node->name, virt->name);
+ 		TreeCCStreamPrint(stream, "\t\t((%s *)(this__)", node->name);
+ 		param = virt->params;
+ 		num = 1;
+ 		while(param != 0)
+ 		{
+ 			if(param->name)
+ 			{
+ 				TreeCCStreamPrint(stream, ", (%s)", param->name);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ", (P%d__)", num);
+ 				++num;
+ 			}
+ 			param = param->next;
+ 		}
+ 		TreeCCStreamPrint(stream, "))\n\n");
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the type definitions for a node type.
+  */
+ static void DeclareTypeDefs(TreeCCContext *context,
+ 						    TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->header;
+ 	if((node->flags & TREECC_NODE_ENUM) != 0)
+ 	{
+ 		/* Define an enumerated type */
+ 		char const *sep = "\n";
+ 		TreeCCNode *child;
+ 		TreeCCStreamPrint(stream, "typedef enum {");
+ 		child = node->firstChild;
+ 		while(child != 0)
+ 		{
+ 			if((child->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "%s\t%s", sep, child->name);
+ 				sep = ",\n";
+ 			}
+ 			child = child->nextSibling;
+ 		}
+ 		TreeCCStreamPrint(stream, "\n} %s;\n\n", node->name);
+ 	}
+ 	else if((node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 	{
+ 		/* Define a regular node type */
+ 		TreeCCStreamPrint(stream, "typedef struct %s__ %s;\n",
+ 						  node->name, node->name);
+ 	}
+ }
+ 
+ /*
+  * Declare the virtual method implementation functions for a node type.
+  */
+ static int DeclareVirtualImpls(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	TreeCCOperation *oper;
+ 	int num;
+ 	int needComma;
+ 	int haveVirts = 0;
+ 	if(node->parent)
+ 	{
+ 		haveVirts = DeclareVirtualImpls(context, stream,
+ 										node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			/* We don't have a direct implementation in this class */
+ 			virt = virt->next;
+ 			continue;
+ 		}
+ 		TreeCCStreamPrint(stream, "extern %s %s_%s__(",
+ 						  virt->returnType, actualNode->name, virt->name);
+ 		oper = operCase->oper;
+ 		param = oper->params;
+ 		needComma = 0;
+ 		num = 1;
+ 		while(param != 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 				if(param->name)
+ 				{
+ 					TreeCCStreamPrint(stream, "%s %s",
+ 									  param->type, param->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "%s P%d__",
+ 									  param->type, num);
+ 					++num;
+ 				}
+ 			}
+ 			else
+ 			{
+ 				/* First argument must be declared with the actual type */
+ 				if(param->name)
+ 				{
+ 					TreeCCStreamPrint(stream, "%s *%s",
+ 									  actualNode->name, param->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "%s *P%d__",
+ 									  actualNode->name, num);
+ 					++num;
+ 				}
+ 			}
+ 			needComma = 1;
+ 			param = param->next;
+ 		}
+ 		TreeCCStreamPrint(stream, ");\n");
+ 		haveVirts = 1;
+ 		virt = virt->next;
+ 	}
+ 	return haveVirts;
+ }
+ 
+ /*
+  * Build the type declarations for a node type.
+  */
+ static void BuildTypeDecls(TreeCCContext *context,
+ 						   TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->header;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Output the structure header */
+ 	TreeCCStreamPrint(stream, "struct %s__ {\n", node->name);
+ 
+ 	/* Declare the vtable member variable */
+ 	TreeCCStreamPrint(stream, "\tconst struct %s_vtable__ *vtable__;\n",
+ 					  node->name);
+ 
+ 	/* Declare the node kind member variable */
+ 	if(!(context->kind_in_vtable))
+ 	{
+ 		TreeCCStreamPrint(stream, "\tint kind__;\n");
+ 	}
+ 
+ 	/* Declare the filename and linenum fields if we are tracking lines */
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tchar *filename__;\n");
+ 		TreeCCStreamPrint(stream, "\tlong linenum__;\n");
+ 	}
+ 
+ 	/* Declare the fields */
+ 	DeclareFields(context, stream, node);
+ 
+ 	/* Output the structure footer */
+ 	TreeCCStreamPrint(stream, "};\n\n");
+ 
+ 	/* Output the vtable type header */
+ 	TreeCCStreamPrint(stream, "struct %s_vtable__ {\n", node->name);
+ 
+ 	/* Declare standard vtable members */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tconst struct %s_vtable__ *parent__;\n",
+ 						  node->parent->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tconst void *parent__;\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "\tint kind__;\n");
+ 	TreeCCStreamPrint(stream, "\tconst char *name__;\n");
+ 
+ 	/* Declare the vtable function prototypes */
+ 	DeclareVirtuals(context, stream, node);
+ 
+ 	/* Output the vtable footer */
+ 	TreeCCStreamPrint(stream, "};\n\n");
+ 
+ 	/* Declare the actual vtable for this node type */
+ 	TreeCCStreamPrint(stream, "extern struct %s_vtable__ const %s_vt__;\n\n",
+ 					  node->name, node->name);
+ 
+ 	/* Declare the macros for calling the virtuals in this node type */
+ 	DeclareVirtualMacros(context, stream, node);
+ 
+ 	/* Declare the functions that implement all virtuals in this node type */
+ 	if(DeclareVirtualImpls(context, stream, node, node))
+ 	{
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ }
+ 
+ /*
+  * Output the parameters for a node creation function.
+  */
+ static int CreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParams(context, stream, node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s",
+ 							  field->type, field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Get the name of the "%typedef" type for a node.
+  */
+ static const char *TypedefName(TreeCCNode *node)
+ {
+ 	while(node->parent != 0 && (node->flags & TREECC_NODE_TYPEDEF) == 0)
+ 	{
+ 		node = node->parent;
+ 	}
+ 	return node->name;
+ }
+ 
+ /*
+  * Declare the prototypes for the node creation functions.
+  */
+ static void DeclareCreateFuncs(TreeCCContext *context,
+ 						  	   TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->header;
+ 	int needComma;
+ 
+ 	/* Don't need the create function if this node is abstract or enumerated */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0 ||
+ 	   (node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Output the return type and name */
+ 	TreeCCStreamPrint(stream, "extern %s *%s_create(",
+ 					  TypedefName(node), node->name);
+ 
+ 	/* Add the state type if building a re-entrant compiler */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 		needComma = 1;
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 
+ 	/* Output the field types and names as the create parameters */
+ 	needComma = CreateParams(context, stream, node, needComma);
+ 	if(!needComma)
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 
+ 	/* Terminate the declaration */
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Declare the prototypes for the non-virtual operations.
+  */
+ static void DeclareNonVirtuals(TreeCCContext *context,
+ 						  	   TreeCCOperation *oper)
+ {
+ 	TreeCCStream *stream = oper->header;
+ 	TreeCCParam *param;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Bail out if the operation is virtual */
+ 	if((oper->flags & TREECC_OPER_VIRTUAL) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Output the prototype */
+ 	TreeCCStreamPrint(stream, "extern %s %s(",
+ 					  oper->returnType, oper->name);
+ 	param = oper->params;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s %s",
+ 							  param->type, param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "%s P%d__",
+ 							  param->type, num);
+ 			++num;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	if(!needComma)
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Output helper macros to the header stream.
+  */
+ static void OutputHelpers(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->commonHeader)
+ 	{
+ 		stream = context->commonHeader;
+ 	}
+ 	else
+ 	{
+ 		stream = context->headerStream;
+ 	}
+ 
+ 	/* yykind macro */
+ 	TreeCCStreamPrint(stream, "#ifndef %skind\n", context->yy_replacement);
+ 	if(context->kind_in_vtable)
+ 	{
+ 		TreeCCStreamPrint(stream,
+ 				"#define %skind(node__) ((node__)->vtable__->kind__)\n",
+ 				context->yy_replacement);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream,
+ 				"#define %skind(node__) ((node__)->kind__)\n",
+ 				context->yy_replacement);
+ 	}
+ 	TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 	/* yykindname macro */
+ 	TreeCCStreamPrint(stream, "#ifndef %skindname\n", context->yy_replacement);
+ 	TreeCCStreamPrint(stream,
+ 			"#define %skindname(node__) ((node__)->vtable__->name__)\n",
+ 			context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 	/* yykindof macro */
+ 	TreeCCStreamPrint(stream, "#ifndef %skindof\n", context->yy_replacement);
+ 	TreeCCStreamPrint(stream,
+ 			"#define %skindof(type__) (type__##_kind)\n",
+ 			context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 	/* yyisa macro */
+ 	TreeCCStreamPrint(stream, "#ifndef %sisa\n", context->yy_replacement);
+ 	TreeCCStreamPrint(stream,
+ 			"extern int %sisa__(const void *vtable__, int kind__);\n",
+ 			context->yy_replacement);
+ 	TreeCCStreamPrint(stream,
+ 			"#define %sisa(node__,type__) \\\n",
+    			context->yy_replacement);
+ 	TreeCCStreamPrint(stream,
+ 		"\t(%sisa__((node__)->vtable__, (type__##_kind)))\n",
+ 		context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 	/* Are we tracking line numbers? */
+ 	if(context->track_lines)
+ 	{
+ 		/* yygetfilename macro */
+ 		TreeCCStreamPrint(stream,
+ 				"#ifndef %sgetfilename\n", context->yy_replacement);
+ 		TreeCCStreamPrint(stream,
+ 				"#define %sgetfilename(node__) ((node__)->filename__)\n",
+ 				context->yy_replacement);
+ 		TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 		/* yygetlinenum macro */
+ 		TreeCCStreamPrint(stream,
+ 				"#ifndef %sgetlinenum\n", context->yy_replacement);
+ 		TreeCCStreamPrint(stream,
+ 				"#define %sgetlinenum(node__) ((node__)->linenum__)\n",
+ 				context->yy_replacement);
+ 		TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 		/* yysetfilename macro */
+ 		TreeCCStreamPrint(stream,
+ 				"#ifndef %ssetfilename\n", context->yy_replacement);
+ 		TreeCCStreamPrint(stream,
+ 				"#define %ssetfilename(node__, value__) \\\n",
+ 				context->yy_replacement);
+ 		TreeCCStreamPrint(stream,
+ 				"\t((node__)->filename__ = (value__))\n");
+ 		TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 		/* yysetlinenum macro */
+ 		TreeCCStreamPrint(stream,
+ 				"#ifndef %ssetlinenum\n", context->yy_replacement);
+ 		TreeCCStreamPrint(stream,
+ 				"#define %ssetlinenum(node__, value__) \\\n",
+ 				context->yy_replacement);
+ 		TreeCCStreamPrint(stream,
+ 				"\t((node__)->linenum__ = (value__))\n");
+ 		TreeCCStreamPrint(stream, "#endif\n\n");
+ 
+ 		/* yycurrfilename and yycurrlinenum functions */
+ 		TreeCCStreamPrint(stream, "#ifndef %stracklines_declared\n",
+ 						  context->yy_replacement);
+ 		TreeCCStreamPrint(stream, "extern char *%scurrfilename(",
+ 						  context->yy_replacement);
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "void");
+ 		}
+ 		TreeCCStreamPrint(stream, ");\n");
+ 		TreeCCStreamPrint(stream, "extern long %scurrlinenum(",
+ 						  context->yy_replacement);
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "void");
+ 		}
+ 		TreeCCStreamPrint(stream, ");\n");
+ 		TreeCCStreamPrint(stream, "#define %stracklines_declared 1\n",
+ 						  context->yy_replacement);
+ 		TreeCCStreamPrint(stream, "#endif\n\n");
+ 	}
+ 
+ 	/* Declare the "yynodealloc", "yynodepush", "yynodepop", and
+ 	   "yynodeclear", and "yynodefailed" functions */
+ 	TreeCCStreamPrint(stream, "#ifndef %snodeops_declared\n",
+ 					  context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "extern void %snodeinit(",
+ 					  context->yy_replacement);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ 	TreeCCStreamPrint(stream, "extern void *%snodealloc(",
+ 					  context->yy_replacement);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__, ", context->state_type);
+ 	}
+ 	TreeCCStreamPrint(stream, "unsigned int size__");
+ 	TreeCCStreamPrint(stream, ");\n");
+ 	TreeCCStreamPrint(stream, "extern int %snodepush(",
+ 					  context->yy_replacement);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ 	TreeCCStreamPrint(stream, "extern void %snodepop(",
+ 					  context->yy_replacement);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ 	TreeCCStreamPrint(stream, "extern void %snodeclear(",
+ 					  context->yy_replacement);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ 	TreeCCStreamPrint(stream, "extern void %snodefailed(",
+ 					  context->yy_replacement);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ 	TreeCCStreamPrint(stream, "#define %snodeops_declared 1\n",
+ 					  context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "#endif\n\n");
+ }
+ 
+ /*
+  * Output the vtable function implementations for a node type.
+  */
+ static void OutputVtableImpls(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	TreeCCOperation *oper;
+ 	int num;
+ 	int needComma;
+ 	if(node->parent)
+ 	{
+ 		OutputVtableImpls(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			/* We don't have a direct implementation in this class */
+ 			virt = virt->next;
+ 			continue;
+ 		}
+ 		TreeCCStreamPrint(stream, "%s %s_%s__(",
+ 						  virt->returnType, actualNode->name, virt->name);
+ 		oper = operCase->oper;
+ 		param = oper->params;
+ 		needComma = 0;
+ 		num = 1;
+ 		while(param != 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			if(!needComma)
+ 			{
+ 				/* First argument must be declared with the actual type */
+ 				if(param->name)
+ 				{
+ 					TreeCCStreamPrint(stream, "%s *%s",
+ 									  actualNode->name, param->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "%s *P%d__",
+ 									  actualNode->name, num);
+ 					++num;
+ 				}
+ 			}
+ 			else
+ 			{
+ 				if(param->name)
+ 				{
+ 					TreeCCStreamPrint(stream, "%s %s",
+ 									  param->type, param->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "%s P%d__",
+ 									  param->type, num);
+ 					++num;
+ 				}
+ 			}
+ 			needComma = 1;
+ 			param = param->next;
+ 		}
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		TreeCCStreamLine(stream, operCase->codeLinenum, operCase->codeFilename);
+ 		TreeCCStreamPrint(stream, "{");
+ 		TreeCCStreamCode(stream, operCase->code);
+ 		TreeCCStreamPrint(stream, "}\n");
+ 		TreeCCStreamFixLine(stream);
+ 		TreeCCStreamPrint(stream, "\n");
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Output the vtable function references for a node type.
+  */
+ static void OutputVtableFuncs(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	TreeCCNode *parent;
+ 	int num;
+ 	if(node->parent)
+ 	{
+ 		OutputVtableFuncs(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t(%s (*)(%s *this__",
+ 						  virt->returnType, node->name);
+ 		param = virt->params;
+ 		num = 1;
+ 		while(param != 0)
+ 		{
+ 			if(param->name)
+ 			{
+ 				TreeCCStreamPrint(stream, ", %s %s",
+ 							      param->type, param->name);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ", %s P%d__",
+ 							 	  param->type, num);
+ 				++num;
+ 			}
+ 			param = param->next;
+ 		}
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		parent = actualNode;
+ 		while(!operCase)
+ 		{
+ 			parent = parent->parent;
+ 			if(!parent)
+ 			{
+ 				break;
+ 			}
+ 			operCase = TreeCCOperationFindCase(context, parent, virt->name);
+ 		}
+ 		if(operCase)
+ 		{
+ 			/* We are inheriting the implementation from "parent" */
+ 			TreeCCStreamPrint(stream, "))%s_%s__,\n",
+ 							  parent->name, virt->name);
+ 		}
+ 		else
+ 		{
+ 			/* No implementation for the method at all */
+ 			TreeCCStreamPrint(stream, "))0,\n");
+ 		}
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Define a vtable for a node type.
+  */
+ static void DefineVtables(TreeCCContext *context,
+ 						  TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->source;
+ 
+ 	/* Ignore this node if it is an enumerated type */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Output the implementations of the node vtable functions */
+ 	OutputVtableImpls(context, stream, node, node);
+ 
+ 	/* Output the vtable header */
+ 	TreeCCStreamPrint(stream, "struct %s_vtable__ const %s_vt__ = {\n",
+ 					  node->name, node->name);
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t&%s_vt__,\n", node->parent->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\t0,\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "\t%s_kind,\n", node->name);
+ 	TreeCCStreamPrint(stream, "\t\"%s\",\n", node->name);
+ 
+ 	/* Output the function references */
+ 	OutputVtableFuncs(context, stream, node, node);
+ 
+ 	/* Output the vtable footer */
+ 	TreeCCStreamPrint(stream, "};\n\n");
+ }
+ 
+ /*
+  * Output a create function parameter list to the source stream.
+  */
+ static int CreateParamsSource(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParamsSource(context, stream,
+ 									   node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s", field->type, field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Initialize a node's fields within a create function.
+  */
+ static void InitFields(TreeCCContext *context, TreeCCStream *stream,
+ 					   TreeCCNode *node)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		InitFields(context, stream, node->parent);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tnode__->%s = %s;\n",
+ 							  field->name, field->name);
+ 		}
+ 		else if(field->value)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tnode__->%s = %s;\n",
+ 							  field->name, field->value);
+ 		}
+ 		field = field->next;
+ 	}
+ }
+ 
+ /*
+  * Implement a create function for a node type.
+  */
+ static void ImplementCreateFuncs(TreeCCContext *context,
+ 						  		 TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->source;
+ 	const char *typedefName;
+ 	int needComma;
+ 
+ 	/* Ignore this node if it is an enumerated type */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Don't need a create function if this node type is abstract */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Find the name of the "%typedef" node type for this node */
+ 	typedefName = TypedefName(node);
+ 
+ 	/* Output the create function header */
+ 	TreeCCStreamPrint(stream, "%s *%s_create(", typedefName, node->name);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 		needComma = 1;
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 	needComma = CreateParamsSource(context, stream, node, needComma);
+ 	if(!needComma)
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 	TreeCCStreamPrint(stream, "{\n");
+ 
+ 	/* Is the node type a singleton? */
+ 	if(!(context->track_lines) && !(context->no_singletons) &&
+ 	   TreeCCNodeIsSingleton(node))
+ 	{
+ 		/* This node type is a singleton, so create
+ 		   a static node instance and always return it */
+ 		TreeCCStreamPrint(stream, "\tstatic struct %s__ instance__ = {\n",
+ 						  node->name);
+ 		TreeCCStreamPrint(stream, "\t\t&%s_vt__,\n", node->name);
+ 		if(!(context->kind_in_vtable))
+ 		{
+ 			TreeCCStreamPrint(stream, "\t\t%s_kind\n", node->name);
+ 		}
+ 		TreeCCStreamPrint(stream, "\t};\n");
+ 		TreeCCStreamPrint(stream, "\treturn (%s *)&instance__;\n",
+ 						  typedefName);
+ 	}
+ 	else
+ 	{
+ 		/* Non-singleton node type */
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 			  "\t%s *node__ = (%s *)%snodealloc(state__, "
+ 			  			"sizeof(struct %s__));\n",
+ 				node->name, node->name, context->yy_replacement, node->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 				"\t%s *node__ = (%s *)%snodealloc(sizeof(struct %s__));\n",
+ 				node->name, node->name, context->yy_replacement, node->name);
+ 		}
+ 
+ 		/* Bail out to the caller if "yynodealloc" returned NULL */
+ 		TreeCCStreamPrint(stream, "\tif(node__ == 0) return 0;\n");
+ 
+ 		/* Set the vtable and kind */
+ 		TreeCCStreamPrint(stream, "\tnode__->vtable__ = &%s_vt__;\n",
+ 						  node->name);
+ 		if(!(context->kind_in_vtable))
+ 		{
+ 			TreeCCStreamPrint(stream, "\tnode__->kind__ = %s_kind;\n",
+ 							  node->name);
+ 		}
+ 
+ 		/* Track the filename and line number if necessary */
+ 		if(context->track_lines)
+ 		{
+ 			if(context->reentrant)
+ 			{
+ 				TreeCCStreamPrint(stream,
+ 						"\tnode__->filename__ = %scurrfilename(state__);\n",
+ 						context->yy_replacement);
+ 				TreeCCStreamPrint(stream,
+ 						"\tnode__->linenum__ = %scurrlinenum(state__);\n",
+ 						context->yy_replacement);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream,
+ 						"\tnode__->filename__ = %scurrfilename();\n",
+ 						context->yy_replacement);
+ 				TreeCCStreamPrint(stream,
+ 						"\tnode__->linenum__ = %scurrlinenum();\n",
+ 						context->yy_replacement);
+ 			}
+ 		}
+ 
+ 		/* Initialize the fields */
+ 		InitFields(context, stream, node);
+ 
+ 		/* Return the node to the caller */
+ 		TreeCCStreamPrint(stream, "\treturn (%s *)node__;\n", typedefName);
+ 	}
+ 
+ 	/* Output the create function footer */
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Output the source code for the "yyisa__" helper function.
+  */
+ static void OutputIsA(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->commonSource)
+ 	{
+ 		stream = context->commonSource;
+ 	}
+ 	else
+ 	{
+ 		stream = context->sourceStream;
+ 	}
+ 
+ 	/* Declare a helper structure for walking vtable types */
+ 	TreeCCStreamPrint(stream, "struct %s_vtable__ {\n",
+ 					  context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "\tconst struct %s_vtable__ *parent__;\n",
+ 					  context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "\tint kind__;\n");
+ 	TreeCCStreamPrint(stream, "};\n\n");
+ 
+ 	/* Output the function header */
+ 	TreeCCStreamPrint(stream,
+ 		"int %sisa__(const void *vtable__, int kind__)\n",
+ 		context->yy_replacement);
+ 
+ 	/* Output the body of the function */
+ 	TreeCCStreamPrint(stream, "{\n");
+ 	TreeCCStreamPrint(stream, "\tconst struct %s_vtable__ *vt;\n",
+ 					  context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "\tvt = (const struct %s_vtable__ *)vtable__;\n",
+ 					  context->yy_replacement);
+ 	TreeCCStreamPrint(stream, "\twhile(vt != 0) {\n");
+ 	TreeCCStreamPrint(stream, "\t\tif(vt->kind__ == kind__)\n");
+ 	TreeCCStreamPrint(stream, "\t\t\treturn 1;\n");
+ 	TreeCCStreamPrint(stream, "\t\tvt = vt->parent__;\n");
+ 	TreeCCStreamPrint(stream, "\t}\n");
+ 	TreeCCStreamPrint(stream, "\treturn 0;\n");
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Determine if a type name corresponds to an enumerated type.
+  */
+ static int IsEnumType(TreeCCContext *context, const char *type)
+ {
+ 	TreeCCNode *node = TreeCCNodeFindByType(context, type);
+ 	if(node)
+ 	{
+ 		if((node->flags & TREECC_NODE_ENUM) != 0)
+ 		{
+ 			return 1;
+ 		}
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * Generate the start declarations for a non-virtual operation.
+  */
+ static void C_GenStart(TreeCCContext *context, TreeCCStream *stream,
+ 					   TreeCCOperation *oper)
+ {
+ 	/* Nothing to do here for C and C++ */
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void CGenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					  TreeCCOperation *oper, int number)
+ {
+ 	TreeCCParam *param;
+ 	int num;
+ 	int needComma;
+ 	if(number != -1)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s %s_split_%d__(",
+ 						  oper->returnType, oper->name, number);
+ 	}
+ 	else if(context->language == TREECC_LANG_C || !(oper->className))
+ 	{
+ 		TreeCCStreamPrint(stream, "%s %s(",
+ 						  oper->returnType, oper->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "%s %s::%s(",
+ 						  oper->returnType, oper->className, oper->name);
+ 	}
+ 	param = oper->params;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		TreeCCStreamPrint(stream, "%s ", param->type);
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(!IsEnumType(context, param->type))
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	if(!needComma)
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 	TreeCCStreamPrint(stream, "{\n");
+ }
+ 
+ /*
+  * Generate the entry point for a split-out function.
+  */
+ static void C_GenSplitEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					        TreeCCOperation *oper, int number)
+ {
+ 	CGenEntry(context, stream, oper, number);
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void C_GenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					   TreeCCOperation *oper)
+ {
+ 	CGenEntry(context, stream, oper, -1);
+ }
+ 
+ /*
+  * Output TAB's for a specific level of indenting.
+  */
+ static void Indent(TreeCCStream *stream, int indent)
+ {
+ 	while(indent >= 4)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\t\t");
+ 		indent -= 4;
+ 	}
+ 	if(indent == 1)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t");
+ 	}
+ 	else if(indent == 2)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t");
+ 	}
+ 	else if(indent == 3)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\t");
+ 	}
+ }
+ 
+ /*
+  * Generate the head of a "switch" statement.
+  */
+ static void C_GenSwitchHead(TreeCCContext *context, TreeCCStream *stream,
+ 							char *paramName, int level, int isEnum)
+ {
+ 	Indent(stream, level * 2 + 1);
+ 	if(isEnum)
+ 	{
+ 		TreeCCStreamPrint(stream, "switch(%s)\n", paramName);
+ 	}
+ 	else if(context->language == TREECC_LANG_C)
+ 	{
+ 		if(context->kind_in_vtable)
+ 		{
+ 			TreeCCStreamPrint(stream, "switch(%s__->vtable__->kind__)\n",
+ 							  paramName);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "switch(%s__->kind__)\n", paramName);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "switch(%s__->getKind())\n", paramName);
+ 	}
+ 	Indent(stream, level * 2 + 1);
+ 	TreeCCStreamPrint(stream, "{\n");
+ }
+ 
+ /*
+  * Generate a selector for a "switch" case.
+  */
+ static void C_GenSelector(TreeCCContext *context, TreeCCStream *stream,
+ 						  TreeCCNode *node, int level)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 	{
+ 		Indent(stream, level * 2 + 2);
+ 		TreeCCStreamPrint(stream, "case %s:\n", node->name);
+ 	}
+ 	else if((node->flags & TREECC_NODE_ENUM) == 0)
+ 	{
+ 		Indent(stream, level * 2 + 2);
+ 		TreeCCStreamPrint(stream, "case %s_kind:\n", node->name);
+ 	}
+ }
+ 
+ /*
+  * Terminate the selectors and begin the body of a "switch" case.
+  */
+ static void C_GenEndSelectors(TreeCCContext *context, TreeCCStream *stream,
+ 							  int level)
+ {
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "{\n");
+ }
+ 
+ /*
+  * Generate the code for a case within a function.
+  */
+ static void C_GenCaseFunc(TreeCCContext *context, TreeCCStream *stream,
+ 						  TreeCCOperationCase *operCase, int number)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 	char *type;
+ 	char *suffix;
+ 
+ 	/* Output the header for the function */
+ 	TreeCCStreamPrint(stream, "static %s %s_%d__(",
+ 					  operCase->oper->returnType,
+ 					  operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 		   	if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				type = trigger->node->name;
+ 				suffix = "*";
+ 			}
+ 			else
+ 			{
+ 				type = param->type;
+ 				suffix = "";
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		else
+ 		{
+ 			type = param->type;
+ 			suffix = "";
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s %s%s",
+ 							  type, suffix, param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "%s %sP%d__",
+ 							  type, suffix, num);
+ 			++num;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	if(!needComma)
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 
+ 	/* Output the code for the operation case */
+ 	TreeCCStreamLine(stream, operCase->codeLinenum, operCase->codeFilename);
+ 	TreeCCStreamPrint(stream, "{");
+ 	if(operCase->code)
+ 	{
+ 		TreeCCStreamCode(stream, operCase->code);
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	TreeCCStreamFixLine(stream);
+ 	TreeCCStreamPrint(stream, "\n");
+ }
+ 
+ /*
+  * Generate a call to a case function from within the "switch".
+  */
+ static void C_GenCaseCall(TreeCCContext *context, TreeCCStream *stream,
+ 						  TreeCCOperationCase *operCase, int number,
+ 						  int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 3);
+ 
+ 	/* Add "return" to the front if the operation is non-void */
+ 	if(strcmp(operCase->oper->returnType, "void") != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "return ");
+ 	}
+ 
+ 	/* Print out the call */
+ 	TreeCCStreamPrint(stream, "%s_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "(%s *)", trigger->node->name);
+ 			}
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Generate the code for a case inline within the "switch".
+  */
+ static void C_GenCaseInline(TreeCCContext *context, TreeCCStream *stream,
+ 						    TreeCCOperationCase *operCase, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 
+ 	/* Copy the parameters to new variables of the correct types */
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	while(param != 0)
+ 	{
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(param->name != 0)
+ 			{
+ 				if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 				   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 				{
+ 					Indent(stream, level * 2 + 3);
+ 					TreeCCStreamPrint(stream, "%s *%s = (%s *)%s__;\n",
+ 									  trigger->node->name, param->name,
+ 									  trigger->node->name, param->name);
+ 				}
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		param = param->next;
+ 	}
+ 
+ 	/* Output the inline code for the case */
+ 	TreeCCStreamLine(stream, operCase->codeLinenum, operCase->codeFilename);
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "{");
+ 	if(operCase->code)
+ 	{
+ 		TreeCCStreamCodeIndent(stream, operCase->code, level * 2 + 3);
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	TreeCCStreamFixLine(stream);
+ }
+ 
+ /*
+  * Generate the code for a call to a split function within the "switch".
+  */
+ static void C_GenCaseSplit(TreeCCContext *context, TreeCCStream *stream,
+ 						   TreeCCOperationCase *operCase,
+ 						   int number, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 3);
+ 
+ 	/* Add "return" to the front if the operation is non-void */
+ 	if(strcmp(operCase->oper->returnType, "void") != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "return ");
+ 	}
+ 
+ 	/* Print out the call */
+ 	TreeCCStreamPrint(stream, "%s_split_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "(%s *)", trigger->node->name);
+ 			}
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Terminate a "switch" case.
+  */
+ static void C_GenEndCase(TreeCCContext *context, TreeCCStream *stream,
+ 						 int level)
+ {
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "break;\n\n");
+ }
+ 
+ /*
+  * Terminate the "switch" statement.
+  */
+ static void C_GenEndSwitch(TreeCCContext *context, TreeCCStream *stream,
+ 						   int level)
+ {
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "default: break;\n");
+ 	Indent(stream, level * 2 + 1);
+ 	TreeCCStreamPrint(stream, "}\n");
+ }
+ 
+ /*
+  * Generate the exit point for a non-virtual operation.
+  */
+ static void C_GenExit(TreeCCContext *context, TreeCCStream *stream,
+ 					  TreeCCOperation *oper)
+ {
+ 	if(strcmp(oper->returnType, "void") != 0)
+ 	{
+ 		/* Generate a default return value for the function */
+ 		if(oper->defValue)
+ 		{
+ 			TreeCCStreamPrint(stream, "\treturn (%s);\n", oper->defValue);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "\treturn 0;\n");
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Generate the end declarations for a non-virtual operation.
+  */
+ static void C_GenEnd(TreeCCContext *context, TreeCCStream *stream,
+ 					 TreeCCOperation *oper)
+ {
+ 	/* Nothing to do here for C and C++ */
+ }
+ 
+ /*
+  * Table of non-virtual code generation functions.
+  */
+ TreeCCNonVirtual const TreeCCNonVirtualFuncsC = {
+ 	C_GenStart,
+ 	C_GenEntry,
+ 	C_GenSplitEntry,
+ 	C_GenSwitchHead,
+ 	C_GenSelector,
+ 	C_GenEndSelectors,
+ 	C_GenCaseFunc,
+ 	C_GenCaseCall,
+ 	C_GenCaseInline,
+ 	C_GenCaseSplit,
+ 	C_GenEndCase,
+ 	C_GenEndSwitch,
+ 	C_GenExit,
+ 	C_GenEnd,
+ };
+ 
+ /*
+  * Write out header information for all streams.
+  */
+ static void WriteHeaders(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->isHeader)
+ 		{
+ 			TreeCCStreamHeaderTop(stream);
+ 			TreeCCStreamPrint(stream, "\n");
+ 			TreeCCStreamPrint(stream, "#ifdef __cplusplus\n");
+ 			TreeCCStreamPrint(stream, "extern \"C\" {\n");
+ 			TreeCCStreamPrint(stream, "#endif\n");
+ 			TreeCCStreamPrint(stream, "\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamSourceTop(stream);
+ 			TreeCCStreamPrint(stream, "\n");
+ 		}
+ 		if(stream->defaultFile)
+ 		{
+ 			/* Reset the dirty flag if this is a default stream,
+ 			   because we don't want to write out the final file
+ 			   if it isn't actually written to in practice */
+ 			stream->dirty = 0;
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Write out footer information for all streams.
+  */
+ static void WriteFooters(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->defaultFile && !(stream->dirty))
+ 		{
+ 			/* Clear the default file's contents, which we don't need */
+ 			TreeCCStreamClear(stream);
+ 		}
+ 		else if(stream->isHeader)
+ 		{
+ 			TreeCCStreamPrint(stream, "#ifdef __cplusplus\n");
+ 			TreeCCStreamPrint(stream, "};\n");
+ 			TreeCCStreamPrint(stream, "#endif\n");
+ 			TreeCCStreamPrint(stream, "\n");
+ 			TreeCCStreamHeaderBottom(stream);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamSourceBottom(stream);
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Write the skeleton for the node memory manager to a source stream.
+  */
+ static void WriteSourceSkeleton(TreeCCContext *context, TreeCCStream *stream)
+ {
+ 	if(context->block_size)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_BLKSIZ %d\n",
+ 						  context->state_type, context->block_size);
+ 	}
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_REENTRANT 1\n",
+ 						  context->state_type);
+ 	}
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_TRACK_LINES 1\n",
+ 						  context->state_type);
+ 	}
+ 	if(context->use_gc_allocator)
+ 	{
+ 		TreeCCIncludeSkeleton(context, stream, "c_gc_skel.c");
+ 	}
+ 	else
+ 	{
+ 		TreeCCIncludeSkeleton(context, stream, "c_skel.c");
+ 	}
+ }
+ 
+ void TreeCCGenerateC(TreeCCContext *context)
+ {
+ 	/* Write all stream headers */
+ 	WriteHeaders(context);
+ 
+ 	/* Generate the contents of the header stream */
+ 	TreeCCNodeVisitAll(context, DefineNodeNumbers);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 	TreeCCNodeVisitAll(context, DeclareTypeDefs);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 	if(context->use_gc_allocator)
+ 	{
+ 		if(context->commonHeader)
+ 		{
+ 			TreeCCIncludeSkeleton
+ 				(context, context->commonHeader, "c_gc_skel.h");
+ 		}
+ 		else
+ 		{
+ 			TreeCCIncludeSkeleton
+ 				(context, context->headerStream, "c_gc_skel.h");
+ 		}
+ 	}
+ 	else
+ 	{
+ 		if(context->commonHeader)
+ 		{
+ 			TreeCCIncludeSkeleton(context, context->commonHeader, "c_skel.h");
+ 		}
+ 		else
+ 		{
+ 			TreeCCIncludeSkeleton(context, context->headerStream, "c_skel.h");
+ 		}
+ 	}
+ 	TreeCCNodeVisitAll(context, BuildTypeDecls);
+ 	TreeCCNodeVisitAll(context, DeclareCreateFuncs);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 	TreeCCOperationVisitAll(context, DeclareNonVirtuals);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 	OutputHelpers(context);
+ 
+ 	/* Generate the contents of the source stream */
+ 	if(context->use_allocator)
+ 	{
+ 		if(context->commonSource)
+ 		{
+ 			WriteSourceSkeleton(context, context->commonSource);
+ 		}
+ 		else
+ 		{
+ 			WriteSourceSkeleton(context, context->sourceStream);
+ 		}
+ 	}
+ 	TreeCCNodeVisitAll(context, DefineVtables);
+ 	TreeCCNodeVisitAll(context, ImplementCreateFuncs);
+ 	TreeCCGenerateNonVirtuals(context, &TreeCCNonVirtualFuncsC);
+ 	OutputIsA(context);
+ 
+ 	/* Write all stream footers */
+ 	WriteFooters(context);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen_cpp.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen_cpp.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen_cpp.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,1107 ----
+ /*
+  * gen_cpp.c - Generate C++ source code from "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "gen.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Define the node numbers.
+  */
+ static void DefineNodeNumbers(TreeCCContext *context,
+ 							  TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->header;
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) == 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "const int %s_kind = %d;\n",
+ 						  node->name, node->number);
+ 	}
+ }
+ 
+ /*
+  * Declare the fields for a node type.
+  */
+ static void DeclareFields(TreeCCContext *context,
+ 						  TreeCCStream *stream, TreeCCNode *node)
+ {
+ 	TreeCCField *field;
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t%s %s;\n", field->type, field->name);
+ 		field = field->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the virtuals for a node type.
+  */
+ static void DeclareVirtuals(TreeCCContext *context, TreeCCStream *stream,
+ 							TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	int num, needComma;
+ 	TreeCCOperationCase *operCase;
+ 	int declareCase, abstractCase;
+ 	TreeCCNode *tempNode;
+ 	if(node->parent)
+ 	{
+ 		DeclareVirtuals(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		/* Determine if we need a definition for this virtual,
+ 		   and whether the definition is real or abstract */
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			tempNode = actualNode->parent;
+ 			abstractCase = 1;
+ 			while(tempNode != 0)
+ 			{
+ 				operCase = TreeCCOperationFindCase
+ 								(context, tempNode, virt->name);
+ 				if(operCase != 0)
+ 				{
+ 					abstractCase = 0;
+ 					break;
+ 				}
+ 				tempNode = tempNode->parent;
+ 			}
+ 			declareCase = abstractCase;
+ 		}
+ 		else
+ 		{
+ 			declareCase = 1;
+ 			abstractCase = 0;
+ 		}
+ 		if(declareCase)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tvirtual %s %s(",
+ 							  virt->returnType, virt->name);
+ 			param = virt->params;
+ 			num = 1;
+ 			needComma = 0;
+ 			while(param != 0)
+ 			{
+ 				if(needComma)
+ 				{
+ 					TreeCCStreamPrint(stream, ", ");
+ 				}
+ 				else
+ 				{
+ 					needComma = 1;
+ 				}
+ 				if(param->name)
+ 				{
+ 					TreeCCStreamPrint(stream, "%s %s",
+ 									  param->type, param->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "%s P%d__",
+ 									  param->type, num);
+ 					++num;
+ 				}
+ 				param = param->next;
+ 			}
+ 			if(abstractCase)
+ 			{
+ 				TreeCCStreamPrint(stream, ") = 0;\n");
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ");\n");
+ 			}
+ 		}
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the type definitions for a node type.
+  */
+ static void DeclareTypeDefs(TreeCCContext *context,
+ 						    TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->header;
+ 	if((node->flags & TREECC_NODE_ENUM) != 0)
+ 	{
+ 		/* Define an enumerated type */
+ 		TreeCCNode *child;
+ 		TreeCCStreamPrint(stream, "typedef enum {\n");
+ 		child = node->firstChild;
+ 		while(child != 0)
+ 		{
+ 			if((child->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "\t%s,\n", child->name);
+ 			}
+ 			child = child->nextSibling;
+ 		}
+ 		TreeCCStreamPrint(stream, "} %s;\n\n", node->name);
+ 	}
+ 	else if((node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 	{
+ 		/* Define a regular node type */
+ 		TreeCCStreamPrint(stream, "class %s;\n", node->name);
+ 	}
+ }
+ 
+ /*
+  * Output the parameters for a node creation function.
+  */
+ static int CreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParams(context, stream, node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s", field->type, field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Build the type declarations for a node type.
+  */
+ static void BuildTypeDecls(TreeCCContext *context,
+ 						   TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->header;
+ 	int needComma;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Output the class header */
+ 	if(node->parent)
+ 	{
+ 		/* Inherit from a specified parent type */
+ 		TreeCCStreamPrint(stream, "class %s : public %s\n{\n",
+ 						  node->name, node->parent->name);
+ 	}
+ 	else
+ 	{
+ 		/* This type is the base of a class hierarchy */
+ 		if(context->baseType)
+ 		{
+ 			TreeCCStreamPrint(stream, "class %s : public %s\n{\n", node->name,context->baseType);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "class %s\n{\n", node->name);
+ 		}
+ 
+ 		/* The following fields have protected access */
+ 		TreeCCStreamPrint(stream, "protected:\n\n");
+ 
+ 		/* Declare the node kind member variable */
+ 		TreeCCStreamPrint(stream, "\tint kind__;\n");
+ 
+ 		/* Declare the filename and linenum fields if we are tracking lines */
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tchar *filename__;\n");
+ 			TreeCCStreamPrint(stream, "\tlong linenum__;\n");
+ 		}
+ 
+ 		/* Declare the public methods for access to the above fields */
+ 		TreeCCStreamPrint(stream, "\npublic:\n\n");
+ 		TreeCCStreamPrint(stream, "\tint getKind() const { return kind__; }\n");
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 				"\tconst char *getFilename() const { return filename__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"\tlong getLinenum() const { return linenum__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 			 "\tvoid setFilename(char *filename) { filename__ = filename; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"\tvoid setLinenum(long linenum) { linenum__ = linenum; }\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 
+ 		/* Declare the overloaded "new" and "delete" operators */
+ 		if(!(context->reentrant))
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"\tvoid *operator new(size_t);\n");
+ 			TreeCCStreamPrint(stream,
+ 					"\tvoid operator delete(void *, size_t);\n\n");
+ 		}
+ 	}
+ 
+ 	/* Declare the constructor for the node type */
+ 	if(context->reentrant)
+ 	{
+ 		/* Re-entrant systems use a factory to create the nodes */
+ 		if(context->virtual_factory || context->abstract_factory)
+ 		{
+ 			TreeCCStreamPrint(stream, "public: // for virtual factory\n\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "protected:\n\n");
+ 			TreeCCStreamPrint(stream, "\tfriend class %s;\n\n",
+ 							  context->state_type);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* Non-reentrant systems can construct nodes directly,
+ 		   unless the node happens to be abstract, in which
+ 		   case we force the constructor to be protected */
+ 		if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 		{
+ 			TreeCCStreamPrint(stream, "protected:\n\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "public:\n\n");
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "\t%s(", node->name);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 		needComma = 1;
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 	CreateParams(context, stream, node, needComma);
+ 	TreeCCStreamPrint(stream, ");\n\n");
+ 
+ 	/* Declare the fields */
+ 	TreeCCStreamPrint(stream, "public:\n\n");
+ 	if(node->fields)
+ 	{
+ 		DeclareFields(context, stream, node);
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the virtual function prototypes */
+ 	DeclareVirtuals(context, stream, node, node);
+ 	TreeCCStreamPrint(stream, "\n");
+ 
+ 	/* Declare the "isA" and "getKindName" helper methods */
+ 	TreeCCStreamPrint(stream, "\tvirtual int isA(int kind) const;\n");
+ 	TreeCCStreamPrint(stream, "\tvirtual const char *getKindName() const;\n\n");
+ 
+ 	/* Declare the protected destructor for the node type.
+ 	   The destructor is never called, but we need it to
+ 	   keep C++ compilers from whinging about classes with
+ 	   virtuals, but no virtual destructor */
+ 	TreeCCStreamPrint(stream, "protected:\n\n");
+ 	TreeCCStreamPrint(stream, "\tvirtual ~%s();\n\n", node->name);
+ 
+ 	/* Output the class footer */
+ 	TreeCCStreamPrint(stream, "};\n\n");
+ }
+ 
+ /*
+  * Declare the prototypes for the non-virtual operations.
+  */
+ static void DeclareNonVirtuals(TreeCCContext *context,
+ 						  	   TreeCCOperation *oper)
+ {
+ 	TreeCCStream *stream = oper->header;
+ 	TreeCCParam *param;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Bail out if the operation is virtual */
+ 	if((oper->flags & TREECC_OPER_VIRTUAL) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Output a class header if the operation is inside a class */
+ 	if(oper->className)
+ 	{
+ 		TreeCCStreamPrint(stream, "class %s\n", oper->className);
+ 		TreeCCStreamPrint(stream, "{\n");
+ 		TreeCCStreamPrint(stream, "public:\n\n");
+ 		TreeCCStreamPrint(stream, "\tstatic ");
+ 	}
+ 
+ 	/* Output the prototype */
+ 	TreeCCStreamPrint(stream, "%s %s(", oper->returnType, oper->name);
+ 	param = oper->params;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s %s", param->type, param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "%s P%d__", param->type, num);
+ 			++num;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	if(!needComma)
+ 	{
+ 		TreeCCStreamPrint(stream, "void");
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ 
+ 	/* Output a class footer if the operation is inside a class */
+ 	if(oper->className)
+ 	{
+ 		TreeCCStreamPrint(stream, "};\n\n");
+ 	}
+ }
+ 
+ /*
+  * Output a constructor parameter list to the source stream.
+  */
+ static int CreateParamsSource(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParamsSource(context, stream,
+ 									   node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s", field->type, field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output the parameters to call an inherited constructor.
+  */
+ static int InheritParamsSource(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = InheritParamsSource(context, stream,
+ 									    node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output the constructor implementation for a node type.
+  */
+ static void ImplementConstructor(TreeCCContext *context, TreeCCStream *stream,
+ 								 TreeCCNode *node)
+ {
+ 	int needComma;
+ 	TreeCCField *field;
+ 
+ 	/* Output the constructor function header */
+ 	TreeCCStreamPrint(stream, "%s::%s(", node->name, node->name);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s *state__", context->state_type);
+ 		needComma = 1;
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 	CreateParamsSource(context, stream, node, needComma);
+ 	TreeCCStreamPrint(stream, ")\n");
+ 
+ 	/* Call the parent class constructor */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t: %s(", node->parent->name);
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream, "state__");
+ 			needComma = 1;
+ 		}
+ 		else
+ 		{
+ 			needComma = 0;
+ 		}
+ 		InheritParamsSource(context, stream, node->parent, needComma);
+ 		TreeCCStreamPrint(stream, ")\n");
+ 	}
+ 
+ 	/* Output the beginning of the function body */
+ 	TreeCCStreamPrint(stream, "{\n");
+ 
+ 	/* Set the node kind */
+ 	TreeCCStreamPrint(stream, "\tthis->kind__ = %s_kind;\n", node->name);
+ 
+ 	/* Track the filename and line number if necessary */
+ 	if(context->track_lines && !(node->parent))
+ 	{
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"\tthis->filename__ = state__->currFilename();\n");
+ 			TreeCCStreamPrint(stream,
+ 					"\tthis->linenum__ = state__->currLinenum();\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"\tthis->filename__ = %s::getState()->currFilename();\n",
+ 					context->state_type);
+ 			TreeCCStreamPrint(stream,
+ 					"\tthis->linenum__ = %s::getState()->currLinenum();\n",
+ 					context->state_type);
+ 		}
+ 	}
+ 
+ 	/* Initialize the fields that are specific to this node type */
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tthis->%s = %s;\n",
+ 							  field->name, field->name);
+ 		}
+ 		else if(field->value)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tthis->%s = %s;\n",
+ 							  field->name, field->value);
+ 		}
+ 		field = field->next;
+ 	}
+ 
+ 	/* Output the constructor function footer */
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Implement the virtual methods that have implementations in a node type.
+  */
+ static void ImplementVirtuals(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	TreeCCOperation *oper;
+ 	int num, first;
+ 	int needComma;
+ 	if(node->parent)
+ 	{
+ 		ImplementVirtuals(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			/* We don't have a direct implementation in this class */
+ 			virt = virt->next;
+ 			continue;
+ 		}
+ 		TreeCCStreamPrint(stream, "%s %s::%s(", virt->returnType,
+ 						  actualNode->name, virt->name);
+ 		oper = operCase->oper;
+ 		param = oper->params;
+ 		needComma = 0;
+ 		num = 1;
+ 		first = 1;
+ 		while(param != 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			if(first)
+ 			{
+ 				/* Skip the first argument, which corresponds to "this" */
+ 				if(!(param->name))
+ 				{
+ 					++num;
+ 				}
+ 				first = 0;
+ 			}
+ 			else
+ 			{
+ 				if(param->name)
+ 				{
+ 					TreeCCStreamPrint(stream, "%s %s",
+ 									  param->type, param->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "%s P%d__",
+ 									  param->type, num);
+ 					++num;
+ 				}
+ 				needComma = 1;
+ 			}
+ 			param = param->next;
+ 		}
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		if(!(oper->params->name) || !strcmp(oper->params->name, "this"))
+ 		{
+ 			/* The first parameter is called "this", so we don't
+ 			   need to declare it at the head of the function */
+ 			TreeCCStreamLine(stream, operCase->codeLinenum,
+ 							 operCase->codeFilename);
+ 			TreeCCStreamPrint(stream, "{");
+ 			TreeCCStreamCode(stream, operCase->code);
+ 			TreeCCStreamPrint(stream, "}\n");
+ 			TreeCCStreamFixLine(stream);
+ 		}
+ 		else
+ 		{
+ 			/* The first parameter is called something else,
+ 			   so create a temporary variable to hold "this" */
+ 		   	TreeCCStreamPrint(stream, "{\n\t%s *%s = this;\n",
+ 							  actualNode->name, oper->params->name);
+ 			TreeCCStreamLine(stream, operCase->codeLinenum,
+ 							 operCase->codeFilename);
+ 			TreeCCStreamPrint(stream, "\t{");
+ 			TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 			TreeCCStreamPrint(stream, "}\n");
+ 			TreeCCStreamFixLine(stream);
+ 			TreeCCStreamPrint(stream, "}\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Implement a node type.
+  */
+ static void ImplementNodeTypes(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	TreeCCStream *stream = node->source;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Implement the "new" and "delete" operators if this is a top-level node */
+ 	if(!(node->parent) && !(context->reentrant))
+ 	{
+ 		TreeCCStreamPrint(stream, "void *%s::operator new(size_t size__)\n",
+ 						  node->name);
+ 		TreeCCStreamPrint(stream, "{\n");
+ 		TreeCCStreamPrint(stream, "\treturn %s::getState()->alloc(size__);\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "}\n\n");
+ 		TreeCCStreamPrint(stream,
+ 				"void %s::operator delete(void *ptr__, size_t size__)\n",
+ 						  node->name);
+ 		TreeCCStreamPrint(stream, "{\n");
+ 		TreeCCStreamPrint(stream, "\t%s::getState()->dealloc(ptr__, size__);\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "}\n\n");
+ 	}
+ 
+ 	/* Implement the constructor */
+ 	ImplementConstructor(context, stream, node);
+ 
+ 	/* Implement the destructor */
+ 	TreeCCStreamPrint(stream, "%s::~%s()\n", node->name, node->name);
+ 	TreeCCStreamPrint(stream, "{\n");
+ 	TreeCCStreamPrint(stream, "\t// not used\n");
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ 
+ 	/* Implement the virtual methods that reside in this node type */
+ 	ImplementVirtuals(context, stream, node, node);
+ 
+ 	/* Implement the "isA" helper method */
+ 	TreeCCStreamPrint(stream, "int %s::isA(int kind) const\n", node->name);
+ 	TreeCCStreamPrint(stream, "{\n");
+ 	TreeCCStreamPrint(stream, "\tif(kind == %s_kind)\n", node->name);
+ 	TreeCCStreamPrint(stream, "\t\treturn 1;\n");
+ 	TreeCCStreamPrint(stream, "\telse\n");
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\treturn %s::isA(kind);\n",
+ 						  node->parent->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\treturn 0;\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ 
+ 	/* Implement the "getKindName" helper method */
+ 	TreeCCStreamPrint(stream, "const char *%s::getKindName() const\n",
+ 					  node->name);
+ 	TreeCCStreamPrint(stream, "{\n");
+ 	TreeCCStreamPrint(stream, "\treturn \"%s\";\n", node->name);
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Declare the parameters for a factory method in the state type.
+  */
+ static int FactoryCreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryCreateParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s", field->type, field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Declare the create function for a node type.
+  */
+ static void DeclareCreateFuncs(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Ignore this if it is an abstract node */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->commonHeader)
+ 	{
+ 		stream = context->commonHeader;
+ 	}
+ 	else
+ 	{
+ 		stream = context->headerStream;
+ 	}
+ 
+ 	/* Output the start of the function definition */
+ 	if(context->virtual_factory || context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tvirtual %s *%sCreate(",
+ 						  node->name, node->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\t%s *%sCreate(",
+ 						  node->name, node->name);
+ 	}
+ 
+ 	/* Output the parameters for the create function */
+ 	FactoryCreateParams(context, stream, node, 0);
+ 
+ 	/* Terminate the function definition */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, ") = 0;\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, ");\n");
+ 	}
+ }
+ 
+ /*
+  * Declare the state type in the header stream.
+  */
+ static void DeclareStateType(TreeCCContext *context, TreeCCStream *stream)
+ {
+ 	/* Declare the class header */
+ 	TreeCCStreamPrint(stream, "class %s\n{\n", context->state_type);
+ 
+ 	/* Declare the constructor and destructor */
+ 	TreeCCStreamPrint(stream, "public:\n\n");
+ 	TreeCCStreamPrint(stream, "\t%s();\n", context->state_type);
+ 	TreeCCStreamPrint(stream, "\tvirtual ~%s();\n\n", context->state_type);
+ 
+ 	/* Include the header skeleton */
+ 	if(context->use_gc_allocator)
+ 	{
+ 		TreeCCIncludeSkeleton(context, stream, "cpp_gc_skel.h");
+ 	}
+ 	else
+ 	{
+ 		TreeCCIncludeSkeleton(context, stream, "cpp_skel.h");
+ 	}
+ 
+ 	/* Singleton handling for non-reentrant systems */
+ 	if(!(context->reentrant))
+ 	{
+ 		TreeCCStreamPrint(stream, "private:\n\n");
+ 		TreeCCStreamPrint(stream, "\tstatic %s *state__;\n\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "public:\n\n");
+ 		TreeCCStreamPrint(stream, "\tstatic %s *getState()\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\t\t{\n");
+ 		TreeCCStreamPrint(stream, "\t\t\tif(state__) return state__;\n");
+ 		TreeCCStreamPrint(stream, "\t\t\tstate__ = new %s();\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\t\t\treturn state__;\n");
+ 		TreeCCStreamPrint(stream, "\t\t}\n\n");
+ 	}
+ 
+ 	/* Declare the create functions for all of the node types */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "public:\n\n");
+ 		TreeCCNodeVisitAll(context, DeclareCreateFuncs);
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the node pool handling functions */
+ 	TreeCCStreamPrint(stream, "public:\n\n");
+ 	TreeCCStreamPrint(stream, "\tvoid *alloc(size_t);\n");
+ 	TreeCCStreamPrint(stream, "\tvoid dealloc(void *, size_t);\n");
+ 	TreeCCStreamPrint(stream, "\tint push();\n");
+ 	TreeCCStreamPrint(stream, "\tvoid pop();\n");
+ 	TreeCCStreamPrint(stream, "\tvoid clear();\n");
+ 
+ 	/* Declare the "failed" method for out of memory error reporting */
+ 	TreeCCStreamPrint(stream, "\tvirtual void failed();\n");
+ 
+ 	/* Declare the line number tracking methods */
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tvirtual char *currFilename();\n");
+ 		TreeCCStreamPrint(stream, "\tvirtual long currLinenum();\n");
+ 	}
+ 
+ 	/* Declare the end of the state type */
+ 	TreeCCStreamPrint(stream, "\n};\n\n");
+ }
+ 
+ /*
+  * Output invocation parameters for a call to a constructor
+  * from within a factory method.
+  */
+ static int FactoryInvokeParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryInvokeParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the create function for a node type.
+  */
+ static void ImplementCreateFuncs(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Ignore this if it is an abstract node */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->commonSource)
+ 	{
+ 		stream = context->commonSource;
+ 	}
+ 	else
+ 	{
+ 		stream = context->sourceStream;
+ 	}
+ 
+ 	/* Output the start of the function definition */
+ 	TreeCCStreamPrint(stream, "%s *%s::%sCreate(",
+ 					  node->name, context->state_type, node->name);
+ 
+ 	/* Output the parameters for the create function */
+ 	FactoryCreateParams(context, stream, node, 0);
+ 	TreeCCStreamPrint(stream, ")\n");
+ 
+ 	/* Output the body of the creation function */
+ 	TreeCCStreamPrint(stream, "{\n");
+ 	TreeCCStreamPrint(stream, "\tvoid *buf__ = this->alloc(sizeof(%s));\n",
+ 					  node->name);
+ 
+ 	/* Bail out to the caller if "alloc" returned NULL */
+ 	TreeCCStreamPrint(stream, "\tif(buf__ == 0) return 0;\n");
+ 
+ 	/* Invoke the constructor and return the node to the caller */
+ 	TreeCCStreamPrint(stream, "\treturn new (buf__) %s(this", node->name);
+ 	FactoryInvokeParams(context, stream, node, 1);
+ 	TreeCCStreamPrint(stream, ");\n");
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Implement the state type in the source stream.
+  */
+ static void ImplementStateType(TreeCCContext *context, TreeCCStream *stream)
+ {
+ 	/* Include the common definitions from the skeleton */
+ 	if(context->block_size)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_BLKSIZ %d\n",
+ 						  context->state_type, context->block_size);
+ 	}
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_REENTRANT 1\n",
+ 						  context->state_type);
+ 	}
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_TRACK_LINES 1\n",
+ 						  context->state_type);
+ 	}
+ 	if(context->use_allocator)
+ 	{
+ 		TreeCCStreamPrint(stream, "#define %s_USE_ALLOCATOR 1\n",
+ 						  context->state_type);
+ 	}
+ 	if(context->use_gc_allocator)
+ 	{
+ 		TreeCCIncludeSkeleton(context, stream, "cpp_gc_skel.cc");
+ 	}
+ 	else
+ 	{
+ 		TreeCCIncludeSkeleton(context, stream, "cpp_skel.cc");
+ 	}
+ 
+ 	/* Implement the create functions for all of the node types */
+ 	if(context->reentrant && !(context->abstract_factory))
+ 	{
+ 		TreeCCNodeVisitAll(context, ImplementCreateFuncs);
+ 	}
+ }
+ 
+ /*
+  * Write out header information for all streams.
+  */
+ static void WriteCPPHeaders(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->isHeader)
+ 		{
+ 			TreeCCStreamHeaderTop(stream);
+ 			TreeCCStreamPrint(stream, "\n");
+ 			TreeCCStreamPrint(stream, "#include <new>\n");
+ 			TreeCCStreamPrint(stream, "\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamSourceTop(stream);
+ 			TreeCCStreamPrint(stream, "\n");
+ 		}
+ 		if(context->namespace)
+ 		{
+ 			TreeCCStreamPrint(stream, "namespace %s\n{\n\n",
+ 					context->namespace);
+ 		}
+ 		if(stream->defaultFile)
+ 		{
+ 			/* Reset the dirty flag if this is a default stream,
+ 			   because we don't want to write out the final file
+ 			   if it isn't actually written to in practice */
+ 			stream->dirty = 0;
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Write out footer information for all streams.
+  */
+ static void WriteCPPFooters(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->defaultFile && !(stream->dirty))
+ 		{
+ 			/* Clear the default file's contents, which we don't need */
+ 			TreeCCStreamClear(stream);
+ 		}
+ 		else
+ 		{
+ 			if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "}\n");
+ 			}
+ 			if(stream->isHeader)
+ 			{
+ 				TreeCCStreamHeaderBottom(stream);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamSourceBottom(stream);
+ 			}
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ void TreeCCGenerateCPP(TreeCCContext *context)
+ {
+ 	/* Write all stream headers */
+ 	WriteCPPHeaders(context);
+ 
+ 	/* Generate the contents of the header stream */
+ 	TreeCCNodeVisitAll(context, DefineNodeNumbers);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 	TreeCCNodeVisitAll(context, DeclareTypeDefs);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 	if(context->commonHeader)
+ 	{
+ 		DeclareStateType(context, context->commonHeader);
+ 	}
+ 	else
+ 	{
+ 		DeclareStateType(context, context->headerStream);
+ 	}
+ 	TreeCCNodeVisitAll(context, BuildTypeDecls);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 	TreeCCOperationVisitAll(context, DeclareNonVirtuals);
+ 	TreeCCStreamPrint(context->headerStream, "\n");
+ 
+ 	/* Implement the state type */
+ 	if(context->commonSource)
+ 	{
+ 		ImplementStateType(context, context->commonSource);
+ 	}
+ 	else
+ 	{
+ 		ImplementStateType(context, context->sourceStream);
+ 	}
+ 
+ 	/* Generate the contents of the source stream */
+ 	TreeCCNodeVisitAll(context, ImplementNodeTypes);
+ 	TreeCCGenerateNonVirtuals(context, &TreeCCNonVirtualFuncsC);
+ 
+ 	/* Write all stream footers */
+ 	WriteCPPFooters(context);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen_cs.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen_cs.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen_cs.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,830 ----
+ /*
+  * gen_cs.c - Generate C# source code from "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "gen.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Declare the fields for a node type.
+  */
+ static void DeclareFields(TreeCCContext *context,
+ 						  TreeCCStream *stream, TreeCCNode *node)
+ {
+ 	TreeCCField *field;
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s %s;\n",
+ 						  field->type, field->name);
+ 		field = field->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the type definitions for a node type.
+  */
+ static void DeclareTypeDefs(TreeCCContext *context,
+ 						    TreeCCNode *node)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM) != 0)
+ 	{
+ 		/* Define an enumerated type */
+ 		TreeCCStream *stream = node->source;
+ 		TreeCCNode *child;
+ 		if(context->internal_access)
+ 		{
+ 			TreeCCStreamPrint(stream, "internal enum %s\n", node->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "public enum %s\n", node->name);
+ 		}
+ 		TreeCCStreamPrint(stream, "{\n");
+ 		child = node->firstChild;
+ 		while(child != 0)
+ 		{
+ 			if((child->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "\t%s,\n", child->name);
+ 			}
+ 			child = child->nextSibling;
+ 		}
+ 		TreeCCStreamPrint(stream, "}\n\n");
+ 	}
+ }
+ 
+ /*
+  * Output the parameters for a node creation function.
+  */
+ static int CreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParams(context, stream, node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s", field->type, field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output the parameters to call an inherited constructor.
+  */
+ static int InheritParamsSource(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = InheritParamsSource(context, stream,
+ 									    node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the virtual methods that have implementations in a node type.
+  */
+ static void ImplementVirtuals(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	int declareCase, abstractCase;
+ 	TreeCCNode *tempNode;
+ 	int num, first;
+ 	int needComma;
+ 	if(node->parent)
+ 	{
+ 		ImplementVirtuals(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		/* Determine if we need a definition for this virtual,
+ 		   and whether the definition is real or abstract */
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			tempNode = actualNode->parent;
+ 			abstractCase = 1;
+ 			while(tempNode != 0)
+ 			{
+ 				operCase = TreeCCOperationFindCase
+ 								(context, tempNode, virt->name);
+ 				if(operCase != 0)
+ 				{
+ 					abstractCase = 0;
+ 					break;
+ 				}
+ 				tempNode = tempNode->parent;
+ 			}
+ 			declareCase = abstractCase;
+ 		}
+ 		else
+ 		{
+ 			declareCase = 1;
+ 			abstractCase = 0;
+ 		}
+ 		if(declareCase)
+ 		{
+ 			if(abstractCase)
+ 			{
+ 				if(node == actualNode)
+ 				{
+ 					TreeCCStreamPrint(stream,
+ 									  "\tpublic abstract %s %s(",
+ 									  virt->returnType, virt->name);
+ 				}
+ 				else
+ 				{
+ 					/* Inherit the "abstract" definition from the parent */
+ 					virt = virt->next;
+ 					continue;
+ 				}
+ 			}
+ 			else
+ 			{
+ 				if(node == actualNode)
+ 				{
+ 					TreeCCStreamPrint(stream, "\tpublic virtual %s %s(",
+ 									  virt->returnType, virt->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "\tpublic override %s %s(",
+ 									  virt->returnType, virt->name);
+ 				}
+ 			}
+ 			param = virt->oper->params;
+ 			needComma = 0;
+ 			num = 1;
+ 			first = 1;
+ 			while(param != 0)
+ 			{
+ 				if(needComma)
+ 				{
+ 					TreeCCStreamPrint(stream, ", ");
+ 				}
+ 				if(first)
+ 				{
+ 					/* Skip the first argument, which corresponds to "this" */
+ 					if(!(param->name))
+ 					{
+ 						++num;
+ 					}
+ 					first = 0;
+ 				}
+ 				else
+ 				{
+ 					if(param->name)
+ 					{
+ 						TreeCCStreamPrint(stream, "%s %s",
+ 										  param->type, param->name);
+ 					}
+ 					else
+ 					{
+ 						TreeCCStreamPrint(stream, "%s P%d__",
+ 										  param->type, num);
+ 						++num;
+ 					}
+ 					needComma = 1;
+ 				}
+ 				param = param->next;
+ 			}
+ 			if(!abstractCase)
+ 			{
+ 				TreeCCStreamPrint(stream, ")\n");
+ 				TreeCCStreamLine(stream, operCase->codeLinenum,
+ 								 operCase->codeFilename);
+ 				TreeCCStreamPrint(stream, "\t{");
+ 				if(!(virt->oper->params->name) ||
+ 				   !strcmp(virt->oper->params->name, "this"))
+ 				{
+ 					/* The first parameter is called "this", so we don't
+ 					   need to declare it at the head of the function */
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				else
+ 				{
+ 					/* The first parameter is called something else,
+ 					   so create a temporary variable to hold "this" */
+ 				   	TreeCCStreamPrint(stream, "\n\t\t%s %s = this;\n\t",
+ 									  actualNode->name,
+ 									  virt->oper->params->name);
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				TreeCCStreamPrint(stream, "}\n");
+ 				TreeCCStreamFixLine(stream);
+ 				TreeCCStreamPrint(stream, "\n");
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ");\n\n");
+ 			}
+ 		}
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Build the type declarations for a node type.
+  */
+ static void BuildTypeDecls(TreeCCContext *context,
+ 						   TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 	int needComma;
+ 	const char *constructorAccess;
+ 	TreeCCField *field;
+ 	int isAbstract;
+ 	const char *accessMode;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine if this class has abstract virtuals */
+ 	isAbstract = TreeCCNodeHasAbstracts(context, node);
+ 
+ 	/* Determine the access mode for the class */
+ 	if(context->internal_access)
+ 	{
+ 		accessMode = "internal";
+ 	}
+ 	else
+ 	{
+ 		accessMode = "public";
+ 	}
+ 
+ 	/* Output the class header */
+ 	stream = node->source;
+ 	if(node->parent)
+ 	{
+ 		/* Inherit from a specified parent type */
+ 		if(isAbstract)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s abstract class %s : %s\n{\n",
+ 							  accessMode, node->name, node->parent->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "%s class %s : %s\n{\n",
+ 							  accessMode, node->name, node->parent->name);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* This type is the base of a class hierarchy */
+ 		if(isAbstract)
+ 		{
+ 			if(context->baseType)
+ 			{
+ 				TreeCCStreamPrint(stream, "%s abstract class %s : %s\n{\n",
+ 							  accessMode, node->name, context->baseType);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, "%s abstract class %s\n{\n",
+ 							  accessMode, node->name);
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if(context->baseType)
+ 			{
+ 				TreeCCStreamPrint(stream, "%s class %s : %s\n{\n",
+ 							  accessMode, node->name, context->baseType);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, "%s class %s\n{\n",
+ 							  accessMode, node->name);
+ 			}
+ 		}
+ 
+ 		/* Declare the node kind member variable */
+ 		TreeCCStreamPrint(stream, "\tprotected int kind__;\n");
+ 
+ 		/* Declare the filename and linenum fields if we are tracking lines */
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tprotected String filename__;\n");
+ 			TreeCCStreamPrint(stream, "\tprotected long linenum__;\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 
+ 		/* Declare the public methods for access to the above fields */
+ 		TreeCCStreamPrint(stream,
+ 				"\tpublic int getKind() { return kind__; }\n");
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 				"\tpublic String getFilename() { return filename__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"\tpublic long getLinenum() { return linenum__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 			 	"\tpublic void setFilename(String filename) "
+ 					"{ filename__ = filename; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"\tpublic void setLinenum(long linenum) "
+ 					"{ linenum__ = linenum; }\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the kind value */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic new const int KIND = %d;\n\n",
+ 						  node->number);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic const int KIND = %d;\n\n",
+ 						  node->number);
+ 	}
+ 
+ 	/* Declare the fields */
+ 	if(node->fields)
+ 	{
+ 		DeclareFields(context, stream, node);
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the constructor for the node type */
+ 	if(context->reentrant)
+ 	{
+ 		/* Re-entrant systems use a factory to create the nodes.
+ 		   C# doesn't have a notion of "access by members of
+ 		   the namespace only".  The closest is "internal", but
+ 		   even that isn't quite right, so we always use "public" */
+ 		constructorAccess = "public ";
+ 	}
+ 	else
+ 	{
+ 		/* Non-reentrant systems can construct nodes directly,
+ 		   unless the node happens to be abstract, in which
+ 		   case we force the constructor to be protected */
+ 		if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 		{
+ 			constructorAccess = "protected ";
+ 		}
+ 		else
+ 		{
+ 			constructorAccess = "public ";
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "\t%s%s(", constructorAccess, node->name);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s state__", context->state_type);
+ 		needComma = 1;
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 	CreateParams(context, stream, node, needComma);
+ 	TreeCCStreamPrint(stream, ")\n");
+ 
+ 	/* Call the parent class constructor */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t: base(");
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream, "state__");
+ 			needComma = 1;
+ 		}
+ 		else
+ 		{
+ 			needComma = 0;
+ 		}
+ 		InheritParamsSource(context, stream, node->parent, needComma);
+ 		TreeCCStreamPrint(stream, ")\n");
+ 	}
+ 
+ 	/* Set the node kind */
+ 	TreeCCStreamPrint(stream, "\t{\n");
+ 	TreeCCStreamPrint(stream, "\t\tthis.kind__ = KIND;\n");
+ 
+ 	/* Track the filename and line number if necessary */
+ 	if(context->track_lines && !(node->parent))
+ 	{
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.filename__ = state__.currFilename();\n");
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.linenum__ = state__.currLinenum();\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.filename__ = %s.getState().currFilename();\n",
+ 					context->state_type);
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.linenum__ = %s.getState().currLinenum();\n",
+ 					context->state_type);
+ 		}
+ 	}
+ 
+ 	/* Initialize the fields that are specific to this node type */
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			TreeCCStreamPrint(stream, "\t\tthis.%s = %s;\n",
+ 							  field->name, field->name);
+ 		}
+ 		else if(field->value)
+ 		{
+ 			TreeCCStreamPrint(stream, "\t\tthis.%s = %s;\n",
+ 							  field->name, field->value);
+ 		}
+ 		field = field->next;
+ 	}
+ 	TreeCCStreamPrint(stream, "\t}\n\n");
+ 
+ 	/* Implement the virtual functions */
+ 	ImplementVirtuals(context, stream, node, node);
+ 
+ 	/* Declare the "isA" and "getKindName" helper methods */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic override int isA(int kind)\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic virtual int isA(int kind)\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "\t{\n");
+ 	TreeCCStreamPrint(stream, "\t\tif(kind == KIND)\n");
+ 	TreeCCStreamPrint(stream, "\t\t\treturn 1;\n");
+ 	TreeCCStreamPrint(stream, "\t\telse\n");
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\treturn base.isA(kind);\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\treturn 0;\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "\t}\n\n");
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic override String getKindName()\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic virtual String getKindName()\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "\t{\n");
+ 	TreeCCStreamPrint(stream, "\t\treturn \"%s\";\n", node->name);
+ 	TreeCCStreamPrint(stream, "\t}\n");
+ 
+ 	/* Output the class footer */
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Declare the parameters for a factory method in the state type.
+  */
+ static int FactoryCreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryCreateParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s",
+ 							  field->type, field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output invocation parameters for a call to a constructor
+  * from within a factory method.
+  */
+ static int FactoryInvokeParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryInvokeParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the create function for a node type.
+  */
+ static void ImplementCreateFuncs(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Ignore this if it is an abstract node */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->commonSource)
+ 	{
+ 		stream = context->commonSource;
+ 	}
+ 	else
+ 	{
+ 		stream = context->sourceStream;
+ 	}
+ 
+ 	/* Output the start of the function definition */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic virtual abstract %s %sCreate(",
+ 						  node->name, node->name);
+ 	}
+ 	else if(context->virtual_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic virtual %s %sCreate(",
+ 						  node->name, node->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s %sCreate(",
+ 						  node->name, node->name);
+ 	}
+ 
+ 	/* Output the parameters for the create function */
+ 	FactoryCreateParams(context, stream, node, 0);
+ 
+ 	/* Output the body of the creation function */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, ");\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		TreeCCStreamPrint(stream, "\t{\n");
+ 		TreeCCStreamPrint(stream, "\t\treturn new %s(this", node->name);
+ 		FactoryInvokeParams(context, stream, node, 1);
+ 		TreeCCStreamPrint(stream, ");\n");
+ 		TreeCCStreamPrint(stream, "\t}\n\n");
+ 	}
+ }
+ 
+ /*
+  * Implement the state type in the source stream.
+  */
+ static void ImplementStateType(TreeCCContext *context, TreeCCStream *stream)
+ {
+ 	/* Declare the class header */
+ 	if(context->reentrant && context->abstract_factory)
+ 	{
+ 		if(context->internal_access)
+ 		{
+ 			TreeCCStreamPrint(stream, "internal abstract class %s\n{\n\n",
+ 							  context->state_type);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "public abstract class %s\n{\n\n",
+ 							  context->state_type);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		if(context->internal_access)
+ 		{
+ 			TreeCCStreamPrint(stream, "internal class %s\n{\n\n",
+ 							  context->state_type);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "public class %s\n{\n\n",
+ 							  context->state_type);
+ 		}
+ 	}
+ 
+ 	/* Singleton handling for non-reentrant systems */
+ 	if(!(context->reentrant))
+ 	{
+ 		TreeCCStreamPrint(stream, "\tprivate static %s state__;\n\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\tpublic static %s getState()\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\t{\n");
+ 		TreeCCStreamPrint(stream, "\t\tif(state__ != null) return state__;\n");
+ 		TreeCCStreamPrint(stream, "\t\tstate__ = new %s();\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\t\treturn state__;\n");
+ 		TreeCCStreamPrint(stream, "\t}\n\n");
+ 	}
+ 
+ 	/* Implement the constructor */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s() {}\n\n", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s() { state__ = this; }\n\n",
+ 						  context->state_type);
+ 	}
+ 
+ 	/* Implement the create functions for all of the node types */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCNodeVisitAll(context, ImplementCreateFuncs);
+ 	}
+ 
+ 	/* Implement the line number tracking methods */
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream,
+ 			"\tpublic virtual String currFilename() { return null; }\n");
+ 		TreeCCStreamPrint(stream,
+ 			"\tpublic virtual long currLinenum() { return 0; }\n\n");
+ 	}
+ 
+ 	/* Declare the end of the state type */
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Write out header information for all streams.
+  */
+ static void WriteCSharpHeaders(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"/* %s.  Generated automatically by treecc */\n\n",
+ 					stream->embedName);
+ 			if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "namespace %s\n{\n\n",
+ 								  context->namespace);
+ 			}
+ 			TreeCCStreamPrint(stream, "using System;\n\n");
+ 			TreeCCStreamSourceTopCS(stream);
+ 		}
+ 		if(stream->defaultFile)
+ 		{
+ 			/* Reset the dirty flag if this is a default stream,
+ 			   because we don't want to write out the final file
+ 			   if it isn't actually written to in practice */
+ 			stream->dirty = 0;
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Write out footer information for all streams.
+  */
+ static void WriteCSharpFooters(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->defaultFile && !(stream->dirty))
+ 		{
+ 			/* Clear the default file's contents, which we don't need */
+ 			TreeCCStreamClear(stream);
+ 		}
+ 		else if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamSourceBottom(stream);
+ 			if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "}\n");
+ 			}
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ void TreeCCGenerateCSharp(TreeCCContext *context)
+ {
+ 	/* Write all stream headers */
+ 	WriteCSharpHeaders(context);
+ 
+ 	/* Generate the contents of the source stream */
+ 	TreeCCNodeVisitAll(context, DeclareTypeDefs);
+ 	if(context->commonSource)
+ 	{
+ 		ImplementStateType(context, context->commonSource);
+ 	}
+ 	else
+ 	{
+ 		ImplementStateType(context, context->sourceStream);
+ 	}
+ 	TreeCCNodeVisitAll(context, BuildTypeDecls);
+ 	TreeCCGenerateNonVirtuals(context, &TreeCCNonVirtualFuncsJava);
+ 
+ 	/* Write all stream footers */
+ 	WriteCSharpFooters(context);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen_java.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen_java.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen_java.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,1339 ----
+ /*
+  * gen_java.c - Generate Java source code from "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "gen.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Convert enumerated types into "int", because Java
+  * doesn't support enumerations.
+  */
+ static const char *ConvertType(TreeCCContext *context, char *type)
+ {
+ 	TreeCCNode *node = TreeCCNodeFind(context, type);
+ 	if(node && (node->flags & TREECC_NODE_ENUM) != 0)
+ 	{
+ 		return "int";
+ 	}
+ 	else
+ 	{
+ 		return type;
+ 	}
+ }
+ 
+ /*
+  * Declare the fields for a node type.
+  */
+ static void DeclareFields(TreeCCContext *context,
+ 						  TreeCCStream *stream, TreeCCNode *node)
+ {
+ 	TreeCCField *field;
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s %s;\n",
+ 						  ConvertType(context, field->type), field->name);
+ 		field = field->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the type definitions for a node type.
+  */
+ static void DeclareTypeDefs(TreeCCContext *context,
+ 						    TreeCCNode *node)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM) != 0)
+ 	{
+ 		/* Define an enumerated type */
+ 		TreeCCStream *stream = TreeCCStreamGetJava(context, node->name);
+ 		TreeCCNode *child;
+ 		int num;
+ 		TreeCCStreamPrint(stream, "public class %s\n", node->name);
+ 		TreeCCStreamPrint(stream, "{\n");
+ 		child = node->firstChild;
+ 		num = 0;
+ 		while(child != 0)
+ 		{
+ 			if((child->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 			{
+ 				TreeCCStreamPrint(stream,
+ 						"\tpublic static final int %s = %d;\n",
+ 						child->name, num);
+ 				++num;
+ 			}
+ 			child = child->nextSibling;
+ 		}
+ 		TreeCCStreamPrint(stream, "}\n");
+ 	}
+ }
+ 
+ /*
+  * Output the parameters for a node creation function.
+  */
+ static int CreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParams(context, stream, node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s",
+ 							  ConvertType(context, field->type),
+ 							  field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output the parameters to call an inherited constructor.
+  */
+ static int InheritParamsSource(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = InheritParamsSource(context, stream,
+ 									    node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the virtual methods that have implementations in a node type.
+  */
+ static void ImplementVirtuals(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	int declareCase, abstractCase;
+ 	TreeCCNode *tempNode;
+ 	int num, first;
+ 	int needComma;
+ 	if(node->parent)
+ 	{
+ 		ImplementVirtuals(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		/* Determine if we need a definition for this virtual,
+ 		   and whether the definition is real or abstract */
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			tempNode = actualNode->parent;
+ 			abstractCase = 1;
+ 			while(tempNode != 0)
+ 			{
+ 				operCase = TreeCCOperationFindCase
+ 								(context, tempNode, virt->name);
+ 				if(operCase != 0)
+ 				{
+ 					abstractCase = 0;
+ 					break;
+ 				}
+ 				tempNode = tempNode->parent;
+ 			}
+ 			declareCase = abstractCase;
+ 		}
+ 		else
+ 		{
+ 			declareCase = 1;
+ 			abstractCase = 0;
+ 		}
+ 		if(declareCase)
+ 		{
+ 			if(abstractCase)
+ 			{
+ 				TreeCCStreamPrint(stream, "\tpublic abstract %s %s(",
+ 								  ConvertType(context, virt->returnType),
+ 								  virt->name);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, "\tpublic %s %s(",
+ 								  ConvertType(context, virt->returnType),
+ 								  virt->name);
+ 			}
+ 			param = virt->oper->params;
+ 			needComma = 0;
+ 			num = 1;
+ 			first = 1;
+ 			while(param != 0)
+ 			{
+ 				if(needComma)
+ 				{
+ 					TreeCCStreamPrint(stream, ", ");
+ 				}
+ 				if(first)
+ 				{
+ 					/* Skip the first argument, which corresponds to "this" */
+ 					if(!(param->name))
+ 					{
+ 						++num;
+ 					}
+ 					first = 0;
+ 				}
+ 				else
+ 				{
+ 					if(param->name)
+ 					{
+ 						TreeCCStreamPrint(stream, "%s %s",
+ 										  ConvertType(context, param->type),
+ 										  param->name);
+ 					}
+ 					else
+ 					{
+ 						TreeCCStreamPrint(stream, "%s P%d__",
+ 										  ConvertType(context, param->type),
+ 										  num);
+ 						++num;
+ 					}
+ 					needComma = 1;
+ 				}
+ 				param = param->next;
+ 			}
+ 			if(!abstractCase)
+ 			{
+ 				TreeCCStreamPrint(stream, ")\n");
+ 				TreeCCStreamPrint(stream, "\t{\n");
+ 				if(!(virt->oper->params->name) ||
+ 				   !strcmp(virt->oper->params->name, "this"))
+ 				{
+ 					/* The first parameter is called "this", so we don't
+ 					   need to declare it at the head of the function */
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				else
+ 				{
+ 					/* The first parameter is called something else,
+ 					   so create a temporary variable to hold "this" */
+ 				   	TreeCCStreamPrint(stream, "\t\t%s %s = this;\n",
+ 									  actualNode->name,
+ 									  virt->oper->params->name);
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				TreeCCStreamPrint(stream, "}\n\n");
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ");\n\n");
+ 			}
+ 		}
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Build the type declarations for a node type.
+  */
+ static void BuildTypeDecls(TreeCCContext *context,
+ 						   TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 	int needComma;
+ 	const char *constructorAccess;
+ 	TreeCCField *field;
+ 	int isAbstract;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine if this class has abstract virtuals */
+ 	isAbstract = TreeCCNodeHasAbstracts(context, node);
+ 
+ 	/* Output the class header */
+ 	stream = TreeCCStreamGetJava(context, node->name);
+ 	if(node->parent)
+ 	{
+ 		/* Inherit from a specified parent type */
+ 		if(isAbstract)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 							  "public abstract class %s extends %s\n{\n",
+ 							  node->name, node->parent->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "public class %s extends %s\n{\n",
+ 							  node->name, node->parent->name);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* This type is the base of a class hierarchy */
+ 		if(isAbstract)
+ 		{
+ 			if(context->baseType)
+ 			{
+ 				TreeCCStreamPrint(stream, "public abstract class %s extends %s\n{\n",
+ 								  node->name,context->baseType);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, "public abstract class %s\n{\n",
+ 								  node->name);
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if(context->baseType)
+ 			{
+ 				TreeCCStreamPrint(stream, "public class %s extends %s\n{\n",
+ 								  node->name,context->baseType);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, "public class %s\n{\n", node->name);
+ 			}
+ 		}
+ 
+ 		/* Declare the node kind member variable */
+ 		TreeCCStreamPrint(stream, "\tprotected int kind__;\n");
+ 
+ 		/* Declare the filename and linenum fields if we are tracking lines */
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream, "\tprotected String filename__;\n");
+ 			TreeCCStreamPrint(stream, "\tprotected long linenum__;\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 
+ 		/* Declare the public methods for access to the above fields */
+ 		TreeCCStreamPrint(stream,
+ 				"\tpublic int getKind() { return kind__; }\n");
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 				"\tpublic String getFilename() { return filename__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"\tpublic long getLinenum() { return linenum__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 			 	"\tpublic void setFilename(String filename) "
+ 					"{ filename__ = filename; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"\tpublic void setLinenum(long linenum) "
+ 					"{ linenum__ = linenum; }\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the kind value */
+ 	TreeCCStreamPrint(stream, "\tpublic static final int KIND = %d;\n\n",
+ 					  node->number);
+ 
+ 	/* Declare the fields */
+ 	if(node->fields)
+ 	{
+ 		DeclareFields(context, stream, node);
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the constructor for the node type */
+ 	if(context->reentrant)
+ 	{
+ 		/* Re-entrant systems use a factory to create the nodes */
+ 		if(context->virtual_factory || context->abstract_factory)
+ 		{
+ 			/* Subclasses need to be able to construct the node */
+ 			constructorAccess = "public ";
+ 		}
+ 		else
+ 		{
+ 			/* Only the state type needs to be able to construct the node */
+ 			constructorAccess = "";
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* Non-reentrant systems can construct nodes directly,
+ 		   unless the node happens to be abstract, in which
+ 		   case we force the constructor to be protected */
+ 		if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 		{
+ 			constructorAccess = "protected ";
+ 		}
+ 		else
+ 		{
+ 			constructorAccess = "public ";
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "\t%s%s(", constructorAccess, node->name);
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s state__", context->state_type);
+ 		needComma = 1;
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 	CreateParams(context, stream, node, needComma);
+ 	TreeCCStreamPrint(stream, ")\n");
+ 	TreeCCStreamPrint(stream, "\t{\n");
+ 
+ 	/* Call the parent class constructor */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\tsuper(");
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream, "state__");
+ 			needComma = 1;
+ 		}
+ 		else
+ 		{
+ 			needComma = 0;
+ 		}
+ 		InheritParamsSource(context, stream, node->parent, needComma);
+ 		TreeCCStreamPrint(stream, ");\n");
+ 	}
+ 
+ 	/* Set the node kind */
+ 	TreeCCStreamPrint(stream, "\t\tthis.kind__ = KIND;\n");
+ 
+ 	/* Track the filename and line number if necessary */
+ 	if(context->track_lines && !(node->parent))
+ 	{
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.filename__ = state__.currFilename();\n");
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.linenum__ = state__.currLinenum();\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.filename__ = %s.getState().currFilename();\n",
+ 					context->state_type);
+ 			TreeCCStreamPrint(stream,
+ 					"\t\tthis.linenum__ = %s.getState().currLinenum();\n",
+ 					context->state_type);
+ 		}
+ 	}
+ 
+ 	/* Initialize the fields that are specific to this node type */
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			TreeCCStreamPrint(stream, "\t\tthis.%s = %s;\n",
+ 							  field->name, field->name);
+ 		}
+ 		else if(field->value)
+ 		{
+ 			TreeCCStreamPrint(stream, "\t\tthis.%s = %s;\n",
+ 							  field->name, field->value);
+ 		}
+ 		field = field->next;
+ 	}
+ 	TreeCCStreamPrint(stream, "\t}\n\n");
+ 
+ 	/* Implement the virtual functions */
+ 	ImplementVirtuals(context, stream, node, node);
+ 
+ 	/* Declare the "isA" and "getKindName" helper methods */
+ 	TreeCCStreamPrint(stream, "\tpublic int isA(int kind)\n");
+ 	TreeCCStreamPrint(stream, "\t{\n");
+ 	TreeCCStreamPrint(stream, "\t\tif(kind == KIND)\n");
+ 	TreeCCStreamPrint(stream, "\t\t\treturn 1;\n");
+ 	TreeCCStreamPrint(stream, "\t\telse\n");
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\treturn super.isA(kind);\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\treturn 0;\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "\t}\n\n");
+ 	TreeCCStreamPrint(stream, "\tpublic String getKindName()\n");
+ 	TreeCCStreamPrint(stream, "\t{\n");
+ 	TreeCCStreamPrint(stream, "\t\treturn \"%s\";\n", node->name);
+ 	TreeCCStreamPrint(stream, "\t}\n");
+ 
+ 	/* Output the class footer */
+ 	TreeCCStreamPrint(stream, "}\n");
+ }
+ 
+ /*
+  * Declare the parameters for a factory method in the state type.
+  */
+ static int FactoryCreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryCreateParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s %s",
+ 							  ConvertType(context, field->type),
+ 							  field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output invocation parameters for a call to a constructor
+  * from within a factory method.
+  */
+ static int FactoryInvokeParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryInvokeParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the create function for a node type.
+  */
+ static void ImplementCreateFuncs(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Ignore this if it is an abstract node */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine which stream to write to */
+ 	stream = TreeCCStreamGetJava(context, context->state_type);
+ 
+ 	/* Output the start of the function definition */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic abstract %s %sCreate(",
+ 						  node->name, node->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s %sCreate(",
+ 						  node->name, node->name);
+ 	}
+ 
+ 	/* Output the parameters for the create function */
+ 	FactoryCreateParams(context, stream, node, 0);
+ 
+ 	/* Output the body of the creation function */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, ");\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		TreeCCStreamPrint(stream, "\t{\n");
+ 		TreeCCStreamPrint(stream, "\t\treturn new %s(this", node->name);
+ 		FactoryInvokeParams(context, stream, node, 1);
+ 		TreeCCStreamPrint(stream, ");\n");
+ 		TreeCCStreamPrint(stream, "\t}\n\n");
+ 	}
+ }
+ 
+ /*
+  * Implement the state type in the source stream.
+  */
+ static void ImplementStateType(TreeCCContext *context, TreeCCStream *stream)
+ {
+ 	/* Declare the class header */
+ 	if(context->reentrant && context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "public abstract class %s\n{\n\n",
+ 						  context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "public class %s\n{\n\n",
+ 						  context->state_type);
+ 	}
+ 
+ 	/* Singleton handling for non-reentrant systems */
+ 	if(!(context->reentrant))
+ 	{
+ 		TreeCCStreamPrint(stream, "\tprivate static %s state__;\n\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\tpublic static %s getState()\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\t{\n");
+ 		TreeCCStreamPrint(stream, "\t\tif(state__ != null) return state__;\n");
+ 		TreeCCStreamPrint(stream, "\t\tstate__ = new %s();\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "\t\treturn state__;\n");
+ 		TreeCCStreamPrint(stream, "\t}\n\n");
+ 	}
+ 
+ 	/* Implement the constructor */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s() {}\n\n", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic %s() { state__ = this; }\n\n",
+ 						  context->state_type);
+ 	}
+ 
+ 	/* Implement the create functions for all of the node types */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCNodeVisitAll(context, ImplementCreateFuncs);
+ 	}
+ 
+ 	/* Implement the line number tracking methods */
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream,
+ 			"\tpublic String currFilename() { return null; }\n");
+ 		TreeCCStreamPrint(stream,
+ 			"\tpublic long currLinenum() { return 0; }\n\n");
+ 	}
+ 
+ 	/* Declare the end of the state type */
+ 	TreeCCStreamPrint(stream, "}\n");
+ }
+ 
+ /*
+  * Determine if a type name corresponds to an enumerated type.
+  */
+ static int IsEnumType(TreeCCContext *context, const char *type)
+ {
+ 	TreeCCNode *node = TreeCCNodeFindByType(context, type);
+ 	if(node)
+ 	{
+ 		if((node->flags & TREECC_NODE_ENUM) != 0)
+ 		{
+ 			return 1;
+ 		}
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * Generate the start declarations for a non-virtual operation.
+  */
+ static void Java_GenStart(TreeCCContext *context, TreeCCStream *stream,
+ 					      TreeCCOperation *oper)
+ {
+ 	const char *accessMode;
+ 	if(context->internal_access && context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		accessMode = "internal";
+ 	}
+ 	else
+ 	{
+ 		accessMode = "public";
+ 	}
+ 	if(oper->className)
+ 	{
+ 		TreeCCStreamPrint(stream, "%s class %s\n{\n",
+ 						  accessMode, oper->className);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "%s class %s\n{\n",
+ 						  accessMode, oper->name);
+ 	}
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void JavaGenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					     TreeCCOperation *oper, int number)
+ {
+ 	TreeCCParam *param;
+ 	int num;
+ 	int needComma;
+ 	if(number != -1)
+ 	{
+ 		TreeCCStreamPrint(stream, "\tprivate static %s %s_split_%d__(",
+ 						  oper->returnType, oper->name, number);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "\tpublic static %s %s(",
+ 						  oper->returnType, oper->name);
+ 	}
+ 	param = oper->params;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if(context->language == TREECC_LANG_CSHARP)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s ", param->type);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "%s ", ConvertType(context, param->type));
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(!IsEnumType(context, param->type))
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 	TreeCCStreamPrint(stream, "\t{\n");
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void Java_GenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					      TreeCCOperation *oper)
+ {
+ 	JavaGenEntry(context, stream, oper, -1);
+ }
+ 
+ /*
+  * Generate the entry point for a split-out function.
+  */
+ static void Java_GenSplitEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					           TreeCCOperation *oper, int number)
+ {
+ 	JavaGenEntry(context, stream, oper, number);
+ }
+ 
+ /*
+  * Output TAB's for a specific level of indenting.
+  */
+ static void Indent(TreeCCStream *stream, int indent)
+ {
+ 	while(indent >= 4)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\t\t");
+ 		indent -= 4;
+ 	}
+ 	if(indent == 1)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t");
+ 	}
+ 	else if(indent == 2)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t");
+ 	}
+ 	else if(indent == 3)
+ 	{
+ 		TreeCCStreamPrint(stream, "\t\t\t");
+ 	}
+ }
+ 
+ /*
+  * Generate the head of a "switch" statement.
+  */
+ static void Java_GenSwitchHead(TreeCCContext *context, TreeCCStream *stream,
+ 							   char *paramName, int level, int isEnum)
+ {
+ 	Indent(stream, level * 2 + 2);
+ 	if(isEnum)
+ 	{
+ 		TreeCCStreamPrint(stream, "switch(%s)\n", paramName);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "switch(%s__.getKind())\n", paramName);
+ 	}
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "{\n");
+ }
+ 
+ /*
+  * Generate a selector for a "switch" case.
+  */
+ static void Java_GenSelector(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCNode *node, int level)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 	{
+ 		Indent(stream, level * 2 + 3);
+ 		TreeCCStreamPrint(stream, "case %s.%s:\n",
+ 						  node->parent->name, node->name);
+ 	}
+ 	else if((node->flags & TREECC_NODE_ENUM) == 0)
+ 	{
+ 		Indent(stream, level * 2 + 3);
+ 		TreeCCStreamPrint(stream, "case %s.KIND:\n", node->name);
+ 	}
+ }
+ 
+ /*
+  * Terminate the selectors and begin the body of a "switch" case.
+  */
+ static void Java_GenEndSelectors(TreeCCContext *context, TreeCCStream *stream,
+ 							     int level)
+ {
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "{\n");
+ }
+ 
+ /*
+  * Generate the code for a case within a function.
+  */
+ static void Java_GenCaseFunc(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCOperationCase *operCase, int number)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 	char *type;
+ 
+ 	/* Output the header for the function */
+ 	TreeCCStreamPrint(stream, "\tprivate static %s %s_%d__(",
+ 					  ConvertType(context, operCase->oper->returnType),
+ 					  operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 		   	if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				type = trigger->node->name;
+ 			}
+ 			else
+ 			{
+ 				type = param->type;
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		else
+ 		{
+ 			type = param->type;
+ 		}
+ 		if(param->name)
+ 		{
+ 			if(context->language == TREECC_LANG_CSHARP)
+ 			{
+ 				TreeCCStreamPrint(stream, "%s %s", type, param->name);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, "%s %s",
+ 								  ConvertType(context, type), param->name);
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if(context->language == TREECC_LANG_CSHARP)
+ 			{
+ 				TreeCCStreamPrint(stream, "%s P%d__", type, num);
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, "%s P%d__",
+ 								  ConvertType(context, type), num);
+ 			}
+ 			++num;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 
+ 	/* Output the code for the operation case */
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamLine(stream, operCase->codeLinenum, operCase->codeFilename);
+ 	}
+ 	TreeCCStreamPrint(stream, "\t{");
+ 	if(operCase->code)
+ 	{
+ 		TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamFixLine(stream);
+ 	}
+ 	TreeCCStreamPrint(stream, "\n");
+ }
+ 
+ /*
+  * Generate a call to a case function from within the "switch".
+  */
+ static void Java_GenCaseCall(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCOperationCase *operCase, int number,
+ 						     int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 4);
+ 
+ 	/* Add "return" to the front if the operation is non-void */
+ 	if(strcmp(operCase->oper->returnType, "void") != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "return ");
+ 	}
+ 
+ 	/* Print out the call */
+ 	TreeCCStreamPrint(stream, "%s_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "(%s)", trigger->node->name);
+ 			}
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Generate the code for a case inline within the "switch".
+  */
+ static void Java_GenCaseInline(TreeCCContext *context, TreeCCStream *stream,
+ 						       TreeCCOperationCase *operCase, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 
+ 	/* Copy the parameters to new variables of the correct types */
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	while(param != 0)
+ 	{
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(param->name != 0)
+ 			{
+ 				if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 				   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 				{
+ 					Indent(stream, level * 2 + 4);
+ 					TreeCCStreamPrint(stream, "%s %s = (%s)%s__;\n",
+ 									  trigger->node->name, param->name,
+ 									  trigger->node->name, param->name);
+ 				}
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		param = param->next;
+ 	}
+ 
+ 	/* Output the inline code for the case */
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamLine(stream, operCase->codeLinenum, operCase->codeFilename);
+ 	}
+ 	Indent(stream, level * 2 + 4);
+ 	TreeCCStreamPrint(stream, "{");
+ 	if(operCase->code)
+ 	{
+ 		TreeCCStreamCodeIndent(stream, operCase->code, level * 2 + 4);
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamFixLine(stream);
+ 	}
+ }
+ 
+ /*
+  * Generate a call to a split function from within the "switch".
+  */
+ static void Java_GenCaseSplit(TreeCCContext *context, TreeCCStream *stream,
+ 						      TreeCCOperationCase *operCase,
+ 							  int number, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 4);
+ 
+ 	/* Add "return" to the front if the operation is non-void */
+ 	if(strcmp(operCase->oper->returnType, "void") != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "return ");
+ 	}
+ 
+ 	/* Print out the call */
+ 	TreeCCStreamPrint(stream, "%s_split_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "(%s)", trigger->node->name);
+ 			}
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Terminate a "switch" case.
+  */
+ static void Java_GenEndCase(TreeCCContext *context, TreeCCStream *stream,
+ 						    int level)
+ {
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "break;\n\n");
+ }
+ 
+ /*
+  * Terminate the "switch" statement.
+  */
+ static void Java_GenEndSwitch(TreeCCContext *context, TreeCCStream *stream,
+ 						      int level)
+ {
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "default: break;\n");
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "}\n");
+ }
+ 
+ /*
+  * Generate the exit point for a non-virtual operation.
+  */
+ static void Java_GenExit(TreeCCContext *context, TreeCCStream *stream,
+ 					     TreeCCOperation *oper)
+ {
+ 	if(strcmp(oper->returnType, "void") != 0)
+ 	{
+ 		/* Generate a default return value for the function */
+ 		if(oper->defValue)
+ 		{
+ 			TreeCCStreamPrint(stream, "\treturn (%s);\n", oper->defValue);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "\treturn 0;\n");
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "\t}\n");
+ }
+ 
+ /*
+  * Generate the end declarations for a non-virtual operation.
+  */
+ static void Java_GenEnd(TreeCCContext *context, TreeCCStream *stream,
+ 					    TreeCCOperation *oper)
+ {
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ }
+ 
+ /*
+  * Table of non-virtual code generation functions.
+  */
+ TreeCCNonVirtual const TreeCCNonVirtualFuncsJava = {
+ 	Java_GenStart,
+ 	Java_GenEntry,
+ 	Java_GenSplitEntry,
+ 	Java_GenSwitchHead,
+ 	Java_GenSelector,
+ 	Java_GenEndSelectors,
+ 	Java_GenCaseFunc,
+ 	Java_GenCaseCall,
+ 	Java_GenCaseInline,
+ 	Java_GenCaseSplit,
+ 	Java_GenEndCase,
+ 	Java_GenEndSwitch,
+ 	Java_GenExit,
+ 	Java_GenEnd,
+ };
+ 
+ /*
+  * Write out header information for all streams.
+  */
+ static void WriteJavaHeaders(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamSourceTop(stream);
+ 			TreeCCStreamPrint(stream, "\n");
+ 			if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "package %s;\n\n",
+ 								  context->namespace);
+ 			}
+ 			TreeCCStreamPrint(stream, "import java.lang.*;\n\n");
+ 		}
+ 		if(stream->defaultFile)
+ 		{
+ 			/* Reset the dirty flag if this is a default stream,
+ 			   because we don't want to write out the final file
+ 			   if it isn't actually written to in practice */
+ 			stream->dirty = 0;
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Write out footer information for all streams.
+  */
+ static void WriteJavaFooters(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->defaultFile && !(stream->dirty))
+ 		{
+ 			/* Clear the default file's contents, which we don't need */
+ 			TreeCCStreamClear(stream);
+ 		}
+ 		else if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamSourceBottom(stream);
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Create streams for all of the node types.
+  */
+ static void CreateNodeStreams(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 	{
+ 		TreeCCStreamGetJava(context, node->name);
+ 	}
+ }
+ 
+ /*
+  * Create streams for all of the non-virtual operations
+  */
+ static void CreateNonVirtualStreams(TreeCCContext *context,
+ 						  	   	    TreeCCOperation *oper)
+ {
+ 	if((oper->flags & TREECC_OPER_VIRTUAL) == 0)
+ 	{
+ 		if(oper->className)
+ 		{
+ 			TreeCCStreamGetJava(context, oper->className);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamGetJava(context, oper->name);
+ 		}
+ 	}
+ }
+ 
+ void TreeCCGenerateJava(TreeCCContext *context)
+ {
+ 	/* Create all streams that we will require later */
+ 	TreeCCStreamGetJava(context, context->state_type);
+ 	TreeCCNodeVisitAll(context, CreateNodeStreams);
+ 	TreeCCOperationVisitAll(context, CreateNonVirtualStreams);
+ 
+ 	/* Write all stream headers */
+ 	WriteJavaHeaders(context);
+ 
+ 	/* Generate the contents of the source stream */
+ 	TreeCCNodeVisitAll(context, DeclareTypeDefs);
+ 	ImplementStateType(context,
+ 					   TreeCCStreamGetJava(context, context->state_type));
+ 	TreeCCNodeVisitAll(context, BuildTypeDecls);
+ 	TreeCCGenerateNonVirtuals(context, &TreeCCNonVirtualFuncsJava);
+ 
+ 	/* Write all stream footers */
+ 	WriteJavaFooters(context);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen_php.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen_php.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen_php.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,1366 ----
+ /*
+  * gen_php.c - Generate Php source code from "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "gen.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Declare the fields for a node type.
+  */
+ static void DeclareFields(TreeCCContext *context,
+ 						  TreeCCStream *stream, TreeCCNode *node)
+ {
+ 	TreeCCField *field;
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "    var $%s;\n",
+ 						  /*field->type, */ field->name);
+ 		field = field->next;
+ 	}
+ }
+ 
+ /*
+  * Declare the type definitions for a node type.
+  */
+ static void DeclareTypeDefs(TreeCCContext *context,
+ 						    TreeCCNode *node)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM) != 0)
+ 	{
+ 		/* Define an enumerated type */
+ 		/* since PHP doesnt have enums - we are going to have to create defines...
+ 		 */
+ 		int i=1;
+ 		
+ 		
+ 		TreeCCStream *stream = node->source;
+ 		TreeCCNode *child;
+ 		/* TreeCCStreamPrint(stream, "public enum %s\n", node->name); */
+ 		/* TreeCCStreamPrint(stream, "{\n"); */
+ 		child = node->firstChild;
+ 		
+ 		while(child != 0)
+ 		{
+ 			if((child->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "define('%s_%s',%d);\n", node->name,child->name,i);
+ 				i++;
+ 			}
+ 			child = child->nextSibling;
+ 		}
+ 		TreeCCStreamPrint(stream, "\n\n");
+ 	}
+ }
+ 
+ /*
+  * Output the parameters for a node creation function.
+  */
+ static int CreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParams(context, stream, node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, " $%s", /*field->type,*/ field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output the parameters to call an inherited constructor.
+  */
+ static int InheritParamsSource(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = InheritParamsSource(context, stream,
+ 									    node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "$%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the virtual methods that have implementations in a node type.
+  */
+ static void ImplementVirtuals(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	int declareCase, abstractCase;
+ 	TreeCCNode *tempNode;
+ 	int num, first;
+ 	int needComma;
+ 	if(node->parent)
+ 	{
+ 		ImplementVirtuals(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		/* Determine if we need a definition for this virtual,
+ 		   and whether the definition is real or abstract */
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			tempNode = actualNode->parent;
+ 			abstractCase = 1;
+ 			while(tempNode != 0)
+ 			{
+ 				operCase = TreeCCOperationFindCase
+ 								(context, tempNode, virt->name);
+ 				if(operCase != 0)
+ 				{
+ 					abstractCase = 0;
+ 					break;
+ 				}
+ 				tempNode = tempNode->parent;
+ 			}
+ 			declareCase = abstractCase;
+ 		}
+ 		else
+ 		{
+ 			declareCase = 1;
+ 			abstractCase = 0;
+ 		}
+ 		if(declareCase)
+ 		{
+ 			if(abstractCase)
+ 			{
+ 				if(node == actualNode)
+ 				{
+ 				/*	TreeCCStreamPrint(stream,
+ 				 					  "    public abstract %s %s(",
+ 				 					  virt->returnType, virt->name); */
+ 				TreeCCStreamPrint(stream,  "    function  %s(", virt->name);
+ 				}
+ 				else
+ 				{
+ 					/* Inherit the "abstract" definition from the parent */
+ 					virt = virt->next;
+ 					continue;
+ 				}
+ 			}
+ 			else
+ 			{
+ 				/*if(node == actualNode)
+ 				{
+ 					TreeCCStreamPrint(stream, "    public virtual %s %s(",
+ 									  virt->returnType, virt->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "    public override %s %s(",
+ 									  virt->returnType, virt->name);
+ 				}*/
+ 				TreeCCStreamPrint(stream, "    function %s(", virt->name);
+ 				
+ 				
+ 			}
+ 			param = virt->oper->params;
+ 			needComma = 0;
+ 			num = 1;
+ 			first = 1;
+ 			while(param != 0)
+ 			{
+ 				if(needComma)
+ 				{
+ 					TreeCCStreamPrint(stream, ", ");
+ 				}
+ 				if(first)
+ 				{
+ 					/* Skip the first argument, which corresponds to "this" */
+ 					if(!(param->name))
+ 					{
+ 						++num;
+ 					}
+ 					first = 0;
+ 				}
+ 				else
+ 				{
+ 					if(param->name)
+ 					{
+ 						TreeCCStreamPrint(stream, "$%s ",
+ 										/*  param->type, */ param->name);
+ 					}
+ 					else
+ 					{
+ 						TreeCCStreamPrint(stream, "$P%d__",
+ 										  /* param->type, */ num);
+ 						++num;
+ 					}
+ 					needComma = 1;
+ 				}
+ 				param = param->next;
+ 			}
+ 			if(!abstractCase)
+ 			{
+ 				TreeCCStreamPrint(stream, ")\n");
+ 				TreeCCStreamLine(stream, operCase->codeLinenum,
+ 								 operCase->codeFilename);
+ 				TreeCCStreamPrint(stream, "    {");
+ 				if(!(virt->oper->params->name) ||
+ 				   !strcmp(virt->oper->params->name, "this"))
+ 				{
+ 					/* The first parameter is called "this", so we don't
+ 					   need to declare it at the head of the function */
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				else
+ 				{
+ 					/* The first parameter is called something else,
+ 					   so create a temporary variable to hold "this" */
+ 				   	/*
+ 					TreeCCStreamPrint(stream, "\n        %s %s = $this;\n    ",
+ 									  actualNode->name,
+ 									  virt->oper->params->name);
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 					*/
+ 					TreeCCStreamPrint(stream, "\n        $%s = &$this;\n    ", virt->oper->params->name);
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				TreeCCStreamPrint(stream, "}\n");
+ 				TreeCCStreamFixLine(stream);
+ 				TreeCCStreamPrint(stream, "\n");
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ") {}\n\n");
+ 			}
+ 		}
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Build the type declarations for a node type.
+  */
+ static void BuildTypeDecls(TreeCCContext *context,
+ 						   TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 	int needComma;
+ 	const char *constructorAccess;
+ 	TreeCCField *field;
+ 	int isAbstract;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 	/* Determine if this class has abstract virtuals */
+ 	isAbstract = TreeCCNodeHasAbstracts(context, node);
+ 
+ 	/* Output the class header */
+ 	stream = node->source;
+ 	
+ 	if(node->parent)
+ 	{
+ 		/*
+ 		TreeCCStreamPrint(stream, "    public new const int KIND = %d;\n\n",
+ 						  node->number);
+ 		*/
+ 		TreeCCStreamPrint(stream, "define('%s_KIND',%d);\n",
+ 						  node->name,node->number);
+ 	}
+ 	else
+ 	{
+ 		/*
+ 		TreeCCStreamPrint(stream, "    public const int KIND = %d;\n\n",
+ 						  node->number);
+ 		*/
+ 		TreeCCStreamPrint(stream, "define('%s_KIND', %d);\n",
+ 						  node->name,node->number);
+ 	}
+ 	
+ 	if(node->parent)
+ 	{
+ 		/* Inherit from a specified parent type */
+ 		if(isAbstract)
+ 		{
+ 			TreeCCStreamPrint(stream, "class %s extends %s\n{\n",
+ 							  node->name, node->parent->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "class %s extends %s\n{\n",
+ 							  node->name, node->parent->name);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* This type is the base of a class hierarchy */
+ 		if(isAbstract)
+ 		{
+ 			TreeCCStreamPrint(stream, "class %s\n{\n",
+ 							  node->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "class %s\n{\n", node->name);
+ 		}
+ 
+ 		/* Declare the node kind member variable */
+ 		TreeCCStreamPrint(stream, "    var $kind__;\n");
+ 
+ 		/* Declare the filename and linenum fields if we are tracking lines */
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream, "    var $filename__;\n");
+ 			TreeCCStreamPrint(stream, "    var $linenum__;\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 
+ 		/* Declare the public methods for access to the above fields */
+ 		TreeCCStreamPrint(stream,
+ 				"    function getKind() { return $this->kind__; }\n");
+ 		if(context->track_lines)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 				"    function getFilename() { return $this->filename__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"    function getLinenum() { return $this->linenum__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 			 	"    function setFilename($filename) "
+ 					"{ $this->filename__ = $filename; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"    function setLinenum($linenum) "
+ 					"{ $this->linenum__ = $linenum; }\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the kind value */
+ 	
+ 
+ 	/* Declare the fields */
+ 	if(node->fields)
+ 	{
+ 		DeclareFields(context, stream, node);
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Declare the constructor for the node type */
+ 	if(context->reentrant)
+ 	{
+ 		/* Re-entrant systems use a factory to create the nodes.
+ 		   C# doesn't have a notion of "access by members of
+ 		   the namespace only".  The closest is "internal", but
+ 		   even that isn't quite right, so we always use "public" */
+ 		/*constructorAccess = "public "; */
+ 		constructorAccess = ""; 
+ 	}
+ 	else
+ 	{
+ 		/* Non-reentrant systems can construct nodes directly,
+ 		   unless the node happens to be abstract, in which
+ 		   case we force the constructor to be protected */
+ 		if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 		{
+ 			/* constructorAccess = "protected "; */
+ 			constructorAccess = "";
+ 		}
+ 		else
+ 		{
+ 			/* constructorAccess = "public "; */
+ 			constructorAccess = "";
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "    function %s%s(", constructorAccess, node->name);
+ 	if(context->reentrant)
+ 	{
+ 		/* TreeCCStreamPrint(stream, "%s state__", context->state_type); */
+ 		TreeCCStreamPrint(stream, "&$state__"); 
+ 		needComma = 1;
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 	CreateParams(context, stream, node, needComma);
+ 	TreeCCStreamPrint(stream, ")\n");
+ 	 TreeCCStreamPrint(stream, "    {\n"); 
+ 	/* Call the parent class constructor */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "        parent::%s (",node->parent->name);
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream, "&$state__");
+ 			needComma = 1;
+ 		}
+ 		else
+ 		{
+ 			needComma = 0;
+ 		}
+ 		InheritParamsSource(context, stream, node->parent, needComma);
+ 		TreeCCStreamPrint(stream, ");\n");
+ 	}
+ 
+ 	/* Set the node kind */
+ 
+ 	TreeCCStreamPrint(stream, "        $this->kind__ = %s_KIND;\n",node->name);
+ 
+ 	/* Track the filename and line number if necessary */
+ 	if(context->track_lines && !(node->parent))
+ 	{
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"        $this->filename__ = $state__->currFilename();\n");
+ 			TreeCCStreamPrint(stream,
+ 					"        $this->linenum__ = $state__->currLinenum();\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"        $_tmp = &%s::getState(); $this->filename__ = $_tmp->currFilename();\n",
+ 					context->state_type);
+ 			TreeCCStreamPrint(stream,
+ 					"        $_tmp = &%s::getState(); $this->linenum__ = $_tmp->currLinenum();\n",
+ 					context->state_type);
+ 		}
+ 	}
+ 
+ 	/* Initialize the fields that are specific to this node type */
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			TreeCCStreamPrint(stream, "        $this->%s = $%s;\n",
+ 							  field->name, field->name);
+ 		}
+ 		else if(field->value)
+ 		{
+ 			TreeCCStreamPrint(stream, "        $this->%s = $%s;\n",
+ 							  field->name, field->value);
+ 		}
+ 		field = field->next;
+ 	}
+ 	TreeCCStreamPrint(stream, "    }\n\n");
+ 
+ 	/* Implement the virtual functions */
+ 	ImplementVirtuals(context, stream, node, node);
+ 
+ 	/* Declare the "isA" and "getKindName" helper methods */
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "    function isA($kind)\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "    function isA($kind)\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "    {\n");
+ 	TreeCCStreamPrint(stream, "        if($kind == %s_KIND)\n",node->name);
+ 	TreeCCStreamPrint(stream, "            return 1;\n");
+ 	TreeCCStreamPrint(stream, "        else\n");
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "            return parent::isA($kind);\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "            return 0;\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "    }\n\n");
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "    function getKindName()\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "    function getKindName()\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "    {\n");
+ 	TreeCCStreamPrint(stream, "        return \"%s\";\n", node->name);
+ 	TreeCCStreamPrint(stream, "    }\n");
+ 
+ 	/* Output the class footer */
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Declare the parameters for a factory method in the state type.
+  */
+ static int FactoryCreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryCreateParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "$%s",
+ 							  /* field->type, */ field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output invocation parameters for a call to a constructor
+  * from within a factory method.
+  */
+ static int FactoryInvokeParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryInvokeParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "$%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the create function for a node type.
+  */
+ static void ImplementCreateFuncs(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Ignore this if it is an abstract node */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->commonSource)
+ 	{
+ 		stream = context->commonSource;
+ 	}
+ 	else
+ 	{
+ 		stream = context->sourceStream;
+ 	}
+ 
+ 	/* Output the start of the function definition */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "    function %sCreate(",
+ 						  /* node->name, */ node->name);
+ 	}
+ 	else if(context->virtual_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "    function %sCreate(",
+ 						  /*node->name, */ node->name);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "    function %sCreate(",
+ 						  /* node->name, */ node->name);
+ 	}
+ 
+ 	/* Output the parameters for the create function */
+ 	FactoryCreateParams(context, stream, node, 0);
+ 
+ 	/* Output the body of the creation function */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, ");\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		TreeCCStreamPrint(stream, "    {\n");
+ 		TreeCCStreamPrint(stream, "        return new %s($this", node->name);
+ 		FactoryInvokeParams(context, stream, node, 1);
+ 		TreeCCStreamPrint(stream, ");\n");
+ 		TreeCCStreamPrint(stream, "    }\n\n");
+ 	}
+ }
+ 
+ /*
+  * Implement the state type in the source stream.
+  */
+ static void ImplementStateType(TreeCCContext *context, TreeCCStream *stream)
+ {
+ 	/* Declare the class header */
+ 	if(context->reentrant && context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, "class %s\n{\n\n",
+ 						  context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "class %s\n{\n\n",
+ 						  context->state_type);
+ 	}
+ 
+ 	/* Singleton handling for non-reentrant systems */
+ 	if(!(context->reentrant))
+ 	{
+ 		/* TreeCCStreamPrint(stream, "    var $state;\n\n" ,
+ 		 				  context->state_type );*/
+ 		TreeCCStreamPrint(stream, "    function &getState()\n" /*,
+ 						  context->state_type*/ );
+ 		TreeCCStreamPrint(stream, "    {\n");
+ 		TreeCCStreamPrint(stream, "        static $state = null;\n");
+ 		TreeCCStreamPrint(stream, "        if($state != null) return $state;\n");
+ 		TreeCCStreamPrint(stream, "        $state = new %s();\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "        return $state;\n");
+ 		TreeCCStreamPrint(stream, "    }\n\n");
+ 	}
+ 
+ 	/* Implement the constructor */
+ 	/*
+ 	-- we cant do constructor too well for this - (as $state is a static var in getState..)
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "    function %s() {}\n\n", context->state_type);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "    function %s() { $this->state__ = $this; }\n\n",
+ 						  context->state_type);
+ 	}
+ 	*/
+ 	/* Implement the create functions for all of the node types */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCNodeVisitAll(context, ImplementCreateFuncs);
+ 	}
+ 
+ 	/* Implement the line number tracking methods */
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream,
+ 			"    function currFilename() { return null; }\n");
+ 		TreeCCStreamPrint(stream,
+ 			"    function currLinenum() { return 0; }\n\n");
+ 	}
+ 
+ 	/* Declare the end of the state type */
+ 	TreeCCStreamPrint(stream, "}\n\n");
+ }
+ 
+ /*
+  * Write out header information for all streams.
+  */
+ static void WritePHPHeaders(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"<?php\n\n/* %s.  Generated automatically by treecc */\n\n",
+ 					stream->embedName);
+ 			/* if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "namespace %s\n{\n\n",
+ 								  context->namespace);
+ 			}
+ 			
+ 			TreeCCStreamPrint(stream, "using System;\n\n");
+ 			*/
+ 			TreeCCStreamSourceTopCS(stream);
+ 		}
+ 		if(stream->defaultFile)
+ 		{
+ 			/* Reset the dirty flag if this is a default stream,
+ 			   because we don't want to write out the final file
+ 			   if it isn't actually written to in practice */
+ 			stream->dirty = 0;
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Write out footer information for all streams.
+  */
+ static void WritePHPFooters(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->defaultFile && !(stream->dirty))
+ 		{
+ 			/* Clear the default file's contents, which we don't need */
+ 			TreeCCStreamClear(stream);
+ 		}
+ 		else if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamSourceBottom(stream);
+ 			/* if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "}\n");
+ 			}
+ 			*/
+ 		}
+ 		TreeCCStreamPrint(stream, "\n?>");
+ 		stream = stream->nextStream;
+ 	}
+ }
+  
+  
+ static int IsEnumType(TreeCCContext *context, const char *type)
+ {
+ 	TreeCCNode *node = TreeCCNodeFindByType(context, type);
+ 	if(node)
+ 	{
+ 		if((node->flags & TREECC_NODE_ENUM) != 0)
+ 		{
+ 			return 1;
+ 		}
+ 	}
+ 	return 0;
+ }
+  
+  
+ /*
+  * Generate the start declarations for a non-virtual operation.
+  */
+ static void PHP_GenStart(TreeCCContext *context, TreeCCStream *stream,
+ 					      TreeCCOperation *oper)
+ {
+ 	if(oper->className)
+ 	{
+ 		TreeCCStreamPrint(stream, "class %s\n{\n", oper->className);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "class %s\n{\n", oper->name);
+ 	}
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void PHPGenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					     TreeCCOperation *oper, int number)
+ {
+ 	TreeCCParam *param;
+ 	int num;
+ 	int needComma;
+ 	/*
+ 	if(number != -1)
+ 	{
+ 		TreeCCStreamPrint(stream, "    private static %s %s_split_%d__(",
+ 						  oper->returnType, oper->name, number);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "    public static %s %s(",
+ 						  oper->returnType, oper->name);
+ 	}
+ 	*/
+ 	if(number != -1)
+ 	{
+ 		TreeCCStreamPrint(stream, "    function %s_split_%d__(&",
+ 						  oper->name, number);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "    function %s(&", oper->name);
+ 	}	
+ 	param = oper->params;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		/*
+ 		if(context->language == TREECC_LANG_CSHARP)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s ", param->type);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "%s ", ConvertType(context, param->type));
+ 		}
+ 		*/
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "$%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "$P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(!IsEnumType(context, param->type))
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 	TreeCCStreamPrint(stream, "    {\n");
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void PHP_GenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					      TreeCCOperation *oper)
+ {
+ 	PHPGenEntry(context, stream, oper, -1);
+ }
+ 
+ /*
+  * Generate the entry point for a split-out function.
+  */
+ static void PHP_GenSplitEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					           TreeCCOperation *oper, int number)
+ {
+ 	PHPGenEntry(context, stream, oper, number);
+ }
+ 
+ /*
+  * Output TAB's for a specific level of indenting.
+  */
+ static void Indent(TreeCCStream *stream, int indent)
+ {
+ 	while(indent >= 4)
+ 	{
+ 		TreeCCStreamPrint(stream, "                ");
+ 		indent -= 4;
+ 	}
+ 	if(indent == 1)
+ 	{
+ 		TreeCCStreamPrint(stream, "    ");
+ 	}
+ 	else if(indent == 2)
+ 	{
+ 		TreeCCStreamPrint(stream, "        ");
+ 	}
+ 	else if(indent == 3)
+ 	{
+ 		TreeCCStreamPrint(stream, "            ");
+ 	}
+ }
+ 
+ /*
+  * Generate the head of a "switch" statement.
+  */
+ static void PHP_GenSwitchHead(TreeCCContext *context, TreeCCStream *stream,
+ 							   char *paramName, int level, int isEnum)
+ {
+ 	Indent(stream, level * 2 + 2);
+ 	if(isEnum)
+ 	{
+ 		TreeCCStreamPrint(stream, "switch($%s)\n", paramName);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "switch($%s__->getKind())\n", paramName);
+ 	}
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "{\n");
+ }
+ 
+ /*
+  * Generate a selector for a "switch" case.
+  */
+ static void PHP_GenSelector(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCNode *node, int level)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 	{
+ 		Indent(stream, level * 2 + 3);
+ 		TreeCCStreamPrint(stream, "case %s_%s:\n",
+ 						  node->parent->name, node->name);
+ 	}
+ 	else if((node->flags & TREECC_NODE_ENUM) == 0)
+ 	{
+ 		Indent(stream, level * 2 + 3);
+ 		TreeCCStreamPrint(stream, "case %s_KIND:\n", node->name);
+ 	}
+ }
+ 
+ /*
+  * Terminate the selectors and begin the body of a "switch" case.
+  */
+ static void PHP_GenEndSelectors(TreeCCContext *context, TreeCCStream *stream,
+ 							     int level)
+ {
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "{\n");
+ }
+ 
+ /*
+  * Generate the code for a case within a function.
+  */
+ static void PHP_GenCaseFunc(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCOperationCase *operCase, int number)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 	char *type;
+ 
+ 	/* Output the header for the function */
+ 	/*TreeCCStreamPrint(stream, "    private static %s %s_%d__(",
+ 					  ConvertType(context, operCase->oper->returnType),
+ 					  operCase->oper->name, number);
+ 					  */
+ 	TreeCCStreamPrint(stream, "    function %s_%d__(&",
+ 					  operCase->oper->name, number);					  
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 		   	if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				type = trigger->node->name;
+ 			}
+ 			else
+ 			{
+ 				type = param->type;
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		else
+ 		{
+ 			type = param->type;
+ 		}
+ 		if(param->name)
+ 		{
+ 			
+ 				TreeCCStreamPrint(stream, "$%s", param->name);
+ 			 
+ 		}
+ 		else
+ 		{
+ 			 
+ 				TreeCCStreamPrint(stream, "$P%d__",   num);
+ 			 
+ 			 
+ 			++num;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 
+ 	/* Output the code for the operation case */
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamLine(stream, operCase->codeLinenum, operCase->codeFilename);
+ 	}
+ 	TreeCCStreamPrint(stream, "    {");
+ 	if(operCase->code)
+ 	{
+ 		TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamFixLine(stream);
+ 	}
+ 	TreeCCStreamPrint(stream, "\n");
+ }
+ 
+ /*
+  * Generate a call to a case function from within the "switch".
+  */
+ static void PHP_GenCaseCall(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCOperationCase *operCase, int number,
+ 						     int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 4);
+ 
+ 	/* Add "return" to the front if the operation is non-void */
+ 	if(strcmp(operCase->oper->returnType, "void") != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "return ");
+ 	}
+ 
+ 	/* Print out the call */
+ 	TreeCCStreamPrint(stream, "$_t = __CLASS__;$_t = new $_t; $_t->%s_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		/* if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "(%s)", trigger->node->name);
+ 			}
+ 		}
+ 		*/
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "$%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "$P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Generate the code for a case inline within the "switch".
+  */
+ static void PHP_GenCaseInline(TreeCCContext *context, TreeCCStream *stream,
+ 						       TreeCCOperationCase *operCase, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 
+ 	/* Copy the parameters to new variables of the correct types */
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	while(param != 0)
+ 	{
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(param->name != 0)
+ 			{
+ 				if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 				   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 				{
+ 					Indent(stream, level * 2 + 4);
+ 					/* TreeCCStreamPrint(stream, "%s %s = (%s)%s__;\n",
+ 									  trigger->node->name, param->name,
+ 									  trigger->node->name, param->name); */
+ 					TreeCCStreamPrint(stream, "$%s = %s__;\n",
+ 									param->name, param->name);
+ 
+ 									  
+ 				}
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		param = param->next;
+ 	}
+ 
+ 	/* Output the inline code for the case */
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamLine(stream, operCase->codeLinenum, operCase->codeFilename);
+ 	}
+ 	Indent(stream, level * 2 + 4);
+ 	TreeCCStreamPrint(stream, "{");
+ 	if(operCase->code)
+ 	{
+ 		TreeCCStreamCodeIndent(stream, operCase->code, level * 2 + 4);
+ 	}
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamFixLine(stream);
+ 	}
+ }
+ 
+ /*
+  * Generate a call to a split function from within the "switch".
+  */
+ static void PHP_GenCaseSplit(TreeCCContext *context, TreeCCStream *stream,
+ 						      TreeCCOperationCase *operCase,
+ 							  int number, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 4);
+ 
+ 	/* Add "return" to the front if the operation is non-void */
+ 	if(strcmp(operCase->oper->returnType, "void") != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "return ");
+ 	}
+ 
+ 	/* Print out the call */
+ 	/* cheezy kludge, as self::method() doesnt working php4 (although it will in php5) */
+ 	TreeCCStreamPrint(stream, "$_t = __CLASS__;$_t = new $_t; $_t->%s_split_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		/*if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "(%s)", trigger->node->name);
+ 			}
+ 		}
+ 		*/
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "$%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "P%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ");\n");
+ }
+ 
+ /*
+  * Terminate a "switch" case.
+  */
+ static void PHP_GenEndCase(TreeCCContext *context, TreeCCStream *stream,
+ 						    int level)
+ {
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "break;\n\n");
+ }
+ 
+ /*
+  * Terminate the "switch" statement.
+  */
+ static void PHP_GenEndSwitch(TreeCCContext *context, TreeCCStream *stream,
+ 						      int level)
+ {
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "default: break;\n");
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "}\n");
+ }
+ 
+ /*
+  * Generate the exit point for a non-virtual operation.
+  */
+ static void PHP_GenExit(TreeCCContext *context, TreeCCStream *stream,
+ 					     TreeCCOperation *oper)
+ {
+ 	if(strcmp(oper->returnType, "void") != 0)
+ 	{
+ 		/* Generate a default return value for the function */
+ 		if(oper->defValue)
+ 		{
+ 			TreeCCStreamPrint(stream, "    return (%s);\n", oper->defValue);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "    return 0;\n");
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "    }\n");
+ }
+ 
+ /*
+  * Generate the end declarations for a non-virtual operation.
+  */
+ static void PHP_GenEnd(TreeCCContext *context, TreeCCStream *stream,
+ 					    TreeCCOperation *oper)
+ {
+ 	TreeCCStreamPrint(stream, "}\n");
+ 	if(context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ }
+ 
+ /*
+  * Table of non-virtual code generation functions.
+  */
+ TreeCCNonVirtual const TreeCCNonVirtualFuncsPHP = {
+ 	PHP_GenStart,
+ 	PHP_GenEntry,
+ 	PHP_GenSplitEntry,
+ 	PHP_GenSwitchHead,
+ 	PHP_GenSelector,
+ 	PHP_GenEndSelectors,
+ 	PHP_GenCaseFunc,
+ 	PHP_GenCaseCall,
+ 	PHP_GenCaseInline,
+ 	PHP_GenCaseSplit,
+ 	PHP_GenEndCase,
+ 	PHP_GenEndSwitch,
+ 	PHP_GenExit,
+ 	PHP_GenEnd,
+ };
+ 
+  
+  
+  
+  
+  
+  
+  
+  
+  
+ 
+ void TreeCCGeneratePHP(TreeCCContext *context)
+ {
+ 	/* Write all stream headers */
+ 	WritePHPHeaders(context);
+ 
+ 	/* Generate the contents of the source stream */
+ 	TreeCCNodeVisitAll(context, DeclareTypeDefs);
+ 	if(context->commonSource)
+ 	{
+ 		ImplementStateType(context, context->commonSource);
+ 	}
+ 	else
+ 	{
+ 		ImplementStateType(context, context->sourceStream);
+ 	}
+ 	TreeCCNodeVisitAll(context, BuildTypeDecls);
+ 	TreeCCGenerateNonVirtuals(context, &TreeCCNonVirtualFuncsPHP);
+ 
+ 	/* Write all stream footers */
+ 	WritePHPFooters(context);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/gen_ruby.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/gen_ruby.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/gen_ruby.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,1218 ----
+ /*
+  * gen_ruby.c - Generate Ruby source code from "treecc" input files.
+  *
+  * Copyright (C) 2001, 2002  Southern Storm Software, Pty Ltd.
+  *
+  * Hacked by Peter Minten <silvernerd at users.sf.net>
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "gen.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Declare the type definitions for a node type.
+  */
+ static void DeclareTypeDefs(TreeCCContext *context,
+ 						    TreeCCNode *node)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM) != 0)
+ 	{
+ 		int counter = 0;
+ 		/* Define an enumerated type */
+ 		TreeCCStream *stream = node->source;
+ 		TreeCCNode *child;
+ 		TreeCCStreamPrint(stream, "class %s \n", node->name);
+ 		child = node->firstChild;
+ 		while(child != 0)
+ 		{
+ 			if((child->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "  %s = %i\n", child->name, counter++);
+ 			}
+ 
+ 			child = child->nextSibling;
+ 		}
+ 		TreeCCStreamPrint(stream, "end\n\n");
+ 	}
+ }
+ 
+ /*
+  * Output the parameters for a node creation function.
+  */
+ static int CreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 						TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = CreateParams(context, stream, node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			/* Don't name the types, Ruby figures that out */
+ 			TreeCCStreamPrint(stream, "%s", /*field->type,*/ field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output the parameters to call an inherited constructor.
+  */
+ static int InheritParamsSource(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = InheritParamsSource(context, stream,
+ 									    node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /* 
+  * Implement the virtual methods that have implementations in a node type.
+  */
+ static void ImplementVirtuals(TreeCCContext *context, TreeCCStream *stream,
+ 							  TreeCCNode *node, TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCParam *param;
+ 	TreeCCOperationCase *operCase;
+ 	int declareCase, abstractCase;
+ 	TreeCCNode *tempNode;
+ 	int num, first;
+ 	int needComma;
+ 	if(node->parent)
+ 	{
+ 		ImplementVirtuals(context, stream, node->parent, actualNode);
+ 	}
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		/* Determine if we need a definition for this virtual,
+ 		   and whether the definition is real or abstract */
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			tempNode = actualNode->parent;
+ 			abstractCase = 1;
+ 			while(tempNode != 0)
+ 			{
+ 				operCase = TreeCCOperationFindCase
+ 								(context, tempNode, virt->name);
+ 				if(operCase != 0)
+ 				{
+ 					abstractCase = 0;
+ 					break;
+ 				}
+ 				tempNode = tempNode->parent;
+ 			}
+ 			declareCase = abstractCase;
+ 		}
+ 		else
+ 		{
+ 			declareCase = 1;
+ 			abstractCase = 0;
+ 		}
+ 		if(declareCase)
+ 		{
+ 			if(abstractCase)
+ 			{
+ 				if(node == actualNode)
+ 				{
+ 					TreeCCStreamPrint(stream, "  def %s(", virt->name);
+ 				}
+ 				else
+ 				{
+ 					/* Inherit the "abstract" definition from the parent */
+ 					virt = virt->next;
+ 					continue;
+ 				}
+ 			}
+ 			else
+ 			{
+ 				if(node == actualNode)
+ 				{
+ 					TreeCCStreamPrint(stream, "  def %s(", virt->name);
+ 				}
+ 				else
+ 				{
+ 					TreeCCStreamPrint(stream, "  def %s(", virt->name);
+ 				}
+ 			}
+ 			param = virt->oper->params;
+ 			needComma = 0;
+ 			num = 1;
+ 			first = 1;
+ 			while(param != 0)
+ 			{
+ 				if(needComma)
+ 				{
+ 					TreeCCStreamPrint(stream, ", ");
+ 				}
+ 				if(first)
+ 				{
+ 					/* Skip the first argument, which corresponds to "this" */
+ 					if(!(param->name))
+ 					{
+ 						++num;
+ 					}
+ 					first = 0;
+ 				}
+ 				else
+ 				{
+ 					if(param->name)
+ 					{
+ 						TreeCCStreamPrint(stream, "%s", param->name);
+ 					}
+ 					else
+ 					{
+ 						TreeCCStreamPrint(stream, "P%d__", num);
+ 						++num;
+ 					}
+ 					needComma = 1;
+ 				}
+ 				param = param->next;
+ 			}
+ 			if(!abstractCase)
+ 			{
+ 				TreeCCStreamPrint(stream, ")\n");
+ 				TreeCCStreamLine(stream, operCase->codeLinenum,
+ 								 operCase->codeFilename);
+ 				TreeCCStreamPrint(stream, "  ");
+ 				if(!(virt->oper->params->name) ||
+ 				   !strcmp(virt->oper->params->name, "self"))
+ 				{
+ 					/* The first parameter is called "this", so we don't
+ 					   need to declare it at the head of the function */
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				else
+ 				{
+ 					/* The first parameter is called something else,
+ 					   so create a temporary variable to hold "this" */
+ 				   	TreeCCStreamPrint(stream, "\n    %s %s = self\n  ",
+ 									  actualNode->name,
+ 									  virt->oper->params->name);
+ 					TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 				}
+ 				TreeCCStreamPrint(stream, "  end\n");
+ 				TreeCCStreamFixLine(stream);
+ 				TreeCCStreamPrint(stream, "\n");
+ 			}
+ 			else
+ 			{
+ 				TreeCCStreamPrint(stream, ")\n  end\n");
+ 			}
+ 		}
+ 		virt = virt->next;
+ 	}
+ }
+ 
+ /*
+  * Build the type declarations for a node type.
+  */
+ static void BuildTypeDecls(TreeCCContext *context,
+ 						   TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 	int needComma;
+ 	/*const char *constructorAccess; NOT USED*/
+ 	TreeCCField *field;
+ 	int isAbstract;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine if this class has abstract virtuals */
+ 	isAbstract = TreeCCNodeHasAbstracts(context, node);
+ 
+ 	/* Output the class header */
+ 	stream = node->source;
+ 	if(node->parent)
+ 	{
+ 		/* Inherit from a specified parent type */
+ 		/* Ruby doesn't know abstract */	
+ 		/*   
+ 		if(isAbstract)
+ 		{
+ 			TreeCCStreamPrint(stream, "public abstract class %s : %s\n{\n",
+ 							  node->name, node->parent->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "public class %s : %s\n{\n",
+ 							  node->name, node->parent->name);
+ 		}
+ 		*/
+ 		TreeCCStreamPrint(stream, "class %s < %s\n",
+ 						  node->name, node->parent->name);
+ 	}
+ 	else
+ 	{
+ 		/* This type is the base of a class hierarchy */
+ 		/* Ruby doesn't know abstract */
+ /*		if(isAbstract)
+ 		{
+ 			TreeCCStreamPrint(stream, "public abstract class %s\n{\n",
+ 							  node->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "public class %s\n{\n", node->name);
+ 		}*/
+ 
+ 		TreeCCStreamPrint(stream, "class %s\n", node->name);
+ 
+ 		/* Declare the node kind member variable */
+ 		/* No declaration needed in Ruby */
+ 
+ 		/* Declare the filename and linenum fields if we are tracking lines */
+ 		/* Not needed */
+ 
+ 		/* Declare the public methods for access to the above fields */
+ 		/* Ruby has handy accessor creating stuff */
+ 		/*TreeCCStreamPrint(stream,
+ 				"  public int getKind() { return kind__; }\n");*/
+ 		TreeCCStreamPrint(stream,
+ 				"  protected\n  attr_reader :kind\n  public\n\n");
+ 			
+ 		if(context->track_lines)
+ 		{
+ 			/* A same kind of hack here*/
+ 			/*TreeCCStreamPrint(stream,
+ 				"  public String getFilename() { return filename__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"  public long getLinenum() { return linenum__; }\n");
+ 			TreeCCStreamPrint(stream,
+ 			 	"  public void setFilename(String filename) "
+ 					"{ filename__ = filename; }\n");
+ 			TreeCCStreamPrint(stream,
+ 				"  public void setLinenum(long linenum) "
+ 					"{ linenum__ = linenum; }\n");*/
+ 			TreeCCStreamPrint(stream,
+ 				"  attr_accessor :Linenum, :Filename\n");
+ 		}
+ 		TreeCCStreamPrint(stream, "\n");
+ 	}
+ 
+ 	/* Add the attr_accessor stuff for nodes specific to this node type */
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		TreeCCStreamPrint(stream, "  attr_accessor :%s\n", field->name);
+ 		field = field->next;
+ 	}
+ 	/* End this section with an extra newline */
+ 	TreeCCStreamPrint(stream, "\n");
+ 
+ 	/* Declare the kind value */
+ 	/* Stick to the Ruby convention of constants, start with Uppercase,
+ 	   continue with lowercase */
+ 	/* The parent doesn't matter, so don't check it */
+ 	TreeCCStreamPrint(stream, "  KIND = %d\n\n",
+ 					  node->number);
+ 
+ 	/* Declare the constructor for the node type */
+ 	/* A constructor is always public (I hope) anyway I don't expect
+ 	   Ruby to cause troubles here */
+ 
+ 	/* The constructor is ALWAYS called initialize */
+ 	TreeCCStreamPrint(stream, "  def initialize(");
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCStreamPrint(stream, "state__");
+ 		needComma = 1;
+ 
+ 	}
+ 	else
+ 	{
+ 		needComma = 0;
+ 	}
+ 	
+ 	CreateParams(context, stream, node, needComma);
+ 
+ 	TreeCCStreamPrint(stream, ")\n");
+ 	
+ 	/* Enter the super call */
+ 	/* Call the parent class constructor */
+ 	if(node->parent)
+ 	{
+ 		/* Do not use base, Ruby uses super for that */
+ 		/*TreeCCStreamPrint(stream, "    : base(");*/
+ 		TreeCCStreamPrint(stream, "    super(");
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream, "@state");
+ 			needComma = 1;
+ 		}
+ 		else
+ 		{
+ 			needComma = 0;
+ 		}
+ 		CreateParams(context, stream, node, needComma);		
+ 		InheritParamsSource(context, stream, node->parent, needComma);
+ 		TreeCCStreamPrint(stream, ")\n");
+ 	}
+ 	
+ 	/* Set the node kind */	
+ 	TreeCCStreamPrint(stream, "    @kind = KIND\n");
+ 
+ 	/* Track the filename and line number if necessary */
+ 	if(context->track_lines && !(node->parent))
+ 	{
+ 		if(context->reentrant)
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"    @Filename = @state.currFilename\n");
+ 			TreeCCStreamPrint(stream,
+ 					"    @Finenum = @state.currLinenum\n");
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"    @Filename = %s.state.currFilename()\n",
+ 					context->state_type);
+ 			TreeCCStreamPrint(stream,
+ 					"    @Linenum = %s.state.currLinenum()\n",
+ 					context->state_type);
+ 		}
+ 	}
+ 
+ 	/* Initialize the fields that are specific to this node type */
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			TreeCCStreamPrint(stream, "    self.%s = %s\n",
+ 							  field->name, field->name);
+ 		}
+ 		else if(field->value)
+ 		{
+ 			TreeCCStreamPrint(stream, "    self.%s = %s\n",
+ 							  field->name, field->value);
+ 		}
+ 		field = field->next;
+ 	}
+ 	TreeCCStreamPrint(stream, "  end\n\n");
+ 
+ 	/* Implement the virtual functions */
+ 	ImplementVirtuals(context, stream, node, node);
+ 
+ 	/* Declare the "isA" and "getKindName" helper methods */
+ 
+ 	TreeCCStreamPrint(stream, "  def isA(kind)\n");
+ 
+ 	TreeCCStreamPrint(stream, "    if(@kind == KIND) then\n");
+ 	TreeCCStreamPrint(stream, "      return true\n");
+ 	TreeCCStreamPrint(stream, "    else\n");
+ 	if(node->parent)
+ 	{
+ 		TreeCCStreamPrint(stream, "      return super(kind)\n    end\n");
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "      return 0\n    end\n");
+ 	}
+ 	TreeCCStreamPrint(stream, "  end\n\n");
+ 
+ 	TreeCCStreamPrint(stream, "  def KindName\n");
+ 
+ 	TreeCCStreamPrint(stream, "    return \"%s\"\n", node->name);
+ 	TreeCCStreamPrint(stream, "  end\n");
+ 
+ 	/* Output the class footer */
+ 	TreeCCStreamPrint(stream, "end\n\n");
+ }
+ 
+ /*
+  * Declare the parameters for a factory method in the state type.
+  */
+ static int FactoryCreateParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryCreateParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			/* Delete the types */
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Output invocation parameters for a call to a constructor
+  * from within a factory method.
+  */
+ static int FactoryInvokeParams(TreeCCContext *context, TreeCCStream *stream,
+ 							   TreeCCNode *node, int needComma)
+ {
+ 	TreeCCField *field;
+ 	if(node->parent)
+ 	{
+ 		needComma = FactoryInvokeParams(context, stream,
+ 										node->parent, needComma);
+ 	}
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if((field->flags & TREECC_FIELD_NOCREATE) == 0)
+ 		{
+ 			if(needComma)
+ 			{
+ 				TreeCCStreamPrint(stream, ", ");
+ 			}
+ 			TreeCCStreamPrint(stream, "%s", field->name);
+ 			needComma = 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return needComma;
+ }
+ 
+ /*
+  * Implement the create function for a node type.
+  */
+ static void ImplementCreateFuncs(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	TreeCCStream *stream;
+ 
+ 	/* Ignore if this is an enumerated type node */
+ 	if((node->flags & (TREECC_NODE_ENUM | TREECC_NODE_ENUM_VALUE)) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Ignore this if it is an abstract node */
+ 	if((node->flags & TREECC_NODE_ABSTRACT) != 0)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Determine which stream to write to */
+ 	if(context->commonSource)
+ 	{
+ 		stream = context->commonSource;
+ 	}
+ 	else
+ 	{
+ 		stream = context->sourceStream;
+ 	}
+ 
+ 	/* Output the start of the function definition */
+ 	TreeCCStreamPrint(stream, "  def %s %sCreate(",
+ 					  node->name, node->name);
+ 
+ 	/* Output the parameters for the create function */
+ 	FactoryCreateParams(context, stream, node, 0);
+ 
+ 	/* Output the body of the creation function */
+ 	if(context->abstract_factory)
+ 	{
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		TreeCCStreamPrint(stream, "raise \"Abstract method called: %s\\n\"\n", node->name);		
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		TreeCCStreamPrint(stream, "    return %s.new(this", node->name);
+ 		FactoryInvokeParams(context, stream, node, 1);
+ 		TreeCCStreamPrint(stream, ")\n");
+ 		TreeCCStreamPrint(stream, "  end\n\n");
+ 	}
+ }
+ 
+ /*
+  * Implement the state type in the source stream.
+  */
+ static void ImplementStateType(TreeCCContext *context, TreeCCStream *stream)
+ {
+ 	TreeCCStreamPrint(stream, "class %s\n",
+ 					  context->state_type);
+ 
+ 	TreeCCStreamPrint(stream, "  @@state = nil\n");
+ 
+ 	/* Singleton handling for non-reentrant systems */
+ 	if(!(context->reentrant))
+ 	{
+ 		TreeCCStreamPrint(stream, "  def %s.state\n", context->state_type);
+ 		TreeCCStreamPrint(stream, "    return @@state unless @@state.nil?\n");
+ 		TreeCCStreamPrint(stream, "    @@state = %s.new()\n",
+ 						  context->state_type);
+ 		TreeCCStreamPrint(stream, "    return @@state\n");
+ 		TreeCCStreamPrint(stream, "  end\n\n");
+ 	}
+ 
+ 	/* Implement the constructor */
+ 	if(context->reentrant)
+ 	{
+ 		/* No constructor */
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "  def intialize \n     @@state = self \n   end\n\n");
+ 	}
+ 
+ 	/* Implement the create functions for all of the node types */
+ 	if(context->reentrant)
+ 	{
+ 		TreeCCNodeVisitAll(context, ImplementCreateFuncs);
+ 	}
+ 
+ 	/* Implement the line number tracking methods */
+ 	if(context->track_lines)
+ 	{
+ 		TreeCCStreamPrint(stream,
+ 			"  def currFilename \n     return nil \n  end\n\n");
+ 		TreeCCStreamPrint(stream,
+ 			"  def currLinenum \n     return 0 \n  end\n\n");
+ 	}
+ 
+ 	/* Declare the end of the state type */
+ 	TreeCCStreamPrint(stream, "end\n\n");
+ }
+ 
+ /*
+  * Write out header information for all streams.
+  */
+ static void WriteRubyHeaders(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamPrint(stream,
+ 					"# %s.  Generated automatically by treecc \n\n",
+ 					stream->embedName);
+ 			if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "module %s\nbegin\n\n",
+ 								  context->namespace);
+ 			}
+ 			/*Ruby doesn't require a System lib to be included*/
+ 			/*TreeCCStreamPrint(stream, "using System;\n\n");*/
+ 			TreeCCStreamSourceTopCS(stream);
+ 		}
+ 		if(stream->defaultFile)
+ 		{
+ 			/* Reset the dirty flag if this is a default stream,
+ 			   because we don't want to write out the final file
+ 			   if it isn't actually written to in practice */
+ 			stream->dirty = 0;
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Write out footer information for all streams.
+  */
+ static void WriteRubyFooters(TreeCCContext *context)
+ {
+ 	TreeCCStream *stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(stream->defaultFile && !(stream->dirty))
+ 		{
+ 			/* Clear the default file's contents, which we don't need */
+ 			TreeCCStreamClear(stream);
+ 		}
+ 		else if(!(stream->isHeader))
+ 		{
+ 			TreeCCStreamSourceBottom(stream);
+ 			if(context->namespace)
+ 			{
+ 				TreeCCStreamPrint(stream, "end\n");
+ 			}
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ }
+ 
+ /*
+  * Determine if a type name corresponds to an enumerated type.
+  */
+ static int IsEnumType(TreeCCContext *context, const char *type)
+ {
+ 	TreeCCNode *node = TreeCCNodeFindByType(context, type);
+ 	if(node)
+ 	{
+ 		if((node->flags & TREECC_NODE_ENUM) != 0)
+ 		{
+ 			return 1;
+ 		}
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * Output spaces's for a specific level of indenting.
+  */
+ static void Indent(TreeCCStream *stream, int indent)
+ {
+ 	while(indent >= 4)
+ 	{
+ 		TreeCCStreamPrint(stream, "        ");
+ 		indent -= 4;
+ 	}
+ 	if(indent == 1)
+ 	{
+ 		TreeCCStreamPrint(stream, "  ");
+ 	}
+ 	else if(indent == 2)
+ 	{
+ 		TreeCCStreamPrint(stream, "    ");
+ 	}
+ 	else if(indent == 3)
+ 	{
+ 		TreeCCStreamPrint(stream, "      ");
+ 	}
+ }
+ 
+ /*
+  * Non-virtual code generation functions start here
+  */
+ 
+ /*
+  * Generate the start declarations for a non-virtual operation.
+  */
+ static void Ruby_GenStart(TreeCCContext *context, TreeCCStream *stream,
+ 					      TreeCCOperation *oper)
+ {
+ 	if(oper->className)
+ 	{
+ 		TreeCCStreamPrint(stream, "class %s\n", oper->className);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "class %s\n", oper->name);
+ 	}
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void RubyGenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					     TreeCCOperation *oper, int number)
+ {
+ 	TreeCCParam *param;
+ 	int num;
+ 	int needComma;
+ 	char *cname;
+ 
+ 	if(oper->className)
+ 	{
+ 		cname = oper->className;
+ 	}
+ 	else
+ 	{
+ 		cname = oper->name;
+ 	}	
+ 
+ 	if(number != -1)
+ 	{
+ 		TreeCCStreamPrint(stream, "  private \n  def %s.%s_split_%d__(",
+ 						  cname, oper->name, number);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "  public \n  def %s.%s(",
+ 						  cname, oper->name);
+ 	}
+ 
+ 	param = oper->params;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "p%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(!IsEnumType(context, param->type))
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ }
+ 
+ /*
+  * Generate the entry point for a non-virtual operation.
+  */
+ static void Ruby_GenEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					      TreeCCOperation *oper)
+ {
+ 	RubyGenEntry(context, stream, oper, -1);
+ }
+ 
+ /*
+  * Generate the entry point for a split-out function.
+  */
+ static void Ruby_GenSplitEntry(TreeCCContext *context, TreeCCStream *stream,
+ 					           TreeCCOperation *oper, int number)
+ {
+ 	RubyGenEntry(context, stream, oper, number);
+ }
+ 
+ /*
+  * Generate the head of a "switch" statement.
+  */
+ static void Ruby_GenSwitchHead(TreeCCContext *context, TreeCCStream *stream,
+ 							   char *paramName, int level, int isEnum)
+ {
+ 	Indent(stream, level * 2 + 2);
+ 	if(isEnum)
+ 	{
+ 		TreeCCStreamPrint(stream, "case %s\n", paramName);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamPrint(stream, "case %s__.type::KIND\n", paramName);
+ 	}
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "\n");
+ }
+ 
+ /*
+  * Generate a selector for a "switch" case.
+  */
+ static void Ruby_GenSelector(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCNode *node, int level)
+ {
+ 	if((node->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 	{
+ 		Indent(stream, level * 2 + 3);
+ 		TreeCCStreamPrint(stream, "when %s.%s\n",
+ 						  node->parent->name, node->name);
+ 	}
+ 	else if((node->flags & TREECC_NODE_ENUM) == 0)
+ 	{
+ 		Indent(stream, level * 2 + 3);
+ 		TreeCCStreamPrint(stream, "when %s::KIND\n", node->name);
+ 	}
+ }
+ 
+ /*
+  * Terminate the selectors and begin the body of a "switch" case.
+  */
+ static void Ruby_GenEndSelectors(TreeCCContext *context, TreeCCStream *stream,
+ 							     int level)
+ {
+ 	/* No use for this in Ruby */
+ }
+ 
+ /*
+  * Generate the code for a case within a function.
+  */
+ static void Ruby_GenCaseFunc(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCOperationCase *operCase, int number)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 	char *type;
+ 	char *cname;
+ 
+ 	if(operCase->oper->className)
+ 	{
+ 		cname = operCase->oper->className;
+ 	}
+ 	else
+ 	{
+ 		cname = operCase->oper->name;
+ 	}	
+ 
+ 	/* Output the header for the function */
+ 	TreeCCStreamPrint(stream, "  private \n  def %s.%s_%d__(",
+ 					  cname, operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 		   	if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				type = trigger->node->name;
+ 			}
+ 			else
+ 			{
+ 				type = param->type;
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		else
+ 		{
+ 			type = param->type;
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "p%d__", num);
+ 			++num;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ 
+ 	/* Output the code for the operation case */
+ 	if(operCase->code)
+ 	{
+ 		TreeCCStreamCodeIndent(stream, operCase->code, 1);
+ 	}
+ 	TreeCCStreamPrint(stream, "end\n");
+ 	TreeCCStreamPrint(stream, "\n");
+ }
+ 
+ /*
+  * Generate a call to a case function from within the "switch".
+  */
+ static void Ruby_GenCaseCall(TreeCCContext *context, TreeCCStream *stream,
+ 						     TreeCCOperationCase *operCase, int number,
+ 						     int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 1);
+ 
+ 	/* Print out the call */
+ 	TreeCCStreamPrint(stream, "%s_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ /*		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "(%s)", trigger->node->name);
+ 			}
+ 		}*/
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "p%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ }
+ 
+ /*
+  * Generate the code for a case inline within the "switch".
+  */
+ static void Ruby_GenCaseInline(TreeCCContext *context, TreeCCStream *stream,
+ 						       TreeCCOperationCase *operCase, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 
+ 	/* Copy the parameters to new variables of the correct types */
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	while(param != 0)
+ 	{
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if(param->name != 0)
+ 			{
+ 				if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 				   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 				{
+ 					Indent(stream, level * 2 + 4);
+ 					TreeCCStreamPrint(stream, "%s = %s__;\n",
+ 									  param->name, param->name);
+ 				}
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		param = param->next;
+ 	}
+ 
+ 	/* Output the inline code for the case */
+ 	Indent(stream, level * 2 + 4);
+ 	if(operCase->code)
+ 	{
+ 		/* Multiply the indent level by two because every ident is one space */
+ 		TreeCCStreamCodeIndentCustom
+ 			(stream, operCase->code,' ',(level * 2 + 3) * 2);		
+ 	}
+ 	Indent(stream, level * 2 + 4);
+ 	TreeCCStreamPrint(stream, "\n");
+ }
+ 
+ /*
+  * Generate a call to a split function from within the "switch".
+  */
+ static void Ruby_GenCaseSplit(TreeCCContext *context, TreeCCStream *stream,
+ 						      TreeCCOperationCase *operCase,
+ 							  int number, int level)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCTrigger *trigger;
+ 	int num;
+ 	int needComma;
+ 
+ 	/* Indent to the correct level */
+ 	Indent(stream, level * 2 + 2);
+ 
+ 	/* Print out the call */
+ 	TreeCCStreamPrint(stream, "%s_split_%d__(", operCase->oper->name, number);
+ 	param = operCase->oper->params;
+ 	trigger = operCase->triggers;
+ 	num = 1;
+ 	needComma = 0;
+ 	while(param != 0)
+ 	{
+ 		if(needComma)
+ 		{
+ 			TreeCCStreamPrint(stream, ", ");
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "%s", trigger->node->name);
+ 			}
+ 		}
+ 		if(param->name)
+ 		{
+ 			TreeCCStreamPrint(stream, "%s", param->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "p%d__", num);
+ 			++num;
+ 		}
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			if((trigger->node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   	   (trigger->node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 			{
+ 				TreeCCStreamPrint(stream, "__");
+ 			}
+ 			trigger = trigger->next;
+ 		}
+ 		needComma = 1;
+ 		param = param->next;
+ 	}
+ 	TreeCCStreamPrint(stream, ")\n");
+ }
+ 
+ /*
+  * Terminate a "switch" case.
+  */
+ static void Ruby_GenEndCase(TreeCCContext *context, TreeCCStream *stream,
+ 						    int level)
+ {
+ 	/*Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "\n");*/
+ }
+ 
+ /*
+  * Terminate the "switch" statement.
+  */
+ static void Ruby_GenEndSwitch(TreeCCContext *context, TreeCCStream *stream,
+ 						      int level)
+ {
+ 	Indent(stream, level * 2 + 3);
+ 	TreeCCStreamPrint(stream, "else\n");
+ 	Indent(stream, level * 2 + 2);
+ 	TreeCCStreamPrint(stream, "end\n");
+ }
+ 
+ /*
+  * Generate the exit point for a non-virtual operation.
+  */
+ static void Ruby_GenExit(TreeCCContext *context, TreeCCStream *stream,
+ 					     TreeCCOperation *oper)
+ {
+ 	if(strcmp(oper->returnType, "void") != 0)
+ 	{
+ 		/* Generate a default return value for the function */
+ 		if(oper->defValue)
+ 		{
+ 			TreeCCStreamPrint(stream, "  return %s\n", oper->defValue);
+ 		}
+ 		else
+ 		{
+ 			TreeCCStreamPrint(stream, "  return 0\n");
+ 		}
+ 	}
+ 	TreeCCStreamPrint(stream, "  end\n");
+ }
+ 
+ /*
+  * Generate the end declarations for a non-virtual operation.
+  */
+ static void Ruby_GenEnd(TreeCCContext *context, TreeCCStream *stream,
+ 					    TreeCCOperation *oper)
+ {
+ 	TreeCCStreamPrint(stream, "end\n");
+ }
+ 
+ /*
+  * Table of non-virtual code generation functions.
+  */
+ TreeCCNonVirtual const TreeCCNonVirtualFuncsRuby = {
+ 	Ruby_GenStart,
+ 	Ruby_GenEntry,
+ 	Ruby_GenSplitEntry,
+ 	Ruby_GenSwitchHead,
+ 	Ruby_GenSelector,
+ 	Ruby_GenEndSelectors,
+ 	Ruby_GenCaseFunc,
+ 	Ruby_GenCaseCall,
+ 	Ruby_GenCaseInline,
+ 	Ruby_GenCaseSplit,
+ 	Ruby_GenEndCase,
+ 	Ruby_GenEndSwitch,
+ 	Ruby_GenExit,
+ 	Ruby_GenEnd,
+ };
+ 
+ void TreeCCGenerateRuby(TreeCCContext *context)
+ {
+ 	/* Write all stream headers */
+ 	WriteRubyHeaders(context);
+ 
+ 	/* Generate the contents of the source stream */
+ 	TreeCCNodeVisitAll(context, DeclareTypeDefs);
+ 	if(context->commonSource)
+ 	{
+ 		ImplementStateType(context, context->commonSource);
+ 	}
+ 	else
+ 	{
+ 		ImplementStateType(context, context->sourceStream);
+ 	}
+ 	TreeCCNodeVisitAll(context, BuildTypeDecls);
+ 	/* NO JAVA PLEASE */
+ 	TreeCCGenerateNonVirtuals(context, &TreeCCNonVirtualFuncsRuby);
+ 	
+ 
+ 	/* Write all stream footers */
+ 	WriteRubyFooters(context);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/info.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/info.h:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/info.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,413 ----
+ /*
+  * info.h - Store information about parsed "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_INFO_H
+ #define	_TREECC_INFO_H
+ 
+ #include "stream.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Forward declarations.
+  */
+ typedef struct _tagTreeCCField			TreeCCField;
+ typedef struct _tagTreeCCNode			TreeCCNode;
+ typedef struct _tagTreeCCOperation		TreeCCOperation;
+ typedef struct _tagTreeCCParam			TreeCCParam;
+ typedef struct _tagTreeCCVirtual		TreeCCVirtual;
+ typedef struct _tagTreeCCTrigger		TreeCCTrigger;
+ typedef struct _tagTreeCCOperationCase	TreeCCOperationCase;
+ 
+ /*
+  * Field definition flags.
+  */
+ #define	TREECC_FIELD_NOCREATE		1
+ 
+ /*
+  * Node definition flags.
+  */
+ #define	TREECC_NODE_UNDEFINED		1
+ #define	TREECC_NODE_ABSTRACT		2
+ #define	TREECC_NODE_TYPEDEF			4
+ #define	TREECC_NODE_ENUM			8
+ #define	TREECC_NODE_ENUM_VALUE		16
+ #define	TREECC_NODE_MARK(n)			(0x100 << (n))
+ #define	TREECC_NODE_MARK_BITS		0xFF00
+ 
+ /*
+  * Operation flags.
+  */
+ #define	TREECC_OPER_VIRTUAL			1
+ #define	TREECC_OPER_INLINE			2
+ #define	TREECC_OPER_SPLIT			4
+ 
+ /*
+  * Parameter flags.
+  */
+ #define	TREECC_PARAM_TRIGGER		1
+ 
+ /*
+  * Language values.
+  */
+ #define	TREECC_LANG_C				0
+ #define	TREECC_LANG_CPP				1
+ #define	TREECC_LANG_JAVA			2
+ #define	TREECC_LANG_CSHARP			3
+ #define	TREECC_LANG_RUBY			4
+ #define	TREECC_LANG_PHP				5
+ 
+ /*
+  * Information that is stored about a field.
+  */
+ struct _tagTreeCCField
+ {
+ 	char		   *name;		/* Name of the field */
+ 	char		   *type;		/* Type associated with the field */
+ 	char		   *value;		/* Default value for the field */
+ 	int				flags;		/* Field flags */
+ 	char		   *filename;	/* File that defines the field */
+ 	long			linenum;	/* Line where the field is defined */
+ 	TreeCCField	   *next;		/* Next field for the node type */
+ 
+ };
+ 
+ /*
+  * Information that is stored about a node type.
+  */
+ struct _tagTreeCCNode
+ {
+ 	TreeCCNode	   *parent;		/* Parent node type */
+ 	TreeCCNode	   *firstChild;	/* First child node type */
+ 	TreeCCNode	   *lastChild;	/* Last child node type */
+ 	TreeCCNode	   *nextSibling;/* Next sibling node type under parent */
+ 	char		   *name;		/* Name of this node type */
+ 	int				flags;		/* Node flags */
+ 	int				number;		/* Number associated with this node type */
+ 	int				position;	/* Position within the tree for operations */
+ 	char		   *filename;	/* File that defines the node type */
+ 	long			linenum;	/* Line where the node type is defined */
+ 	TreeCCField    *fields;		/* List of fields for this node type */
+ 	TreeCCVirtual  *virtuals;	/* List of virtual methods for this node */
+ 	TreeCCNode	   *nextHash;	/* Next in the name hash table */
+ 	TreeCCStream   *header;		/* Stream to write header to */
+ 	TreeCCStream   *source;		/* Stream to write source to */
+ 
+ };
+ 
+ /*
+  * Information that is stored about an operation.
+  */
+ struct _tagTreeCCOperation
+ {
+ 	char		   *name;		/* Name of the operation */
+ 	char		   *className;	/* Name of the enclosing class */
+ 	char		   *returnType;	/* Return type for the operation */
+ 	char		   *defValue;	/* Default value for the operation */
+ 	TreeCCParam    *params;		/* Parameters for the operation */
+ 	int				flags;		/* Flags associated with the operation */
+ 	int				numTriggers;/* Number of trigger parameters */
+ 	char		   *filename;	/* File where the operation is declared */
+ 	long			linenum;	/* Line where the operation is declared */
+ 	TreeCCOperation *nextHash;	/* Next in the operation hash table */
+ 	TreeCCOperationCase *firstCase; /* First case associated with operation */
+ 	TreeCCOperationCase *lastCase;  /* Last case associated with operation */
+ 	TreeCCOperationCase **sortedCases; /* Cases sorted for non-virtual ops */
+ 	int				numCases;	/* Number of operation cases */
+ 	TreeCCStream   *header;		/* Stream to write header to */
+ 	TreeCCStream   *source;		/* Stream to write source to */
+ 
+ };
+ 
+ /*
+  * Information that is stored about an operation parameter.
+  */
+ struct _tagTreeCCParam
+ {
+ 	char		   *name;		/* Name of the parameter */
+ 	char		   *type;		/* Type for the parameter */
+ 	int				flags;		/* Flags associated with the parameter */
+ 	int				size;		/* Dimension size for non-virtual operations */
+ 	TreeCCParam	   *next;		/* Next parameter for the operation */
+ 
+ };
+ 
+ /*
+  * Information that is stored about a virtual method on a node type.
+  */
+ struct _tagTreeCCVirtual
+ {
+ 	char		   *name;		/* Name of the virtual method */
+ 	char		   *returnType;	/* Return type for the virtual method */
+ 	TreeCCParam	   *params;		/* Non-instance parameters */
+ 	TreeCCOperation *oper;		/* Operation block for the virtual */
+ 	TreeCCVirtual  *next;		/* Next virtual method for the node type */
+ 
+ };
+ 
+ /*
+  * Information that is stored about a trigger match on an operation case.
+  */
+ struct _tagTreeCCTrigger
+ {
+ 	TreeCCNode	   *node;		/* Node type for the trigger */
+ 	TreeCCTrigger  *next;		/* Next trigger for this case */
+ 
+ };
+ 
+ /*
+  * Information that is stored about an operation case.
+  */
+ struct _tagTreeCCOperationCase
+ {
+ 	TreeCCTrigger  *triggers;	/* Trigger list for this case */
+ 	char		   *code;		/* Code associated with the case */
+ 	TreeCCOperation *oper;		/* Operation this case is associated with */
+ 	int				number;		/* Reference number for code generation */
+ 	char		   *filename;	/* File that starts the case definition */
+ 	long		   	linenum;	/* Line that starts the case definition */
+ 	char		   *codeFilename;/* File that starts the code */
+ 	long		   	codeLinenum;/* Line that starts the code */
+ 	TreeCCOperationCase *next;	/* Next case for the operation */
+ 	TreeCCOperationCase *nextHeader; /* Next header for same code block */
+ 
+ };
+ 
+ /*
+  * Context object that stores all definitions parsed from the input.
+  */
+ #define	TREECC_HASH_SIZE	512
+ typedef struct _tagTreeCCContext
+ {
+ 	/* Hash table that allows quick lookup of node types */
+ 	TreeCCNode	   *nodeHash[TREECC_HASH_SIZE];
+ 
+ 	/* Hash table that allows quick lookup of operation names */
+ 	TreeCCOperation *operHash[TREECC_HASH_SIZE];
+ 
+ 	/* Current input stream */
+ 	TreeCCInput	   *input;
+ 
+ 	/* Output streams */
+ 	TreeCCStream   *streamList;			/* List of all streams */
+ 	TreeCCStream   *headerStream;		/* Current header stream */
+ 	TreeCCStream   *sourceStream;		/* Current source stream */
+ 	TreeCCStream   *commonHeader;		/* Stream for common definitions */
+ 	TreeCCStream   *commonSource;		/* Stream for common source */
+ 
+ 	/* Flags that control the behaviour of the program */
+ 	int				debugMode : 1;		/* Enable debug output */
+ 	int				track_lines : 1;	/* Track node creation lines */
+ 	int				no_singletons : 1;	/* Don't handle singletons specially */
+ 	int				reentrant : 1;		/* Build a re-entrant system */
+ 	int				force : 1;			/* Force the creation of files */
+ 	int				virtual_factory : 1;/* Allow overrides of factory methods */
+ 	int				abstract_factory : 1;/* Declare factory methods abstract */
+ 	int				kind_in_vtable : 1;	/* Put kind value in vtable only */
+ 	int				strip_filenames : 1; /* Strip names in #line directives */
+ 	int				print_lines : 1;	/* Dont emit #line directives */
+ 	int				internal_access : 1; /* Use "internal" classes in C# */
+ 	int				use_allocator : 1;	/* Use the skeleton allocator */
+ 	int				use_gc_allocator : 1; /* Use the libgc allocator */
+ 
+ 	/* String to use to replace "yy" in output files */
+ 	char		   *yy_replacement;
+ 
+ 	/* Name of the type to use for re-entrant state */
+ 	char		   *state_type;
+ 
+ 	/* Namespace to store declarations within */
+ 	char		   *namespace;
+ 
+ 	/* Current node type number */
+ 	int				nodeNumber;
+ 
+ 	/* Output source language to use */
+ 	int				language;
+ 
+ 	/* Size of blocks to use in C/C++ memory alloction */
+ 	int				block_size;
+ 
+ 	/* Name of the directory to output Java source files to */
+ 	char		   *outputDirectory;
+ 
+ 	/* name of the base type which is what %typedef expands to */
+ 	char		   *baseType;
+ 
+ } TreeCCContext;
+ 
+ /*
+  * Create a context.
+  */
+ TreeCCContext *TreeCCContextCreate(TreeCCInput *input);
+ 
+ /*
+  * Destroy a context.
+  */
+ void TreeCCContextDestroy(TreeCCContext *context);
+ 
+ /*
+  * Hash a string.
+  */
+ unsigned int TreeCCHashString(const char *str);
+ 
+ /*
+  * Flags for "TreeCCAddLiteralDefn".
+  */
+ #define	TREECC_LITERAL_CODE			1		/* In source */
+ #define	TREECC_LITERAL_DECLS		2		/* In header */
+ #define	TREECC_LITERAL_END			4		/* Place at end */
+ 
+ /*
+  * Add a literal code definition block to the context.
+  */
+ void TreeCCAddLiteralDefn(TreeCCContext *context, char *code, int flags);
+ 
+ /*
+  * Free a node definition.
+  */
+ void TreeCCNodeFree(TreeCCNode *node);
+ 
+ /*
+  * Create a new node definition.
+  */
+ TreeCCNode *TreeCCNodeCreate(TreeCCContext *context, long linenum,
+ 					  		 char *name, char *parent, int flags);
+ 
+ /*
+  * Find a node definition given its name.
+  */
+ TreeCCNode *TreeCCNodeFind(TreeCCContext *context, const char *name);
+ 
+ /*
+  * Find a node definition given a type name, which may be
+  * either "identifier" or "identifier *".
+  */
+ TreeCCNode *TreeCCNodeFindByType(TreeCCContext *context, const char *name);
+ 
+ /*
+  * Validate the node type hierarchy to ensure that everything is defined.
+  */
+ void TreeCCNodeValidate(TreeCCContext *context);
+ 
+ /*
+  * Visit every node type in a context's hierarchy.
+  */
+ typedef void (*TreeCCNodeVisitor)(TreeCCContext *context, TreeCCNode *node);
+ void TreeCCNodeVisitAll(TreeCCContext *context, TreeCCNodeVisitor visitor);
+ 
+ /*
+  * Determine if a node type is a singleton.  i.e. no fields.
+  */
+ int TreeCCNodeIsSingleton(TreeCCNode *node);
+ 
+ /*
+  * Determine if a node type has abstract virtual operation cases.
+  */
+ int TreeCCNodeHasAbstracts(TreeCCContext *context, TreeCCNode *node);
+ 
+ /*
+  * Add a virtual operation to a node.
+  */
+ void TreeCCNodeAddVirtual(TreeCCContext *context, TreeCCNode *node,
+ 						  TreeCCOperation *oper);
+ 
+ /*
+  * Determine if "nodea" inherits from "nodeb".
+  */
+ int TreeCCNodeInheritsFrom(TreeCCNode *nodea, TreeCCNode *nodeb);
+ 
+ /*
+  * Clear all marking bits that are used to track operation coverage.
+  */
+ void TreeCCNodeClearMarking(TreeCCContext *context, int flags);
+ 
+ /*
+  * Assign positions to all nodes started at a particular place
+  * in the node type hierarchy.  Returns the number of positions.
+  */
+ int TreeCCNodeAssignPositions(TreeCCNode *node);
+ 
+ /*
+  * Create a new field definition and add it to a node.
+  */
+ void TreeCCFieldCreate(TreeCCContext *context, TreeCCNode *node,
+ 					   char *name, char *type, char *value, int flags);
+ 
+ /*
+  * Free an operation.
+  */
+ void TreeCCOperationFree(TreeCCOperation *oper);
+ 
+ /*
+  * Create a new operation.
+  */
+ TreeCCOperation *TreeCCOperationCreate(TreeCCContext *context,
+ 									   char *returnType, char *name,
+ 									   char *className, char *defValue,
+ 									   TreeCCParam *params, int flags,
+ 									   int numTriggers, char *filename,
+ 									   long linenum);
+ 
+ /*
+  * Find an operation with a specific name.
+  */
+ TreeCCOperation *TreeCCOperationFind(TreeCCContext *context, char *name);
+ 
+ /*
+  * Add a case definition to an operation.
+  */
+ TreeCCOperationCase *TreeCCOperationAddCase
+ 				(TreeCCContext *context, TreeCCOperation *oper,
+ 				 TreeCCTrigger *triggers, char *filename, long linenum);
+ 
+ /*
+  * Validate all operations.
+  */
+ void TreeCCOperationValidate(TreeCCContext *context);
+ 
+ /*
+  * Find the operation case that corresponds to a virtual method.
+  * Returns NULL if the node does not have a virtual implementation.
+  */
+ TreeCCOperationCase *TreeCCOperationFindCase
+ 		(TreeCCContext *context, TreeCCNode *node, char *name);
+ 
+ /*
+  * Visit all operations declared by a context.
+  */
+ typedef void (*TreeCCOperationVisitor)(TreeCCContext *context,
+ 									   TreeCCOperation *oper);
+ void TreeCCOperationVisitAll(TreeCCContext *context,
+ 							 TreeCCOperationVisitor visitor);
+ 
+ /*
+  * Include the contents of a skeleton file in an output stream.
+  */
+ void TreeCCIncludeSkeleton(TreeCCContext *context, TreeCCStream *stream,
+ 						   const char *skeleton);
+ 
+ #ifdef	__cplusplus
+ };
+ #endif
+ 
+ #endif	/* _TREECC_INFO_H */


Index: llvm/test/Programs/MultiSource/Applications/treecc/input.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/input.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/input.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,990 ----
+ /*
+  * input.c - Process input files for "treecc".
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ void TreeCCOpen(TreeCCInput *input, char *progname,
+ 				FILE *stream, char *filename)
+ {
+ 	input->token = TREECC_TOKEN_IDENTIFIER;
+ 	input->text = 0;
+ 	input->progname = progname;
+ 	input->stream = stream;
+ 	input->filename = filename;
+ 	input->linenum = 1;
+ 	input->nextline = 1;
+ 	input->errors = 0;
+ 	input->sawEOF = 0;
+ 	input->parseLiteral = 1;
+ 	input->readOnly = 0;
+ }
+ 
+ void TreeCCClose(TreeCCInput *input, int closeRaw)
+ {
+ 	if(input->text && input->text != input->buffer)
+ 	{
+ 		free(input->text);
+ 	}
+ 	if(closeRaw)
+ 	{
+ 		fclose(input->stream);
+ 	}
+ }
+ 
+ /*
+  * Determine if the next character looks like part of an identifier.
+  */
+ #define	IS_START_IDENT(ch)	(((ch) >= 'A' && (ch) <= 'Z') || \
+ 						 	 ((ch) >= 'a' && (ch) <= 'z') || \
+ 						 	 (ch) == '_')
+ #define	IS_IDENT(ch)	(((ch) >= 'A' && (ch) <= 'Z') || \
+ 						 ((ch) >= 'a' && (ch) <= 'z') || \
+ 						 ((ch) >= '0' && (ch) <= '9') || \
+ 						 (ch) == '_')
+ 
+ /*
+  * Report an invalid character error.
+  */
+ static void InvalidChar(TreeCCInput *input, int ch)
+ {
+ 	if(ch >= ' ' && ch <= (char)0x7E)
+ 	{
+ 		TreeCCError(input, "invalid `%c' character in input", ch);
+ 	}
+ 	else
+ 	{
+ 		TreeCCError(input, "invalid `\\x%02X' character in input", ch);
+ 	}
+ }
+ 
+ /*
+  * Report EOF inside a literal code block.
+  */
+ static void LiteralEOF(TreeCCInput *input)
+ {
+ 	TreeCCError(input, "end of file inside literal code block");
+ }
+ 
+ /*
+  * Recognise an identifier from an input stream.
+  */
+ static void RecogIdentifier(TreeCCInput *input, int ch, const char *name)
+ {
+ 	int len = 0;
+ 	int overflow = 0;
+ 	for(;;)
+ 	{
+ 		/* Add the character to the buffer */
+ 		if(len < (TREECC_BUFSIZ - 1))
+ 		{
+ 			input->buffer[len++] = ch;
+ 		}
+ 		else
+ 		{
+ 			overflow = 1;
+ 		}
+ 
+ 		/* Get the next character */
+ 		ch = getc(input->stream);
+ 		if(ch == EOF)
+ 		{
+ 			input->sawEOF = 1;
+ 			break;
+ 		}
+ 		else if(!IS_IDENT(ch))
+ 		{
+ 			ungetc(ch, input->stream);
+ 			break;
+ 		}
+ 	}
+ 	if(overflow)
+ 	{
+ 		TreeCCError(input, "%s is too long", name);
+ 	}
+ 	input->buffer[len] = '\0';
+ 	input->text = input->buffer;
+ }
+ 
+ /*
+  * Flush a buffer of data to "input->text".
+  */
+ static int FlushBuffer(TreeCCInput *input, int len, int currlen)
+ {
+ 	char *newText;
+ 
+ 	/* Ignore the request if "len" is zero */
+ 	if(!len)
+ 	{
+ 		return currlen;
+ 	}
+ 
+ 	/* Reallocate the text buffer to the new length */
+ 	if((newText = (char *)realloc(input->text, currlen + len + 1)) == 0)
+ 	{
+ 		TreeCCOutOfMemory(input);
+ 	}
+ 	input->text = newText;
+ 
+ 	/* Copy the data to the buffer */
+ 	strncpy(newText + currlen, input->buffer, len);
+ 	newText[currlen + len] = '\0';
+ 	return currlen + len;
+ }
+ 
+ /*
+  * Finalize the text buffer.
+  */
+ static void FinalizeBuffer(TreeCCInput *input, int len, int currlen)
+ {
+ 	if(currlen != 0)
+ 	{
+ 		FlushBuffer(input, len, currlen);
+ 	}
+ 	else
+ 	{
+ 		input->buffer[len] = '\0';
+ 		input->text = input->buffer;
+ 	}
+ }
+ 
+ /*
+  * Recognise a literal code definition section.
+  */
+ static void LiteralCodeDefn(TreeCCInput *input, int tillEnd)
+ {
+ 	int len = 0;
+ 	int currlen = 0;
+ 	int ch;
+ 
+ 	/* Read characters until EOF or "%}" */
+ 	for(;;)
+ 	{
+ 		ch = getc(input->stream);
+ 		if(ch == EOF)
+ 		{
+ 			input->sawEOF = 1;
+ 			if(!tillEnd)
+ 			{
+ 				LiteralEOF(input);
+ 			}
+ 			break;
+ 		}
+ 		else if(ch == '%' && !tillEnd)
+ 		{
+ 			/* Check for the "%}" terminating sequence */
+ 			ch = getc(input->stream);
+ 			if(ch == '}')
+ 			{
+ 				break;
+ 			}
+ 			else if(ch == EOF)
+ 			{
+ 				input->buffer[len++] = '%';
+ 				input->sawEOF = 1;
+ 				LiteralEOF(input);
+ 				break;
+ 			}
+ 			else
+ 			{
+ 				ungetc(ch, input->stream);
+ 				input->buffer[len++] = '%';
+ 				if(len >= (TREECC_BUFSIZ - 1))
+ 				{
+ 					currlen = FlushBuffer(input, len, currlen);
+ 					len = 0;
+ 				}
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if(ch == '\n')
+ 			{
+ 				/* Unix-style end of line sequence */
+ 				++(input->nextline);
+ 				input->buffer[len++] = '\n';
+ 			}
+ 			else if(ch == '\r')
+ 			{
+ 				/* MS-DOS or Mac-style end of line sequence */
+ 				++(input->nextline);
+ 				input->buffer[len++] = '\n';
+ 				ch = getc(input->stream);
+ 				if(ch == EOF)
+ 				{
+ 					input->sawEOF = 1;
+ 					if(!tillEnd)
+ 					{
+ 						LiteralEOF(input);
+ 					}
+ 					break;
+ 				}
+ 				else if(ch != '\n')
+ 				{
+ 					ungetc(ch, input->stream);
+ 				}
+ 			}
+ 			else if(ch == '\0')
+ 			{
+ 				/* Strip out embedded NUL's */
+ 				InvalidChar(input, ch);
+ 			}
+ 			else
+ 			{
+ 				/* Ordinary character */
+ 				input->buffer[len++] = (char)ch;
+ 			}
+ 			if(len >= (TREECC_BUFSIZ - 1))
+ 			{
+ 				currlen = FlushBuffer(input, len, currlen);
+ 				len = 0;
+ 			}
+ 		}
+ 	}
+ 
+ 	/* Finalize the text return buffer */
+ 	FinalizeBuffer(input, len, currlen);
+ }
+ 
+ /*
+  * Recognise a literal code section.  This version is a little
+  * harder because we need to find a matching '}', while handling
+  * C-style and C++-style comments and strings.
+  */
+ static void LiteralCode(TreeCCInput *input)
+ {
+ 	unsigned long level = 0;
+ 	int len = 0;
+ 	int currlen = 0;
+ 	int ch, quotech;
+ 
+ 	/* Parse input until the next matching '}' */
+ 	for(;;)
+ 	{
+ 		ch = getc(input->stream);
+ 		if(ch == EOF)
+ 		{
+ 			/* Premate end of file within the code block */
+ 			input->sawEOF = 1;
+ 			LiteralEOF(input);
+ 			break;
+ 		}
+ 		else if(ch == '}')
+ 		{
+ 			/* Go out one code level */
+ 			if(level == 0)
+ 			{
+ 				break;
+ 			}
+ 			--level;
+ 			input->buffer[len++] = '}';
+ 		}
+ 		else if(ch == '{')
+ 		{
+ 			/* Go in one code level */
+ 			++level;
+ 			input->buffer[len++] = '{';
+ 		}
+ 		else if(ch == '"' || ch == '\'')
+ 		{
+ 			/* Skip to the end of this string */
+ 			quotech = ch;
+ 			input->buffer[len++] = (char)ch;
+ 			if(len >= (TREECC_BUFSIZ - 1))
+ 			{
+ 				currlen = FlushBuffer(input, len, currlen);
+ 				len = 0;
+ 			}
+ 			while((ch = getc(input->stream)) != EOF && ch != quotech)
+ 			{
+ 				if(ch == '\\')
+ 				{
+ 					input->buffer[len++] = (char)ch;
+ 					if(len >= (TREECC_BUFSIZ - 1))
+ 					{
+ 						currlen = FlushBuffer(input, len, currlen);
+ 						len = 0;
+ 					}
+ 					ch = getc(input->stream);
+ 					if(ch == EOF)
+ 					{
+ 						break;
+ 					}
+ 				}
+ 				if(ch == '\n' || ch == '\r')
+ 				{
+ 					TreeCCError(input, "end of line inside string");
+ 					ungetc(ch, input->stream);
+ 					break;
+ 				}
+ 				input->buffer[len++] = (char)ch;
+ 				if(len >= (TREECC_BUFSIZ - 1))
+ 				{
+ 					currlen = FlushBuffer(input, len, currlen);
+ 					len = 0;
+ 				}
+ 			}
+ 			if(ch == EOF)
+ 			{
+ 				input->sawEOF = 1;
+ 				TreeCCError(input, "end of file inside string");
+ 				break;
+ 			}
+ 			else
+ 			{
+ 				input->buffer[len++] = (char)quotech;
+ 			}
+ 		}
+ 		else if(ch == '/')
+ 		{
+ 			/* May be the start of a comment */
+ 			input->buffer[len++] = '/';
+ 			if(len >= (TREECC_BUFSIZ - 1))
+ 			{
+ 				currlen = FlushBuffer(input, len, currlen);
+ 				len = 0;
+ 			}
+ 			ch = getc(input->stream);
+ 			if(ch == EOF)
+ 			{
+ 				/* EOF in the middle of a code block */
+ 				input->sawEOF = 1;
+ 				LiteralEOF(input);
+ 				break;
+ 			}
+ 			else if(ch == '/')
+ 			{
+ 				/* Single-line comment */
+ 				input->buffer[len++] = '/';
+ 				if(len >= (TREECC_BUFSIZ - 1))
+ 				{
+ 					currlen = FlushBuffer(input, len, currlen);
+ 					len = 0;
+ 				}
+ 				while((ch = getc(input->stream)) != '\n' &&
+ 					  ch != '\r' && ch != EOF)
+ 				{
+ 					if(ch != '\0')
+ 					{
+ 						input->buffer[len++] = (char)ch;
+ 						if(len >= (TREECC_BUFSIZ - 1))
+ 						{
+ 							currlen = FlushBuffer(input, len, currlen);
+ 							len = 0;
+ 						}
+ 					}
+ 					else
+ 					{
+ 						InvalidChar(input, ch);
+ 					}
+ 				}
+ 				if(ch == EOF)
+ 				{
+ 					input->sawEOF = 1;
+ 					LiteralEOF(input);
+ 					break;
+ 				}
+ 				ungetc(ch, input->stream);
+ 			}
+ 			else if(ch == '*')
+ 			{
+ 				/* Multi-line comment */
+ 				input->buffer[len++] = '*';
+ 				if(len >= (TREECC_BUFSIZ - 1))
+ 				{
+ 					currlen = FlushBuffer(input, len, currlen);
+ 					len = 0;
+ 				}
+ 				for(;;)
+ 				{
+ 					ch = getc(input->stream);
+ 					if(ch == EOF)
+ 					{
+ 						/* EOF encountered in a comment */
+ 						input->sawEOF = 1;
+ 						LiteralEOF(input);
+ 						goto finalize;
+ 					}
+ 					else if(ch == '*')
+ 					{
+ 						/* Check for the end of the comment */
+ 						input->buffer[len++] = '*';
+ 						if(len >= (TREECC_BUFSIZ - 1))
+ 						{
+ 							currlen = FlushBuffer(input, len, currlen);
+ 							len = 0;
+ 						}
+ 						ch = getc(input->stream);
+ 						if(ch == '/')
+ 						{
+ 							input->buffer[len++] = '/';
+ 							break;
+ 						}
+ 						else if(ch == EOF)
+ 						{
+ 							input->sawEOF = 1;
+ 							LiteralEOF(input);
+ 							goto finalize;
+ 						}
+ 						else
+ 						{
+ 							ungetc(ch, input->stream);
+ 							continue;
+ 						}
+ 					}
+ 					else if(ch == '\n')
+ 					{
+ 						/* Unix-style end of line in a comment */
+ 						++(input->nextline);
+ 					}
+ 					else if(ch == '\r')
+ 					{
+ 						/* MS-DOS or Mac-style end of line in a comment */
+ 						++(input->nextline);
+ 						ch = getc(input->stream);
+ 						if(ch == EOF)
+ 						{
+ 							input->buffer[len++] = '\n';
+ 							input->sawEOF = 1;
+ 							LiteralEOF(input);
+ 							goto finalize;
+ 						}
+ 						else if(ch != '\n')
+ 						{
+ 							ungetc(ch, input->stream);
+ 						}
+ 						ch = '\n';
+ 					}
+ 					input->buffer[len++] = (char)ch;
+ 					if(len >= (TREECC_BUFSIZ - 1))
+ 					{
+ 						currlen = FlushBuffer(input, len, currlen);
+ 						len = 0;
+ 					}
+ 				}
+ 			}
+ 			else
+ 			{
+ 				/* Simple '/' character */
+ 				ungetc(ch, input->stream);
+ 			}
+ 		}
+ 		else if(ch == '\n')
+ 		{
+ 			/* Unix-like end of line sequence */
+ 			++(input->nextline);
+ 			input->buffer[len++] = '\n';
+ 		}
+ 		else if(ch == '\r')
+ 		{
+ 			/* MS-DOS or Mac-like end of line sequence */
+ 			++(input->nextline);
+ 			input->buffer[len++] = '\n';
+ 			ch = getc(input->stream);
+ 			if(ch == EOF)
+ 			{
+ 				input->sawEOF = 1;
+ 				LiteralEOF(input);
+ 				break;
+ 			}
+ 			else if(ch != '\n')
+ 			{
+ 				ungetc(ch, input->stream);
+ 			}
+ 		}
+ 		else if(ch == '\0')
+ 		{
+ 			/* NUL characters are invalid in literal code blocks */
+ 			InvalidChar(input, ch);
+ 		}
+ 		else
+ 		{
+ 			/* Normal character */
+ 			input->buffer[len++] = (char)ch;
+ 		}
+ 		if(len >= (TREECC_BUFSIZ - 1))
+ 		{
+ 			currlen = FlushBuffer(input, len, currlen);
+ 			len = 0;
+ 		}
+ 	}
+ 
+ 	/* Finalize the text return buffer */
+ finalize:
+ 	FinalizeBuffer(input, len, currlen);
+ }
+ 
+ /*
+  * Recognise a string from an input file.  Escape sequences
+  * are not supported in this type of string.
+  */
+ static void RecogString(TreeCCInput *input, int quotech)
+ {
+ 	int len = 0;
+ 	int currlen = 0;
+ 	int ch;
+ 
+ 	/* Parse the contents of the string */
+ 	for(;;)
+ 	{
+ 		ch = getc(input->stream);
+ 		if(ch == quotech)
+ 		{
+ 			/* Terminating quote for the string */
+ 			break;
+ 		}
+ 		else if(ch == EOF)
+ 		{
+ 			/* EOF embedded in the string */
+ 			input->sawEOF = 1;
+ 			TreeCCError(input, "end of file inside string");
+ 			break;
+ 		}
+ 		else if(ch == '\n' || ch == '\r')
+ 		{
+ 			/* End of line embedding in the string */
+ 			ungetc(ch, input->stream);
+ 			TreeCCError(input, "end of line inside string");
+ 			break;
+ 		}
+ 		else if(ch == '\0')
+ 		{
+ 			/* NUL characters are invalid inside a string */
+ 			InvalidChar(input, ch);
+ 		}
+ 		else
+ 		{
+ 			/* Ordinary character */
+ 			input->buffer[len++] = (char)ch;
+ 			if(len >= (TREECC_BUFSIZ - 1))
+ 			{
+ 				currlen = FlushBuffer(input, len, currlen);
+ 				len = 0;
+ 			}
+ 		}
+ 	}
+ 
+ 	/* Finalize the text return buffer */
+ 	FinalizeBuffer(input, len, currlen);
+ }
+ 
+ /*
+  * Keyword table.  Must be sorted into ascending order.
+  */
+ static struct
+ {
+ 	const char *keyword;
+ 	TreeCCToken token;
+ 
+ } const KeywordTable[] = {
+ 	{"abstract",		TREECC_TOKEN_ABSTRACT},
+ 	{"both",			TREECC_TOKEN_BOTH},
+ 	{"common",			TREECC_TOKEN_COMMON},
+ 	{"decls",			TREECC_TOKEN_DECLS},
+ 	{"end",				TREECC_TOKEN_END},
+ 	{"enum",			TREECC_TOKEN_ENUM},
+ 	{"header",			TREECC_TOKEN_HEADER},
+ 	{"include",			TREECC_TOKEN_INCLUDE},
+ 	{"inline",			TREECC_TOKEN_INLINE},
+ 	{"nocreate",		TREECC_TOKEN_NOCREATE},
+ 	{"node",			TREECC_TOKEN_NODE},
+ 	{"operation",		TREECC_TOKEN_OPERATION},
+ 	{"option",			TREECC_TOKEN_OPTION},
+ 	{"outdir",			TREECC_TOKEN_OUTDIR},
+ 	{"output",			TREECC_TOKEN_OUTPUT},
+ 	{"readonly",		TREECC_TOKEN_READONLY},
+ 	{"split",			TREECC_TOKEN_SPLIT},
+ 	{"typedef",			TREECC_TOKEN_TYPEDEF},
+ 	{"virtual",			TREECC_TOKEN_VIRTUAL},
+ };
+ #define	KeywordTableSize	(sizeof(KeywordTable) / sizeof(KeywordTable[0]))
+ 
+ int TreeCCNextToken(TreeCCInput *input)
+ {
+ 	int ch;
+ 	int low, middle, high;
+ 
+ 	/* If we have seen EOF already, then bail out now */
+ 	if(input->sawEOF)
+ 	{
+ 		input->linenum = input->nextline;
+ 		input->token = TREECC_TOKEN_EOF;
+ 		return 0;
+ 	}
+ 
+ 	/* Free the text input buffer used by the previous token */
+ 	if(input->text && input->text != input->buffer)
+ 	{
+ 		free(input->text);
+ 	}
+ 	input->text = 0;
+ 
+ 	/* Determine what kind of token we have from the next character */
+ 	for(;;)
+ 	{
+ 		input->linenum = input->nextline;
+ 		ch = getc(input->stream);
+ 		if(ch == EOF)
+ 		{
+ 			break;
+ 		}
+ 		else if(ch == '%')
+ 		{
+ 			ch = getc(input->stream);
+ 			if(ch == '{')
+ 			{
+ 				/* Start of a literal code definition section that
+ 				   extends until the next occurrence of "%}" */
+ 				LiteralCodeDefn(input, 0);
+ 				input->token = TREECC_TOKEN_LITERAL_DEFNS;
+ 				return 1;
+ 			}
+ 			else if(ch == '%')
+ 			{
+ 				/* Start of a literal code definition section that
+ 				   extends until the end of the file */
+ 				LiteralCodeDefn(input, 1);
+ 				input->token = TREECC_TOKEN_LITERAL_END;
+ 				return 1;
+ 			}
+ 			else if(IS_START_IDENT(ch))
+ 			{
+ 				/* Start of a keyword */
+ 				RecogIdentifier(input, ch, "keyword");
+ 				low = 0;
+ 				high = KeywordTableSize - 1;
+ 				while(low <= high)
+ 				{
+ 					middle = ((low + high) / 2);
+ 					ch = strcmp(input->text, KeywordTable[middle].keyword);
+ 					if(!ch)
+ 					{
+ 						input->token = KeywordTable[middle].token;
+ 						return 1;
+ 					}
+ 					else if(ch < 0)
+ 					{
+ 						high = middle - 1;
+ 					}
+ 					else
+ 					{
+ 						low = middle + 1;
+ 					}
+ 				}
+ 				TreeCCError(input, "unknown keyword `%%%s'", input->text);
+ 				input->token = TREECC_TOKEN_UNKNOWN;
+ 				return 1;
+ 			}
+ 			else
+ 			{
+ 				TreeCCError(input,
+ 							"`%%' must be followed by a keyword, `{', or `%%'");
+ 				if(ch == EOF)
+ 				{
+ 					break;
+ 				}
+ 				else
+ 				{
+ 					ungetc(ch, input->stream);
+ 				}
+ 			}
+ 		}
+ 		else if(IS_START_IDENT(ch))
+ 		{
+ 			/* Start of an identifier */
+ 			RecogIdentifier(input, ch, "identifier");
+ 			input->token = TREECC_TOKEN_IDENTIFIER;
+ 			return 1;
+ 		}
+ 		else if(ch == '(')
+ 		{
+ 			input->token = TREECC_TOKEN_LPAREN;
+ 			return 1;
+ 		}
+ 		else if(ch == ')')
+ 		{
+ 			input->token = TREECC_TOKEN_RPAREN;
+ 			return 1;
+ 		}
+ 		else if(ch == '}')
+ 		{
+ 			input->token = TREECC_TOKEN_RBRACE;
+ 			return 1;
+ 		}
+ 		else if(ch == '[')
+ 		{
+ 			input->token = TREECC_TOKEN_LSQUARE;
+ 			return 1;
+ 		}
+ 		else if(ch == ']')
+ 		{
+ 			input->token = TREECC_TOKEN_RSQUARE;
+ 			return 1;
+ 		}
+ 		else if(ch == ',')
+ 		{
+ 			input->token = TREECC_TOKEN_COMMA;
+ 			return 1;
+ 		}
+ 		else if(ch == '=')
+ 		{
+ 			input->token = TREECC_TOKEN_EQUALS;
+ 			return 1;
+ 		}
+ 		else if(ch == '*')
+ 		{
+ 			input->token = TREECC_TOKEN_STAR;
+ 			return 1;
+ 		}
+ 		else if(ch == '&')
+ 		{
+ 			input->token = TREECC_TOKEN_REF;
+ 			return 1;
+ 		}
+ 		else if(ch == ';')
+ 		{
+ 			input->token = TREECC_TOKEN_SEMI;
+ 			return 1;
+ 		}
+ 		else if(ch == ':')
+ 		{
+ 			ch = getc(input->stream);
+ 			if(ch == ':')
+ 			{
+ 				input->token = TREECC_TOKEN_COLON_COLON;
+ 				return 1;
+ 			}
+ 			else if(ch == EOF)
+ 			{
+ 				InvalidChar(input, ':');
+ 				input->sawEOF = 1;
+ 				input->linenum = input->nextline;
+ 				input->token = TREECC_TOKEN_EOF;
+ 				return 0;
+ 			}
+ 			else
+ 			{
+ 				ungetc(ch, input->stream);
+ 				InvalidChar(input, ':');
+ 			}
+ 		}
+ 		else if(ch == '"' || ch == '\'')
+ 		{
+ 			RecogString(input, ch);
+ 			input->token = TREECC_TOKEN_STRING;
+ 			return 1;
+ 		}
+ 		else if(ch == '\n')
+ 		{
+ 			/* Unix-like end of line sequence */
+ 			++(input->nextline);
+ 		}
+ 		else if(ch == '\r')
+ 		{
+ 			/* MS-DOS or Mac-like end of line sequence */
+ 			ch = getc(input->stream);
+ 			if(ch == EOF)
+ 			{
+ 				input->sawEOF = 1;
+ 			}
+ 			else if(ch != '\n')
+ 			{
+ 				ungetc(ch, input->stream);
+ 			}
+ 			++(input->nextline);
+ 		}
+ 		else if(ch == '{')
+ 		{
+ 			if(input->parseLiteral)
+ 			{
+ 				/* Start of a literal code block */
+ 				LiteralCode(input);
+ 				input->token = TREECC_TOKEN_LITERAL_CODE;
+ 				return 1;
+ 			}
+ 			else
+ 			{
+ 				/* Probably a field definition block */
+ 				input->token = TREECC_TOKEN_LBRACE;
+ 				return 1;
+ 			}
+ 		}
+ 		else if(ch == ' ' || ch == '\t' || ch == '\f' || ch == '\v')
+ 		{
+ 			/* Ignore white space on the current line */
+ 		}
+ 		else if(ch == '/')
+ 		{
+ 			/* May be the start of a comment */
+ 			ch = getc(input->stream);
+ 			if(ch == '*')
+ 			{
+ 				/* Multi-line comment */
+ 				for(;;)
+ 				{
+ 					ch = getc(input->stream);
+ 					if(ch == EOF)
+ 					{
+ 					eofInComment:
+ 						TreeCCError(input, "end of file inside comment");
+ 						input->sawEOF = 1;
+ 						input->linenum = input->nextline;
+ 						input->token = TREECC_TOKEN_EOF;
+ 						return 0;
+ 					}
+ 					else if(ch == '*')
+ 					{
+ 						for(;;)
+ 						{
+ 							ch = getc(input->stream);
+ 							if(ch == EOF)
+ 							{
+ 								goto eofInComment;
+ 							}
+ 							else if(ch == '/')
+ 							{
+ 								goto endComment;
+ 							}
+ 							else if(ch != '*')
+ 							{
+ 								ungetc(ch, input->stream);
+ 								break;
+ 							}
+ 						}
+ 					}
+ 					else if(ch == '\n')
+ 					{
+ 						++(input->nextline);
+ 					}
+ 					else if(ch == '\r')
+ 					{
+ 						++(input->nextline);
+ 						ch = getc(input->stream);
+ 						if(ch == EOF)
+ 						{
+ 							goto eofInComment;
+ 						}
+ 						else if(ch != '\n')
+ 						{
+ 							ungetc(ch, input->stream);
+ 						}
+ 					}
+ 				}
+ 			endComment: ;
+ 			}
+ 			else if(ch == '/')
+ 			{
+ 				/* Single-line comment */
+ 				for(;;)
+ 				{
+ 					ch = getc(input->stream);
+ 					if(ch == EOF)
+ 					{
+ 						input->sawEOF = 1;
+ 						input->linenum = input->nextline;
+ 						input->token = TREECC_TOKEN_EOF;
+ 						return 0;
+ 					}
+ 					else if(ch == '\n')
+ 					{
+ 						break;
+ 					}
+ 					else if(ch == '\r')
+ 					{
+ 						ch = getc(input->stream);
+ 						if(ch == EOF)
+ 						{
+ 							input->sawEOF = 1;
+ 						}
+ 						else if(ch != '\n')
+ 						{
+ 							ungetc(ch, input->stream);
+ 						}
+ 						break;
+ 					}
+ 				}
+ 				++(input->nextline);
+ 			}
+ 			else
+ 			{
+ 				/* Invalid comment sequence */
+ 				InvalidChar(input, '/');
+ 				if(ch == EOF)
+ 				{
+ 					break;
+ 				}
+ 				else
+ 				{
+ 					ungetc(ch, input->stream);
+ 				}
+ 			}
+ 		}
+ 		else
+ 		{
+ 			/* Invalid character in the input stream */
+ 			InvalidChar(input, ch);
+ 		}
+ 	}
+ 
+ 	/* If we get here, then we have reached EOF */
+ 	input->linenum = input->nextline;
+ 	input->token = TREECC_TOKEN_EOF;
+ 	input->sawEOF = 1;
+ 	return 0;
+ }
+ 
+ char *TreeCCValue(TreeCCInput *input)
+ {
+ 	char *result;
+ 	if(!(input->text))
+ 	{
+ 		/* We don't have a text version of this token */
+ 		TreeCCAbort(input, "no text for token type %d", input->token);
+ 		return 0;
+ 	}
+ 	else if(input->text != input->buffer)
+ 	{
+ 		/* The text is already malloc'ed, so return that */
+ 		result = input->text;
+ 		input->text = 0;
+ 		return result;
+ 	}
+ 	else
+ 	{
+ 		/* Copy the text into a malloc'ed buffer */
+ 		result = (char *)malloc(strlen(input->buffer) + 1);
+ 		if(!result)
+ 		{
+ 			TreeCCOutOfMemory(input);
+ 		}
+ 		strcpy(result, input->buffer);
+ 		input->text = 0;
+ 		return result;
+ 	}
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/input.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/input.h:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/input.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,121 ----
+ /*
+  * input.h - Process input files for "treecc".
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_INPUT_H
+ #define	_TREECC_INPUT_H
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Token types.
+  */
+ typedef enum
+ {
+ 	TREECC_TOKEN_EOF,
+ 	TREECC_TOKEN_IDENTIFIER,
+ 	TREECC_TOKEN_LITERAL_DEFNS,
+ 	TREECC_TOKEN_LITERAL_CODE,
+ 	TREECC_TOKEN_LITERAL_END,
+ 	TREECC_TOKEN_LPAREN,
+ 	TREECC_TOKEN_RPAREN,
+ 	TREECC_TOKEN_LBRACE,
+ 	TREECC_TOKEN_RBRACE,
+ 	TREECC_TOKEN_LSQUARE,
+ 	TREECC_TOKEN_RSQUARE,
+ 	TREECC_TOKEN_COMMA,
+ 	TREECC_TOKEN_EQUALS,
+ 	TREECC_TOKEN_STAR,
+ 	TREECC_TOKEN_REF,
+ 	TREECC_TOKEN_SEMI,
+ 	TREECC_TOKEN_COLON_COLON,
+ 	TREECC_TOKEN_STRING,
+ 	TREECC_TOKEN_UNKNOWN,
+ 	TREECC_TOKEN_NODE,
+ 	TREECC_TOKEN_ABSTRACT,
+ 	TREECC_TOKEN_TYPEDEF,
+ 	TREECC_TOKEN_OPERATION,
+ 	TREECC_TOKEN_NOCREATE,
+ 	TREECC_TOKEN_VIRTUAL,
+ 	TREECC_TOKEN_INLINE,
+ 	TREECC_TOKEN_SPLIT,
+ 	TREECC_TOKEN_OPTION,
+ 	TREECC_TOKEN_HEADER,
+ 	TREECC_TOKEN_OUTPUT,
+ 	TREECC_TOKEN_OUTDIR,
+ 	TREECC_TOKEN_BOTH,
+ 	TREECC_TOKEN_DECLS,
+ 	TREECC_TOKEN_END,
+ 	TREECC_TOKEN_ENUM,
+ 	TREECC_TOKEN_COMMON,
+ 	TREECC_TOKEN_INCLUDE,
+ 	TREECC_TOKEN_READONLY,
+ 
+ } TreeCCToken;
+ 
+ /*
+  * Information structure for an input stream.
+  */
+ #define	TREECC_BUFSIZ		1024
+ typedef struct
+ {
+ 	TreeCCToken		token;
+ 	char		   *text;
+ 	char		   *progname;
+ 	FILE		   *stream;
+ 	char		   *filename;
+ 	long			linenum;
+ 	long			nextline;
+ 	int				errors;
+ 	int				sawEOF;
+ 	int				parseLiteral;
+ 	int				readOnly;
+ 	char			buffer[TREECC_BUFSIZ];
+ 
+ } TreeCCInput;
+ 
+ /*
+  * Open an input stream.
+  */
+ void TreeCCOpen(TreeCCInput *input, char *progname,
+ 				FILE *stream, char *filename);
+ 
+ /*
+  * Close an input stream.
+  */
+ void TreeCCClose(TreeCCInput *input, int closeRaw);
+ 
+ /*
+  * Get the next token from an input stream.
+  * Returns zero if at EOF, or non-zero if OK.
+  */
+ int TreeCCNextToken(TreeCCInput *input);
+ 
+ /*
+  * Copy the value of the current text token into a malloc'ed string.
+  */
+ char *TreeCCValue(TreeCCInput *input);
+ 
+ #ifdef	__cplusplus
+ };
+ #endif
+ 
+ #endif	/* _TREECC_INPUT_H */


Index: llvm/test/Programs/MultiSource/Applications/treecc/literal.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/literal.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/literal.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,67 ----
+ /*
+  * literal.c - Management node types for literal code blocks.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ void TreeCCAddLiteralDefn(TreeCCContext *context, char *code, int flags)
+ {
+ 	if(context->debugMode)
+ 	{
+ 		TreeCCDebug(context->input->linenum, "%%literal %d %s",
+ 					flags, code);
+ 	}
+ 	if((flags & TREECC_LITERAL_CODE) != 0 &&
+ 	   (flags & TREECC_LITERAL_DECLS) != 0)
+ 	{
+ 		TreeCCStreamAddLiteral(context->headerStream, code,
+ 							   context->input->filename,
+ 							   context->input->linenum,
+ 							   (flags & TREECC_LITERAL_END) != 0, 0);
+ 		TreeCCStreamAddLiteral(context->sourceStream, code,
+ 							   context->input->filename,
+ 							   context->input->linenum,
+ 							   (flags & TREECC_LITERAL_END) != 0, 1);
+ 	}
+ 	else if((flags & TREECC_LITERAL_CODE) != 0)
+ 	{
+ 		TreeCCStreamAddLiteral(context->sourceStream, code,
+ 							   context->input->filename,
+ 							   context->input->linenum,
+ 							   (flags & TREECC_LITERAL_END) != 0, 0);
+ 	}
+ 	else
+ 	{
+ 		TreeCCStreamAddLiteral(context->headerStream, code,
+ 							   context->input->filename,
+ 							   context->input->linenum,
+ 							   (flags & TREECC_LITERAL_END) != 0, 0);
+ 	}
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/main.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/main.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/main.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,590 ----
+ /*
+  * main.c - Main program entry point for "treecc".
+  *
+  * Copyright (C) 2001, 2002  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "parse.h"
+ #include "errors.h"
+ #include "gen.h"
+ #include "options.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ static void Usage(char *progname);
+ static void Version(void);
+ static int ExtraOptions(TreeCCContext *context, char **options, int num);
+ static char *GetDefault(const char *filename, const char *extension);
+ 
+ int main(int argc, char *argv[])
+ {
+ 	char *progname = argv[0];
+ 	char *opt;
+ 	char *outputFile = NULL;
+ 	char *headerFile = NULL;
+ 	char *extension = "c";
+ 	char *outputDir = NULL;
+ 	int forceCreate = 0;
+ 	TreeCCInput input;
+ 	TreeCCContext *context;
+ 	int sawStdin = 0;
+ 	int generateOutput = 1;
+ 	FILE *file;
+ 	int len, result;
+ 	char **options = (char **)malloc(sizeof(char *) * argc);
+ 	int num_options = 0;
+ 
+ 	/* Allocate the array for external "%option" values */
+ 	options = (char **)malloc(sizeof(char *) * argc);
+ 	if(!options)
+ 	{
+ 		TreeCCOutOfMemory(0);
+ 	}
+ 
+ 	/* Parse the command-line options */
+ 	while(argc > 1 && argv[1][0] == '-')
+ 	{
+ 		if(argv[1][1] == '\0')
+ 		{
+ 			/* The input is stdin */
+ 			break;
+ 		}
+ 		else if(argv[1][1] == '-')
+ 		{
+ 			/* The option begins with "--" */
+ 			if(argv[1][2] == '\0')
+ 			{
+ 				/* End of options, and start of filenames */
+ 				--argc;
+ 				++argv;
+ 				break;
+ 			}
+ 			if(!strcmp(argv[1], "--output"))
+ 			{
+ 				--argc;
+ 				++argv;
+ 				if(argc <= 1)
+ 				{
+ 					Usage(progname);
+ 					return 1;
+ 				}
+ 				outputFile = argv[1];
+ 			}
+ 			else if(!strcmp(argv[1], "--header"))
+ 			{
+ 				--argc;
+ 				++argv;
+ 				if(argc <= 1)
+ 				{
+ 					Usage(progname);
+ 					return 1;
+ 				}
+ 				headerFile = argv[1];
+ 			}
+ 			else if(!strcmp(argv[1], "--output-dir"))
+ 			{
+ 				--argc;
+ 				++argv;
+ 				if(argc <= 1)
+ 				{
+ 					Usage(progname);
+ 					return 1;
+ 				}
+ 				outputDir = argv[1];
+ 			}
+ 			else if(!strcmp(argv[1], "--skeleton-dir"))
+ 			{
+ 				/* This option is obsolete: we still parse it just in
+ 				   case there are older build systems that expect it */
+ 				--argc;
+ 				++argv;
+ 				if(argc <= 1)
+ 				{
+ 					Usage(progname);
+ 					return 1;
+ 				}
+ 			}
+ 			else if(!strcmp(argv[1], "--extension"))
+ 			{
+ 				--argc;
+ 				++argv;
+ 				if(argc <= 1)
+ 				{
+ 					Usage(progname);
+ 					return 1;
+ 				}
+ 				extension = argv[1];
+ 			}
+ 			else if(!strcmp(argv[1], "--option"))
+ 			{
+ 				--argc;
+ 				++argv;
+ 				if(argc <= 1)
+ 				{
+ 					Usage(progname);
+ 					return 1;
+ 				}
+ 				options[num_options++] = argv[1];
+ 			}
+ 			else if(!strcmp(argv[1], "--force-create"))
+ 			{
+ 				forceCreate = 1;
+ 			}
+ 			else if(!strcmp(argv[1], "--no-output"))
+ 			{
+ 				generateOutput = 0;
+ 			}
+ 			else if(!strcmp(argv[1], "--help"))
+ 			{
+ 				Usage(progname);
+ 				return 1;
+ 			}
+ 			else if(!strcmp(argv[1], "--version"))
+ 			{
+ 				Version();
+ 				return 0;
+ 			}
+ 			else
+ 			{
+ 				Usage(progname);
+ 				return 1;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			/* Single-character option */
+ 			opt = argv[1] + 1;
+ 			while(*opt != '\0')
+ 			{
+ 				switch(*opt++)
+ 				{
+ 					case 'o':
+ 					{
+ 						if(*opt != '\0')
+ 						{
+ 							outputFile = opt;
+ 							opt = "";
+ 						}
+ 						else if(argc <= 2)
+ 						{
+ 							Usage(progname);
+ 							return 1;
+ 						}
+ 						else
+ 						{
+ 							--argc;
+ 							++argv;
+ 							outputFile = argv[1];
+ 						}
+ 					}
+ 					break;
+ 
+ 					case 'h':
+ 					{
+ 						if(*opt != '\0')
+ 						{
+ 							headerFile = opt;
+ 							opt = "";
+ 						}
+ 						else if(argc <= 2)
+ 						{
+ 							Usage(progname);
+ 							return 1;
+ 						}
+ 						else
+ 						{
+ 							--argc;
+ 							++argv;
+ 							headerFile = argv[1];
+ 						}
+ 					}
+ 					break;
+ 
+ 					case 'd':
+ 					{
+ 						if(*opt != '\0')
+ 						{
+ 							outputDir = opt;
+ 							opt = "";
+ 						}
+ 						else if(argc <= 2)
+ 						{
+ 							Usage(progname);
+ 							return 1;
+ 						}
+ 						else
+ 						{
+ 							--argc;
+ 							++argv;
+ 							outputDir = argv[1];
+ 						}
+ 					}
+ 					break;
+ 
+ 					case 's':
+ 					{
+ 						/* This option is obsolete: we still parse it just in
+ 						   case there are older build systems that expect it */
+ 						if(*opt != '\0')
+ 						{
+ 							opt = "";
+ 						}
+ 						else if(argc <= 2)
+ 						{
+ 							Usage(progname);
+ 							return 1;
+ 						}
+ 						else
+ 						{
+ 							--argc;
+ 							++argv;
+ 						}
+ 					}
+ 					break;
+ 
+ 					case 'e':
+ 					{
+ 						if(*opt != '\0')
+ 						{
+ 							extension = opt;
+ 							opt = "";
+ 						}
+ 						else if(argc <= 2)
+ 						{
+ 							Usage(progname);
+ 							return 1;
+ 						}
+ 						else
+ 						{
+ 							--argc;
+ 							++argv;
+ 							extension = argv[1];
+ 						}
+ 					}
+ 					break;
+ 
+ 					case 'O':
+ 					{
+ 						if(*opt != '\0')
+ 						{
+ 							options[num_options++] = opt;
+ 							opt = "";
+ 						}
+ 						else if(argc <= 2)
+ 						{
+ 							Usage(progname);
+ 							return 1;
+ 						}
+ 						else
+ 						{
+ 							--argc;
+ 							++argv;
+ 							options[num_options++] = argv[1];
+ 						}
+ 					}
+ 					break;
+ 
+ 					case 'f':
+ 					{
+ 						forceCreate = 1;
+ 					}
+ 					break;
+ 
+ 					case 'n':
+ 					{
+ 						generateOutput = 0;
+ 					}
+ 					break;
+ 
+ 					case 'v':
+ 					{
+ 						Version();
+ 						return 0;
+ 					}
+ 					/* Not reached */
+ 
+ 					default:
+ 					{
+ 						Usage(progname);
+ 						return 1;
+ 					}
+ 					/* Not reached */
+ 				}
+ 			}
+ 		}
+ 		--argc;
+ 		++argv;
+ 	}
+ 	if(argc <= 1)
+ 	{
+ 		Usage(progname);
+ 		return 1;
+ 	}
+ 
+ 	/* Determine the default output and header filenames */
+ 	if(!outputFile)
+ 	{
+ 		if(*extension == '.')
+ 		{
+ 			++extension;
+ 		}
+ 		outputFile = GetDefault(argv[1], extension);
+ 	}
+ 	if(!headerFile)
+ 	{
+ 		headerFile = GetDefault(outputFile, "h");
+ 	}
+ 
+ 	/* Initialize the input routines */
+ 	TreeCCOpen(&input, progname, NULL, NULL);
+ 
+ 	/* Determine the default Java output directory */
+ 	if(!outputDir)
+ 	{
+ 		len = strlen(argv[1]);
+ 		while(len > 0 && argv[1][len - 1] != '/' && argv[1][len - 1] != '\\')
+ 		{
+ 			--len;
+ 		}
+ 		if(len > 0)
+ 		{
+ 			--len;
+ 		}
+ 		if(len > 0)
+ 		{
+ 			outputDir = (char *)malloc(len + 1);
+ 			if(!outputDir)
+ 			{
+ 				TreeCCOutOfMemory(&input);
+ 			}
+ 			strncpy(outputDir, argv[1], len);
+ 			outputDir[len] = '\0';
+ 		}
+ 	}
+ 
+ 	/* Create the parsing context */
+ 	context = TreeCCContextCreate(&input);
+ 	if(!context)
+ 	{
+ 		TreeCCOutOfMemory(&input);
+ 	}
+ 	context->force = forceCreate;
+ 	context->outputDirectory = outputDir;
+ 
+ 	/* Process additional options from the command-line */
+ 	if(!ExtraOptions(context, options, num_options))
+ 	{
+ 		return 1;
+ 	}
+ 	free(options);
+ 
+ 	/* Create the default source and header streams */
+ 	context->sourceStream = TreeCCStreamCreate(context, outputFile,
+ 											   NULL, 0);
+ 	context->sourceStream->defaultFile = 1;
+ 	context->headerStream = TreeCCStreamCreate(context, headerFile,
+ 											   NULL, 1);
+ 	context->headerStream->defaultFile = 1;
+ 
+ 	/* Process the input files */
+ 	while(argc > 1)
+ 	{
+ 		if(!strcmp(argv[1], "-"))
+ 		{
+ 			/* Parse stdin, but only once */
+ 			if(!sawStdin)
+ 			{
+ 				TreeCCOpen(&input, progname, stdin, "stdin");
+ 				TreeCCParse(context);
+ 				TreeCCClose(&input, 0);
+ 				sawStdin = 1;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			/* Parse some other file */
+ 			if((file = fopen(argv[1], "r")) == NULL)
+ 			{
+ 				perror(argv[1]);
+ 				input.errors = 1;
+ 			}
+ 			else
+ 			{
+ 				TreeCCOpen(&input, progname, file, argv[1]);
+ 				TreeCCParse(context);
+ 				TreeCCClose(&input, 1);
+ 			}
+ 		}
+ 		--argc;
+ 		++argv;
+ 	}
+ 
+ 	/* Validate node and operation coverage */
+ 	TreeCCNodeValidate(context);
+ 	TreeCCOperationValidate(context);
+ 
+ 	/* Abort if we encountered errors during parsing and validation */
+ 	if(input.errors)
+ 	{
+ 		TreeCCContextDestroy(context);
+ 		return 1;
+ 	}
+ 
+ 	/* Generate the output files */
+ 	result = 0;
+ 	if(generateOutput)
+ 	{
+ 		TreeCCStream *stream;
+ 		TreeCCGenerate(context);
+ 		stream = context->streamList;
+ 		while(stream != 0)
+ 		{
+ 			if(!TreeCCStreamFlush(stream))
+ 			{
+ 				result = 1;
+ 			}
+ 			stream = stream->nextStream;
+ 		}
+ 	}
+ 
+ 	/* Done */
+ 	TreeCCContextDestroy(context);
+ 	return result;
+ }
+ 
+ static void Usage(char *progname)
+ {
+ 	fprintf(stderr, "TREECC " VERSION " - Tree Compiler-Compiler\n");
+ 	fprintf(stderr, "Copyright (c) 2001, 2002 Southern Storm Software, Pty Ltd.\n");
+ 	fprintf(stderr, "\n");
+ 	fprintf(stderr, "Usage: %s [options] input ...\n", progname);
+ 	fprintf(stderr, "\n");
+ 	fprintf(stderr, "    -o file, --output file\n");
+ 	fprintf(stderr, "        Set the name of the output file.\n");
+ 	fprintf(stderr, "    -h file, --header file\n");
+ 	fprintf(stderr, "        Set the name of the header output file.\n");
+ 	fprintf(stderr, "    -d dir,  --output-dir file\n");
+ 	fprintf(stderr, "        Set the name of the Java output directory.\n");
+ 	fprintf(stderr, "    -e ext,  --extension ext\n");
+ 	fprintf(stderr, "        Set the output file extension (default is \".c\").\n");
+ 	fprintf(stderr, "    -f,      --force-create\n");
+ 	fprintf(stderr, "        Force the creation of unchanged output files.\n");
+ 	fprintf(stderr, "    -O opt,  --option opt\n");
+ 	fprintf(stderr, "        Set a treecc source option value.\n");
+ 	fprintf(stderr, "    --help\n");
+ 	fprintf(stderr, "        Print this help message.\n");
+ 	fprintf(stderr, "    -v,      --version\n");
+ 	fprintf(stderr, "        Print the program version.\n");
+ }
+ 
+ static void Version(void)
+ {
+ 	printf("TREECC " VERSION " - Tree Compiler-Compiler\n");
+ 	printf("Copyright (c) 2001, 2002 Southern Storm Software, Pty Ltd.\n");
+ 	printf("\n");
+ 	printf("TREECC comes with ABSOLUTELY NO WARRANTY.  This is free software,\n");
+ 	printf("and you are welcome to redistribute it under the terms of the\n");
+ 	printf("GNU General Public License.  See the file COPYING for further details.\n");
+ 	printf("\n");
+ 	printf("Use the `--help' option to get help on the command-line options.\n");
+ }
+ 
+ /*
+  * Process extra treecc "%option" values from the command-line.
+  */
+ static int ExtraOptions(TreeCCContext *context, char **options, int num)
+ {
+ 	char *name;
+ 	char *value;
+ 	while(num-- > 0)
+ 	{
+ 		name = *options++;
+ 		value = name;
+ 		while(*value != '\0' && *value != '=')
+ 		{
+ 			++value;
+ 		}
+ 		if(*value == '\0')
+ 		{
+ 			value = 0;
+ 		}
+ 		else
+ 		{
+ 			*value++ = '\0';
+ 		}
+ 		if(TreeCCOptionProcess(context, name, value) != TREECC_OPT_OK)
+ 		{
+ 			fprintf(stderr, "%s: unknown option or invalid value\n", name);
+ 			return 0;
+ 		}
+ 	}
+ 	return 1;
+ }
+ 
+ /*
+  * Get a default output or header filename from an input filename.
+  */
+ static char *GetDefault(const char *filename, const char *extension)
+ {
+ 	int len;
+ 	char *name;
+ 
+ 	/* USe a default filename pattern if we are reading from stdin */
+ 	if(!strcmp(filename, "-"))
+ 	{
+ 		filename = "yy_tree.tc";
+ 	}
+ 
+ 	/* Find the end of the input filename, without its extension */
+ 	len = strlen(filename);
+ 	while(len > 0 && filename[len - 1] != '/' && filename[len - 1] != '\\' &&
+ 		  filename[len - 1] != '.')
+ 	{
+ 		--len;
+ 	}
+ 
+ 	/* Construct the new filename */
+ 	if(len > 0 && filename[len - 1] == '.')
+ 	{
+ 		name = (char *)malloc(len + strlen(extension) + 1);
+ 		if(!name)
+ 		{
+ 			TreeCCOutOfMemory((TreeCCInput *)0);
+ 		}
+ 		strncpy(name, filename, len);
+ 		strcpy(name + len, extension);
+ 	}
+ 	else
+ 	{
+ 		len = strlen(filename);
+ 		name = (char *)malloc(len + strlen(extension) + 2);
+ 		if(!name)
+ 		{
+ 			TreeCCOutOfMemory((TreeCCInput *)0);
+ 		}
+ 		strcpy(name, filename);
+ 		name[len] = '.';
+ 		strcpy(name + len + 1, extension);
+ 	}
+ 	return name;
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/node.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/node.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/node.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,682 ----
+ /*
+  * node.c - Management for node types for "treecc".
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ unsigned int TreeCCHashString(const char *str)
+ {
+ 	unsigned int hash = 0;
+ 	while(*str != '\0')
+ 	{
+ 		hash = (hash << 5) + hash + (unsigned int)(*str++);
+ 	}
+ 	return hash;
+ }
+ 
+ static unsigned int HashStringLen(const char *str, int len)
+ {
+ 	unsigned int hash = 0;
+ 	while(len > 0)
+ 	{
+ 		hash = (hash << 5) + hash + (unsigned int)(*str++);
+ 		--len;
+ 	}
+ 	return hash;
+ }
+ 
+ void TreeCCNodeFree(TreeCCNode *node)
+ {
+ 	TreeCCField *field, *nextField;
+ 	TreeCCVirtual *virt, *nextVirt;
+ 
+ 	/* Free the node's fields */
+ 	field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		nextField = field->next;
+ 		free(field->name);
+ 		free(field->type);
+ 		if(field->value)
+ 		{
+ 			free(field->value);
+ 		}
+ 		free(field);
+ 		field = nextField;
+ 	}
+ 
+ 	/* Free the virtual member function references */
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		nextVirt = virt->next;
+ 		free(virt);
+ 		virt = nextVirt;
+ 	}
+ 
+ 	/* Free other members and the node itself */
+ 	free(node->name);
+ 	free(node);
+ }
+ 
+ /*
+  * Add a node to the hash table.
+  */
+ static void AddToHash(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	unsigned int hash = (TreeCCHashString(node->name) & (TREECC_HASH_SIZE - 1));
+ 	node->nextHash = context->nodeHash[hash];
+ 	context->nodeHash[hash] = node;
+ }
+ 
+ TreeCCNode *TreeCCNodeCreate(TreeCCContext *context, long linenum,
+ 					  		 char *name, char *parent, int flags)
+ {
+ 	TreeCCNode *parentNode;
+ 	TreeCCNode *node;
+ 
+ 	/* Print debugging information if required */
+ 	if(context->debugMode)
+ 	{
+ 		TreeCCDebug(linenum, "%%node %s %s %d", name,
+ 					(parent ? parent : "no_parent"), flags);
+ 	}
+ 
+ 	/* Find or create the parent node */
+ 	if(parent)
+ 	{
+ 		parentNode = TreeCCNodeFind(context, parent);
+ 		if(!parentNode)
+ 		{
+ 			/* Create an undefined placeholder for the parent */
+ 			parentNode = (TreeCCNode *)malloc(sizeof(TreeCCNode));
+ 			if(!parentNode)
+ 			{
+ 				TreeCCOutOfMemory(context->input);
+ 			}
+ 			parentNode->parent = 0;
+ 			parentNode->firstChild = 0;
+ 			parentNode->lastChild = 0;
+ 			parentNode->nextSibling = 0;
+ 			parentNode->name = parent;
+ 			parentNode->flags = TREECC_NODE_UNDEFINED;
+ 			parentNode->number = (context->nodeNumber)++;
+ 			parentNode->filename = context->input->filename;
+ 			parentNode->linenum = linenum;
+ 			parentNode->fields = 0;
+ 			parentNode->virtuals = 0;
+ 			parentNode->header = context->headerStream;
+ 			parentNode->source = context->sourceStream;
+ 			AddToHash(context, parentNode);
+ 		}
+ 		else
+ 		{
+ 			free(parent);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		parentNode = 0;
+ 	}
+ 
+ 	/* Find or create the current node */
+ 	node = TreeCCNodeFind(context, name);
+ 	if(node)
+ 	{
+ 		if((node->flags & TREECC_NODE_UNDEFINED) == 0)
+ 		{
+ 			TreeCCErrorOnLine(context->input, context->input->filename, linenum,
+ 							  "node type `%s' is already declared", name);
+ 			TreeCCErrorOnLine(context->input, node->filename, node->linenum,
+ 							  "previous declaration here");
+ 			free(name);
+ 		}
+ 		else
+ 		{
+ 			node->flags = flags;
+ 			node->parent = parentNode;
+ 			node->filename = context->input->filename;
+ 			node->linenum = linenum;
+ 			node->header = context->headerStream;
+ 			node->source = context->sourceStream;
+ 			node->nextSibling = 0;
+ 			if(parentNode)
+ 			{
+ 				if(parentNode->lastChild)
+ 				{
+ 					parentNode->lastChild->nextSibling = node;
+ 				}
+ 				else
+ 				{
+ 					parentNode->firstChild = node;
+ 				}
+ 				parentNode->lastChild = node;
+ 			}
+ 		}
+ 	}
+ 	else
+ 	{
+ 		node = (TreeCCNode *)malloc(sizeof(TreeCCNode));
+ 		if(!node)
+ 		{
+ 			TreeCCOutOfMemory(context->input);
+ 		}
+ 		node->parent = parentNode;
+ 		node->firstChild = 0;
+ 		node->lastChild = 0;
+ 		node->name = name;
+ 		node->flags = flags;
+ 		node->number = (context->nodeNumber)++;
+ 		node->filename = context->input->filename;
+ 		node->linenum = linenum;
+ 		node->fields = 0;
+ 		node->virtuals = 0;
+ 		node->header = context->headerStream;
+ 		node->source = context->sourceStream;
+ 		node->nextSibling = 0;
+ 		if(parentNode)
+ 		{
+ 			if(parentNode->lastChild)
+ 			{
+ 				parentNode->lastChild->nextSibling = node;
+ 			}
+ 			else
+ 			{
+ 				parentNode->firstChild = node;
+ 			}
+ 			parentNode->lastChild = node;
+ 		}
+ 		AddToHash(context, node);
+ 	}
+ 	return node;
+ }
+ 
+ TreeCCNode *TreeCCNodeFind(TreeCCContext *context, const char *name)
+ {
+ 	unsigned int hash = (TreeCCHashString(name) & (TREECC_HASH_SIZE - 1));
+ 	TreeCCNode *node = context->nodeHash[hash];
+ 	while(node != 0)
+ 	{
+ 		if(!strcmp(node->name, name))
+ 		{
+ 			return node;
+ 		}
+ 		node = node->nextHash;
+ 	}
+ 	return 0;
+ }
+ 
+ TreeCCNode *TreeCCNodeFindByType(TreeCCContext *context, const char *name)
+ {
+ 	unsigned int hash;
+ 	TreeCCNode *node;
+ 	int len;
+ 	int hasSuffix;
+ 	
+ 	/* Strip " *" from the end of the name, if present */
+ 	len = strlen(name);
+ 	if(len >= 2 && name[len - 1] == '*' && name[len - 2] == ' ')
+ 	{
+ 		len -= 2;
+ 		hasSuffix = 1;
+ 	}
+ 	else
+ 	{
+ 		hasSuffix = 0;
+ 	}
+ 
+ 	/* Look for the name */
+ 	hash = (HashStringLen(name, len) & (TREECC_HASH_SIZE - 1));
+ 	node = context->nodeHash[hash];
+ 	while(node != 0)
+ 	{
+ 		if(!strncmp(node->name, name, len) && node->name[len] == '\0')
+ 		{
+ 			if((node->flags & TREECC_NODE_ENUM) != 0)
+ 			{
+ 				/* We can only use enumerations as types if no suffix */
+ 				if(hasSuffix)
+ 				{
+ 					return 0;
+ 				}
+ 				else
+ 				{
+ 					return node;
+ 				}
+ 			}
+ 			else if((node->flags & TREECC_NODE_ENUM_VALUE) != 0)
+ 			{
+ 				/* Enumerated values cannot be used as types */
+ 				return 0;
+ 			}
+ 			else
+ 			{
+ 				return node;
+ 			}
+ 		}
+ 		node = node->nextHash;
+ 	}
+ 	return 0;
+ }
+ 
+ void TreeCCNodeValidate(TreeCCContext *context)
+ {
+ 	unsigned int hash;
+ 	TreeCCNode *node;
+ 	TreeCCNode *type;
+ 	TreeCCField *field;
+ 	int len;
+ 	int typeCheck = (context->language == TREECC_LANG_C ||
+ 					 context->language == TREECC_LANG_CPP);
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		node = context->nodeHash[hash];
+ 		while(node != 0)
+ 		{
+ 			if((node->flags & TREECC_NODE_UNDEFINED) != 0)
+ 			{
+ 				TreeCCErrorOnLine(context->input,
+ 								  node->filename, node->linenum,
+ 								  "node type `%s' is not declared",
+ 								  node->name);
+ 			}
+ 			if(!(node->parent) &&
+ 			   (node->flags & TREECC_NODE_UNDEFINED) == 0 &&
+ 			   (node->flags & TREECC_NODE_TYPEDEF) == 0)
+ 			{
+ 				TreeCCErrorOnLine(context->input,
+ 					  node->filename, node->linenum,
+ 					  "base node type `%s' must be declared with %%typedef",
+ 					  node->name);
+ 			}
+ 			if(typeCheck)
+ 			{
+ 				/* In C or C++, fields that are declared as node
+ 				   types must end in "*" */
+ 				field = node->fields;
+ 				while(field != 0)
+ 				{
+ 					type = TreeCCNodeFindByType(context, field->type);
+ 					if(type != 0 && (type->flags & TREECC_NODE_ENUM) == 0)
+ 					{
+ 						len = strlen(field->type);
+ 						if(len < 2 || field->type[len - 1] != '*' ||
+ 						   field->type[len - 2] != ' ')
+ 						{
+ 							TreeCCErrorOnLine(context->input,
+ 									field->filename, field->linenum,
+ 									"field type does not end in `*'");
+ 						}
+ 					}
+ 					field = field->next;
+ 				}
+ 			}
+ 			node = node->nextHash;
+ 		}
+ 	}
+ }
+ 
+ /*
+  * Visit the children of a node in breadth-first order.
+  */
+ static void Visit(TreeCCContext *context, TreeCCNode *node,
+ 				  TreeCCNodeVisitor visitor)
+ {
+ 	TreeCCNode *child;
+ 
+ 	/* Visit the children of the node */
+ 	child = node->firstChild;
+ 	while(child != 0)
+ 	{
+ 		(*visitor)(context, child);
+ 		child = child->nextSibling;
+ 	}
+ 
+ 	/* Visit their children */
+ 	child = node->firstChild;
+ 	while(child != 0)
+ 	{
+ 		Visit(context, child, visitor);
+ 		child = child->nextSibling;
+ 	}
+ }
+ 
+ void TreeCCNodeVisitAll(TreeCCContext *context, TreeCCNodeVisitor visitor)
+ {
+ 	unsigned int hash;
+ 	TreeCCNode *node;
+ 
+ 	/* Find and visit all top-level nodes */
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		node = context->nodeHash[hash];
+ 		while(node != 0)
+ 		{
+ 			if(!(node->parent))
+ 			{
+ 				(*visitor)(context, node);
+ 				Visit(context, node, visitor);
+ 			}
+ 			node = node->nextHash;
+ 		}
+ 	}
+ }
+ 
+ int TreeCCNodeIsSingleton(TreeCCNode *node)
+ {
+ 	while(node != 0)
+ 	{
+ 		if(node->fields != 0)
+ 		{
+ 			return 0;
+ 		}
+ 		node = node->parent;
+ 	}
+ 	return 1;
+ }
+ 
+ static int HasAbstracts(TreeCCContext *context, TreeCCNode *node,
+ 						TreeCCNode *actualNode)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCOperationCase *operCase;
+ 	TreeCCNode *tempNode;
+ 	int abstractCase;
+ 
+ 	/* Check for abstracts in the parent node type */
+ 	if(node->parent)
+ 	{
+ 		if(HasAbstracts(context, node->parent, actualNode))
+ 		{
+ 			return 1;
+ 		}
+ 	}
+ 
+ 	/* Check for abstracts in this node type */
+ 	virt = node->virtuals;
+ 	while(virt != 0)
+ 	{
+ 		/* Determine if we need a definition for this virtual,
+ 		   and whether the definition is real or abstract */
+ 		operCase = TreeCCOperationFindCase(context, actualNode, virt->name);
+ 		if(!operCase)
+ 		{
+ 			tempNode = actualNode->parent;
+ 			abstractCase = 1;
+ 			while(tempNode != 0)
+ 			{
+ 				operCase = TreeCCOperationFindCase
+ 								(context, tempNode, virt->name);
+ 				if(operCase != 0)
+ 				{
+ 					abstractCase = 0;
+ 					break;
+ 				}
+ 				tempNode = tempNode->parent;
+ 			}
+ 			if(abstractCase)
+ 			{
+ 				return 1;
+ 			}
+ 		}
+ 		virt = virt->next;
+ 	}
+ 	return 0;
+ }
+ 
+ int TreeCCNodeHasAbstracts(TreeCCContext *context, TreeCCNode *node)
+ {
+ 	return HasAbstracts(context, node, node);
+ }
+ 
+ void TreeCCNodeAddVirtual(TreeCCContext *context, TreeCCNode *node,
+ 						  TreeCCOperation *oper)
+ {
+ 	TreeCCVirtual *virt;
+ 	TreeCCVirtual *last;
+ 
+ 	/* Print debugging information if required */
+ 	if(context->debugMode)
+ 	{
+ 		TreeCCDebug(oper->linenum, "%%virtual %s %s",
+ 					node->name, oper->name);
+ 	}
+ 
+ 	/* Allocate the virtual method block */
+ 	if((virt = (TreeCCVirtual *)malloc(sizeof(TreeCCVirtual))) == 0)
+ 	{
+ 		TreeCCOutOfMemory(context->input);
+ 	}
+ 
+ 	/* Initialise the virtual method fields */
+ 	virt->name = oper->name;
+ 	virt->returnType = oper->returnType;
+ 	virt->params = oper->params->next;
+ 	virt->oper = oper;
+ 	virt->next = 0;
+ 
+ 	/* Add the virtual method to the end of the node's virtual list */
+ 	if(node->virtuals)
+ 	{
+ 		last = node->virtuals;
+ 		while(last->next != 0)
+ 		{
+ 			last = last->next;
+ 		}
+ 		last->next = virt;
+ 	}
+ 	else
+ 	{
+ 		node->virtuals = virt;
+ 	}
+ }
+ 
+ int TreeCCNodeInheritsFrom(TreeCCNode *nodea, TreeCCNode *nodeb)
+ {
+ 	while(nodea != 0)
+ 	{
+ 		if(nodea == nodeb)
+ 		{
+ 			return 1;
+ 		}
+ 		nodea = nodea->parent;
+ 	}
+ 	return 0;
+ }
+ 
+ void TreeCCNodeClearMarking(TreeCCContext *context, int flags)
+ {
+ 	unsigned int hash;
+ 	TreeCCNode *node;
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		node = context->nodeHash[hash];
+ 		while(node != 0)
+ 		{
+ 			node->flags &= ~flags;
+ 			node = node->nextHash;
+ 		}
+ 	}
+ }
+ 
+ /*
+  * Assign positions starting at a particular value.
+  */
+ static int AssignPositions(TreeCCNode *node, int posn)
+ {
+ 	TreeCCNode *child;
+ 
+ 	/* Assign positions to the children */
+ 	child = node->firstChild;
+ 	while(child != 0)
+ 	{
+ 		posn = AssignPositions(child, posn);
+ 		child = child->nextSibling;
+ 	}
+ 
+ 	/* Assign a position to this node */
+ 	node->position = posn;
+ 	return posn + 1;
+ }
+ 
+ int TreeCCNodeAssignPositions(TreeCCNode *node)
+ {
+ 	return AssignPositions(node, 0);
+ }
+ 
+ /*
+  * Determine if a field name is already declared in a node type.
+  */
+ static int IsDeclared(TreeCCContext *context, TreeCCNode *node,
+ 					  char *name, int reverseError)
+ {
+ 	TreeCCField *field = node->fields;
+ 	while(field != 0)
+ 	{
+ 		if(!strcmp(field->name, name))
+ 		{
+ 			if(reverseError)
+ 			{
+ 				/* We are attempting to declare a field already in a child */
+ 				TreeCCErrorOnLine(context->input,
+ 						field->filename, field->linenum,
+ 					  	"field `%s' is already declared", name);
+ 				TreeCCError(context->input, "previous declaration here");
+ 			}
+ 			else
+ 			{
+ 				/* We are attempting to declare a field already in a parent */
+ 				TreeCCError(context->input, "field `%s' is already declared",
+ 							name);
+ 				TreeCCErrorOnLine(context->input,
+ 						field->filename, field->linenum,
+ 					  	"previous declaration here");
+ 			}
+ 			return 1;
+ 		}
+ 		field = field->next;
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * Determine if a field name is already declared in child node types.
+  */
+ static int IsDeclaredInChildren(TreeCCContext *context, TreeCCNode *node,
+ 								char *name)
+ {
+ 	TreeCCNode *child = node->firstChild;
+ 	while(child != 0)
+ 	{
+ 		if(IsDeclared(context, child, name, 1))
+ 		{
+ 			return 1;
+ 		}
+ 		if(IsDeclaredInChildren(context, child, name))
+ 		{
+ 			return 1;
+ 		}
+ 		child = child->nextSibling;
+ 	}
+ 	return 0;
+ }
+ 
+ void TreeCCFieldCreate(TreeCCContext *context, TreeCCNode *node,
+ 					   char *name, char *type, char *value, int flags)
+ {
+ 	TreeCCNode *current;
+ 	TreeCCField *field;
+ 	TreeCCField *prev;
+ 
+ 	/* Print debugging information if required */
+ 	if(context->debugMode)
+ 	{
+ 		TreeCCDebug(context->input->linenum,
+ 					"%%field %s %s %s %d", name,
+ 					(type ? type : "no_type"),
+ 					(value ? value : "no_value"), flags);
+ 	}
+ 
+ 	/* Check to make sure that the field does not already exist
+ 	   in this node type or any of its ancestor node types */
+ 	current = node;
+ 	while(current != 0)
+ 	{
+ 		if(IsDeclared(context, current, name, 0))
+ 		{
+ 			free(name);
+ 			free(type);
+ 			if(value)
+ 			{
+ 				free(value);
+ 			}
+ 			return;
+ 		}
+ 		current = current->parent;
+ 	}
+ 
+ 	/* Check to make sure that the field does not already exist
+ 	   in any of the child classes.  This may happen if a child
+ 	   class is declared before one of its ancestors */
+ 	IsDeclaredInChildren(context, node, name);
+ 
+ 	/* Find the end of the node's field list */
+ 	field = node->fields;
+ 	prev = 0;
+ 	while(field != 0)
+ 	{
+ 		prev = field;
+ 		field = field->next;
+ 	}
+ 
+ 	/* Create a new field block and fill it in */
+ 	field = (TreeCCField *)malloc(sizeof(TreeCCField));
+ 	if(!field)
+ 	{
+ 		TreeCCOutOfMemory(context->input);
+ 	}
+ 	field->name = name;
+ 	field->type = type;
+ 	field->value = value;
+ 	field->flags = flags;
+ 	field->filename = context->input->filename;
+ 	field->linenum = context->input->linenum;
+ 	field->next = 0;
+ 
+ 	/* Add the field to the list */
+ 	if(prev)
+ 	{
+ 		prev->next = field;
+ 	}
+ 	else
+ 	{
+ 		node->fields = field;
+ 	}
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/oper.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/oper.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/oper.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,835 ----
+ /*
+  * oper.c - Management for operations for "treecc".
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ void TreeCCOperationFree(TreeCCOperation *oper)
+ {
+ 	TreeCCParam *param, *nextParam;
+ 	TreeCCOperationCase *operCase, *nextCase;
+ 	TreeCCTrigger *trigger, *nextTrigger;
+ 
+ 	/* Free the name and return type */
+ 	free(oper->name);
+ 	if(oper->className)
+ 	{
+ 		free(oper->className);
+ 	}
+ 	free(oper->returnType);
+ 
+ 	/* Free the parameters */
+ 	param = oper->params;
+ 	while(param != 0)
+ 	{
+ 		nextParam = param->next;
+ 		if(param->name)
+ 		{
+ 			free(param->name);
+ 		}
+ 		free(param->type);
+ 		param = nextParam;
+ 	}
+ 
+ 	/* Free the operation cases */
+ 	operCase = oper->firstCase;
+ 	while(operCase != 0)
+ 	{
+ 		nextCase = operCase->next;
+ 		if(operCase->code && !(operCase->nextHeader))
+ 		{
+ 			free(operCase->code);
+ 		}
+ 		trigger = operCase->triggers;
+ 		while(trigger != 0)
+ 		{
+ 			nextTrigger = trigger->next;
+ 			free(trigger);
+ 			trigger = nextTrigger;
+ 		}
+ 		free(operCase);
+ 		operCase = nextCase;
+ 	}
+ 
+ 	/* Free the array of sorted operation cases */
+ 	if(oper->sortedCases)
+ 	{
+ 		free(oper->sortedCases);
+ 	}
+ 
+ 	/* Free the operation block itself */
+ 	free(oper);
+ }
+  
+ TreeCCOperation *TreeCCOperationCreate(TreeCCContext *context,
+ 									   char *returnType, char *name,
+ 									   char *className, char *defValue,
+ 									   TreeCCParam *params, int flags,
+ 									   int numTriggers, char *filename,
+ 									   long linenum)
+ {
+ 	TreeCCOperation *oper;
+ 	unsigned int hash;
+ 
+ 	/* Print debugging information if required */
+ 	if(context->debugMode)
+ 	{
+ 		TreeCCParam *param;
+ 		TreeCCDebug(linenum, "%%operation %s %s%s%s %d",
+ 					returnType,
+ 					(className ? className : ""),
+ 					(className ? "::" : ""),
+ 					name, flags);
+ 		param = params;
+ 		while(param != 0)
+ 		{
+ 			TreeCCDebug(linenum, "%%param %s %s %d",
+ 						param->type, (param->name ? param->name : "no_name"),
+ 						param->flags);
+ 			param = param->next;
+ 		}
+ 	}
+ 
+ 	/* Allocate the operation block */
+ 	if((oper = (TreeCCOperation *)malloc(sizeof(TreeCCOperation))) == 0)
+ 	{
+ 		TreeCCOutOfMemory(context->input);
+ 	}
+ 
+ 	/* Initialise the operation block */
+ 	oper->name = name;
+ 	oper->className = className;
+ 	oper->returnType = returnType;
+ 	oper->defValue = defValue;
+ 	oper->params = params;
+ 	oper->flags = flags;
+ 	oper->numTriggers = numTriggers;
+ 	oper->filename = filename;
+ 	oper->linenum = linenum;
+ 	oper->firstCase = 0;
+ 	oper->lastCase = 0;
+ 	oper->sortedCases = 0;
+ 	oper->numCases = 0;
+ 	oper->header = context->headerStream;
+ 	oper->source = context->sourceStream;
+ 
+ 	/* Add the operation to the hash table */
+ 	hash = (TreeCCHashString(name) & (TREECC_HASH_SIZE - 1));
+ 	oper->nextHash = context->operHash[hash];
+ 	context->operHash[hash] = oper;
+ 
+ 	/* Done */
+ 	return oper;
+ }
+ 
+ TreeCCOperation *TreeCCOperationFind(TreeCCContext *context, char *name)
+ {
+ 	unsigned int hash = (TreeCCHashString(name) & (TREECC_HASH_SIZE - 1));
+ 	TreeCCOperation *oper = context->operHash[hash];
+ 	while(oper != 0)
+ 	{
+ 		if(!strcmp(oper->name, name))
+ 		{
+ 			return oper;
+ 		}
+ 		oper = oper->nextHash;
+ 	}
+ 	return 0;
+ }
+ 
+ TreeCCOperationCase *TreeCCOperationAddCase
+ 			(TreeCCContext *context, TreeCCOperation *oper,
+ 			 TreeCCTrigger *triggers, char *filename, long linenum)
+ {
+ 	TreeCCOperationCase *operCase;
+ 
+ 	/* Print debugging information if required */
+ 	if(context->debugMode)
+ 	{
+ 		if(!triggers)
+ 		{
+ 			TreeCCDebug(linenum, "%%case %s", oper->name);
+ 		}
+ 		else
+ 		{
+ 			TreeCCDebug(linenum, "%%case %s %s", triggers->node->name,
+ 						oper->name);
+ 		}
+ 	}
+ 
+ 	/* Allocate the operation case block */
+ 	if((operCase = (TreeCCOperationCase *)malloc(sizeof(TreeCCOperationCase)))
+ 						== 0)
+ 	{
+ 		TreeCCOutOfMemory(context->input);
+ 	}
+ 
+ 	/* Initialise the operation case block */
+ 	operCase->triggers = triggers;
+ 	operCase->code = 0;
+ 	operCase->oper = oper;
+ 	operCase->number = 0;
+ 	operCase->filename = filename;
+ 	operCase->linenum = linenum;
+ 	operCase->codeFilename = 0;
+ 	operCase->codeLinenum = 0;
+ 	operCase->next = 0;
+ 	operCase->nextHeader = 0;
+ 
+ 	/* Add the case to the operation's case list */
+ 	if(oper->lastCase)
+ 	{
+ 		oper->lastCase->next = operCase;
+ 	}
+ 	else
+ 	{
+ 		oper->firstCase = operCase;
+ 	}
+ 	oper->lastCase = operCase;
+ 	++(oper->numCases);
+ 
+ 	/* Return the case to the caller */
+ 	return operCase;
+ }
+ 
+ /*
+  * Verify the coverage of an operation over a node hierarchy.
+  */
+ static void VerifyHierarchy(TreeCCContext *context, TreeCCOperation *oper,
+ 							TreeCCNode *node)
+ {
+ 	if((node->flags & TREECC_NODE_MARK(0)) != 0)
+ 	{
+ 		return;
+ 	}
+ 	if((node->flags & TREECC_NODE_ABSTRACT) == 0)
+ 	{
+ 		TreeCCErrorOnLine(context->input, oper->filename, oper->linenum,
+ 						  "node type `%s' is not handled in operation `%s'",
+ 						  node->name, oper->name);
+ 		return;
+ 	}
+ 	node = node->firstChild;
+ 	while(node != 0)
+ 	{
+ 		VerifyHierarchy(context, oper, node);
+ 		node = node->nextSibling;
+ 	}
+ }
+ 
+ /*
+  * Append a parameter type name to a comma-separated string.
+  */
+ static char *AppendParam(TreeCCContext *context, char *str, const char *type)
+ {
+ 	if(str)
+ 	{
+ 		int slen = strlen(str);
+ 		int tlen = strlen(type);
+ 		str = (char *)realloc(str, slen + tlen + 3);
+ 		if(!str)
+ 		{
+ 			TreeCCOutOfMemory(context->input);
+ 		}
+ 		strcpy(str + slen, ", ");
+ 		strcpy(str + slen + 2, type);
+ 		return str;
+ 	}
+ 	else
+ 	{
+ 		return TreeCCDupString((char *)type);
+ 	}
+ }
+ 
+ /*
+  * Forward declaration.
+  */
+ static void MarkMultiCase(TreeCCOperationCase **sortedCases, int base,
+ 						  int multiplier, TreeCCParam *nextParam,
+ 						  TreeCCOperationCase *operCase,
+ 						  TreeCCTrigger *nextTrigger);
+ 
+ /*
+  * Scan down a node type hierarchy to mark all covered children.
+  */
+ static void MarkMultiScan(TreeCCOperationCase **sortedCases, int base,
+ 						  int multiplier, TreeCCParam *nextParam,
+ 						  TreeCCOperationCase *operCase,
+ 						  TreeCCTrigger *nextTrigger, TreeCCNode *node)
+ {
+ 	/* Go in one level for this node */
+ 	MarkMultiCase(sortedCases, base + node->position * multiplier,
+ 				  multiplier * nextParam->size, nextParam->next,
+ 				  operCase, nextTrigger->next);
+ 
+ 	/* Scan all of the children */
+ 	node = node->firstChild;
+ 	while(node != 0)
+ 	{
+ 		MarkMultiScan(sortedCases, base, multiplier, nextParam,
+ 					  operCase, nextTrigger, node);
+ 		node = node->nextSibling;
+ 	}
+ }
+ 
+ /*
+  * Mark all of the node types associated with an operation case.
+  */
+ static void MarkMultiCase(TreeCCOperationCase **sortedCases, int base,
+ 						  int multiplier, TreeCCParam *nextParam,
+ 						  TreeCCOperationCase *operCase,
+ 						  TreeCCTrigger *nextTrigger)
+ {
+ 	/* Scan for the next trigger parameter */
+ 	while(nextParam != 0 && (nextParam->flags & TREECC_PARAM_TRIGGER) == 0)
+ 	{
+ 		nextParam = nextParam->next;
+ 	}
+ 
+ 	/* If we are out of triggers, then we need to set the current value */
+ 	if(!nextParam)
+ 	{
+ 		if(sortedCases[base] == 0)
+ 		{
+ 			sortedCases[base] = operCase;
+ 		}
+ 		return;
+ 	}
+ 
+ 	/* Scan down the node type hierarchy for this trigger level */
+ 	MarkMultiScan(sortedCases, base, multiplier, nextParam,
+ 				  operCase, nextTrigger, nextTrigger->node);
+ }
+ 
+ /*
+  * Forward declaration.
+  */
+ static void VerifyMultiCoverage(TreeCCContext *context, TreeCCOperation *oper,
+ 								TreeCCOperationCase **sortedCases, int base,
+ 								int multiplier, TreeCCParam *nextParam,
+ 								TreeCCNode **nodeStack,
+ 								TreeCCNode **nodeStackTop);
+ 
+ /*
+  * Scan all children to verify a multi-coverage trigger.
+  */
+ static void VerifyMultiScan(TreeCCContext *context, TreeCCOperation *oper,
+ 							TreeCCOperationCase **sortedCases, int base,
+ 							int multiplier, TreeCCParam *nextParam,
+ 							TreeCCNode *node, TreeCCNode **nodeStack,
+ 							TreeCCNode **nodeStackTop)
+ {
+ 	/* Go in one level for this node */
+ 	*nodeStackTop = node;
+ 	VerifyMultiCoverage(context, oper, sortedCases,
+ 						base + node->position * multiplier,
+ 						multiplier * nextParam->size,
+ 						nextParam->next, nodeStack, nodeStackTop + 1);
+ 
+ 	/* Scan all of the children */
+ 	node = node->firstChild;
+ 	while(node != 0)
+ 	{
+ 		VerifyMultiScan(context, oper, sortedCases, base, multiplier,
+ 						nextParam, node, nodeStack, nodeStackTop);
+ 		node = node->nextSibling;
+ 	}
+ }
+ 
+ /*
+  * Verify coverage of a multi-trigger operation.
+  */
+ static void VerifyMultiCoverage(TreeCCContext *context, TreeCCOperation *oper,
+ 								TreeCCOperationCase **sortedCases, int base,
+ 								int multiplier, TreeCCParam *nextParam,
+ 								TreeCCNode **nodeStack,
+ 								TreeCCNode **nodeStackTop)
+ {
+ 	TreeCCNode *type;
+ 
+ 	/* Scan for the next trigger */
+ 	while(nextParam != 0 && (nextParam->flags & TREECC_PARAM_TRIGGER) == 0)
+ 	{
+ 		nextParam = nextParam->next;
+ 	}
+ 
+ 	/* If we are out of triggers, then we need to do a test */
+ 	if(!nextParam)
+ 	{
+ 		if(sortedCases[base] == 0)
+ 		{
+ 			/* No case: report an error if none of the node types
+ 			   that led us here are abstract */
+ 			int posn;
+ 			int isAbstract = 0;
+ 			for(posn = 0; posn < oper->numTriggers; ++posn)
+ 			{
+ 				if((nodeStack[posn]->flags & TREECC_NODE_ABSTRACT) != 0)
+ 				{
+ 					isAbstract = 1;
+ 					break;
+ 				}
+ 			}
+ 			if(!isAbstract)
+ 			{
+ 				char *str = 0;
+ 				for(posn = 0; posn < oper->numTriggers; ++posn)
+ 				{
+ 					str = AppendParam(context, str, nodeStack[posn]->name);
+ 				}
+ 				if(!str)
+ 				{
+ 					str = TreeCCDupString("?");
+ 				}
+ 				TreeCCErrorOnLine(context->input, oper->filename, oper->linenum,
+ 								  "case `%s' is missing from operation `%s'",
+ 								  str, oper->name);
+ 				free(str);
+ 			}
+ 		}
+ 		return;
+ 	}
+ 
+ 	/* Scan down the node type hierarchy for this parameter level */
+ 	type = TreeCCNodeFindByType(context, nextParam->type);
+ 	if(!type)
+ 	{
+ 		return;
+ 	}
+ 	VerifyMultiScan(context, oper, sortedCases, base,
+ 				    multiplier, nextParam, type,
+ 					nodeStack, nodeStackTop);
+ }
+ 
+ /*
+  * Test the coverage of a multi-trigger operation.
+  */
+ static void MultiCoverageTest(TreeCCContext *context, TreeCCOperation *oper)
+ {
+ 	TreeCCParam *param;
+ 	TreeCCParam *param2;
+ 	TreeCCNode *type;
+ 	TreeCCNode *type2;
+ 	int size;
+ 	TreeCCNode **nodeStack;
+ 	TreeCCOperationCase *operCase;
+ 
+ 	/* Determine the size of the "sortedCases" array, and also
+ 	   check to make sure there are no overlaps between triggers
+ 	   that will cause position information to be inconsistent */
+ 	size = 1;
+ 	param = oper->params;
+ 	while(param != 0)
+ 	{
+ 		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 		{
+ 			type = TreeCCNodeFindByType(context, param->type);
+ 			if(type)
+ 			{
+ 				param->size = TreeCCNodeAssignPositions(type);
+ 				size *= param->size;
+ 				param2 = oper->params;
+ 				while(param2 != 0)
+ 				{
+ 					if((param2->flags & TREECC_PARAM_TRIGGER) != 0 &&
+ 					   param2 != param)
+ 					{
+ 						type2 = TreeCCNodeFindByType(context, param2->type);
+ 						if(type2 && type2 != type)
+ 						{
+ 							if(TreeCCNodeInheritsFrom(type, type2) ||
+ 							   TreeCCNodeInheritsFrom(type2, type))
+ 							{
+ 								TreeCCErrorOnLine(context->input,
+ 										  oper->filename, oper->linenum,
+ 										  "overlap between trigger types");
+ 								return;
+ 							}
+ 						}
+ 					}
+ 					param2 = param2->next;
+ 				}
+ 			}
+ 		}
+ 		param = param->next;
+ 	}
+ 
+ 	/* Create the "sortedCases" array */
+ 	if((oper->sortedCases = (TreeCCOperationCase **)calloc
+ 				(size, sizeof(TreeCCOperationCase *))) == 0)
+ 	{
+ 		TreeCCOutOfMemory(context->input);
+ 	}
+ 
+ 	/* Find the operation case to use for each combination of values */
+ 	operCase = oper->firstCase;
+ 	while(operCase != 0)
+ 	{
+ 		MarkMultiCase(oper->sortedCases, 0, 1, oper->params,
+ 					  operCase, operCase->triggers);
+ 		operCase = operCase->next;
+ 	}
+ 
+ 	/* Verify that every combination of values has been handled */
+ 	nodeStack = (TreeCCNode **)calloc(oper->numTriggers, sizeof(TreeCCNode *));
+ 	if(!nodeStack)
+ 	{
+ 		TreeCCOutOfMemory(context->input);
+ 	}
+ 	VerifyMultiCoverage(context, oper, oper->sortedCases, 0, 1,
+ 						oper->params, nodeStack, nodeStack);
+ 	free(nodeStack);
+ }
+ 
+ /*
+  * Test that an operation covers all relevant node type cases.
+  */
+ static void OperationTest(TreeCCContext *context, TreeCCOperation *oper)
+ {
+ 	TreeCCOperationCase *operCase;
+ 	TreeCCTrigger *trigger;
+ 	TreeCCParam *param;
+ 	TreeCCNode *node;
+ 
+ 	/* Clear the marking bits */
+ 	TreeCCNodeClearMarking(context, TREECC_NODE_MARK_BITS);
+ 
+ 	/* Print an error if the operation has no cases at all */
+ 	if(!(oper->firstCase))
+ 	{
+ 		TreeCCErrorOnLine(context->input, oper->filename, oper->linenum,
+ 						  "operation `%s' has no cases", oper->name);
+ 	}
+ 
+ 	/* Single or multiple triggers? */
+ 	if(oper->numTriggers == 1)
+ 	{
+ 		/* Mark the coverage of all operation cases */
+ 		operCase = oper->firstCase;
+ 		while(operCase != 0)
+ 		{
+ 			trigger = operCase->triggers;
+ 			if(trigger != 0)
+ 			{
+ 				if((trigger->node->flags & TREECC_NODE_MARK(0)) != 0)
+ 				{
+ 					TreeCCErrorOnLine(context->input, operCase->filename,
+ 									  operCase->linenum,
+ 					  				  "node type `%s' is handled multiple "
+ 									  		"times for operation `%s'",
+ 									  trigger->node->name, oper->name);
+ 				}
+ 				else
+ 				{
+ 					trigger->node->flags |= TREECC_NODE_MARK(0);
+ 				}
+ 			}
+ 			operCase = operCase->next;
+ 		}
+ 
+ 		/* Walk the node hierarchy to verify coverage */
+ 		param = oper->params;
+ 		while(param != 0)
+ 		{
+ 			if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 			{
+ 				node = TreeCCNodeFindByType(context, param->type);
+ 				if(node)
+ 				{
+ 					VerifyHierarchy(context, oper, node);
+ 				}
+ 			}
+ 			param = param->next;
+ 		}
+ 	}
+ 	else if(oper->numTriggers == 0)
+ 	{
+ 		/* Zero triggers: look for a single case definition */
+ 		operCase = oper->firstCase;
+ 		if(operCase && operCase->next)
+ 		{
+ 			do
+ 			{
+ 				operCase = operCase->next;
+ 				TreeCCErrorOnLine(context->input, operCase->filename,
+ 								  operCase->linenum,
+ 								  "multiple definitions for operation `%s'",
+ 								  oper->name);
+ 			}
+ 			while(operCase->next != 0);
+ 			TreeCCErrorOnLine(context->input, oper->firstCase->filename,
+ 							  oper->firstCase->linenum,
+ 							  "first definition here");
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* Multiple triggers need a more complex algorithm to verify */
+ 		if(oper->firstCase != 0)
+ 		{
+ 			MultiCoverageTest(context, oper);
+ 		}
+ 	}
+ }
+ 
+ /*
+  * Compare two operation cases for a sort operation.
+  */
+ static int CaseCompare(const void *e1, const void *e2)
+ {
+ 	TreeCCOperationCase *operCase1 = *((TreeCCOperationCase **)e1);
+ 	TreeCCOperationCase *operCase2 = *((TreeCCOperationCase **)e2);
+ 	TreeCCTrigger *trigger1 = operCase1->triggers;
+ 	TreeCCTrigger *trigger2 = operCase2->triggers;
+ 	TreeCCNode *ancestor1;
+ 	TreeCCNode *ancestor2;
+ 	while(trigger1 != 0 && trigger2 != 0)
+ 	{
+ 		if(trigger1->node != trigger2->node)
+ 		{
+ 			/* See if trigger1->node inherits from trigger2->node */
+ 			ancestor1 = trigger1->node;
+ 			while(ancestor1->parent != 0)
+ 			{
+ 				if(ancestor1->parent == trigger2->node)
+ 				{
+ 					return -1;
+ 				}
+ 				ancestor1 = ancestor1->parent;
+ 			}
+ 
+ 			/* See if trigger2->node inherits from trigger1->node */
+ 			ancestor2 = trigger2->node;
+ 			while(ancestor2->parent != 0)
+ 			{
+ 				if(ancestor2->parent == trigger1->node)
+ 				{
+ 					return 1;
+ 				}
+ 				ancestor2 = ancestor2->parent;
+ 			}
+ 
+ 			/* If the ancestors are separate, then use the node numbers
+ 			   to order the separate trees.  Note: this is highly unlikely
+ 			   because operation definition forces all cases to inherit
+ 			   from a declared common type.  However, if we change this
+ 			   requirement in the future, this code will be needed, so
+ 			   we are being paranoid and including it now */
+ 			if(ancestor1 != ancestor2)
+ 			{
+ 				if(ancestor1->number < ancestor2->number)
+ 				{
+ 					return -1;
+ 				}
+ 				else
+ 				{
+ 					return 1;
+ 				}
+ 			}
+ 
+ 			/* This is the hard case: the two nodes are in separate
+ 			   subtrees of the same ancestor, but we still need an
+ 			   ordering between them.  We need to find the lowest
+ 			   common ancestor, and the nodes just below it */
+ 			ancestor1 = trigger1->node;
+ 			while(ancestor1->parent != 0)
+ 			{
+ 				ancestor1 = ancestor1->parent;
+ 				ancestor1->flags |= TREECC_NODE_MARK(0);
+ 			}
+ 			ancestor2 = trigger2->node;
+ 			while(ancestor2->parent != 0)
+ 			{
+ 				if((ancestor2->parent->flags & TREECC_NODE_MARK(0)) != 0)
+ 				{
+ 					break;
+ 				}
+ 				ancestor2 = ancestor2->parent;
+ 			}
+ 			ancestor1 = trigger1->node;
+ 			while(ancestor1->parent != 0)
+ 			{
+ 				ancestor1 = ancestor1->parent;
+ 				ancestor1->flags &= ~(TREECC_NODE_MARK(0));
+ 			}
+ 			ancestor1 = trigger1->node;
+ 			while(ancestor1->parent != ancestor2->parent)
+ 			{
+ 				ancestor1 = ancestor1->parent;
+ 			}
+ 
+ 			/* ancestor1 and ancestor2 are now one step down
+ 			   from the common ancestor that we found.  Use
+ 			   their node numbers to order the trees */
+ 			if(ancestor1->number < ancestor2->number)
+ 			{
+ 				return -1;
+ 			}
+ 			else
+ 			{
+ 				return 1;
+ 			}
+ 		}
+ 		trigger1 = trigger1->next;
+ 		trigger2 = trigger2->next;
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * Sort a set of operation cases so that A precedes B
+  * if A inherits directly or indirectly from B.  Operations
+  * with multiple triggers sort on the first, then the second,
+  * then the third, etc.
+  */
+ static void SortCases(TreeCCContext *context, TreeCCOperation *oper)
+ {
+ 	TreeCCOperationCase **caseList;
+ 	TreeCCOperationCase *operCase;
+ 	int num;
+ 
+ 	/* Bail out early if there are 0 or 1 cases, or no triggers */
+ 	if(oper->numCases < 2 || !(oper->numTriggers))
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Clear the marking bits */
+ 	TreeCCNodeClearMarking(context, TREECC_NODE_MARK_BITS);
+ 
+ 	/* Build an array that contains all operation cases */
+ 	if((caseList = (TreeCCOperationCase **)malloc
+ 				(sizeof(TreeCCOperationCase *) * oper->numCases)) == 0)
+ 	{
+ 		TreeCCOutOfMemory(context->input);
+ 	}
+ 	num = 0;
+ 	operCase = oper->firstCase;
+ 	while(operCase != 0)
+ 	{
+ 		caseList[num++] = operCase;
+ 		operCase = operCase->next;
+ 	}
+ 
+ 	/* Sort the case list.  There are probably more efficient
+ 	   ways to do this (e.g. topological sorting), but this
+ 	   version is perhaps easier to understand and maintain */
+ #if HAVE_QSORT
+ 	qsort(caseList, oper->numCases, sizeof(TreeCCOperationCase *), CaseCompare);
+ #else
+ 	{
+ 		int i, j;
+ 		num = oper->numCases;
+ 		for(i = 0; i < (num - 1); ++i)
+ 		{
+ 			for(j = (i + 1); j < num; ++j)
+ 			{
+ 				if(CaseCompare(&(caseList[i]), &(caseList[j])) > 0)
+ 				{
+ 					operCase = caseList[i];
+ 					caseList[i] = caseList[j];
+ 					caseList[j] = operCase;
+ 				}
+ 			}
+ 		}
+ 	}
+ #endif
+ 
+ 	/* Build a new case list from the sorted array */
+ 	oper->firstCase = caseList[0];
+ 	for(num = 1; num < oper->numCases; ++num)
+ 	{
+ 		caseList[num - 1]->next = caseList[num];
+ 	}
+ 	oper->lastCase = caseList[oper->numCases - 1];
+ 	caseList[oper->numCases - 1]->next = 0;
+ 	free(caseList);
+ }
+ 
+ void TreeCCOperationValidate(TreeCCContext *context)
+ {
+ 	unsigned int hash;
+ 	TreeCCOperation *oper;
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		oper = context->operHash[hash];
+ 		while(oper != 0)
+ 		{
+ 			if((oper->flags & TREECC_OPER_VIRTUAL) == 0)
+ 			{
+ 				/* Non-virtuals must be sorted for code generation,
+ 				   and we also rely upon the sorted order to help us
+ 				   test for operation coverage when multiple triggers
+ 				   are used by the operation */
+ 				SortCases(context, oper);
+ 			}
+ 			OperationTest(context, oper);
+ 			oper = oper->nextHash;
+ 		}
+ 	}
+ }
+ 
+ TreeCCOperationCase *TreeCCOperationFindCase
+ 		(TreeCCContext *context, TreeCCNode *node, char *name)
+ {
+ 	TreeCCOperation *oper;
+ 	TreeCCOperationCase *operCase;
+ 	oper = TreeCCOperationFind(context, name);
+ 	if(!oper)
+ 	{
+ 		return 0;
+ 	}
+ 	operCase = oper->firstCase;
+ 	while(operCase != 0)
+ 	{
+ 		if(operCase->triggers && operCase->triggers->node == node)
+ 		{
+ 			return operCase;
+ 		}
+ 		operCase = operCase->next;
+ 	}
+ 	return 0;
+ }
+ 
+ void TreeCCOperationVisitAll(TreeCCContext *context,
+ 							 TreeCCOperationVisitor visitor)
+ {
+ 	unsigned int hash;
+ 	TreeCCOperation *oper;
+ 	for(hash = 0; hash < TREECC_HASH_SIZE; ++hash)
+ 	{
+ 		oper = context->operHash[hash];
+ 		while(oper != 0)
+ 		{
+ 			(*visitor)(context, oper);
+ 			oper = oper->nextHash;
+ 		}
+ 	}
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/options.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/options.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/options.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,467 ----
+ /*
+  * options.c - Process options from "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "options.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * "track_lines": track line numbers when creating new nodes.
+  */
+ static int TrackLinesOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->track_lines = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "no_singletons": suppress special create code for singletons.
+  */
+ static int NoSingletonsOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->no_singletons = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "reentrant": generate re-entrant tree handling code.
+  */
+ static int ReentrantOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->reentrant = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "force": force source files to be created even if unchanged.
+  */
+ static int ForceOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->force = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "virtual_factory": use virtual factory methods.
+  */
+ static int VirtualFactoryOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->virtual_factory = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "abstract_factory": use abstract factory methods.
+  */
+ static int AbstractFactoryOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->abstract_factory = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "kind_in_vtable": put the kind value in the vtable, and not the node.
+  */
+ static int KindInVtableOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->kind_in_vtable = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "prefix": specify the prefix to use instead of "yy".
+  */
+ static int PrefixOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(!value)
+ 	{
+ 		return TREECC_OPT_NEED_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->yy_replacement = value;
+ 		return TREECC_OPT_KEEP_VALUE;
+ 	}
+ }
+ 
+ /*
+  * "state_type": specify the type name to use for re-entrant state.
+  */
+ static int StateTypeOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(!value)
+ 	{
+ 		return TREECC_OPT_NEED_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->state_type = value;
+ 		return TREECC_OPT_KEEP_VALUE;
+ 	}
+ }
+ 
+ /*
+  * "namespace": specify the namespace to use for subsequent definitions.
+  */
+ static int NamespaceOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(!value)
+ 	{
+ 		return TREECC_OPT_NEED_VALUE;
+ 	}
+ 	else if(*value == '\0')
+ 	{
+ 		/* Put following declarations into the global namespace */
+ 		context->namespace = 0;
+ 		return TREECC_OPT_OK;
+ 	}
+ 	else
+ 	{
+ 		context->namespace = value;
+ 		return TREECC_OPT_KEEP_VALUE;
+ 	}
+ }
+ 
+ /*
+  * "base": specify a new base to use for node type identifiers.
+  */
+ static int BaseOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(!value)
+ 	{
+ 		return TREECC_OPT_NEED_VALUE;
+ 	}
+ 	else if(*value == '\0')
+ 	{
+ 		return TREECC_OPT_INVALID_VALUE;
+ 	}
+ 	else
+ 	{
+ 		int num = 0;
+ 		while(*value >= '0' && *value <= '9')
+ 		{
+ 			num = num * 10 + (int)(*value - '0');
+ 			++value;
+ 		}
+ 		if(*value != '\0')
+ 		{
+ 			return TREECC_OPT_INVALID_VALUE;
+ 		}
+ 		context->nodeNumber = num;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "lang": specify the source language to use in the output files.
+  */
+ static int LangOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(!value)
+ 	{
+ 		return TREECC_OPT_NEED_VALUE;
+ 	}
+ 	else
+ 	{
+ 		if(!strcmp(value, "c") || !strcmp(value, "C"))
+ 		{
+ 			context->language = TREECC_LANG_C;
+ 		}
+ 		else if(!strcmp(value, "c++") || !strcmp(value, "C++"))
+ 		{
+ 			context->language = TREECC_LANG_CPP;
+ 		}
+ 		else if(!strcmp(value, "java") || !strcmp(value, "Java"))
+ 		{
+ 			context->language = TREECC_LANG_JAVA;
+ 		}
+ 		else if(!strcmp(value, "c#") || !strcmp(value, "C#") ||
+ 		        !strcmp(value, "csharp"))
+ 		{
+ 			context->language = TREECC_LANG_CSHARP;
+ 		}
+ 		else if(!strcmp(value, "ruby") || !strcmp(value, "Ruby"))
+ 		{
+ 			context->language = TREECC_LANG_RUBY;
+ 		}
+ 		else if(!strcmp(value, "php") || !strcmp(value, "PHP"))
+ 		{
+ 			context->language = TREECC_LANG_PHP;
+ 		}
+ 		else
+ 		{
+ 			return TREECC_OPT_INVALID_VALUE;
+ 		}
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "block_size": specify a new block size for C and C++ allocators.
+  */
+ static int BlockSizeOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(!value)
+ 	{
+ 		return TREECC_OPT_NEED_VALUE;
+ 	}
+ 	else if(*value == '\0')
+ 	{
+ 		return TREECC_OPT_INVALID_VALUE;
+ 	}
+ 	else
+ 	{
+ 		int num = 0;
+ 		while(*value >= '0' && *value <= '9')
+ 		{
+ 			num = num * 10 + (int)(*value - '0');
+ 			++value;
+ 		}
+ 		if(*value != '\0')
+ 		{
+ 			return TREECC_OPT_INVALID_VALUE;
+ 		}
+ 		context->block_size = num;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ 
+ 
+ /*
+  * "print_lines": print out line number directives.
+  */
+ static int PrintLineNumberOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->print_lines = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "strip_filenames": strip filenames in #line directives down
+  * to their base name, with no directory information.
+  */
+ static int StripFilenamesOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->strip_filenames = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "internal_access": use "internal" access on classes in C#, instead
+  * of using "public".  "public_access" is used to select "public".
+  */
+ static int InternalAccessOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->internal_access = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "allocator": use (or don't use) the standard treecc allocator for C/C++.
+  */
+ static int AllocatorOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->use_allocator = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "gc_allocator": use (or don't use) the libgc treecc allocator for C/C++.
+  */
+ static int GCAllocatorOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(value)
+ 	{
+ 		return TREECC_OPT_NO_VALUE;
+ 	}
+ 	else
+ 	{
+ 		context->use_gc_allocator = flag;
+ 		return TREECC_OPT_OK;
+ 	}
+ }
+ 
+ /*
+  * "base_type": use the type as the base type for the root treecc node 
+  */
+ static int BaseTypeOption(TreeCCContext *context, char *value, int flag)
+ {
+ 	if(!value)
+ 	{
+ 		return TREECC_OPT_NEED_VALUE;
+ 	}
+ 	else if(value == '\0')
+ 	{
+ 		context->baseType = 0;
+ 		return TREECC_OPT_OK;
+ 	}
+ 	else
+ 	{
+ 		context->baseType = value;
+ 		return TREECC_OPT_KEEP_VALUE;
+ 	}
+ }
+ 
+ /*
+  * Table of option handlers.
+  */
+ static struct
+ {
+ 	const char *name;
+ 	int (*func)(TreeCCContext *context, char *value, int flag);
+ 	int flag;
+ 
+ } const OptionHandlers[] = {
+ 	{"track_lines",			TrackLinesOption,		1},
+ 	{"no_track_lines",		TrackLinesOption,		0},
+ 	{"no_singletons",		NoSingletonsOption,		1},
+ 	{"singletons",			NoSingletonsOption,		0},
+ 	{"reentrant",			ReentrantOption,		1},
+ 	{"no_reentrant",		ReentrantOption,		0},
+ 	{"force",				ForceOption,			1},
+ 	{"no_force",			ForceOption,			0},
+ 	{"virtual_factory",		VirtualFactoryOption,	1},
+ 	{"no_virtual_factory",	VirtualFactoryOption,	0},
+ 	{"abstract_factory",	AbstractFactoryOption,	1},
+ 	{"no_abstract_factory",	AbstractFactoryOption,	0},
+ 	{"kind_in_vtable",		KindInVtableOption,		1},
+ 	{"kind_in_node",		KindInVtableOption,		0},
+ 	{"prefix",				PrefixOption,			0},
+ 	{"state_type",			StateTypeOption,		0},
+ 	{"namespace",			NamespaceOption,		0},
+ 	{"package",				NamespaceOption,		0},
+ 	{"base",				BaseOption,				0},
+ 	{"lang",				LangOption,				0},
+ 	{"block_size",			BlockSizeOption,		0},
+ 	{"strip_filenames",		StripFilenamesOption,	1},
+ 	{"print_lines",			PrintLineNumberOption,	1},
+ 	{"no_print_lines",		PrintLineNumberOption,	0},
+ 	{"no_strip_filenames",	StripFilenamesOption,	0},
+ 	{"internal_access",		InternalAccessOption,	1},
+ 	{"public_access",		InternalAccessOption,	0},
+ 	{"allocator",			AllocatorOption,		1},
+ 	{"no_allocator",		AllocatorOption,		0},
+ 	{"gc_allocator",		GCAllocatorOption,		1},
+ 	{"no_gc_allocator",		GCAllocatorOption,		0},
+ 	{"base_type",			BaseTypeOption,			0},
+ 	{0,						0,						0},
+ };
+ 
+ int TreeCCOptionProcess(TreeCCContext *context, char *name, char *value)
+ {
+ 	int opt = 0;
+ 	while(OptionHandlers[opt].name != 0)
+ 	{
+ 		if(!strcmp(name, OptionHandlers[opt].name))
+ 		{
+ 			return (*(OptionHandlers[opt].func))
+ 						(context, value, OptionHandlers[opt].flag);
+ 		}
+ 		++opt;
+ 	}
+ 	return TREECC_OPT_UNKNOWN;
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/options.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/options.h:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/options.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,47 ----
+ /*
+  * options.h - Process options from "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_OPTIONS_H
+ #define	_TREECC_OPTIONS_H
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Return values from "TreeCCOptionProcess".
+  */
+ #define	TREECC_OPT_OK				0
+ #define	TREECC_OPT_KEEP_VALUE		1
+ #define	TREECC_OPT_UNKNOWN			2
+ #define	TREECC_OPT_INVALID_VALUE	3
+ #define	TREECC_OPT_NEED_VALUE		4
+ #define	TREECC_OPT_NO_VALUE			5
+ 
+ /*
+  * Process an option declaration.
+  */
+ int TreeCCOptionProcess(TreeCCContext *context, char *name, char *value);
+ 
+ #ifdef	__cplusplus
+ };
+ #endif
+ 
+ #endif	/* _TREECC_OPTIONS_H */


Index: llvm/test/Programs/MultiSource/Applications/treecc/parse.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/parse.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/parse.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,1461 ----
+ /*
+  * parse.c - Parse "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "parse.h"
+ #include "errors.h"
+ #include "options.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Append two strings and return a malloc'ed result.
+  */
+ static char *AppendStrings(TreeCCInput *input, char *str1,
+ 						   char *str2, int sep, int free2)
+ {
+ 	int len1 = strlen(str1);
+ 	int len2 = strlen(str2);
+ 	int len = len1 + len2 + sep + 1;
+ 	char *value = (char *)realloc(str1, len);
+ 	if(!value)
+ 	{
+ 		TreeCCOutOfMemory(input);
+ 	}
+ 	if(sep)
+ 	{
+ 		value[len1] = ' ';
+ 		strcpy(value + len1 + 1, str2);
+ 		value[len1 + len2 + 1] = '\0';
+ 	}
+ 	else
+ 	{
+ 		strcpy(value + len1, str2);
+ 		value[len1 + len2] = '\0';
+ 	}
+ 	if(free2)
+ 	{
+ 		free(str2);
+ 	}
+ 	return value;
+ }
+ 
+ /*
+  * Parse a type specification and variable name using a
+  * simplified subset of C type syntax.
+  *
+  * TypeAndName ::= Type [IDENTIFIER]
+  *
+  * Type ::= TypeName
+  *        | Type '*'
+  *        | Type '&'
+  *        | Type '[' ']'
+  * TypeName ::= IDENTIFIER { IDENTIFIER }
+  *
+  * Examples are "expression", "const char *", and "Item[]".
+  * Types that don't fit this pattern should use typedef'ed
+  * names from the underlying source language.
+  */
+ static void ParseTypeAndName(TreeCCInput *input, char **type, char **name)
+ {
+ 	char *tempType;
+ 	char *last;
+ 
+ 	/* Type names must begin with an identifier */
+ 	if(input->token != TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		TreeCCError(input, "type name expected");
+ 		*type = 0;
+ 		*name = 0;
+ 		return;
+ 	}
+ 
+ 	/* Collect up the identifiers within the type name.
+ 	   We don't add the last to "tempType" until we've
+ 	   seen what comes after it.  This resolves the
+ 	   ambiguity in the grammar */
+ 	tempType = 0;
+ 	last = 0;
+ 	while(input->token == TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		if(!tempType)
+ 		{
+ 			/* This is the first identifier, which is
+ 			   always part of the type */
+ 			tempType = TreeCCValue(input);
+ 		}
+ 		else if(!last)
+ 		{
+ 			/* No last identifier yet, so just save this one */
+ 			last = TreeCCValue(input);
+ 		}
+ 		else
+ 		{
+ 			/* Append "last" to "tempType" */
+ 			tempType = AppendStrings(input, tempType, last, 1, 1);
+ 
+ 			/* Save the new identifier as "last" */
+ 			last = TreeCCValue(input);
+ 		}
+ 		TreeCCNextToken(input);
+ 	}
+ 
+ 	/* If the next token is '*', '&', or '[', then "last" is
+ 	   part of the type name, and not the variable name */
+ 	if(last && (input->token == TREECC_TOKEN_STAR ||
+ 				input->token == TREECC_TOKEN_REF ||
+ 	            input->token == TREECC_TOKEN_LSQUARE))
+ 	{
+ 		tempType = AppendStrings(input, tempType, last, 1, 1);
+ 		last = 0;
+ 	}
+ 
+ 	/* Parse the type suffixes */
+ 	while(input->token == TREECC_TOKEN_STAR ||
+ 		  input->token == TREECC_TOKEN_REF ||
+ 		  input->token == TREECC_TOKEN_LSQUARE)
+ 	{
+ 		if(input->token == TREECC_TOKEN_STAR)
+ 		{
+ 			tempType = AppendStrings(input, tempType, "*", 1, 0);
+ 		}
+ 		else if(input->token == TREECC_TOKEN_REF)
+ 		{
+ 			tempType = AppendStrings(input, tempType, "&", 1, 0);
+ 		}
+ 		else
+ 		{
+ 			tempType = AppendStrings(input, tempType, "[]", 0, 0);
+ 			TreeCCNextToken(input);
+ 			if(input->token != TREECC_TOKEN_RSQUARE)
+ 			{
+ 				TreeCCError(input, "`]' expected");
+ 				continue;
+ 			}
+ 		}
+ 		TreeCCNextToken(input);
+ 	}
+ 
+ 	/* Parse the variable name, if necessary */
+ 	if(!last && input->token == TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		last = TreeCCValue(input);
+ 		TreeCCNextToken(input);
+ 	}
+ 
+ 	/* Return the values to the caller */
+ 	*type = tempType;
+ 	*name = last;
+ }
+ 
+ /*
+  * Parse a node definition.
+  *
+  * Node ::= %node IDENTIFIER [ IDENTIFIER ] { NodeFlag } [ "=" Fields ]
+  * NodeFlag ::= %abstract | %typedef
+  * Fields ::= "{" { Field } "}"
+  * Field ::= [ %nocreate ] TypeAndName [ "=" LITERAL_CODE ] ";"
+  */
+ static void ParseNode(TreeCCContext *context)
+ {
+ 	TreeCCInput *input = context->input;
+ 	char *name;
+ 	char *parent;
+ 	int flags;
+ 	long linenum;
+ 	TreeCCNode *node;
+ 	char *fieldName;
+ 	char *fieldType;
+ 	char *fieldValue;
+ 
+ 	/* Skip the "%node" keyword */
+ 	TreeCCNextToken(input);
+ 	linenum = input->linenum;
+ 
+ 	/* We need an identifier for the node that is being declared */
+ 	if(input->token != TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		/* Report an error for the identifier */
+ 		TreeCCError(input, "identifier expected");
+ 		return;
+ 	}
+ 	name = TreeCCValue(input);
+ 	TreeCCNextToken(input);
+ 
+ 	/* Get the name of the parent */
+ 	if(input->token == TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		parent = TreeCCValue(input);
+ 		TreeCCNextToken(input);
+ 	}
+ 	else
+ 	{
+ 		parent = 0;
+ 	}
+ 
+ 	/* Parse the node definition flags */
+ 	flags = 0;
+ 	for(;;)
+ 	{
+ 		if(input->token == TREECC_TOKEN_ABSTRACT)
+ 		{
+ 			flags |= TREECC_NODE_ABSTRACT;
+ 			TreeCCNextToken(input);
+ 		}
+ 		else if(input->token == TREECC_TOKEN_TYPEDEF)
+ 		{
+ 			flags |= TREECC_NODE_TYPEDEF;
+ 			TreeCCNextToken(input);
+ 		}
+ 		else
+ 		{
+ 			break;
+ 		}
+ 	}
+ 
+ 	/* Create the node */
+ 	node = TreeCCNodeCreate(context, linenum, name, parent, flags);
+ 
+ 	/* If we have a field definition block, then read it */
+ 	if(input->token == TREECC_TOKEN_EQUALS)
+ 	{
+ 		input->parseLiteral = 0;
+ 		TreeCCNextToken(input);
+ 		input->parseLiteral = 1;
+ 		if(input->token == TREECC_TOKEN_LBRACE)
+ 		{
+ 			/* Skip the "{" token */
+ 			TreeCCNextToken(input);
+ 
+ 			/* Process the field definitions */
+ 			while(input->token != TREECC_TOKEN_RBRACE &&
+ 				  input->token != TREECC_TOKEN_EOF)
+ 			{
+ 				/* Skip spurious semi-colons in the field definition */
+ 				if(input->token == TREECC_TOKEN_SEMI)
+ 				{
+ 					TreeCCNextToken(input);
+ 					continue;
+ 				}
+ 
+ 				/* Process field definition flags */
+ 				if(input->token == TREECC_TOKEN_NOCREATE)
+ 				{
+ 					flags = TREECC_FIELD_NOCREATE;
+ 					TreeCCNextToken(input);
+ 				}
+ 				else
+ 				{
+ 					flags = 0;
+ 				}
+ 
+ 				/* Parse the field type and name */
+ 				ParseTypeAndName(input, &fieldType, &fieldName);
+ 				if(fieldType && fieldName)
+ 				{
+ 					if(input->token == TREECC_TOKEN_EQUALS)
+ 					{
+ 						TreeCCNextToken(input);
+ 						if(input->token == TREECC_TOKEN_LITERAL_CODE)
+ 						{
+ 							fieldValue = TreeCCValue(input);
+ 							TreeCCNextToken(input);
+ 						}
+ 						else
+ 						{
+ 							TreeCCError
+ 								(input, "literal code constant expected");
+ 							fieldValue = 0;
+ 						}
+ 					}
+ 					else
+ 					{
+ 						fieldValue = 0;
+ 					}
+ 					if(fieldValue && (flags & TREECC_FIELD_NOCREATE) == 0)
+ 					{
+ 						TreeCCError(input,
+ 							"default values can only be specified for "
+ 							"`%%nocreate' fields");
+ 					}
+ 					TreeCCFieldCreate(context, node, fieldName, fieldType,
+ 									  fieldValue, flags);
+ 				}
+ 				else
+ 				{
+ 					if(fieldType)
+ 					{
+ 						TreeCCError(input, "field name expected");
+ 					}
+ 					else
+ 					{
+ 						TreeCCError(input, "field declaration expected");
+ 					}
+ 					if(fieldType)
+ 					{
+ 						free(fieldType);
+ 					}
+ 					if(fieldName)
+ 					{
+ 						free(fieldName);
+ 					}
+ 
+ 					/* Attempt to recover from the error */
+ 					while(input->token != TREECC_TOKEN_SEMI &&
+ 						  input->token != TREECC_TOKEN_RBRACE &&
+ 						  input->token != TREECC_TOKEN_IDENTIFIER &&
+ 						  input->token != TREECC_TOKEN_EOF)
+ 					{
+ 						TreeCCNextToken(input);
+ 					}
+ 				}
+ 
+ 				/* Recognize the ";" at the end of the field */
+ 				if(input->token == TREECC_TOKEN_SEMI)
+ 				{
+ 					TreeCCNextToken(input);
+ 				}
+ 				else
+ 				{
+ 					/* Attempt to recover from the lack of a semi-colon */
+ 					TreeCCError(input, "`;' expected");
+ 					if(input->token != TREECC_TOKEN_IDENTIFIER &&
+ 					   input->token != TREECC_TOKEN_RBRACE)
+ 					{
+ 						TreeCCNextToken(input);
+ 					}
+ 				}
+ 			}
+ 
+ 			/* Skip the "}" token */
+ 			TreeCCNextToken(input);
+ 		}
+ 		else
+ 		{
+ 			TreeCCError(input, "field definition block expected");
+ 		}
+ 	}
+ }
+ 
+ /*
+  * Validate trigger type suffixes against the language.
+  */
+ static void ValidateSuffixes(TreeCCContext *context, const char *type,
+ 						     TreeCCNode *node, char *filename, long linenum)
+ {
+ 	int len = strlen(type);
+ 	if(context->language == TREECC_LANG_C ||
+ 	   context->language == TREECC_LANG_CPP)
+ 	{
+ 		if((node->flags & TREECC_NODE_ENUM) == 0 &&
+ 		   (node->flags & TREECC_NODE_ENUM_VALUE) == 0)
+ 		{
+ 			if(len < 2 || type[len - 1] != '*' ||
+ 			   type[len - 2] != ' ')
+ 			{
+ 				TreeCCErrorOnLine(context->input, filename, linenum,
+ 								  "trigger types must end in `*'");
+ 			}
+ 		}
+ 	}
+ }
+ 
+ /*
+  * Parse an operation definition.
+  *
+  * Operation ::= %operation { OperFlag } Type [ClassName ] IDENTIFIER
+  *                  '(' [ Params ] ')' [ '=' LITERAL_CODE ] [ ';' ]
+  * OperFlag ::= %virtual | %inline
+  * ClassName ::= IDENTIFIER "::"
+  * Params ::= Param { ',' Param }
+  * Param ::= TypeAndName | '[' TypeAndName ']'
+  */
+ static void ParseOperation(TreeCCContext *context)
+ {
+ 	TreeCCInput *input = context->input;
+ 	int flags;
+ 	char *returnType;
+ 	char *name;
+ 	char *className;
+ 	char *defValue;
+ 	TreeCCParam *params = 0;
+ 	TreeCCParam *lastParam = 0;
+ 	TreeCCParam *newParam;
+ 	int numTriggers = 0;
+ 	char *paramType;
+ 	char *paramName;
+ 	int paramFlags;
+ 	TreeCCOperation *oper;
+ 	char *filename;
+ 	long linenum;
+ 	TreeCCNode *typeNode;
+ 
+ 	/* Skip the "%operation" keyword */
+ 	TreeCCNextToken(input);
+ 
+ 	/* Parse the operation flags */
+ 	flags = 0;
+ 	for(;;)
+ 	{
+ 		if(input->token == TREECC_TOKEN_VIRTUAL)
+ 		{
+ 			flags |= TREECC_OPER_VIRTUAL;
+ 			TreeCCNextToken(input);
+ 		}
+ 		else if(input->token == TREECC_TOKEN_INLINE)
+ 		{
+ 			flags |= TREECC_OPER_INLINE;
+ 			TreeCCNextToken(input);
+ 		}
+ 		else if(input->token == TREECC_TOKEN_SPLIT)
+ 		{
+ 			flags |= TREECC_OPER_SPLIT;
+ 			TreeCCNextToken(input);
+ 		}
+ 		else
+ 		{
+ 			break;
+ 		}
+ 	}
+ 	if((flags & TREECC_OPER_VIRTUAL) != 0 &&
+ 	   (flags & TREECC_OPER_INLINE) != 0)
+ 	{
+ 		TreeCCError(input, "`virtual' and `inline' cannot be used together");
+ 		flags &= ~TREECC_OPER_INLINE;
+ 	}
+ 
+ 	/* Parse the return type and name of the operation */
+ 	ParseTypeAndName(input, &returnType, &name);
+ 	filename = input->filename;
+ 	linenum = input->linenum;
+ 	if(!returnType || !name)
+ 	{
+ 		if(returnType)
+ 		{
+ 			TreeCCError(input, "operation name expected");
+ 		}
+ 		else
+ 		{
+ 			TreeCCError(input, "operation return type expected");
+ 		}
+ 		if(returnType)
+ 		{
+ 			free(returnType);
+ 		}
+ 		if(name)
+ 		{
+ 			free(name);
+ 		}
+ 		return;
+ 	}
+ 
+ 	/* If the next token is "::", then "name" is actually the
+ 	   class name and we need to get the real operation name */
+ 	if(input->token == TREECC_TOKEN_COLON_COLON)
+ 	{
+ 		className = name;
+ 		TreeCCNextToken(input);
+ 		if(input->token != TREECC_TOKEN_IDENTIFIER)
+ 		{
+ 			TreeCCError(input, "operation name expected");
+ 			free(returnType);
+ 			free(className);
+ 			return;
+ 		}
+ 		name = TreeCCValue(input);
+ 		TreeCCNextToken(input);
+ 	}
+ 	else
+ 	{
+ 		className = 0;
+ 	}
+ 
+ 	/* If the operation is non-virtual, and the language is C#,
+ 	   then we must have a class name which is different from
+ 	   the operation name.  This is necessary because of a
+ 	   "feature" in the design of C# and Microsoft's compilers */
+ 	if((flags & TREECC_OPER_VIRTUAL) == 0 &&
+ 	   context->language == TREECC_LANG_CSHARP)
+ 	{
+ 		if(!className)
+ 		{
+ 			TreeCCErrorOnLine(input, filename, linenum,
+ 							  "C# requires that a class name be specified");
+ 		}
+ 		else if(!strcmp(className, name))
+ 		{
+ 			TreeCCErrorOnLine(input, filename, linenum,
+ 				  "C# requires different class and operation names");
+ 		}
+ 	}
+ 
+ 	/* Parse the parameter list for the operation */
+ 	if(input->token == TREECC_TOKEN_LPAREN)
+ 	{
+ 		TreeCCNextToken(input);
+ 		while(input->token == TREECC_TOKEN_IDENTIFIER ||
+ 		      input->token == TREECC_TOKEN_LSQUARE)
+ 		{
+ 			/* Parse the parameter information */
+ 			if(input->token == TREECC_TOKEN_IDENTIFIER)
+ 			{
+ 				paramFlags = 0;
+ 				ParseTypeAndName(input, &paramType, &paramName);
+ 			}
+ 			else
+ 			{
+ 				paramFlags = TREECC_PARAM_TRIGGER;
+ 				TreeCCNextToken(input);
+ 				ParseTypeAndName(input, &paramType, &paramName);
+ 				if(input->token == TREECC_TOKEN_RSQUARE)
+ 				{
+ 					TreeCCNextToken(input);
+ 				}
+ 				else
+ 				{
+ 					TreeCCError(input, "`]' expected");
+ 				}
+ 				++numTriggers;
+ 			}
+ 
+ 			/* Create the parameter block */
+ 			if(!paramType)
+ 			{
+ 				TreeCCError(input, "parameter declaration expected");
+ 			}
+ 			else if(!strcmp(paramType, "void"))
+ 			{
+ 				/* Ignore "void" parameters */
+ 				free(paramType);
+ 				if(paramName)
+ 				{
+ 					free(paramName);
+ 				}
+ 			}
+ 			else
+ 			{
+ 				newParam = (TreeCCParam *)malloc(sizeof(TreeCCParam));
+ 				if(!newParam)
+ 				{
+ 					TreeCCOutOfMemory(input);
+ 				}
+ 				newParam->name = paramName;
+ 				newParam->type = paramType;
+ 				newParam->flags = paramFlags;
+ 				newParam->size = 0;
+ 				newParam->next = 0;
+ 				if(lastParam)
+ 				{
+ 					lastParam->next = newParam;
+ 				}
+ 				else
+ 				{
+ 					params = newParam;
+ 				}
+ 				lastParam = newParam;
+ 				if((paramFlags & TREECC_PARAM_TRIGGER) != 0)
+ 				{
+ 					if((typeNode = TreeCCNodeFindByType(context, paramType))
+ 								== 0)
+ 					{
+ 						TreeCCError(input, "`%s' is not a valid trigger type",
+ 									paramType);
+ 					}
+ 					else
+ 					{
+ 						ValidateSuffixes(context, paramType, typeNode,
+ 										 input->filename, input->linenum);
+ 					}
+ 				}
+ 			}
+ 
+ 			/* Skip the comma and go on to the next parameter */
+ 			if(input->token == TREECC_TOKEN_COMMA)
+ 			{
+ 				TreeCCNextToken(input);
+ 				if(input->token != TREECC_TOKEN_IDENTIFIER &&
+ 				   input->token != TREECC_TOKEN_LSQUARE)
+ 				{
+ 					TreeCCError(input, "parameter declaration expected");
+ 				}
+ 			}
+ 			else
+ 			{
+ 				break;
+ 			}
+ 		}
+ 		if(input->token == TREECC_TOKEN_RPAREN)
+ 		{
+ 			TreeCCNextToken(input);
+ 		}
+ 		else
+ 		{
+ 			TreeCCError(input, "`)' expected");
+ 		}
+ 	}
+ 	else
+ 	{
+ 		TreeCCError(input, "`(' expected");
+ 	}
+ 
+ 	/* Recognise the default value, if present */
+ 	if(input->token == TREECC_TOKEN_EQUALS)
+ 	{
+ 		TreeCCNextToken(input);
+ 		if(input->token == TREECC_TOKEN_LITERAL_CODE)
+ 		{
+ 			defValue = TreeCCValue(input);
+ 			TreeCCNextToken(input);
+ 		}
+ 		else
+ 		{
+ 			TreeCCError(input, "default value expected");
+ 			defValue = 0;
+ 		}
+ 	}
+ 	else
+ 	{
+ 		defValue = 0;
+ 		if((flags & TREECC_OPER_VIRTUAL) == 0 &&
+ 		   strcmp(returnType, "void") != 0)
+ 		{
+ 			TreeCCError(input, "default value required");
+ 		}
+ 	}
+ 
+ 	/* Recognise an optional semi-colon */
+ 	if(input->token == TREECC_TOKEN_SEMI)
+ 	{
+ 		TreeCCNextToken(input);
+ 	}
+ 
+ 	/* Set a default trigger parameter if necessary */
+ 	if(numTriggers == 0 && params != 0)
+ 	{
+ 		numTriggers = 1;
+ 		params->flags |= TREECC_PARAM_TRIGGER;
+ 		if((typeNode = TreeCCNodeFindByType(context, params->type)) == 0)
+ 		{
+ 			TreeCCErrorOnLine(input, filename, linenum,
+ 							  "`%s' is not a valid trigger type",
+ 							  params->type);
+ 		}
+ 		else
+ 		{
+ 			ValidateSuffixes(context, params->type, typeNode,
+ 							 filename, linenum);
+ 		}
+ 	}
+ 
+ 	/* If the operation is virtual, then check that the first
+ 	   parameter is the sole trigger for the operation */
+ 	if((flags & TREECC_OPER_VIRTUAL) != 0)
+ 	{
+ 		if(!params || numTriggers != 1 ||
+ 		   (params->flags & TREECC_PARAM_TRIGGER) == 0)
+ 		{
+ 			if(!params)
+ 			{
+ 				TreeCCError(input,
+ 					"virtual operations must have at least one parameter");
+ 			}
+ 			else
+ 			{
+ 				TreeCCError(input,
+ 					"the first parameter of a virtual must be the trigger");
+ 			}
+ 			flags &= ~TREECC_OPER_VIRTUAL;
+ 		}
+ 		else if((typeNode = TreeCCNodeFindByType(context, params->type)) == 0)
+ 		{
+ 			flags &= ~TREECC_OPER_VIRTUAL;
+ 		}
+ 		else if((typeNode->flags & TREECC_NODE_ENUM) != 0)
+ 		{
+ 			TreeCCError(input,
+ 			  "cannot use enumerated types as triggers for virtual operations");
+ 			flags &= ~TREECC_OPER_VIRTUAL;
+ 		}
+ 	}
+ 
+ 	/* See if we already have an operation with this name */
+ 	oper = TreeCCOperationFind(context, name);
+ 	if(oper != 0)
+ 	{
+ 		TreeCCErrorOnLine(input, filename, linenum,
+ 						  "operation `%s' is already declared", name);
+ 		TreeCCErrorOnLine(input, oper->filename, oper->linenum,
+ 						  "previous declaration here");
+ 		free(returnType);
+ 		free(name);
+ 		if(className)
+ 		{
+ 			free(className);
+ 		}
+ 		if(defValue)
+ 		{
+ 			free(defValue);
+ 		}
+ 		while(params != 0)
+ 		{
+ 			newParam = params->next;
+ 			if(params->name)
+ 			{
+ 				free(params->name);
+ 			}
+ 			if(params->type)
+ 			{
+ 				free(params->type);
+ 			}
+ 			free(params);
+ 			params = newParam;
+ 		}
+ 		return;
+ 	}
+ 
+ 	/* Create the operation */
+ 	oper = TreeCCOperationCreate(context, returnType, name, className,
+ 								 defValue, params, flags, numTriggers,
+ 								 filename, linenum);
+ 
+ 	/* If the operation is virtual, then attach it to the node type */
+ 	if((flags & TREECC_OPER_VIRTUAL) != 0)
+ 	{
+ 		TreeCCNodeAddVirtual
+ 			(context, TreeCCNodeFindByType(context, params->type), oper);
+ 	}
+ }
+ 
+ /*
+  * Parse an operation case header.
+  *
+  * OperationHead ::= IDENTIFIER '(' [ TypeList ] ')'
+  * TypeList ::= IDENTIFIER { ',' IDENTIFIER }
+  */
+ static TreeCCOperationCase *ParseOperationHeader(TreeCCContext *context)
+ {
+ 	TreeCCInput *input = context->input;
+ 	TreeCCTrigger *triggers = 0;
+ 	TreeCCTrigger *lastTrigger = 0;
+ 	TreeCCTrigger *newTrigger;
+ 	TreeCCOperation *oper;
+ 	TreeCCNode *node;
+ 	int fatalError = 0;
+ 	int numTriggers = 0;
+ 	char *filename;
+ 	long linenum;
+ 
+ 	/* Look up the operation name */
+ 	filename = input->filename;
+ 	linenum = input->linenum;
+ 	oper = TreeCCOperationFind(context, input->text);
+ 	if(!oper)
+ 	{
+ 		TreeCCError(input, "operation `%s' is not declared", input->text);
+ 		fatalError = 1;
+ 	}
+ 	TreeCCNextToken(input);
+ 
+ 	/* Parse the type trigger list */
+ 	if(input->token == TREECC_TOKEN_LPAREN)
+ 	{
+ 		TreeCCNextToken(input);
+ 		while(input->token == TREECC_TOKEN_IDENTIFIER)
+ 		{
+ 			++numTriggers;
+ 			node = TreeCCNodeFind(context, input->text);
+ 			if(!node)
+ 			{
+ 				TreeCCError(input, "node type `%s' is not declared",
+ 							input->text);
+ 				fatalError = 1;
+ 			}
+ 			newTrigger = (TreeCCTrigger *)malloc(sizeof(TreeCCTrigger));
+ 			if(!newTrigger)
+ 			{
+ 				TreeCCOutOfMemory(input);
+ 			}
+ 			newTrigger->node = node;
+ 			newTrigger->next = 0;
+ 			if(lastTrigger)
+ 			{
+ 				lastTrigger->next = newTrigger;
+ 			}
+ 			else
+ 			{
+ 				triggers = newTrigger;
+ 			}
+ 			lastTrigger = newTrigger;
+ 			TreeCCNextToken(input);
+ 			if(input->token == TREECC_TOKEN_COMMA)
+ 			{
+ 				TreeCCNextToken(input);
+ 				if(input->token != TREECC_TOKEN_IDENTIFIER)
+ 				{
+ 					TreeCCError(input, "type name expected");
+ 				}
+ 			}
+ 			else
+ 			{
+ 				if(input->token != TREECC_TOKEN_RPAREN)
+ 				{
+ 					TreeCCError(input, "`,' expected");
+ 				}
+ 				break;
+ 			}
+ 		}
+ 		if(input->token == TREECC_TOKEN_RPAREN)
+ 		{
+ 			TreeCCNextToken(input);
+ 		}
+ 		else
+ 		{
+ 			TreeCCError(input, "`)' expected");
+ 		}
+ 	}
+ 	else
+ 	{
+ 		TreeCCError(input, "`(' expected");
+ 	}
+ 
+ 	/* Check that we have a trigger match for the operation */
+ 	if(oper)
+ 	{
+ 		if(oper->numTriggers != numTriggers)
+ 		{
+ 			TreeCCErrorOnLine(input, filename, linenum,
+ 							  "incorrect number of triggers for operation");
+ 			TreeCCErrorOnLine(input, oper->filename, oper->linenum,
+ 							  "operation declared here");
+ 			fatalError = 1;
+ 		}
+ 		else
+ 		{
+ 			TreeCCParam *param = oper->params;
+ 			int reportedError = 0;
+ 			newTrigger = triggers;
+ 			while(param != 0)
+ 			{
+ 				if((param->flags & TREECC_PARAM_TRIGGER) != 0)
+ 				{
+ 					node = TreeCCNodeFindByType(context, param->type);
+ 					if(node && !TreeCCNodeInheritsFrom(newTrigger->node, node))
+ 					{
+ 						if(newTrigger->node)
+ 						{
+ 							TreeCCErrorOnLine(input, filename, linenum,
+ 								"node type `%s' does not inherit from `%s'",
+ 								newTrigger->node->name, node->name);
+ 							reportedError = 1;
+ 							fatalError = 1;
+ 						}
+ 					}
+ 					newTrigger = newTrigger->next;
+ 				}
+ 				param = param->next;
+ 			}
+ 			if(reportedError)
+ 			{
+ 				TreeCCErrorOnLine(input, oper->filename, oper->linenum,
+ 								  "operation declared here");
+ 			}
+ 		}
+ 	}
+ 
+ 	/* Bail out if we've seen a fatal error */
+ 	if(fatalError)
+ 	{
+ 		while(triggers != 0)
+ 		{
+ 			newTrigger = triggers->next;
+ 			free(triggers);
+ 			triggers = newTrigger;
+ 		}
+ 		return 0;
+ 	}
+ 
+ 	/* Add the operation case to the operation */
+ 	return TreeCCOperationAddCase(context, oper, triggers, filename, linenum);
+ }
+ 
+ /*
+  * Parse an operation case definition.
+  *
+  * OperationCase ::= OperationHead { ',' OperationHead } LiteralCode
+  */
+ static void ParseOperationCase(TreeCCContext *context)
+ {
+ 	TreeCCInput *input = context->input;
+ 	TreeCCOperationCase *operCase;
+ 	TreeCCOperationCase *caseList;
+ 	char *code;
+ 	char *codeFilename;
+ 	long codeLinenum;
+ 
+ 	/* Parse the operation case headers */
+ 	caseList = 0;
+ 	while(input->token == TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		operCase = ParseOperationHeader(context);
+ 		if(operCase)
+ 		{
+ 			operCase->nextHeader = caseList;
+ 			caseList = operCase;
+ 		}
+ 		if(input->token == TREECC_TOKEN_IDENTIFIER)
+ 		{
+ 			TreeCCError(input, "`,' expected");
+ 			continue;
+ 		}
+ 		if(input->token != TREECC_TOKEN_COMMA)
+ 		{
+ 			break;
+ 		}
+ 		TreeCCNextToken(input);
+ 		if(input->token != TREECC_TOKEN_IDENTIFIER)
+ 		{
+ 			TreeCCError(input, "identifier expected");
+ 		}
+ 	}
+ 
+ 	/* Recognise the code for the operation case */
+ 	codeFilename = input->filename;
+ 	codeLinenum = input->linenum;
+ 	if(input->token == TREECC_TOKEN_LITERAL_CODE)
+ 	{
+ 		code = TreeCCValue(input);
+ 		TreeCCNextToken(input);
+ 	}
+ 	else
+ 	{
+ 		code = 0;
+ 		TreeCCError(input, "code block expected");
+ 	}
+ 
+ 	/* Add the code to all of the operation cases */
+ 	if(code)
+ 	{
+ 		operCase = caseList;
+ 		while(operCase != 0)
+ 		{
+ 			operCase->code = code;
+ 			operCase->codeFilename = codeFilename;
+ 			operCase->codeLinenum = codeLinenum;
+ 			operCase = operCase->nextHeader;
+ 		}
+ 	}
+ }
+ 
+ /*
+  * Parse an option declaration.
+  *
+  * Option ::= %option IDENTIFIER [ '=' Value ]
+  * Value ::= IDENTIFIER | STRING
+  */
+ static void ParseOption(TreeCCContext *context)
+ {
+ 	TreeCCInput *input = context->input;
+ 	char *name;
+ 	char *value;
+ 	char *filename;
+ 	long linenum;
+ 	int optValue;
+ 
+ 	/* Skip the "%option" keyword */
+ 	TreeCCNextToken(input);
+ 
+ 	/* Recognise the option name */
+ 	if(input->token != TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		TreeCCError(input, "option name expected");
+ 		return;
+ 	}
+ 	name = TreeCCValue(input);
+ 	filename = input->filename;
+ 	linenum = input->linenum;
+ 	TreeCCNextToken(input);
+ 
+ 	/* Recognise the option value, if present */
+ 	if(input->token == TREECC_TOKEN_EQUALS)
+ 	{
+ 		TreeCCNextToken(input);
+ 		if(input->token == TREECC_TOKEN_IDENTIFIER ||
+ 		   input->token == TREECC_TOKEN_STRING)
+ 		{
+ 			value = TreeCCValue(input);
+ 			TreeCCNextToken(input);
+ 		}
+ 		else
+ 		{
+ 			TreeCCError(input, "identifier or string expected");
+ 			value = 0;
+ 		}
+ 	}
+ 	else
+ 	{
+ 		value = 0;
+ 	}
+ 
+ 	/* Dump the option to the debug stream if necessary */
+ 	if(context->debugMode)
+ 	{
+ 		if(value)
+ 		{
+ 			TreeCCDebug(linenum, "%%option %s %s", name, value);
+ 		}
+ 		else
+ 		{
+ 			TreeCCDebug(linenum, "%%option %s", name);
+ 		}
+ 	}
+ 
+ 	/* Process the option */
+ 	optValue = TreeCCOptionProcess(context, name, value);
+ 	if(optValue == TREECC_OPT_UNKNOWN)
+ 	{
+ 		TreeCCErrorOnLine(input, filename, linenum,
+ 						  "unknown option `%s'", name);
+ 	}
+ 	else if(optValue == TREECC_OPT_INVALID_VALUE)
+ 	{
+ 		TreeCCErrorOnLine(input, filename, linenum,
+ 						  "invalid value for option `%s'", name);
+ 	}
+ 	else if(optValue == TREECC_OPT_NEED_VALUE)
+ 	{
+ 		TreeCCErrorOnLine(input, filename, linenum,
+ 						  "option `%s' requires a value", name);
+ 	}
+ 	else if(optValue == TREECC_OPT_NO_VALUE)
+ 	{
+ 		TreeCCErrorOnLine(input, filename, linenum,
+ 						  "option `%s' does not take a value", name);
+ 	}
+ 
+ 	/* Clean up the memory that we used */
+ 	free(name);
+ 	if(optValue != TREECC_OPT_KEEP_VALUE && value)
+ 	{
+ 		free(value);
+ 	}
+ }
+ 
+ /*
+  * Parse an enumerated type declaration.
+  *
+  * Enum ::= %enum IDENTIFIER '=' EnumBody
+  * EnumBody ::= '{' IDENTIFIER { ',' IDENTIFIER } [ ',' ] '}'
+  */
+ static void ParseEnum(TreeCCContext *context)
+ {
+ 	TreeCCInput *input = context->input;
+ 	char *name;
+ 	TreeCCNode *node;
+ 	int sawValue;
+ 
+ 	/* Skip the "%enum" keyword */
+ 	TreeCCNextToken(input);
+ 
+ 	/* Get the name of the enumerated type */
+ 	if(input->token != TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		TreeCCError(input, "enumerated type name expected");
+ 		return;
+ 	}
+ 	name = TreeCCValue(input);
+ 
+ 	/* Create a node for the enumerated type */
+ 	node = TreeCCNodeCreate(context, input->linenum, name, 0,
+ 					 		TREECC_NODE_ABSTRACT |
+ 					 		TREECC_NODE_TYPEDEF |
+ 					 		TREECC_NODE_ENUM);
+ 
+ 	/* Parse the start of the enumeration body */
+ 	TreeCCNextToken(input);
+ 	if(input->token != TREECC_TOKEN_EQUALS)
+ 	{
+ 		TreeCCError(input, "`=' expected");
+ 		return;
+ 	}
+ 	input->parseLiteral = 0;
+ 	TreeCCNextToken(input);
+ 	input->parseLiteral = 1;
+ 	if(input->token != TREECC_TOKEN_LBRACE)
+ 	{
+ 		TreeCCError(input, "`{' expected");
+ 		return;
+ 	}
+ 	TreeCCNextToken(input);
+ 
+ 	/* Parse the enumeration body */
+ 	sawValue = 0;
+ 	while(input->token == TREECC_TOKEN_IDENTIFIER)
+ 	{
+ 		TreeCCNodeCreate(context, input->linenum,
+ 						 TreeCCValue(input),
+ 						 TreeCCDupString(node->name),
+ 						 TREECC_NODE_ENUM_VALUE);
+ 		sawValue = 1;
+ 		TreeCCNextToken(input);
+ 		if(input->token == TREECC_TOKEN_COMMA)
+ 		{
+ 			TreeCCNextToken(input);
+ 		}
+ 		else if(input->token == TREECC_TOKEN_IDENTIFIER)
+ 		{
+ 			TreeCCError(input, "`,' expected");
+ 		}
+ 		else
+ 		{
+ 			break;
+ 		}
+ 	}
+ 	if(input->token == TREECC_TOKEN_COMMA)
+ 	{
+ 		/* Permit an extra trailing comma */
+ 		TreeCCNextToken(input);
+ 	}
+ 	if(!sawValue)
+ 	{
+ 		TreeCCError(input, "no values were specified for the enumeration");
+ 	}
+ 
+ 	/* Recognise the end of the enumeration body */
+ 	if(input->token == TREECC_TOKEN_RBRACE)
+ 	{
+ 		TreeCCNextToken(input);
+ 	}
+ 	else
+ 	{
+ 		TreeCCError(input, "`}' expected");
+ 	}
+ }
+ 
+ /*
+  * Determine if a token is the start of a declaration.
+  */
+ #define	IsStartDecl(token)	\
+ 			((token) == TREECC_TOKEN_EOF || \
+ 			 (token) == TREECC_TOKEN_IDENTIFIER || \
+ 			 (token) == TREECC_TOKEN_LITERAL_DEFNS || \
+ 			 (token) == TREECC_TOKEN_LITERAL_END || \
+ 			 (token) == TREECC_TOKEN_NODE || \
+ 			 (token) == TREECC_TOKEN_OPERATION || \
+ 			 (token) == TREECC_TOKEN_OPTION || \
+ 			 (token) == TREECC_TOKEN_HEADER || \
+ 			 (token) == TREECC_TOKEN_OUTPUT || \
+ 			 (token) == TREECC_TOKEN_BOTH || \
+ 			 (token) == TREECC_TOKEN_DECLS || \
+ 			 (token) == TREECC_TOKEN_END || \
+ 			 (token) == TREECC_TOKEN_ENUM || \
+ 			 (token) == TREECC_TOKEN_COMMON || \
+ 			 (token) == TREECC_TOKEN_INCLUDE)
+ 
+ /*
+  * File ::= { Declaration }
+  * Declaration ::= Node
+  *               | Operation
+  *               | OperationCase
+  *               | Option
+  *               | Enum
+  *               | Literal
+  *               | Header
+  *               | Output
+  *               | Common
+  *               | Include
+  * Literal ::= { LiteralFlag } ( LITERAL_DEFNS | LITERAL_END )
+  * LiteralFlag ::= %both | %decls | %end
+  * Header ::= %header STRING
+  * Output ::= %output STRING
+  * Common ::= %common
+  * Include ::= %include [ %readonly ] STRING
+  */
+ void TreeCCParse(TreeCCContext *context)
+ {
+ 	/* Fetch the first token from the input stream */
+ 	if(!TreeCCNextToken(context->input))
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Parse lines of input until the input is exhausted */
+ 	do
+ 	{
+ 		switch(context->input->token)
+ 		{
+ 			case TREECC_TOKEN_EOF:
+ 			{
+ 				/* Shouldn't happen, but ignore it if it does */
+ 			}
+ 			break;
+ 
+ 			case TREECC_TOKEN_IDENTIFIER:
+ 			{
+ 				/* Parse an operation case definition */
+ 				ParseOperationCase(context);
+ 			}
+ 			continue;	/* Skip the call to TreeCCNextToken */
+ 
+ 			case TREECC_TOKEN_LITERAL_DEFNS:
+ 			case TREECC_TOKEN_LITERAL_END:
+ 			case TREECC_TOKEN_BOTH:
+ 			case TREECC_TOKEN_DECLS:
+ 			case TREECC_TOKEN_END:
+ 			{
+ 				/* Parse a literal definition block for this file */
+ 				int flags = 0;
+ 				while(context->input->token == TREECC_TOKEN_BOTH ||
+ 				      context->input->token == TREECC_TOKEN_DECLS ||
+ 				      context->input->token == TREECC_TOKEN_END)
+ 				{
+ 					if(context->input->token == TREECC_TOKEN_BOTH)
+ 					{
+ 						flags |= TREECC_LITERAL_CODE |
+ 								 TREECC_LITERAL_DECLS;
+ 					}
+ 					else if(context->input->token == TREECC_TOKEN_DECLS)
+ 					{
+ 						flags |= TREECC_LITERAL_DECLS;
+ 					}
+ 					else
+ 					{
+ 						flags |= TREECC_LITERAL_END;
+ 					}
+ 					TreeCCNextToken(context->input);
+ 				}
+ 				if((flags & TREECC_LITERAL_DECLS) == 0)
+ 				{
+ 					flags |= TREECC_LITERAL_CODE;
+ 				}
+ 				if(context->input->token == TREECC_TOKEN_LITERAL_DEFNS)
+ 				{
+ 					TreeCCAddLiteralDefn(context, TreeCCValue(context->input),
+ 										 flags);
+ 				}
+ 				else if(context->input->token == TREECC_TOKEN_LITERAL_END)
+ 				{
+ 					TreeCCAddLiteralDefn(context, TreeCCValue(context->input),
+ 										 flags | TREECC_LITERAL_END);
+ 				}
+ 				else
+ 				{
+ 					TreeCCError(context->input,
+ 								"literal definition block expected");
+ 					continue;
+ 				}
+ 			}
+ 			break;
+ 
+ 			case TREECC_TOKEN_NODE:
+ 			{
+ 				/* Parse a node definition */
+ 				ParseNode(context);
+ 			}
+ 			continue;	/* Skip the call to TreeCCNextToken */
+ 
+ 			case TREECC_TOKEN_OPERATION:
+ 			{
+ 				/* Parse an operation definition */
+ 				ParseOperation(context);
+ 			}
+ 			continue;	/* Skip the call to TreeCCNextToken */
+ 
+ 			case TREECC_TOKEN_OPTION:
+ 			{
+ 				/* Parse an option declaration */
+ 				ParseOption(context);
+ 			}
+ 			continue;	/* Skip the call to TreeCCNextToken */
+ 
+ 			case TREECC_TOKEN_HEADER:
+ 			{
+ 				/* Parse a header filename specification */
+ 				TreeCCNextToken(context->input);
+ 				if(context->input->token == TREECC_TOKEN_STRING)
+ 				{
+ 					TreeCCStream *stream =
+ 						TreeCCStreamCreate(context, context->input->text,
+ 										   context->input->text, 1);
+ 					context->headerStream = stream;
+ 					stream->readOnly |= context->input->readOnly;
+ 					if(!(context->commonHeader))
+ 					{
+ 						context->commonHeader = stream;
+ 					}
+ 				}
+ 				else
+ 				{
+ 					TreeCCError(context->input, "header filename expected");
+ 					continue;
+ 				}
+ 			}
+ 			break;
+ 
+ 			case TREECC_TOKEN_OUTPUT:
+ 			{
+ 				/* Parse an output filename specification */
+ 				TreeCCNextToken(context->input);
+ 				if(context->input->token == TREECC_TOKEN_STRING)
+ 				{
+ 					TreeCCStream *stream =
+ 						TreeCCStreamCreate(context, context->input->text,
+ 										   context->input->text, 0);
+ 					context->sourceStream = stream;
+ 					stream->readOnly |= context->input->readOnly;
+ 					if(!(context->commonSource))
+ 					{
+ 						context->commonSource = stream;
+ 					}
+ 				}
+ 				else
+ 				{
+ 					TreeCCError(context->input, "output filename expected");
+ 					continue;
+ 				}
+ 			}
+ 			break;
+ 
+ 			case TREECC_TOKEN_OUTDIR:
+ 			{
+ 				/* Parse an output directory specification */
+ 				TreeCCNextToken(context->input);
+ 				if(context->input->token == TREECC_TOKEN_STRING)
+ 				{
+ 					context->outputDirectory =
+ 						TreeCCResolvePathname(context->input->filename,
+ 											  context->input->text);
+ 				}
+ 				else
+ 				{
+ 					TreeCCError(context->input, "output filename expected");
+ 					continue;
+ 				}
+ 			}
+ 			break;
+ 
+ 			case TREECC_TOKEN_ENUM:
+ 			{
+ 				/* Parse an enumerated type definition */
+ 				ParseEnum(context);
+ 			}
+ 			continue;	/* Skip the call to TreeCCNextToken */
+ 
+ 			case TREECC_TOKEN_COMMON:
+ 			{
+ 				/* Put the common housekeeping code in the
+ 				   current header and source streams */
+ 				context->commonHeader = context->headerStream;
+ 				context->commonSource = context->sourceStream;
+ 			}
+ 			break;
+ 
+ 			case TREECC_TOKEN_INCLUDE:
+ 			{
+ 				/* Include another file at this point */
+ 				int readOnly = context->input->readOnly;
+ 				TreeCCNextToken(context->input);
+ 				if(context->input->token == TREECC_TOKEN_READONLY)
+ 				{
+ 					readOnly = 1;
+ 					TreeCCNextToken(context->input);
+ 				}
+ 				if(context->input->token == TREECC_TOKEN_STRING)
+ 				{
+ 					char *includeFile =
+ 						TreeCCResolvePathname(context->input->filename,
+ 											  context->input->text);
+ 					FILE *file = fopen(includeFile, "r");
+ 					if(file != NULL)
+ 					{
+ 						/* Parse the contents of the included file */
+ 						TreeCCInput *newInput =
+ 							(TreeCCInput *)malloc(sizeof(TreeCCInput));
+ 						TreeCCInput *origInput = context->input;
+ 						if(!newInput)
+ 						{
+ 							TreeCCOutOfMemory(context->input);
+ 						}
+ 						TreeCCOpen(newInput, context->input->progname,
+ 								   file, includeFile);
+ 						context->input = newInput;
+ 						TreeCCParse(context);
+ 						context->input = origInput;
+ 						TreeCCClose(newInput, 1);
+ 						free(newInput);
+ 					}
+ 					else
+ 					{
+ 						TreeCCError(context->input, "cannot open \"%s\"",
+ 									includeFile);
+ 						free(includeFile);
+ 					}
+ 				}
+ 				else
+ 				{
+ 					TreeCCError(context->input, "include filename expected");
+ 				}
+ 			}
+ 			break;
+ 
+ 			case TREECC_TOKEN_LITERAL_CODE:
+ 			case TREECC_TOKEN_LPAREN:
+ 			case TREECC_TOKEN_RPAREN:
+ 			case TREECC_TOKEN_LBRACE:
+ 			case TREECC_TOKEN_RBRACE:
+ 			case TREECC_TOKEN_LSQUARE:
+ 			case TREECC_TOKEN_RSQUARE:
+ 			case TREECC_TOKEN_COMMA:
+ 			case TREECC_TOKEN_EQUALS:
+ 			case TREECC_TOKEN_STAR:
+ 			case TREECC_TOKEN_REF:
+ 			case TREECC_TOKEN_SEMI:
+ 			case TREECC_TOKEN_COLON_COLON:
+ 			case TREECC_TOKEN_STRING:
+ 			case TREECC_TOKEN_UNKNOWN:
+ 			case TREECC_TOKEN_ABSTRACT:
+ 			case TREECC_TOKEN_TYPEDEF:
+ 			case TREECC_TOKEN_NOCREATE:
+ 			case TREECC_TOKEN_VIRTUAL:
+ 			case TREECC_TOKEN_INLINE:
+ 			case TREECC_TOKEN_SPLIT:
+ 			case TREECC_TOKEN_READONLY:
+ 			{
+ 				/* This token is not valid here */
+ 				TreeCCError(context->input, "declaration expected");
+ 				do
+ 				{
+ 					/* Attempt to re-synchronise on the next declaration */
+ 					TreeCCNextToken(context->input);
+ 				}
+ 				while(!IsStartDecl(context->input->token));
+ 			}
+ 			continue;	/* Skip the call to TreeCCNextToken */
+ 		}
+ 
+ 		/* Get the next token from the input stream */
+ 		TreeCCNextToken(context->input);
+ 	}
+ 	while(context->input->token != TREECC_TOKEN_EOF);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/parse.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/parse.h:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/parse.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,42 ----
+ /*
+  * parse.h - Parse "treecc" input files.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_PARSE_H
+ #define	_TREECC_PARSE_H
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Parse the contents of an input stream and populate "context"
+  * with the definitions that are found within it.
+  */
+ void TreeCCParse(TreeCCContext *context);
+ 
+ #ifdef	__cplusplus
+ };
+ #endif
+ 
+ #endif	/* _TREECC_PARSE_H */


Index: llvm/test/Programs/MultiSource/Applications/treecc/skeleton.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/skeleton.c:1.1
*** /dev/null	Tue Apr  6 12:53:41 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/skeleton.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,147 ----
+ /*
+  * skeleton.c - Include skeleton code in an output stream.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Find a particular skeleton string within "skels.c".
+  */
+ extern const char * const TreeCCSkelFiles[];
+ static char *FindSkeletonString(const char *skeleton)
+ {
+ 	char **search = (char **)TreeCCSkelFiles;
+ 	while(*search != 0)
+ 	{
+ 		if(!strcmp(*search, skeleton))
+ 		{
+ 			return search[1];
+ 		}
+ 		search += 2;
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * Read a line from a skeleton buffer..
+  */
+ static int ReadSkeletonLine(char *buffer, int size, char **skel)
+ {
+ 	char *ptr = *skel;
+ 	if(*ptr == '\0')
+ 	{
+ 		return 0;
+ 	}
+ 	while(*ptr != '\0' && *ptr != '\n')
+ 	{
+ 		if(size > 2)
+ 		{
+ 			*buffer++ = *ptr;
+ 			--size;
+ 		}
+ 		++ptr;
+ 	}
+ 	if(*ptr == '\n')
+ 	{
+ 		*buffer++ = *ptr++;
+ 	}
+ 	*buffer = '\0';
+ 	*skel = ptr;
+ 	return 1;
+ }
+ 
+ void TreeCCIncludeSkeleton(TreeCCContext *context, TreeCCStream *stream,
+ 						   const char *skeleton)
+ {
+ 	char *skelstr = FindSkeletonString(skeleton);
+ 	char buffer[BUFSIZ];
+ 	int posn, start;
+ 	if(!skelstr)
+ 	{
+ 		fprintf(stderr,
+ 				"treecc: internal error - could not find skeleton \"%s\"\n",
+ 				skeleton);
+ 		exit(1);
+ 	}
+ 	TreeCCStreamLine(stream, 1, skeleton);
+ 	while(ReadSkeletonLine(buffer, BUFSIZ, &skelstr))
+ 	{
+ 	#if HAVE_STRCHR
+ 		if(strchr(buffer, 'Y') != 0 || strchr(buffer, 'y') != 0)
+ 	#endif
+ 		{
+ 			/* The line probably contains "YYNODESTATE" or "yy" */
+ 			posn = 0;
+ 			start = 0;
+ 			while(buffer[posn] != '\0')
+ 			{
+ 				if(buffer[posn] == 'Y' &&
+ 				   !strncmp(buffer + posn, "YYNODESTATE", 11))
+ 				{
+ 					buffer[posn] = '\0';
+ 					if(start < posn)
+ 					{
+ 						TreeCCStreamCode(stream, buffer + start);
+ 					}
+ 					TreeCCStreamCode(stream, context->state_type);
+ 					posn += 11;
+ 					start = posn;
+ 				}
+ 				else if(buffer[posn] == 'y' && buffer[posn + 1] == 'y')
+ 				{
+ 					buffer[posn] = '\0';
+ 					if(start < posn)
+ 					{
+ 						TreeCCStreamCode(stream, buffer + start);
+ 					}
+ 					TreeCCStreamCode(stream, context->yy_replacement);
+ 					posn += 2;
+ 					start = posn;
+ 				}
+ 				else
+ 				{
+ 					++posn;
+ 				}
+ 			}
+ 			if(start < posn)
+ 			{
+ 				TreeCCStreamCode(stream, buffer + start);
+ 			}
+ 		}
+ 	#if HAVE_STRCHR
+ 		else
+ 		{
+ 			/* Ordinary line */
+ 			TreeCCStreamCode(stream, buffer);
+ 		}
+ 	#endif
+ 	}
+ 	TreeCCStreamFixLine(stream);
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/skels.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/skels.c:1.1
*** /dev/null	Tue Apr  6 12:53:42 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/skels.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,812 ----
+ /* This file is automatically generated by mkskel-sh - do not edit */
+ 
+ #include "config.h"
+ 
+ static char const TreeCCSkel_c_skel_c[] =
+ "/*\n"
+ " * treecc node allocation routines for C.\n"
+ " *\n"
+ " * Copyright (C) 2001  Southern Storm Software, Pty Ltd.\n"
+ " *\n"
+ " * This program is free software; you can redistribute it and/or modify\n"
+ " * it under the terms of the GNU General Public License as published by\n"
+ " * the Free Software Foundation; either version 2 of the License, or\n"
+ " * (at your option) any later version.\n"
+ " *\n"
+ " * This program is distributed in the hope that it will be useful,\n"
+ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+ " * GNU General Public License for more details.\n"
+ " *\n"
+ " * You should have received a copy of the GNU General Public License\n"
+ " * along with this program; if not, write to the Free Software\n"
+ " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
+ " *\n"
+ " * As a special exception, when this file is copied by treecc into\n"
+ " * a treecc output file, you may use that output file without restriction.\n"
+ " */\n"
+ "\n"
+ "#include <stdlib.h>\n"
+ "\n"
+ "#ifndef YYNODESTATE_BLKSIZ\n"
+ "#define	YYNODESTATE_BLKSIZ	2048\n"
+ "#endif\n"
+ "\n"
+ "/*\n"
+ " * Types used by the allocation routines.\n"
+ " */\n"
+ "struct YYNODESTATE_block\n"
+ "{\n"
+ "	char data__[YYNODESTATE_BLKSIZ];\n"
+ "	struct YYNODESTATE_block *next__;\n"
+ "\n"
+ "};\n"
+ "struct YYNODESTATE_push\n"
+ "{\n"
+ "	struct YYNODESTATE_push *next__;\n"
+ "	struct YYNODESTATE_block *saved_block__;\n"
+ "	int saved_used__;\n"
+ "};\n"
+ "\n"
+ "/*\n"
+ " * The fixed global state to use for non-reentrant allocation.\n"
+ " */\n"
+ "#ifndef YYNODESTATE_REENTRANT\n"
+ "static YYNODESTATE fixed_state__;\n"
+ "#endif\n"
+ "\n"
+ "/*\n"
+ " * Some macro magic to determine the default alignment\n"
+ " * on this machine.  This will compile down to a constant.\n"
+ " */\n"
+ "#define	YYNODESTATE_ALIGN_CHECK_TYPE(type,name)	\\\n"
+ "	struct _YYNODESTATE_align_##name { \\\n"
+ "		char pad; \\\n"
+ "		type field; \\\n"
+ "	}\n"
+ "#define	YYNODESTATE_ALIGN_FOR_TYPE(type)	\\\n"
+ "	((unsigned)(&(((struct _YYNODESTATE_align_##type *)0)->field)))\n"
+ "#define	YYNODESTATE_ALIGN_MAX(a,b)	\\\n"
+ "	((a) > (b) ? (a) : (b))\n"
+ "#define	YYNODESTATE_ALIGN_MAX3(a,b,c) \\\n"
+ "	(YYNODESTATE_ALIGN_MAX((a), YYNODESTATE_ALIGN_MAX((b), (c))))\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(int, int);\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(long, long);\n"
+ "#if defined(WIN32) && !defined(__CYGWIN__)\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(__int64, long_long);\n"
+ "#else\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(long long, long_long);\n"
+ "#endif\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(void *, void_p);\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(float, float);\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(double, double);\n"
+ "#define	YYNODESTATE_ALIGNMENT	\\\n"
+ "	YYNODESTATE_ALIGN_MAX( \\\n"
+ "			YYNODESTATE_ALIGN_MAX3	\\\n"
+ "			(YYNODESTATE_ALIGN_FOR_TYPE(int), \\\n"
+ "		     YYNODESTATE_ALIGN_FOR_TYPE(long), \\\n"
+ "			 YYNODESTATE_ALIGN_FOR_TYPE(long_long)), \\\n"
+ "  	     YYNODESTATE_ALIGN_MAX3 \\\n"
+ "		 	(YYNODESTATE_ALIGN_FOR_TYPE(void_p), \\\n"
+ "			 YYNODESTATE_ALIGN_FOR_TYPE(float), \\\n"
+ "			 YYNODESTATE_ALIGN_FOR_TYPE(double)))\n"
+ "\n"
+ "/*\n"
+ " * Initialize the node allocation pool.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void yynodeinit(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "void yynodeinit()\n"
+ "{\n"
+ "	YYNODESTATE *state__ = &fixed_state__;\n"
+ "#endif\n"
+ "	state__->blocks__ = 0;\n"
+ "	state__->push_stack__ = 0;\n"
+ "	state__->used__ = 0;\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Allocate a block of memory.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void *yynodealloc(state__, size__)\n"
+ "YYNODESTATE *state__;\n"
+ "unsigned int size__;\n"
+ "{\n"
+ "#else\n"
+ "void *yynodealloc(size__)\n"
+ "unsigned int size__;\n"
+ "{\n"
+ "	YYNODESTATE *state__ = &fixed_state__;\n"
+ "#endif\n"
+ "	struct YYNODESTATE_block *block__;\n"
+ "	void *result__;\n"
+ "\n"
+ "	/* Round the size to the next alignment boundary */\n"
+ "	size__ = (size__ + YYNODESTATE_ALIGNMENT - 1) &\n"
+ "				~(YYNODESTATE_ALIGNMENT - 1);\n"
+ "\n"
+ "	/* Do we need to allocate a new block? */\n"
+ "	block__ = state__->blocks__;\n"
+ "	if(!block__ || (state__->used__ + size__) > YYNODESTATE_BLKSIZ)\n"
+ "	{\n"
+ "		if(size__ > YYNODESTATE_BLKSIZ)\n"
+ "		{\n"
+ "			/* The allocation is too big for the node pool */\n"
+ "			return (void *)0;\n"
+ "		}\n"
+ "		block__ = (struct YYNODESTATE_block *)\n"
+ "						malloc(sizeof(struct YYNODESTATE_block));\n"
+ "		if(!block__)\n"
+ "		{\n"
+ "			/* The system is out of memory.  The programmer can\n"
+ "			   supply the \"yynodefailed\" function to report the\n"
+ "			   out of memory state and/or abort the program */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "			yynodefailed(state__);\n"
+ "#else\n"
+ "			yynodefailed();\n"
+ "#endif\n"
+ "			return (void *)0;\n"
+ "		}\n"
+ "		block__->next__ = state__->blocks__;\n"
+ "		state__->blocks__ = block__;\n"
+ "		state__->used__ = 0;\n"
+ "	}\n"
+ "\n"
+ "	/* Allocate the memory and return it */\n"
+ "	result__ = (void *)(block__->data__ + state__->used__);\n"
+ "	state__->used__ += size__;\n"
+ "	return result__;\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Push the node allocation state.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "int yynodepush(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "int yynodepush()\n"
+ "{\n"
+ "	YYNODESTATE *state__ = &fixed_state__;\n"
+ "#endif\n"
+ "	struct YYNODESTATE_block *saved_block__;\n"
+ "	int saved_used__;\n"
+ "	struct YYNODESTATE_push *push_item__;\n"
+ "\n"
+ "	/* Save the current state of the node allocation pool */\n"
+ "	saved_block__ = state__->blocks__;\n"
+ "	saved_used__ = state__->used__;\n"
+ "\n"
+ "	/* Allocate space for a push item */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "	push_item__ = (struct YYNODESTATE_push *)\n"
+ "			yynodealloc(state__, sizeof(struct YYNODESTATE_push));\n"
+ "#else\n"
+ "	push_item__ = (struct YYNODESTATE_push *)\n"
+ "			yynodealloc(sizeof(struct YYNODESTATE_push));\n"
+ "#endif\n"
+ "	if(!push_item__)\n"
+ "	{\n"
+ "		return 0;\n"
+ "	}\n"
+ "\n"
+ "	/* Copy the saved information to the push item */\n"
+ "	push_item__->saved_block__ = saved_block__;\n"
+ "	push_item__->saved_used__ = saved_used__;\n"
+ "\n"
+ "	/* Add the push item to the push stack */\n"
+ "	push_item__->next__ = state__->push_stack__;\n"
+ "	state__->push_stack__ = push_item__;\n"
+ "	return 1;\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Pop the node allocation state.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void yynodepop(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "void yynodepop()\n"
+ "{\n"
+ "	YYNODESTATE *state__ = &fixed_state__;\n"
+ "#endif\n"
+ "	struct YYNODESTATE_push *push_item__;\n"
+ "	struct YYNODESTATE_block *saved_block__;\n"
+ "	struct YYNODESTATE_block *temp_block__;\n"
+ "\n"
+ "	/* Pop the top of the push stack */\n"
+ "	push_item__ = state__->push_stack__;\n"
+ "	if(push_item__ == 0)\n"
+ "	{\n"
+ "		saved_block__ = 0;\n"
+ "		state__->used__ = 0;\n"
+ "	}\n"
+ "	else\n"
+ "	{\n"
+ "		saved_block__ = push_item__->saved_block__;\n"
+ "		state__->used__ = push_item__->saved_used__;\n"
+ "		state__->push_stack__ = push_item__->next__;\n"
+ "	}\n"
+ "\n"
+ "	/* Free unnecessary blocks */\n"
+ "	while(state__->blocks__ != saved_block__)\n"
+ "	{\n"
+ "		temp_block__ = state__->blocks__;\n"
+ "		state__->blocks__ = temp_block__->next__;\n"
+ "		free(temp_block__);\n"
+ "	}\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Clear the node allocation pool completely.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void yynodeclear(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "void yynodeclear()\n"
+ "{\n"
+ "	YYNODESTATE *state__ = &fixed_state__;\n"
+ "#endif\n"
+ "	struct YYNODESTATE_block *temp_block__;\n"
+ "	while(state__->blocks__ != 0)\n"
+ "	{\n"
+ "		temp_block__ = state__->blocks__;\n"
+ "		state__->blocks__ = temp_block__->next__;\n"
+ "		free(temp_block__);\n"
+ "	}\n"
+ "	state__->push_stack__ = 0;\n"
+ "	state__->used__ = 0;\n"
+ "}\n"
+ ;
+ static char const TreeCCSkel_c_skel_h[] =
+ "typedef struct\n"
+ "{\n"
+ "	struct YYNODESTATE_block *blocks__;\n"
+ "	struct YYNODESTATE_push *push_stack__;\n"
+ "	int used__;\n"
+ "\n"
+ "} YYNODESTATE;\n"
+ ;
+ static char const TreeCCSkel_cpp_skel_cc[] =
+ "/*\n"
+ " * treecc node allocation routines for C++.\n"
+ " *\n"
+ " * Copyright (C) 2001  Southern Storm Software, Pty Ltd.\n"
+ " *\n"
+ " * This program is free software; you can redistribute it and/or modify\n"
+ " * it under the terms of the GNU General Public License as published by\n"
+ " * the Free Software Foundation; either version 2 of the License, or\n"
+ " * (at your option) any later version.\n"
+ " *\n"
+ " * This program is distributed in the hope that it will be useful,\n"
+ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+ " * GNU General Public License for more details.\n"
+ " *\n"
+ " * You should have received a copy of the GNU General Public License\n"
+ " * along with this program; if not, write to the Free Software\n"
+ " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
+ " *\n"
+ " * As a special exception, when this file is copied by treecc into\n"
+ " * a treecc output file, you may use that output file without restriction.\n"
+ " */\n"
+ "\n"
+ "#ifndef YYNODESTATE_BLKSIZ\n"
+ "#define	YYNODESTATE_BLKSIZ	2048\n"
+ "#endif\n"
+ "\n"
+ "/*\n"
+ " * Types used by the allocation routines.\n"
+ " */\n"
+ "struct YYNODESTATE_block\n"
+ "{\n"
+ "	char data__[YYNODESTATE_BLKSIZ];\n"
+ "	struct YYNODESTATE_block *next__;\n"
+ "\n"
+ "};\n"
+ "struct YYNODESTATE_push\n"
+ "{\n"
+ "	struct YYNODESTATE_push *next__;\n"
+ "	struct YYNODESTATE_block *saved_block__;\n"
+ "	int saved_used__;\n"
+ "};\n"
+ "\n"
+ "/*\n"
+ " * Initialize the singleton instance.\n"
+ " */\n"
+ "#ifndef YYNODESTATE_REENTRANT\n"
+ "YYNODESTATE *YYNODESTATE::state__ = 0;\n"
+ "#endif\n"
+ "\n"
+ "/*\n"
+ " * Some macro magic to determine the default alignment\n"
+ " * on this machine.  This will compile down to a constant.\n"
+ " */\n"
+ "#define	YYNODESTATE_ALIGN_CHECK_TYPE(type,name)	\\\n"
+ "	struct _YYNODESTATE_align_##name { \\\n"
+ "		char pad; \\\n"
+ "		type field; \\\n"
+ "	}\n"
+ "#define	YYNODESTATE_ALIGN_FOR_TYPE(type)	\\\n"
+ "	((unsigned)(&(((struct _YYNODESTATE_align_##type *)0)->field)))\n"
+ "#define	YYNODESTATE_ALIGN_MAX(a,b)	\\\n"
+ "	((a) > (b) ? (a) : (b))\n"
+ "#define	YYNODESTATE_ALIGN_MAX3(a,b,c) \\\n"
+ "	(YYNODESTATE_ALIGN_MAX((a), YYNODESTATE_ALIGN_MAX((b), (c))))\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(int, int);\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(long, long);\n"
+ "#if defined(WIN32) && !defined(__CYGWIN__)\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(__int64, long_long);\n"
+ "#else\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(long long, long_long);\n"
+ "#endif\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(void *, void_p);\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(float, float);\n"
+ "YYNODESTATE_ALIGN_CHECK_TYPE(double, double);\n"
+ "#define	YYNODESTATE_ALIGNMENT	\\\n"
+ "	YYNODESTATE_ALIGN_MAX( \\\n"
+ "			YYNODESTATE_ALIGN_MAX3	\\\n"
+ "			(YYNODESTATE_ALIGN_FOR_TYPE(int), \\\n"
+ "		     YYNODESTATE_ALIGN_FOR_TYPE(long), \\\n"
+ "			 YYNODESTATE_ALIGN_FOR_TYPE(long_long)), \\\n"
+ "  	     YYNODESTATE_ALIGN_MAX3 \\\n"
+ "		 	(YYNODESTATE_ALIGN_FOR_TYPE(void_p), \\\n"
+ "			 YYNODESTATE_ALIGN_FOR_TYPE(float), \\\n"
+ "			 YYNODESTATE_ALIGN_FOR_TYPE(double)))\n"
+ "\n"
+ "/*\n"
+ " * Constructor for YYNODESTATE.\n"
+ " */\n"
+ "YYNODESTATE::YYNODESTATE()\n"
+ "{\n"
+ "	/* Initialize the allocation state */\n"
+ "	blocks__ = 0;\n"
+ "	push_stack__ = 0;\n"
+ "	used__ = 0;\n"
+ "\n"
+ "#ifndef YYNODESTATE_REENTRANT\n"
+ "	/* Register this object as the singleton instance */\n"
+ "	if(!state__)\n"
+ "	{\n"
+ "		state__ = this;\n"
+ "	}\n"
+ "#endif\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Destructor for YYNODESTATE.\n"
+ " */\n"
+ "YYNODESTATE::~YYNODESTATE()\n"
+ "{\n"
+ "	/* Free all node memory */\n"
+ "	clear();\n"
+ "\n"
+ "#ifndef YYNODESTATE_REENTRANT\n"
+ "	/* We are no longer the singleton instance */\n"
+ "	if(state__ == this)\n"
+ "	{\n"
+ "		state__ = 0;\n"
+ "	}\n"
+ "#endif\n"
+ "}\n"
+ "\n"
+ "#ifdef YYNODESTATE_USE_ALLOCATOR\n"
+ "\n"
+ "/*\n"
+ " * Allocate a block of memory.\n"
+ " */\n"
+ "void *YYNODESTATE::alloc(size_t size__)\n"
+ "{\n"
+ "	struct YYNODESTATE_block *block__;\n"
+ "	void *result__;\n"
+ "\n"
+ "	/* Round the size to the next alignment boundary */\n"
+ "	size__ = (size__ + YYNODESTATE_ALIGNMENT - 1) &\n"
+ "				~(YYNODESTATE_ALIGNMENT - 1);\n"
+ "\n"
+ "	/* Do we need to allocate a new block? */\n"
+ "	block__ = blocks__;\n"
+ "	if(!block__ || (used__ + size__) > YYNODESTATE_BLKSIZ)\n"
+ "	{\n"
+ "		if(size__ > YYNODESTATE_BLKSIZ)\n"
+ "		{\n"
+ "			/* The allocation is too big for the node pool */\n"
+ "			return (void *)0;\n"
+ "		}\n"
+ "		block__ = new YYNODESTATE_block;\n"
+ "		if(!block__)\n"
+ "		{\n"
+ "			/* The system is out of memory.  The programmer can\n"
+ "			   inherit the \"failed\" method to report the\n"
+ "			   out of memory state and/or abort the program */\n"
+ "			failed();\n"
+ "			return (void *)0;\n"
+ "		}\n"
+ "		block__->next__ = blocks__;\n"
+ "		blocks__ = block__;\n"
+ "		used__ = 0;\n"
+ "	}\n"
+ "\n"
+ "	/* Allocate the memory and return it */\n"
+ "	result__ = (void *)(block__->data__ + used__);\n"
+ "	used__ += size__;\n"
+ "	return result__;\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Deallocate a block of memory.\n"
+ " */\n"
+ "void YYNODESTATE::dealloc(void *ptr__, size_t size__)\n"
+ "{\n"
+ "	/* Nothing to do for this type of node allocator */\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Push the node allocation state.\n"
+ " */\n"
+ "int YYNODESTATE::push()\n"
+ "{\n"
+ "	struct YYNODESTATE_block *saved_block__;\n"
+ "	int saved_used__;\n"
+ "	struct YYNODESTATE_push *push_item__;\n"
+ "\n"
+ "	/* Save the current state of the node allocation pool */\n"
+ "	saved_block__ = blocks__;\n"
+ "	saved_used__ = used__;\n"
+ "\n"
+ "	/* Allocate space for a push item */\n"
+ "	push_item__ = (struct YYNODESTATE_push *)\n"
+ "			alloc(sizeof(struct YYNODESTATE_push));\n"
+ "	if(!push_item__)\n"
+ "	{\n"
+ "		return 0;\n"
+ "	}\n"
+ "\n"
+ "	/* Copy the saved information to the push item */\n"
+ "	push_item__->saved_block__ = saved_block__;\n"
+ "	push_item__->saved_used__ = saved_used__;\n"
+ "\n"
+ "	/* Add the push item to the push stack */\n"
+ "	push_item__->next__ = push_stack__;\n"
+ "	push_stack__ = push_item__;\n"
+ "	return 1;\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Pop the node allocation state.\n"
+ " */\n"
+ "void YYNODESTATE::pop()\n"
+ "{\n"
+ "	struct YYNODESTATE_push *push_item__;\n"
+ "	struct YYNODESTATE_block *saved_block__;\n"
+ "	struct YYNODESTATE_block *temp_block__;\n"
+ "\n"
+ "	/* Pop the top of the push stack */\n"
+ "	push_item__ = push_stack__;\n"
+ "	if(push_item__ == 0)\n"
+ "	{\n"
+ "		saved_block__ = 0;\n"
+ "		used__ = 0;\n"
+ "	}\n"
+ "	else\n"
+ "	{\n"
+ "		saved_block__ = push_item__->saved_block__;\n"
+ "		used__ = push_item__->saved_used__;\n"
+ "		push_stack__ = push_item__->next__;\n"
+ "	}\n"
+ "\n"
+ "	/* Free unnecessary blocks */\n"
+ "	while(blocks__ != saved_block__)\n"
+ "	{\n"
+ "		temp_block__ = blocks__;\n"
+ "		blocks__ = temp_block__->next__;\n"
+ "		delete temp_block__;\n"
+ "	}\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Clear the node allocation pool completely.\n"
+ " */\n"
+ "void YYNODESTATE::clear()\n"
+ "{\n"
+ "	struct YYNODESTATE_block *temp_block__;\n"
+ "	while(blocks__ != 0)\n"
+ "	{\n"
+ "		temp_block__ = blocks__;\n"
+ "		blocks__ = temp_block__->next__;\n"
+ "		delete temp_block__;\n"
+ "	}\n"
+ "	push_stack__ = 0;\n"
+ "	used__ = 0;\n"
+ "}\n"
+ "\n"
+ "#endif /* YYNODESTATE_USE_ALLOCATOR */\n"
+ "\n"
+ "/*\n"
+ " * Default implementation of functions which may be overridden.\n"
+ " */\n"
+ "void YYNODESTATE::failed()\n"
+ "{\n"
+ "}\n"
+ "\n"
+ "#ifdef YYNODESTATE_TRACK_LINES\n"
+ "\n"
+ "char *YYNODESTATE::currFilename()\n"
+ "{\n"
+ "	return (char *)0;\n"
+ "}\n"
+ "\n"
+ "long YYNODESTATE::currLinenum()\n"
+ "{\n"
+ "	return 0;\n"
+ "}\n"
+ "\n"
+ "#endif\n"
+ ;
+ static char const TreeCCSkel_cpp_skel_h[] =
+ "private:\n"
+ "\n"
+ "	struct YYNODESTATE_block *blocks__;\n"
+ "	struct YYNODESTATE_push *push_stack__;\n"
+ "	int used__;\n"
+ ;
+ static char const TreeCCSkel_c_gc_skel_h[] =
+ "typedef struct\n"
+ "{\n"
+ "	int dummy__;\n"
+ "\n"
+ "} YYNODESTATE;\n"
+ ;
+ static char const TreeCCSkel_c_gc_skel_c[] =
+ "/*\n"
+ " * treecc node allocation routines for C.\n"
+ " *\n"
+ " * Copyright (C) 2003  Southern Storm Software, Pty Ltd.\n"
+ " *\n"
+ " * This program is free software; you can redistribute it and/or modify\n"
+ " * it under the terms of the GNU General Public License as published by\n"
+ " * the Free Software Foundation; either version 2 of the License, or\n"
+ " * (at your option) any later version.\n"
+ " *\n"
+ " * This program is distributed in the hope that it will be useful,\n"
+ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+ " * GNU General Public License for more details.\n"
+ " *\n"
+ " * You should have received a copy of the GNU General Public License\n"
+ " * along with this program; if not, write to the Free Software\n"
+ " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
+ " *\n"
+ " * As a special exception, when this file is copied by treecc into\n"
+ " * a treecc output file, you may use that output file without restriction.\n"
+ " */\n"
+ "\n"
+ "#include <stdlib.h>\n"
+ "#include <gc.h>\n"
+ "\n"
+ "/*\n"
+ " * Initialize the node allocation pool.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void yynodeinit(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "void yynodeinit()\n"
+ "{\n"
+ "#endif\n"
+ "	GC_INIT();\n"
+ "	GC_init();\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Allocate a block of memory.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void *yynodealloc(state__, size__)\n"
+ "YYNODESTATE *state__;\n"
+ "unsigned int size__;\n"
+ "{\n"
+ "#else\n"
+ "void *yynodealloc(size__)\n"
+ "unsigned int size__;\n"
+ "{\n"
+ "#endif\n"
+ "	return (void *)GC_MALLOC((size_t)size__);\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Push the node allocation state.  Not used in the GC version.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "int yynodepush(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "int yynodepush()\n"
+ "{\n"
+ "#endif\n"
+ "	return 1;\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Pop the node allocation state.  Not used in the GC version.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void yynodepop(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "void yynodepop()\n"
+ "{\n"
+ "#endif\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Clear the node allocation pool completely.  Not used in the GC version.\n"
+ " */\n"
+ "#ifdef YYNODESTATE_REENTRANT\n"
+ "void yynodeclear(state__)\n"
+ "YYNODESTATE *state__;\n"
+ "{\n"
+ "#else\n"
+ "void yynodeclear()\n"
+ "{\n"
+ "#endif\n"
+ "}\n"
+ ;
+ static char const TreeCCSkel_cpp_gc_skel_h[] =
+ "\n"
+ ;
+ static char const TreeCCSkel_cpp_gc_skel_cc[] =
+ "/*\n"
+ " * treecc node allocation routines for C++.\n"
+ " *\n"
+ " * Copyright (C) 2003  Southern Storm Software, Pty Ltd.\n"
+ " *\n"
+ " * This program is free software; you can redistribute it and/or modify\n"
+ " * it under the terms of the GNU General Public License as published by\n"
+ " * the Free Software Foundation; either version 2 of the License, or\n"
+ " * (at your option) any later version.\n"
+ " *\n"
+ " * This program is distributed in the hope that it will be useful,\n"
+ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+ " * GNU General Public License for more details.\n"
+ " *\n"
+ " * You should have received a copy of the GNU General Public License\n"
+ " * along with this program; if not, write to the Free Software\n"
+ " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
+ " *\n"
+ " * As a special exception, when this file is copied by treecc into\n"
+ " * a treecc output file, you may use that output file without restriction.\n"
+ " */\n"
+ "\n"
+ "#include <gc.h>\n"
+ "\n"
+ "/*\n"
+ " * Initialize the singleton instance.\n"
+ " */\n"
+ "#ifndef YYNODESTATE_REENTRANT\n"
+ "YYNODESTATE *YYNODESTATE::state__ = 0;\n"
+ "#endif\n"
+ "\n"
+ "/*\n"
+ " * Constructor for YYNODESTATE.\n"
+ " */\n"
+ "YYNODESTATE::YYNODESTATE()\n"
+ "{\n"
+ "	/* Initialize the garbage collector */\n"
+ "	GC_INIT();\n"
+ "	GC_init();\n"
+ "\n"
+ "#ifndef YYNODESTATE_REENTRANT\n"
+ "	/* Register this object as the singleton instance */\n"
+ "	if(!state__)\n"
+ "	{\n"
+ "		state__ = this;\n"
+ "	}\n"
+ "#endif\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Destructor for YYNODESTATE.\n"
+ " */\n"
+ "YYNODESTATE::~YYNODESTATE()\n"
+ "{\n"
+ "#ifndef YYNODESTATE_REENTRANT\n"
+ "	/* We are no longer the singleton instance */\n"
+ "	if(state__ == this)\n"
+ "	{\n"
+ "		state__ = 0;\n"
+ "	}\n"
+ "#endif\n"
+ "}\n"
+ "\n"
+ "#ifdef YYNODESTATE_USE_ALLOCATOR\n"
+ "\n"
+ "/*\n"
+ " * Allocate a block of memory.\n"
+ " */\n"
+ "void *YYNODESTATE::alloc(size_t size__)\n"
+ "{\n"
+ "	return (void *)GC_MALLOC((size_t)size__);\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Deallocate a block of memory.\n"
+ " */\n"
+ "void YYNODESTATE::dealloc(void *ptr__, size_t size__)\n"
+ "{\n"
+ "	/* Nothing to do for this type of node allocator */\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Push the node allocation state.\n"
+ " */\n"
+ "int YYNODESTATE::push()\n"
+ "{\n"
+ "	/* Not used with the garbage collector */\n"
+ "	return 1;\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Pop the node allocation state.\n"
+ " */\n"
+ "void YYNODESTATE::pop()\n"
+ "{\n"
+ "	/* Not used with the garbage collector */\n"
+ "}\n"
+ "\n"
+ "/*\n"
+ " * Clear the node allocation pool completely.\n"
+ " */\n"
+ "void YYNODESTATE::clear()\n"
+ "{\n"
+ "	/* Not used with the garbage collector */\n"
+ "}\n"
+ "\n"
+ "#endif /* YYNODESTATE_USE_ALLOCATOR */\n"
+ "\n"
+ "/*\n"
+ " * Default implementation of functions which may be overridden.\n"
+ " */\n"
+ "void YYNODESTATE::failed()\n"
+ "{\n"
+ "}\n"
+ "\n"
+ "#ifdef YYNODESTATE_TRACK_LINES\n"
+ "\n"
+ "char *YYNODESTATE::currFilename()\n"
+ "{\n"
+ "	return (char *)0;\n"
+ "}\n"
+ "\n"
+ "long YYNODESTATE::currLinenum()\n"
+ "{\n"
+ "	return 0;\n"
+ "}\n"
+ "\n"
+ "#endif\n"
+ ;
+ const char * const TreeCCSkelFiles[] = {
+     "c_skel.c", TreeCCSkel_c_skel_c,
+     "c_skel.h", TreeCCSkel_c_skel_h,
+     "cpp_skel.cc", TreeCCSkel_cpp_skel_cc,
+     "cpp_skel.h", TreeCCSkel_cpp_skel_h,
+     "c_gc_skel.h", TreeCCSkel_c_gc_skel_h,
+     "c_gc_skel.c", TreeCCSkel_c_gc_skel_c,
+     "cpp_gc_skel.h", TreeCCSkel_cpp_gc_skel_h,
+     "cpp_gc_skel.cc", TreeCCSkel_cpp_gc_skel_cc,
+     0
+ };


Index: llvm/test/Programs/MultiSource/Applications/treecc/stream.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/stream.c:1.1
*** /dev/null	Tue Apr  6 12:53:42 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/stream.c	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,682 ----
+ /*
+  * stream.c - Stream handling for writing source code.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #include "system.h"
+ #include "input.h"
+ #include "info.h"
+ #include "errors.h"
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ char *TreeCCDupString(char *str)
+ {
+ 	char *newstr = (char *)malloc(strlen(str) + 1);
+ 	if(!newstr)
+ 	{
+ 		TreeCCOutOfMemory(0);
+ 	}
+ 	strcpy(newstr, str);
+ 	return newstr;
+ }
+ 
+ char *TreeCCResolvePathname(char *absolute, char *relative)
+ {
+ 	int len;
+ 	char *path;
+ 	if(!absolute)
+ 	{
+ 		return TreeCCDupString(relative);
+ 	}
+ 	len = strlen(absolute);
+ 	while(len > 0 && absolute[len - 1] != '/' && absolute[len - 1] != '\\')
+ 	{
+ 		--len;
+ 	}
+ 	if(len <= 0)
+ 	{
+ 		return TreeCCDupString(relative);
+ 	}
+ 	path = (char *)malloc(len + strlen(relative) + 1);
+ 	if(!path)
+ 	{
+ 		TreeCCOutOfMemory(0);
+ 	}
+ 	strncpy(path, absolute, len);
+ 	strcpy(path + len, relative);
+ 	return path;
+ }
+ 
+ TreeCCStream *TreeCCStreamCreate(PTreeCCContext context,
+ 								 char *filename, char *embedName,
+ 								 int isHeader)
+ {
+ 	TreeCCStream *stream;
+ 	char *path;
+ 
+ 	/* Resolve the filename into a path */
+ 	if(isHeader < 0)
+ 	{
+ 		/* Already resolved by TreeCCStreamGetJava */
+ 		isHeader = 0;
+ 		path = TreeCCDupString(filename);
+ 	}
+ 	else
+ 	{
+ 		path = TreeCCResolvePathname(context->input->filename, filename);
+ 	}
+ 
+ 	/* Search for an existing stream for the file */
+ 	stream = context->streamList;
+ 	while(stream != 0)
+ 	{
+ 		if(!strcmp(stream->filename, path))
+ 		{
+ 			free(path);
+ 			return stream;
+ 		}
+ 		stream = stream->nextStream;
+ 	}
+ 
+ 	/* Create a new stream */
+ 	stream = (TreeCCStream *)malloc(sizeof(TreeCCStream));
+ 	if(!stream)
+ 	{
+ 		TreeCCOutOfMemory(0);
+ 	}
+ 	stream->context = context;
+ 	stream->filename = path;
+ 	stream->embedName = (embedName ? TreeCCDupString(embedName) :
+ 									 TreeCCDupString(filename));
+ 	stream->linenum = 1;
+ 	stream->firstBuf = 0;
+ 	stream->lastBuf = 0;
+ 	stream->posn = TREECC_STREAM_BUFSIZ;
+ 	stream->forceCreate = context->force;
+ 	stream->readOnly = 0;
+ 	stream->isHeader = isHeader;
+ 	stream->defaultFile = 0;
+ 	stream->dirty = 0;
+ 	stream->firstDefn = 0;
+ 	stream->lastDefn = 0;
+ 	stream->nextStream = context->streamList;
+ 	context->streamList = stream;
+ 	return stream;
+ }
+ 
+ TreeCCStream *TreeCCStreamGetJava(PTreeCCContext context, char *className)
+ {
+ 	char *filename;
+ 	int len;
+ 	TreeCCStream *stream;
+ 	if(context->outputDirectory)
+ 	{
+ 		len = strlen(context->outputDirectory) + strlen(className) + 7;
+ 		if((filename = (char *)malloc(len)) == 0)
+ 		{
+ 			TreeCCOutOfMemory(context->input);
+ 		}
+ 		strcpy(filename, context->outputDirectory);
+ 		len = strlen(context->outputDirectory);
+ 		filename[len] = '/';
+ 		strcpy(filename + len + 1, className);
+ 		strcat(filename, ".java");
+ 		++len;
+ 	}
+ 	else
+ 	{
+ 		len = strlen(className) + 6;
+ 		if((filename = (char *)malloc(len)) == 0)
+ 		{
+ 			TreeCCOutOfMemory(context->input);
+ 		}
+ 		strcpy(filename, className);
+ 		strcat(filename, ".java");
+ 		len = 0;
+ 	}
+ 	stream = TreeCCStreamCreate(context, filename, filename + len, -1);
+ 	free(filename);
+ 	return stream;
+ }
+ 
+ void TreeCCStreamDestroy(TreeCCStream *stream)
+ {
+ 	TreeCCStreamDefn *defn, *nextDefn;
+ 
+ 	/* Free the data buffers for the stream */
+ 	TreeCCStreamClear(stream);
+ 
+ 	/* Free the definition list for the stream */
+ 	defn = stream->firstDefn;
+ 	while(defn != 0)
+ 	{
+ 		nextDefn = defn->next;
+ 		if(!(defn->refOnly))
+ 		{
+ 			free(defn->code);
+ 		}
+ 		free(defn);
+ 		defn = nextDefn;
+ 	}
+ 
+ 	/* Free the filenames */
+ 	free(stream->filename);
+ 	free(stream->embedName);
+ 
+ 	/* Free the stream itself */
+ 	free(stream);
+ }
+ 
+ void TreeCCStreamClear(TreeCCStream *stream)
+ {
+ 	TreeCCStreamBuf *buffer, *nextBuffer;
+ 	buffer = stream->firstBuf;
+ 	while(buffer != 0)
+ 	{
+ 		nextBuffer = buffer->next;
+ 		free(buffer);
+ 		buffer = nextBuffer;
+ 	}
+ 	stream->firstBuf = 0;
+ 	stream->lastBuf = 0;
+ 	stream->dirty = 0;
+ 	stream->posn = TREECC_STREAM_BUFSIZ;
+ 	stream->linenum = 1;
+ }
+ 
+ /*
+  * Define the "MemCmp" function.
+  */
+ #if HAVE_MEMCMP
+ #define	MemCmp(s1,s2,size)	(memcmp((s1),(s2),(size)))
+ #else
+ static int MemCmp(const char *s1, const char *s2, int size)
+ {
+ 	while(size > 0)
+ 	{
+ 		if(*s1 < *s2)
+ 		{
+ 			return -1;
+ 		}
+ 		else if(*s1 > *s2)
+ 		{
+ 			return 1;
+ 		}
+ 		++s1;
+ 		++s2;
+ 		--size;
+ 	}
+ 	return 0;
+ }
+ #endif
+ 
+ int TreeCCStreamFlush(TreeCCStream *stream)
+ {
+ 	int result;
+ 	FILE *file;
+ 	TreeCCStreamBuf *buffer;
+ 	char tempbuf[TREECC_STREAM_BUFSIZ];
+ 	int size, changed;
+ 
+ 	/* Ignore default streams with no contents */
+ 	if(stream->defaultFile && !(stream->firstBuf))
+ 	{
+ 		return 1;
+ 	}
+ 
+ 	/* Validate that the contents have changed non-trivially */
+ 	if(!(stream->forceCreate) || stream->readOnly)
+ 	{
+ 		if((file = fopen(stream->filename, "r")) != NULL)
+ 		{
+ 			buffer = stream->firstBuf;
+ 			changed = 0;
+ 			while((size = fread(tempbuf, 1, TREECC_STREAM_BUFSIZ, file)) != 0)
+ 			{
+ 				if(!buffer)
+ 				{
+ 					changed = 1;
+ 					break;
+ 				}
+ 				if(buffer == stream->lastBuf)
+ 				{
+ 					if(stream->posn != size)
+ 					{
+ 						changed = 1;
+ 						break;
+ 					}
+ 					if(MemCmp(buffer->data, tempbuf, size) != 0)
+ 					{
+ 						changed = 1;
+ 						break;
+ 					}
+ 				}
+ 				else
+ 				{
+ 					if(size != TREECC_STREAM_BUFSIZ)
+ 					{
+ 						changed = 1;
+ 						break;
+ 					}
+ 					if(MemCmp(buffer->data, tempbuf, TREECC_STREAM_BUFSIZ) != 0)
+ 					{
+ 						changed = 1;
+ 						break;
+ 					}
+ 				}
+ 				buffer = buffer->next;
+ 				if(size < TREECC_STREAM_BUFSIZ)
+ 				{
+ 					size = 0;
+ 					break;
+ 				}
+ 			}
+ 			if(size == 0 && buffer != 0)
+ 			{
+ 				changed = 1;
+ 			}
+ 			fclose(file);
+ 			if(!changed)
+ 			{
+ 				return 1;
+ 			}
+ 		}
+ 		if(stream->readOnly)
+ 		{
+ 			fprintf(stderr, "%s: read-only file has different contents\n",
+ 					stream->filename);
+ 			return 0;
+ 		}
+ 	}
+ 
+ 	/* Open the output file */
+ 	if((file = fopen(stream->filename, "w")) == NULL)
+ 	{
+ 		perror(stream->filename);
+ 		return 0;
+ 	}
+ 
+ 	/* Flush the data to the output file */
+ 	result = TreeCCStreamFlushStdio(stream, file);
+ 
+ 	/* Close the output file */
+ 	fclose(file);
+ 	return result;
+ }
+ 
+ int TreeCCStreamFlushStdio(TreeCCStream *stream, FILE *file)
+ {
+ 	TreeCCStreamBuf *buffer = stream->firstBuf;
+ 	while(buffer != 0)
+ 	{
+ 		if(buffer == stream->lastBuf)
+ 		{
+ 			if(fwrite(buffer->data, 1, stream->posn, file) != stream->posn)
+ 			{
+ 				return 0;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if(fwrite(buffer->data, 1, TREECC_STREAM_BUFSIZ, file) !=
+ 					TREECC_STREAM_BUFSIZ)
+ 			{
+ 				return 0;
+ 			}
+ 		}
+ 		buffer = buffer->next;
+ 	}
+ 	return (fflush(file) == 0);
+ }
+ 
+ /*
+  * Write the contents of a buffer to a stream.
+  */
+ static void WriteBuffer(TreeCCStream *stream, const char *buf)
+ {
+ 	int len = strlen(buf);
+ 	int templen;
+ 	TreeCCStreamBuf *buffer;
+ 	stream->dirty = 1;
+ 	while(len > 0)
+ 	{
+ 		/* Add another buffer to the stream if necessary */
+ 		if(stream->posn >= TREECC_STREAM_BUFSIZ)
+ 		{
+ 			buffer = (TreeCCStreamBuf *)malloc(sizeof(TreeCCStreamBuf));
+ 			if(!buffer)
+ 			{
+ 				TreeCCOutOfMemory(0);
+ 			}
+ 			buffer->next = 0;
+ 			if(stream->lastBuf)
+ 			{
+ 				stream->lastBuf->next = buffer;
+ 			}
+ 			else
+ 			{
+ 				stream->firstBuf = buffer;
+ 			}
+ 			stream->lastBuf = buffer;
+ 			stream->posn = 0;
+ 			templen = TREECC_STREAM_BUFSIZ;
+ 		}
+ 		else
+ 		{
+ 			buffer = stream->lastBuf;
+ 			templen = TREECC_STREAM_BUFSIZ - stream->posn;
+ 		}
+ 
+ 		/* Copy the data to the stream buffer */
+ 		if(templen > len)
+ 		{
+ 			templen = len;
+ 		}
+ 	#if HAVE_MEMCPY
+ 		memcpy(buffer->data + stream->posn, buf, templen);
+ 	#else
+ 		{
+ 			char *s1 = buffer->data + stream->posn;
+ 			const char *s2 = buf;
+ 			int size = templen;
+ 			while(size > 0)
+ 			{
+ 				*s1++ = *s2++;
+ 				--size;
+ 			}
+ 		}
+ 	#endif
+ 
+ 		/* Advance to the next part of the buffer to be written */
+ 		buf += templen;
+ 		len -= templen;
+ 		stream->posn += templen;
+ 	}
+ }
+ 
+ /*
+  * Update the line number position of a stream.
+  */
+ static void UpdateLineNum(TreeCCStream *stream, const char *buf)
+ {
+ #if HAVE_STRCHR
+ 	while((buf = strchr(buf, '\n')) != 0)
+ 	{
+ 		++buf;
+ 		++(stream->linenum);
+ 	}
+ #else
+ 	while(*buf != '\0')
+ 	{
+ 		if(*buf == '\n')
+ 		{
+ 			++(stream->linenum);
+ 		}
+ 		++buf;
+ 	}
+ #endif
+ }
+ 
+ void TreeCCStreamPrint(TreeCCStream *stream, const char *format, ...)
+ {
+ 	char tempbuf[4096];
+ 
+ 	/* Print the formatted data to tempbuf */
+ 	VA_START;
+ #if HAVE_VSNPRINTF
+ 	vsnprintf(tempbuf, sizeof(tempbuf), format, VA_GET_LIST);
+ #elif HAVE__VSNPRINTF
+ 	_vsnprintf(tempbuf, sizeof(tempbuf), format, VA_GET_LIST);
+ #else
+ 	vsprintf(tempbuf, format, VA_GET_LIST);
+ #endif
+ 	VA_END;
+ 
+ 	/* Write the contents of "tempbuf" to the stream */
+ 	WriteBuffer(stream, tempbuf);
+ 
+ 	/* Count newlines in the buffer to update the line number */
+ 	UpdateLineNum(stream, tempbuf);
+ }
+ 
+ void TreeCCStreamCode(TreeCCStream *stream, char *code)
+ {
+ 	WriteBuffer(stream, code);
+ 	UpdateLineNum(stream, code);
+ }
+ 
+ /*
+  * Put a single character to a stream buffer.
+  */
+ static void _StreamPut(int ch, TreeCCStream *stream)
+ {
+ 	char buf[2];
+ 	buf[0] = (char)ch;
+ 	buf[1] = '\0';
+ 	WriteBuffer(stream, buf);
+ }
+ #define	StreamPut(ch,stream)	\
+ 	do { \
+ 		if((stream)->posn < TREECC_STREAM_BUFSIZ) \
+ 		{ \
+ 			(stream)->lastBuf->data[((stream)->posn)++] = (ch); \
+ 			(stream)->dirty = 1; \
+ 		} \
+ 		else \
+ 		{ \
+ 			_StreamPut((ch), (stream)); \
+ 		} \
+ 	} while (0)
+ 
+ void TreeCCStreamCodeIndent(TreeCCStream *stream, char *code, int indent)
+ {
+ 	int temp;
+ 	while(*code != '\0')
+ 	{
+ 		StreamPut(*code, stream);
+ 		if(*code == '\n')
+ 		{
+ 			++(stream->linenum);
+ 			for(temp = 0; temp < indent; ++temp)
+ 			{
+ 				StreamPut('\t', stream);
+ 			}
+ 		}
+ 		++code;
+ 	}
+ }
+ 
+ void TreeCCStreamCodeIndentCustom(TreeCCStream *stream, char *code, 
+ 								  char indentchar, int indent)
+ {
+ 	int temp;
+ 	while(*code != '\0')
+ 	{
+ 		StreamPut(*code, stream);
+ 		if(*code == '\n')
+ 		{
+ 			++(stream->linenum);
+ 			for(temp = 0; temp < indent; ++temp)
+ 			{
+ 				StreamPut(indentchar, stream);
+ 			}
+ 		}
+ 		++code;
+ 	}
+ }
+ 
+ 
+ void TreeCCStreamFixLine(TreeCCStream *stream)
+ {
+ 	TreeCCStreamLine(stream, stream->linenum + 1, stream->embedName);
+ }
+ 
+ void TreeCCStreamAddLiteral(TreeCCStream *stream, char *code,
+ 							char *filename, long linenum,
+ 							int atEnd, int refOnly)
+ {
+ 	TreeCCStreamDefn *defn;
+ 
+ 	/* Bail out if the stream is NULL (can happen in "test_parse" sometimes) */
+ 	if(!stream)
+ 	{
+ 		return;
+ 	}
+ 
+ 	/* Allocate space for a definition block */
+ 	defn = (TreeCCStreamDefn *)malloc(sizeof(TreeCCStreamDefn));
+ 	if(!defn)
+ 	{
+ 		TreeCCOutOfMemory(0);
+ 	}
+ 
+ 	/* Initialize the definition block */
+ 	defn->code = code;
+ 	defn->filename = filename;
+ 	defn->linenum = linenum;
+ 	defn->atEnd = atEnd;
+ 	defn->refOnly = refOnly;
+ 	defn->next = 0;
+ 
+ 	/* Add the definition block to the stream's definition list */
+ 	if(stream->lastDefn)
+ 	{
+ 		stream->lastDefn->next = defn;
+ 	}
+ 	else
+ 	{
+ 		stream->firstDefn = defn;
+ 	}
+ 	stream->lastDefn = defn;
+ }
+ 
+ /*
+  * Output a macro name that has been generated from a filename.
+  */
+ static void OutputMacroName(TreeCCStream *stream, const char *filename)
+ {
+ 	while(*filename != '\0')
+ 	{
+ 		if((*filename >= 'A' && *filename <= 'Z') ||
+ 		   (*filename >= 'a' && *filename <= 'z') ||
+ 		   (*filename >= '0' && *filename <= '9'))
+ 		{
+ 			StreamPut(*filename, stream);
+ 		}
+ 		else
+ 		{
+ 			StreamPut('_', stream);
+ 		}
+ 		++filename;
+ 	}
+ 	StreamPut('\n', stream);
+ 	++(stream->linenum);
+ }
+ 
+ /*
+  * Output a list of definitions to a header or source stream.
+  */
+ static void OutputDefns(TreeCCStream *stream, int atEnd)
+ {
+ 	TreeCCStreamDefn *defn = stream->firstDefn;
+ 	int sawDefn = 0;
+ 	while(defn != 0)
+ 	{
+ 		if(defn->atEnd == atEnd)
+ 		{
+ 			TreeCCStreamLine(stream, defn->linenum, defn->filename);
+ 			WriteBuffer(stream, defn->code);
+ 			UpdateLineNum(stream, defn->code);
+ 			if(*(defn->code) != '\0' &&
+ 			   defn->code[strlen(defn->code) - 1] != '\n')
+ 			{
+ 				/* Terminate the final line */
+ 				StreamPut('\n', stream);
+ 				++(stream->linenum);
+ 			}
+ 			sawDefn = 1;
+ 		}
+ 		defn = defn->next;
+ 	}
+ 	if(sawDefn)
+ 	{
+ 		TreeCCStreamFixLine(stream);
+ 	}
+ }
+ 
+ void TreeCCStreamHeaderTop(TreeCCStream *stream)
+ {
+ 	char *filename = stream->embedName;
+ 	TreeCCStreamPrint(stream,
+ 			"/* %s.  Generated automatically by treecc */\n", filename);
+ 	TreeCCStreamPrint(stream, "#ifndef __%s_", stream->context->yy_replacement);
+ 	OutputMacroName(stream, filename);
+ 	TreeCCStreamPrint(stream, "#define __%s_", stream->context->yy_replacement);
+ 	OutputMacroName(stream, filename);
+ 	OutputDefns(stream, 0);
+ }
+ 
+ void TreeCCStreamHeaderBottom(TreeCCStream *stream)
+ {
+ 	OutputDefns(stream, 1);
+ 	TreeCCStreamPrint(stream, "#endif\n");
+ }
+ 
+ void TreeCCStreamSourceTop(TreeCCStream *stream)
+ {
+ 	TreeCCStreamPrint(stream, "/* %s.  Generated automatically by treecc */\n",
+ 					  stream->embedName);
+ 	OutputDefns(stream, 0);
+ }
+ 
+ void TreeCCStreamSourceTopCS(TreeCCStream *stream)
+ {
+ 	OutputDefns(stream, 0);
+ }
+ 
+ void TreeCCStreamSourceBottom(TreeCCStream *stream)
+ {
+ 	OutputDefns(stream, 1);
+ }
+ 
+ void TreeCCStreamLine(TreeCCStream *stream, long linenum,
+ 					  const char *filename)
+ {
+ 	if(stream->context->print_lines)
+ 	{
+ 		int len;
+ 		if(stream->context->strip_filenames)
+ 		{
+ 			len = strlen(filename);
+ 			while(len > 0 && filename[len - 1] != '/' &&
+ 				  filename[len - 1] != '\\')
+ 			{
+ 				--len;
+ 			}
+ 			filename += len;
+ 		}
+ 		TreeCCStreamPrint(stream, "#line %ld \"%s\"\n", linenum, filename);
+ 	}
+ }
+ 
+ #ifdef	__cplusplus
+ };
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/treecc/stream.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/stream.h:1.1
*** /dev/null	Tue Apr  6 12:53:42 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/stream.h	Tue Apr  6 12:53:30 2004
***************
*** 0 ****
--- 1,204 ----
+ /*
+  * stream.h - Stream handling for writing source code.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_STREAM_H
+ #define	_TREECC_STREAM_H
+ 
+ #ifdef	__cplusplus
+ extern	"C" {
+ #endif
+ 
+ /*
+  * Stream buffer.
+  */
+ #define	TREECC_STREAM_BUFSIZ	2048
+ typedef struct _tagTreeCCStreamBuf
+ {
+ 	char	data[TREECC_STREAM_BUFSIZ];
+ 	struct _tagTreeCCStreamBuf *next;
+ 
+ } TreeCCStreamBuf;
+ 
+ /*
+  * Stream literal code definition.
+  */
+ typedef struct _tagTreeCCStreamDefn
+ {
+ 	char *code;
+ 	char *filename;
+ 	long  linenum;
+ 	int   atEnd;
+ 	int   refOnly;
+ 	struct _tagTreeCCStreamDefn *next;
+ 
+ } TreeCCStreamDefn;
+ 
+ /*
+  * Structure of a stream.
+  */
+ typedef struct _tagTreeCCStream TreeCCStream;
+ typedef struct _tagTreeCCContext *PTreeCCContext;
+ struct _tagTreeCCStream
+ {
+ 	PTreeCCContext	  context;		/* Context that owns the stream */
+ 	char		     *filename;		/* Name of the file we are writing */
+ 	char		     *embedName;	/* Name of the file to embed in source */
+ 	long			  linenum;		/* Line number we are currently on */
+ 	TreeCCStreamBuf  *firstBuf;		/* First buffer attached to the stream */
+ 	TreeCCStreamBuf  *lastBuf;		/* Last buffer attached to the stream */
+ 	int				  posn;			/* Position within the last buffer */
+ 	int				  forceCreate : 1; /* Force creation of the file */
+ 	int				  readOnly : 1;	/* File is read-only */
+ 	int				  isHeader : 1;	/* File is a header */
+ 	int				  defaultFile : 1; /* File is a discardable default */
+ 	int				  dirty : 1;	/* Something useful has been written */
+ 	TreeCCStreamDefn *firstDefn;	/* First definition for the stream */
+ 	TreeCCStreamDefn *lastDefn;		/* Last definition for the stream */
+ 	TreeCCStream     *nextStream;	/* Next stream associated with context */
+ 
+ };
+ 
+ /*
+  * Duplicate a string into the heap.
+  */
+ char *TreeCCDupString(char *str);
+ 
+ /*
+  * Resolve a pathname.  The return value is malloc'ed.
+  */
+ char *TreeCCResolvePathname(char *absolute, char *relative);
+ 
+ /*
+  * Create an output stream.
+  */
+ TreeCCStream *TreeCCStreamCreate(PTreeCCContext context,
+ 								 char *filename, char *embedName,
+ 								 int isHeader);
+ 
+ /*
+  * Get the stream that corresponds to a Java class.
+  */
+ TreeCCStream *TreeCCStreamGetJava(PTreeCCContext context, char *className);
+ 
+ /*
+  * Destroy an output stream.
+  */
+ void TreeCCStreamDestroy(TreeCCStream *stream);
+ 
+ /*
+  * Clear the contents of a stream.
+  */
+ void TreeCCStreamClear(TreeCCStream *stream);
+ 
+ /*
+  * Flush the contents of a stream to the underlying file.
+  * Returns zero if an error occurred during writing.
+  */
+ int TreeCCStreamFlush(TreeCCStream *stream);
+ 
+ /*
+  * Flush the contents of a stream to a specific stdio file.
+  */
+ int TreeCCStreamFlushStdio(TreeCCStream *stream, FILE *file);
+ 
+ /*
+  * If we are using GCC, then make it perform some extra
+  * error checking for printf-style formats.
+  */
+ #ifdef __GNUC__
+ 	#define	TREECC_PRNFMT(n,m)	\
+      	__attribute__ ((__format__ (__printf__, n, m)))
+ #else
+ 	#define	TREECC_PRNFMT(n,m)
+ #endif
+ 
+ /*
+  * Print formatted data to a stream.
+  */
+ void TreeCCStreamPrint(TreeCCStream *stream, const char *format, ...)
+ 			TREECC_PRNFMT(2, 3);
+ 
+ /*
+  * Output a block of literal code to a stream.
+  */
+ void TreeCCStreamCode(TreeCCStream *stream, char *code);
+ 
+ /*
+  * Output a block of literal code to a stream which is indented.
+  * The first line is not indented.
+  */
+ void TreeCCStreamCodeIndent(TreeCCStream *stream, char *code, int indent);
+ 
+ /*
+  * Output a block of literal code to a stream which is indented.
+  * The first line is not indented. This version supports custom indent chars.
+  */
+ void TreeCCStreamCodeIndentCustom(TreeCCStream *stream, char *code, 
+ 								 char indentchar, int indent);
+ 
+ /*
+  * Fix the line number information in the output stream
+  * after outputting a block of code.
+  */
+ void TreeCCStreamFixLine(TreeCCStream *stream);
+ 
+ /*
+  * Add a literal definition block to a stream.
+  */
+ void TreeCCStreamAddLiteral(TreeCCStream *stream, char *code,
+ 							char *filename, long linenum,
+ 							int atEnd, int refOnly);
+ 
+ /*
+  * Output extra information that is needed at the top of a header file.
+  */
+ void TreeCCStreamHeaderTop(TreeCCStream *stream);
+ 
+ /*
+  * Output extra information that is needed at the bottom of a header file.
+  */
+ void TreeCCStreamHeaderBottom(TreeCCStream *stream);
+ 
+ /*
+  * Output extra information that is needed at the top of a source file.
+  */
+ void TreeCCStreamSourceTop(TreeCCStream *stream);
+ 
+ /*
+  * Output extra information that is needed at the top of a source file for C#.
+  */
+ void TreeCCStreamSourceTopCS(TreeCCStream *stream);
+ 
+ /*
+  * Output extra information that is needed at the bottom of a source file.
+  */
+ void TreeCCStreamSourceBottom(TreeCCStream *stream);
+ 
+ /*
+  * Print a "#line" directive to an output stream.
+  */
+ void TreeCCStreamLine(TreeCCStream *stream, long linenum,
+ 					  const char *filename);
+ 
+ #ifdef	__cplusplus
+ };
+ #endif
+ 
+ #endif	/* _TREECC_STREAM_H */


Index: llvm/test/Programs/MultiSource/Applications/treecc/system.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/system.h:1.1
*** /dev/null	Tue Apr  6 12:53:42 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/system.h	Tue Apr  6 12:53:31 2004
***************
*** 0 ****
--- 1,65 ----
+ /*
+  * system.h - Import useful functions from the system libraries.
+  *
+  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+  *
+  * 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
+  */
+ 
+ #ifndef	_TREECC_SYSTEM_H
+ #define	_TREECC_SYSTEM_H
+ 
+ #include "config.h"
+ 
+ /*
+  * Standard C headers.
+  */
+ #include <stdio.h>
+ #if HAVE_STDLIB_H
+ 	#include <stdlib.h>
+ #endif
+ #if HAVE_STRING_H
+ 	#include <string.h>
+ #else
+ 	#if HAVE_STRINGS_H
+ 		#include <strings.h>
+ 	#endif
+ #endif
+ 
+ /*
+  * Handle varargs.
+  */
+ #ifdef HAVE_STDARG_H
+ #include <stdarg.h>
+ #define	VA_LIST				va_list
+ #define	VA_START			va_list va; va_start(va, format)
+ #define	VA_END				va_end(va)
+ #define	VA_GET_LIST			va
+ #else
+ #ifdef HAVE_VARARGS_H
+ #include <varargs.h>
+ #define	VA_LIST				va_list
+ #define	VA_START			va_list va; va_start(va)
+ #define	VA_END				va_end(va)
+ #define	VA_GET_LIST			va
+ #else
+ #define	VA_LIST				int
+ #define	VA_START
+ #define	VA_END
+ #define	VA_GET_LIST			0
+ #endif
+ #endif
+ 
+ #endif	/* _TREECC_SYSTEM_H */





More information about the llvm-commits mailing list