This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Treelang patch - penultimate version


I have had some more feedback suggestions which I have largely implemented. See below and the attached
new patch. Thank you for the feedback.

I am concerned however that I am never going to get finality on this. I seem to be on a treadmill here,
and I can see no end in sight. Can somone offer me a roadmap or some indication as to how I can have some
reassurance that my efforts are going to result in something happening in some finite period of time?

If anyone has any issues with this patch which they consider show-stoppers, please raise them /now/.

Tim Josling

"Joseph S. Myers" wrote:

> On Sat, 28 Jul 2001, Tim Josling wrote:
> However
> > I have attached a patch file for implementing 'treelang'. Treelang is a
> > sample language front end for gcc, available for people to use as a
> > working example of writing a gcc language, complete with makefiles,
> > specs, documentation and all the code.
>
> > + $(srcdir)/treelang/treelang.info: $(srcdir)/treelang/treelang.texi
> > +       cd $(srcdir)/treelang && $(MAKEINFO) $(MAKEINFOFLAGS)  -I.. -I../doc/include \
>
> Why -I.. ?

Removed

>
>
> > + treelang.dvi: $(srcdir)/treelang/treelang.texi
> > +       TEXINPUTS=$(srcdir)/treelang:$(srcdir):$$TEXINPUTS tex $(srcdir)/treelang/treelang.texi; \
> > +         texindex treelang.??; \
> > +         TEXINPUTS=$(srcdir)/treelang:$(srcdir):$$TEXINPUTS tex $(srcdir)/treelang/treelang.texi; \
> > +         mv treelang.dvi treelang;
>
> Use $(TEXI2DVI) instead.
>

Done

>
> > + @node Copying
> > + @unnumbered GNU GENERAL PUBLIC LICENSE
> > + @center Version 2, June 1991
>
> You should now be using the common gpl.texi file.
>

Done

>
> > + @node Funding
> > + @chapter Funding Free Software
>
> You should now be using the common funding.texi file.
>

Done

>
> > + @node Look and Feel, Getting Started, Funding GNU Treelang, Top
> > + @chapter Protect Your Freedom---Fight ``Look And Feel''
>
> This chapter (copied from the Fortran manual) no longer belongs here - the
> section of the GCC manual it links to was removed in a gcc2 merge some
> time ago.
>

Removed

>
> > + @summarycontents
> > + @contents
> > + @bye
>
> Contents should be at the front of the manual, not the back.
>

According to the texinfo manual, there are arguments for putting at the front or at the back. Left as is.

>
> > --- newgcc/gcc/treelang/root.texi       Sat Jun  2 18:16:41 2001
>
> I think you've just volunteered to fix the problem that update_web_docs
> assumes there to be at most one .texi file with a given name in the source
> tree at any one time :-).  (Remember when fixing it that it still needs to
> work with 2.95.x and 3.0, so needs to handle various different .texi file
> arrangements in the source tree - and that when using a sufficiently
> recent source tree that has gcc/doc/include, no unnecessary -I options
> pointing to gcc/ or gcc/doc should be used for files in other
> directories.)
>

Good try. Removed root.texi.

>
> --
> Joseph S. Myers
> jsm28@cam.ac.uk

> On 28-Jul-2001, Tim Josling  wrote:
> > + @cindex GNU Back End (GBE)
> > + @cindex GBE
> > + @cindex @code{gcc}, back end
> > + @cindex back end, gcc
> > + @cindex code generator
> > + One chunk is the so-called @dfn{GNU Back End}, or GBE,
> > + which knows how to generate fast code for a wide variety of processors.
> > + The same GBE is used by the C, C++, and Treelang compiler programs @code{cc1},
> > + @code{cc1plus}, and @code{tree1}, plus others.
> > + Often the GBE is referred to as the ``gcc back end'' or
>
> I suggest s/gcc/GCC/
>

Done, selectively so that the file names etc are not messed up.

>
> > + even just ``gcc''---in this manual, the term GBE is used
> > + whenever the distinction is important.
>
> Likewise here.
>
Done.

>
> > + @cindex GNU Treelang Front End (FFE)
>
> FFE?  Where did that abbreviation come from?
> Wouldn't that be the Fortran Front End?
>
> I suggest s/FFE/TFE/ here and in several places below.
>
Done.

>
> > + @node Interoperating with C and C++,  , Other Languages, Other Languages
> > + @section Tools and advice for interoperating with C and C++
> > +
> > + The output of treelang programs looks like c program code to the linker
> > + and everybody else, so you should be able to freely mix treelang and C
> > + (and C++) code.
>
> Does treelang promote function argument types and return types to `int'?
> I found that was needed for binary compatibility with C when writing
> the Mercury GCC front-end.
>
In treelang every argument has to match exactly so this is not an issue in treelang.

>
> > + Makefile in turn is the main instruction to actually build
> > + everything. The build instructions are held in the main gcc manual and
> > + web site so they are not repeated here.
>
> s/gcc/GCC/, I think.
>
Done.

>
> > + @cindex lang-options
> > + @item
> > + lang-options. This file is included into gcc.c, the main gcc driver, and
>
> s/gcc driver/GCC driver/
>
Done.

>
> > + @item
> > + lexer. This breaks the input into words and passes these to the
> > + parser. This is lex.l in treelang, which is passed through flex, a lex
> > + variant, to produce c code lex.c.
>
> s/c code/C code/
>
Done.

>
> > + Note there is a school of thought that
> > + says real men hand code their own lexers, however you may prefer to
>
> s/men/programmers/
>
No, unless you can find an example of a female who has done this. This is an illusion to the book 'Real
men don't eat quiche'.

>
> > + @item
> > + parser. This breaks the program into recognizable constructs such as
> > + exprerssions, statemente etc. This is parse.y in treelang, which is
>
> Fix typos: "expressions, statements, etc. This ...".
>
Done.

>
> > + @item
> > + compiler main file. gcc comes with a program toplev.c which is a
> > + perfectly serviceable main program for your compiler. treelang uses
> > + toplev.c but other languages have been known to replace it with their
> > + own main program. Again this is a matter of taste and how much code you
> > + want to write.
>
> Is this really true?
> Which other languages replaced toplev.c??
> Duplicating the code in toplev.c sounds like a maintenance headache.
>
I believe that ADA did their own thing. But they are real men^D^D^Dprogrammers; they even hand coded
their own parser.

>
> Did you mean main.c?
>
> > + The driver (gcc.c) will then drive (exec) in turn a preprocessor, the main
> > + compiler, the assembler and the link editor. gcc options allow you to
>
> s/gcc options/Options to gcc/
>
Done.

>
> > + override all of this. In the case of treelang programs there is no
> > + preprocessor, and mostly these days the C preprocessor is run within the
> > + main C compiler apparently for reasons of speed.
>
> I suggest inserting "rather than as a separate process, "
> before "apparently".
>
Done.

>
> > + @node treelang main compiler,  , treelang driver, treelang compiler interfaces
> > + @subsection treelang main compiler
> > +
> > + The main compiler for treelang consists of toplev.c from the main GCC
> > + compiler, the parser, lexer and back end interface routines, and the
> > + back end routines themselves, of which there are many.
> > +
> > + toplev.c does a lot of work for you and you shoudl seriously consider
> > + whether you want to reinvent it. It is quite possible to reuse it, as in
> > + the case of treelang.
> > +
> > + Writing this code is the hard part of creating a compiler using GCC. The
> > + back end interface documentation is incomplete and the interface is
> > + complex.
>
> Even if it is technically possible to replace toplev.c,
> I'm not sure if we should mention that in this manual.
>
I have toned this down, but the fact some people have done it makes it worth discussing IMHO.

>
> > + @node Interfacing to the garbage collection, Interfacing to the code generation code. ,
> Interfacing to toplev.c, treelang main compiler
> > + @subsubsection Interfacing to the garbage collection
>
> It might be worth mentioning lang_mark_tree somewhere in this section.
>
I think this is getting out of scope (see at the top).

>
> > + Interfacing to the garbage collection. In treelang this is mainly in
> > + tree1.c.
> > +
> > + Memory allocation in the compiler should be done using the ggc_alloc and
> > + kindred routines in ggc*.*. At the end of every function, toplev.c calls
> > + the garbage collection several times. The garbage collection calls mark
> > + routines which go through the memory which is still used, telling the
> > + garbage collection not to free it. Then all the memory not used is
> > + freed.
>
> "at the end of every function" is a bit ambiguous,
> e.g. this could be interpreted as referring to functions in toplev.c.
>
Made it clearer.

>
> This section should have a pointer to the documentation in
>
I think this is getting beyond scope also.

>
> > + @item
> > + GDB: the GCC back end works well with gdb. It traps abort() and allows
> > + you to trace back what went wrong.
>
> It's probably worth mentioning that
>
>         Some gdb macro commands that are useful for debugging GCC,
>         e.g. commands to display the values of GCC tree nodes,
>         are defined in gdbinit.in (which is sourced by the .gdbinit
>         file in the gcc directory).
>
Good idea also but I plead scope again.

>
> > + @node Projects, Index, Service, Top
> > + @chapter Projects
> > + @cindex projects
> > +
> > + If you want to contribute to @code{treelang} by doing research,
> > + design, specification, documentation, coding, or testing,
> > + the following information should give you some ideas.
> > +
> > + Send a message to @email{@value{email-general}} if you plan to add a
> > + feature.
> > +
> > + The main requirement for treelang is to add features and to add
> > + documentation. Features are things that the GCC back end can do but
> > + which are not reflected in treelang. Examples include structures,
> > + unions, pointers, arrays.
>
> Also nested functions and exception handling.
>
True but these are examples not an exhaustive list.

>
> > --- newgcc/gcc/treelang/treetree.c    Sat Jul 28 12:41:52 2001
> > + tree
> > + tree_code_create_function_prototype (unsigned char* chars,
> ...
> > +   if (lineno > 1000000)
> > +     ; /* Probably the line # is rubbish because someone forgot to set
> > +     the line number - and unfortunately impossible line #s are used as
> > +     magic flags at various times. The longest known COBOL program for
> > +     example is about 550,000 lines.  */
> > +   DECL_SOURCE_LINE (fn_decl) = lineno;
>
> That looks like it is COBOL-specific.
>
Reworded to make it clean the COBOL is only an example. If anyone if aware of a single function in any
language longer than 500,000 lines, please let me know.

>
> > +   TREE_PUBLIC (fn_decl) = 0;
> > +   DECL_EXTERNAL (fn_decl) = 0;
> > +   TREE_STATIC (fn_decl) = 0;
> > +   switch (storage_class)
> > +     {
> > +     case STATIC_STORAGE:
> > +       TREE_PUBLIC (fn_decl) = 0;
> > +       break;
>
> Do you really want to set TREE_PUBLIC (func_decl) = 0 twice?
> IMHO that's just confusing.
>
This is just a habit for avoiding variable not assigned messages. I am leaving it as is.

>
> > + tree
> > + tree_code_create_variable (unsigned int storage_class,
> > +                                unsigned char* chars,
> > +                                unsigned int length,
> > +                                unsigned int expression_type,
> > +                                tree init,
> > +                                unsigned char* filename,
> > +                                int lineno)
> > + {
> ...
> > +     case EXTERNAL_REFERENCE_STORAGE:
> > +       DECL_EXTERNAL (var_decl) = 1;
> > +       break;
>
> You also need to set TREE_PUBLIC (var_decl) = 1 here, otherwise you will run
> into problems (on at least on x86-linux) when compiling with `-fpic'.
> I found out the hard way ;-)
>
I did not make the change but I put in a comment saying maybe we should do this, until I can verify this.

>
> > + /* Return a tree for a constant integer value in the token TOK.  No
> > +    size checking is done.  */
> > +
> > + tree
> > + tree_code_get_integer_value (unsigned char* chars, unsigned int length)
> > + {
> > +   long long int val = 0;
>
> That's not portable ISO C89.  You should put a comment here or at least somewhere
> in the treelang source explaining why it is OK to use GCC extensions in this file.
>
Done

>
> > + void
> > + init_decl_processing ()
> > + {
> ...
> > +   /* Set standard type names.  */
> > +
> > +   ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
> > +   ggc_add_tree_root (ridpointers, RID_MAX);
> > +
> > +   ridpointers[ (int) RID_INT] = get_identifier ("int");
> > +   ridpointers[ (int) RID_CHAR] = get_identifier ("char");
> > +   ridpointers[ (int) RID_VOID] = get_identifier ("void");
> > +   ridpointers[ (int) RID_FLOAT] = get_identifier ("float");
> > +   ridpointers[ (int) RID_DOUBLE] = get_identifier ("double");
> > +   ridpointers[ (int) RID_SHORT] = get_identifier ("short");
> > +   ridpointers[ (int) RID_LONG] = get_identifier ("long");
> > +   ridpointers[ (int) RID_UNSIGNED] = get_identifier ("unsigned");
> > +   ridpointers[ (int) RID_SIGNED] = get_identifier ("signed");
> > +   ridpointers[ (int) RID_INLINE] = get_identifier ("inline");
> > +   ridpointers[ (int) RID_CONST] = get_identifier ("const");
> > +   ridpointers[ (int) RID_RESTRICT] = get_identifier ("restrict");
> > +   ridpointers[ (int) RID_VOLATILE] = get_identifier ("volatile");
> > +   ridpointers[ (int) RID_BOUNDED] = get_identifier ("__bounded");
> > +   ridpointers[ (int) RID_UNBOUNDED] = get_identifier ("__unbounded");
> > +   ridpointers[ (int) RID_AUTO] = get_identifier ("auto");
> > +   ridpointers[ (int) RID_STATIC] = get_identifier ("static");
> > +   ridpointers[ (int) RID_EXTERN] = get_identifier ("extern");
> > +   ridpointers[ (int) RID_TYPEDEF] = get_identifier ("typedef");
> > +   ridpointers[ (int) RID_REGISTER] = get_identifier ("register");
> > +   /*  ridpointers[ (int) RID_ITERATOR] = get_identifier ("iterator"); */
> > +   ridpointers[ (int) RID_COMPLEX] = get_identifier ("complex");
> > +   ridpointers[ (int) RID_ID] = get_identifier ("id");
> > +   ridpointers[ (int) RID_IN] = get_identifier ("in");
> > +   ridpointers[ (int) RID_OUT] = get_identifier ("out");
> > +   ridpointers[ (int) RID_INOUT] = get_identifier ("inout");
> > +   ridpointers[ (int) RID_BYCOPY] = get_identifier ("bycopy");
> > +   ridpointers[ (int) RID_BYREF] = get_identifier ("byref");
> > +   ridpointers[ (int) RID_ONEWAY] = get_identifier ("oneway");
>
> Is that code needed?  If so, why?
>
I am not certain it is needed. There is a fair bit of the code later on in treetree.c that I do not fully
understand. I do not have the time to go through it all and make sure that it is all needed, and that it
is all totally kosher. Hopefully we can gradually improve the function and quality over time.

>
> > --- newgcc/gcc/treelang/treetree.h    Mon Jun 11 08:45:27 2001
> > + /* Storage modes.  */
> > + #define STATIC_STORAGE 0
> > + #define AUTOMATIC_STORAGE 1
> > + #define EXTERNAL_REFERENCE_STORAGE 2
> > + #define EXTERNAL_DEFINITION_STORAGE 3
>
> Why use #define rather than enum?
>
I agree it probably would be better but in the past I have had resistence from the gcc community to
enums. Left as is.

>
> > + #define SIGNED_CHAR 1
> > + #define UNSIGNED_CHAR 2
> > + #define SIGNED_INT 3
> > + #define UNSIGNED_INT 4
> > + #define VOID_TYPE 5
> > +
> > +
> > + #define EXP_PLUS 0 /* Addition expression.  */
> > + #define EXP_REFERENCE 1 /* Variable reference.  */
> > + #define EXP_ASSIGN 2 /* Assignment.  */
> > + #define EXP_FUNCTION_INVOCATION 3  /* Call function.  */
> > + #define EXP_MINUS 4  /* Subtraction.  */
> > + #define EXP_EQUALS 5  /* Equality test.  */
>
> Likewise.
>
> --
> Fergus Henderson   |  "I have always known that the pursuit
> The University of Melbourne         |  of excellence is a lethal habit"
> WWW:   |     -- the last words of T. S. Garp.
>
>


diff -c3prN gcccvs/gcc/gcc/testsuite/lib/treelang.exp newgcc/gcc/testsuite/lib/treelang.exp
*** gcccvs/gcc/gcc/testsuite/lib/treelang.exp	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/testsuite/lib/treelang.exp	Sun Jun 10 19:02:46 2001
***************
*** 0 ****
--- 1,19 ----
+ # Copyright (C) 1988, 90, 91, 92, 95, 96, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+ # 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+ # Having this file here magically tells dejagnu that the treelang directory is worthy of testing
+ 
+ 
diff -c3prN gcccvs/gcc/gcc/testsuite/treelang/ChangeLog newgcc/gcc/testsuite/treelang/ChangeLog
*** gcccvs/gcc/gcc/testsuite/treelang/ChangeLog	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/testsuite/treelang/ChangeLog	Mon Jun 11 08:56:24 2001
***************
*** 0 ****
--- 1,10 ----
+ 2001-06-11  Tim Josling  <tej@melbpc.org.au>
+ 
+ 	* treelang.exp (global) remove COBOL specific code. 
+ 
+ 2001-05-24  Tim Josling  <tej@melbpc.org.au>
+ 
+         Created this directory and its tests. All derived from the cobol
+ 	test swamp which was also all written by me.
+ 	
+ 
diff -c3prN gcccvs/gcc/gcc/testsuite/treelang/Makefile.in newgcc/gcc/testsuite/treelang/Makefile.in
*** gcccvs/gcc/gcc/testsuite/treelang/Makefile.in	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/testsuite/treelang/Makefile.in	Sat May 26 12:27:11 2001
***************
*** 0 ****
--- 1,9 ----
+ # Copyright (C) 2001 Free Software Foundation, Inc.
+ 
+ all: 
+ 
+ clean:
+ 	-rm -f *.o *.diff *~ *.bad core *.x
+ 
+ distclean:	clean
+ 	-rm -f Makefile config.status
diff -c3prN gcccvs/gcc/gcc/testsuite/treelang/a01gcci01.c newgcc/gcc/testsuite/treelang/a01gcci01.c
*** gcccvs/gcc/gcc/testsuite/treelang/a01gcci01.c	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/testsuite/treelang/a01gcci01.c	Sat Jun  2 11:31:18 2001
***************
*** 0 ****
--- 1,19 ----
+ /* Driver for treelang test pgm */
+ 
+ int add(int, int);
+ int subtract(int, int);
+ int first_nonzero(int, int);
+ 
+ int 
+ main (int argc, char* argv[])
+ {
+   printf("2:%d\n", add(1,1));
+   printf("7:%d\n", add(3,4));
+   printf("-1:%d\n", subtract(3,4));
+   printf("1:%d\n", subtract(2,1));
+   printf("3:%d\n", first_nonzero(0,3));
+   printf("0:%d\n", first_nonzero(0,0));
+   printf("1:%d\n", first_nonzero(1,0));
+   printf("15:%d\n", double_plus_one(7));
+   return 0;
+ }
diff -c3prN gcccvs/gcc/gcc/testsuite/treelang/a01gcci01.tree newgcc/gcc/testsuite/treelang/a01gcci01.tree
*** gcccvs/gcc/gcc/testsuite/treelang/a01gcci01.tree	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/testsuite/treelang/a01gcci01.tree	Sat Jun  2 13:39:27 2001
***************
*** 0 ****
--- 1,39 ----
+ // -*- c -*- c mode in emacs
+ 
+ external_definition int add(int arg1, int arg2);
+ external_definition int subtract(int arg3, int arg4);
+ external_definition int first_nonzero(int arg5, int arg6);
+ external_definition int double_plus_one(int arg7);
+ 
+ add 
+ {
+   return arg1 + arg2;
+ }
+ 
+         
+ subtract 
+ {
+   return arg3 - arg4;
+ }
+ 
+ double_plus_one
+ {
+   automatic int aaa;
+   aaa=add(arg7, arg7);
+   aaa=add(aaa, aaa);
+   aaa=subtract(subtract(aaa, arg7), arg7) + 1;
+   return aaa;
+ }
+ 
+ first_nonzero
+ {
+   if (arg5)
+     {
+       return arg5;
+     }
+   else
+     {
+     }
+   return arg6;
+ }
+ 
diff -c3prN gcccvs/gcc/gcc/testsuite/treelang/a01gcco01runpgm newgcc/gcc/testsuite/treelang/a01gcco01runpgm
*** gcccvs/gcc/gcc/testsuite/treelang/a01gcco01runpgm	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/testsuite/treelang/a01gcco01runpgm	Sat Jun  2 12:33:38 2001
***************
*** 0 ****
--- 1,8 ----
+ 2:2
+ 7:7
+ -1:-1
+ 1:1
+ 3:3
+ 0:0
+ 1:1
+ 15:15
diff -c3prN gcccvs/gcc/gcc/testsuite/treelang/treetests.exp newgcc/gcc/testsuite/treelang/treetests.exp
*** gcccvs/gcc/gcc/testsuite/treelang/treetests.exp	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/testsuite/treelang/treetests.exp	Sun Jun 10 17:39:12 2001
***************
*** 0 ****
--- 1,285 ----
+ 
+ # Tests for treelang; run from gcc/treelang/Make-lang.in => gcc/Makefile
+ 
+ # Copyright (C) 1999, 2000, 2001 by The Free Software Foundation
+ 
+ # find ttt for the actual tests
+ 
+ # Check the pgm is even there and set up the basics
+ proc init_utility {pgm} {
+     global transform
+     global pgm_actual
+     global pgm_base
+     global fix_progname
+ # maybe add "X" to front of fail to say it is an expected failure
+     global X
+ 
+     set pgm_base ${pgm}
+     set pgm_actual ${pgm}
+ 
+     if { ${transform} != "s,x,x,"} {
+         verbose "1. program name was ${pgm}" 2
+         set sed_rc [catch {eval exec sed -e "${transform}" <<${pgm} } catch_res]
+         if { ${sed_rc} != "0" } {
+             verbose "2. Program name transform failed rc=${sed_rc} stat=${catch_res}" 1
+             ${X}fail "${pgm} sed"
+             return 0
+         }
+         set pgm_actual ${catch_res}
+         verbose "3. program name after transformation is ${pgm_actual}" 2
+     }
+ 
+     set which_rc [catch {exec which ${pgm_actual}} stat]
+     if { ${which_rc} != "0" } {
+         verbose "4. ${pgm_base} cannot be found rc=${which_rc} stat=${stat}" 1
+         ${X}fail "${pgm} = ${pgm_actual} not found in path (${path})"
+         return 0
+     }
+     set fix_progname "s,${pgm_actual},${pgm_base},"
+     verbose "5. fix program name value = ${fix_progname}" 4
+     return 1
+ }
+ 
+ #run pgm, option to remove file names from outputs
+ proc run3 {srcdd testdd parms group_nbr item_nbr nonzero_RC_expected check_file sanitize_output tree1 pipe} {
+ 
+     global transform
+     global pgm_actual
+     global pgm_base
+     global fix_progname
+     global X
+     global extras
+ 
+     set error_msg 0
+     set basefile "a${group_nbr}${pgm_base}.out${item_nbr}"
+     set infile  ""
+     set outfile  ""
+     set suffix ""
+     set temp_extras "-O3 "
+     if  {${tree1} > 0} {
+         if {"${pgm_actual}" == "gcc"} {
+             set temp_extras "${extras}";
+         }
+         set infile "${srcdd}/a${group_nbr}${pgm_base}i${item_nbr}.tree"
+         set mainfile "${srcdd}/a${group_nbr}${pgm_base}i${item_nbr}.c"
+         set outfile "-o ${testdd}/a${group_nbr}${pgm_base}o${item_nbr}${suffix}"
+     }
+     
+     verbose "6. exec ${pgm_actual} ${temp_extras} ${parms} ${mainfile} ${infile} ${outfile} >${testdd}/${basefile} 2>${testdd}/${basefile}err" 2
+     set run_rc [catch {eval exec ${pgm_actual} ${temp_extras} ${parms} ${mainfile} ${infile} ${outfile} >${testdd}/${basefile} 2>${testdd}/${basefile}err} catch_res]
+     if {${run_rc} == 1} {
+         if {${nonzero_RC_expected} == 0} {
+             verbose "7. ${pgm_actual} ${group_nbr} ${item_nbr} failed due to rc=${run_rc} status=${catch_res}" 1
+             ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} rc!=0" 
+             return
+         } 
+     } else {
+         if {${nonzero_RC_expected} == 1} {
+             verbose "8. ${pgm_actual} ${group_nbr} ${item_nbr} failed - did not produce nonzero return code as expected rc=${run_rc} status=${catch_res}" 1
+             ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} rc=0" 
+             return
+         } 
+     }
+ 
+ # change the filenames to (file) in output if needed to allow testing
+     set checkfile1 "${srcdd}/${basefile}"
+     set checkfile2 "${testdd}/${basefile}"
+     if {${sanitize_output} != 0} {
+         set oldcheckfile1 "${checkfile1}"
+         set oldcheckfile2 "${checkfile2}"
+         set checkfile1 "${testdd}/${basefile}.test.nofilename"
+         set checkfile2 "${testdd}/${basefile}.run.nofilename"
+         set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res]
+         if {${run_rc} == 1} {
+             verbose "9. sed to cleanup filenames (std 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1
+             if  {${error_msg} == 0} {
+                 set error_msg "9. sed to cleanup filenames (std 1) in pgm output failed due to rc=${run_rc} status=${catch_res}"
+             }
+         }
+         set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e  "${fix_progname}"  >${checkfile2}} catch_res]
+         if {${run_rc} == 1} {
+             verbose "10. sed to cleanup filenames (std 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1
+             if  {${error_msg} == 0} {
+                 set error_msg "10. sed to cleanup filenames (std 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" 
+             }
+         }
+     }
+     set diff [diff ${checkfile1} ${checkfile2}]
+     if {${diff} != 1} {
+         verbose "11. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout failed rc=${diff}" 1
+         if  {${error_msg} == 0} {
+             set error_msg "11. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout failed rc=${diff}"
+         }
+     }
+ 
+     set checkfile1 "${srcdd}/${basefile}err"
+     set checkfile2 "${testdd}/${basefile}err"
+     if {${sanitize_output} != 0} {
+         set oldcheckfile1 "${checkfile1}"
+         set oldcheckfile2 "${checkfile2}"
+         set checkfile1 "${testdd}/${basefile}err.test.nofilename"
+         set checkfile2 "${testdd}/${basefile}err.run.nofilename"
+         set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res]
+         if {${run_rc} == 1} {
+             verbose "12. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1
+             if  {${error_msg} == 0} {
+                 set error_msg "12. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}"
+             }
+         }
+         set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e  "${fix_progname}"  >${checkfile2}} catch_res]
+         if {${run_rc} == 1} {
+             verbose "13. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1
+             if  {${error_msg} == 0} {
+                 set error_msg "13. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}"
+             }
+         }
+     }
+     set diff [diff ${checkfile1} ${checkfile2}]
+     if {${diff} != 1} {
+         verbose "14. ${pgm_actual} ${group_nbr} ${item_nbr} diff stderr failed rc=${diff}" 1
+         if  {${error_msg} == 0} {
+             set error_msg "14. ${pgm_actual} ${group_nbr} ${item_nbr} diff stderr failed rc=${diff}"
+         }
+     }
+ 
+     if {${check_file} >0} {
+         if  {${tree1} == 0} {
+             set checkfile1 "${srcdd}/${basefile}file"
+             set checkfile2 "${testdd}/${basefile}file"
+             if {${sanitize_output} != 0} {
+                 set oldcheckfile1 "${checkfile1}"
+                 set oldcheckfile2 "${checkfile2}"
+                 set checkfile1 "${testdd}/${basefile}file.test.nofilename"
+                 set checkfile2 "${testdd}/${basefile}file.run.nofilename"
+                 set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res]
+                 if {${run_rc} == 1} {
+                     verbose "15. sed to cleanup filenames (err 1) in pgm stdout failed due to rc=${run_rc} status=${catch_res}" 1
+                     if  {${error_msg} == 0} {
+                         set error_msg "15. sed to cleanup filenames (err 1) in pgm stdout failed due to rc=${run_rc} status=${catch_res}"
+                     }
+                 }
+                 set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e  "${fix_progname}"  >${checkfile2}} catch_res]
+                 if {${run_rc} == 1} {
+                     verbose "16. sed to cleanup filenames (err 2) in pgm stdout failed due to rc=${run_rc} status=${catch_res}" 1
+                     if  {${error_msg} == 0} {
+                         set error_msg "16. sed to cleanup filenames (err 2) in pgm stdout failed due to rc=${run_rc} status=${catch_res}"
+                     }
+                 }
+             }
+             set diff [diff ${checkfile1} ${checkfile2}]
+             if {${diff} != 1} {
+                 verbose "17. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout file failed rc=${diff}" 1
+                 if  {${error_msg} == 0} {
+                     set error_msg "17. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout file failed rc=${diff}"
+                 }
+             }
+         }
+     }
+     
+     if {${check_file} >1} {
+         if  {${tree1} == 0} {
+             set checkfile1 "${srcdd}/${outfile}"
+             set checkfile2 "${testdd}/${outfile}"
+             if {${sanitize_output} != 0} {
+                 set oldcheckfile1 "${checkfile1}"
+                 set oldcheckfile2 "${checkfile2}"
+                 set checkfile1 "${testdd}/${basefile}out.test.nofilename"
+                 set checkfile2 "${testdd}/${basefile}out.run.nofilename"
+                 set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res]
+                 if {${run_rc} == 1} {
+                     verbose "18. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1
+                     if  {${error_msg} == 0} {
+                         set error_msg "18. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}"
+                     }
+                 }
+                 set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e  "${fix_progname}"  >${checkfile2}} catch_res]
+                 if {${run_rc} == 1} {
+                     verbose "19. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1
+                     if  {${error_msg} == 0} {
+                         set error_msg "19. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}"
+                     }
+                 }
+             }
+             set diff [diff ${checkfile1} ${checkfile2}]
+             if {${diff} != 1} {
+                 verbose "20. ${pgm_actual} ${group_nbr} ${item_nbr} diff output file failed rc=${diff}" 1
+                 if  {${error_msg} == 0} {
+                     set error_msg "20. ${pgm_actual} ${group_nbr} ${item_nbr} diff output file failed rc=${diff}"
+                 }
+             }
+         }
+     }
+     
+     if {${check_file} >2} {
+         set outfile "a${group_nbr}${pgm_base}o${item_nbr}${suffix}"
+         set pgmrun "${testdd}/a${group_nbr}${pgm_base}o${item_nbr}${suffix}"
+         set checkfile1 "${srcdd}/${outfile}runpgm"
+         set checkfile2 "${testdd}/${outfile}runpgm"
+         verbose "21. exec ${pgmrun} >${checkfile2} 2>${checkfile2}err" 2
+         set run_rc [catch {eval exec ${pgmrun} >${checkfile2} 2>${checkfile2}err} catch_res]
+         if {${run_rc} == 1} {
+             if {${nonzero_RC_expected} == 0} {
+                 verbose "22. ${pgm_actual} ${group_nbr} ${item_nbr} failed due to rc=${run_rc} status=${catch_res}" 1
+                 ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} run" 
+                 return
+             } 
+         } else {
+             if {${nonzero_RC_expected} == 1} {
+                 verbose "23. ${pgm_actual} ${group_nbr} ${item_nbr} failed - did not produce nonzero return code as expected rc=${run_rc} status=${catch_res}" 1
+                 ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} run" 
+                 return
+             } 
+         }
+         set diff [diff ${checkfile1} ${checkfile2}]
+         if {${diff} != 1} {
+             verbose "24. ${pgm_actual} ${group_nbr} ${item_nbr} diff run output file failed rc=${diff}" 1
+             if  {${error_msg} == 0} {
+                 set error_msg "24. ${pgm_actual} ${group_nbr} ${item_nbr} diff run output file failed rc=${diff}"
+             }
+         }
+         set diff [diff ${checkfile1}err ${checkfile2}err]
+         if {${diff} != 1} {
+             verbose "25. ${pgm_actual} ${group_nbr} ${item_nbr} diff run stderr file failed rc=${diff}" 1
+             if  {${error_msg} == 0} {
+                 set error_msg "25. ${pgm_actual} ${group_nbr} ${item_nbr} diff run stderr file failed rc=${diff}"
+             }
+         }
+     }
+ 
+     if {${error_msg}>0} {
+         ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} fail code=${error_msg}" 
+     } else {
+         pass "${pgm_base} ${group_nbr} ${item_nbr}" 
+     }
+     return 
+ }
+ 
+ set extras "$env(GCC_EXTRAS)"
+ set path $env(PATH)
+ set transform $env(TRANSFORM)
+ set srcdir $env(srcdir)
+ verbose "source directory ${srcdir}\n" 2
+ verbose "transform ${transform}\n" 2
+ set sourcedir "${srcdir}/testsuite/treelang"
+ set testdir "treelang"
+ 
+ set pgm_actual ""
+ 
+ # srcdd testdd parms group_nbr item_nbr nonzero_RC_expected check_file sanitize_output tree1
+ 
+ # ttt
+ 
+ #GCC - main compiler tests via GCC
+ 
+ set X ""
+ 
+ set check_rc [init_utility "gcc"]
+ 
+ if {${check_rc} == 1} {
+ #
+ #set X "x"
+ set X ""
+     run3 "${sourcedir}" "${testdir}" " -g -O3 " 01 01 0 3 0 1 0
+ set X ""
+ }
+ 
diff -c3prN gcccvs/gcc/gcc/treelang/.cvsignore newgcc/gcc/treelang/.cvsignore
*** gcccvs/gcc/gcc/treelang/.cvsignore	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/.cvsignore	Sat Jul 28 12:01:44 2001
***************
*** 0 ****
--- 1,6 ----
+ lex.c
+ parse.c
+ parse.h
+ parse.output
+ *.html
+ *.info
diff -c3prN gcccvs/gcc/gcc/treelang/ChangeLog newgcc/gcc/treelang/ChangeLog
*** gcccvs/gcc/gcc/treelang/ChangeLog	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/ChangeLog	Mon Jun 11 08:55:25 2001
***************
*** 0 ****
--- 1,16 ----
+ 2001-07-30  Tim Josling  <tej@melbpc.org.au>
+ 
+ 	* root.texi: remove
+ 	* treelang,texi: updates based on feedback
+ 
+ 2001-06-11  Tim Josling  <tej@melbpc.org.au>
+ 
+ 	* all (all) Revamp code to conform to GCC coding standards, fix
+ 	typos in texi files. 
+ 
+ 2001-05-11  Tim Josling  <tej@melbpc.org.au>
+ 
+         Create the new language.
+ 
+ 	
+ 	
diff -c3prN gcccvs/gcc/gcc/treelang/Make-lang.in newgcc/gcc/treelang/Make-lang.in
*** gcccvs/gcc/gcc/treelang/Make-lang.in	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/Make-lang.in	Sat Jul 28 12:36:04 2001
***************
*** 0 ****
--- 1,293 ----
+ # Top level makefile fragment for TREELANG For GCC. -*- makefile -*-
+ 
+ #   Copyright (C) 1994, 1995, 1997, 1998, 1999 2000, 2001 Free
+ #   Software Foundation, Inc.
+ 
+ #This file is part of GNU CC.
+ 
+ #GNU CC 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, or (at your option)
+ #any later version.
+ 
+ #GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+ #the Free Software Foundation, 59 Temple Place - Suite 330,
+ #Boston, MA 02111-1307, USA.
+ 
+ # This file provides the language dependent support in the main Makefile.
+ # Each language makefile fragment must provide the following targets:
+ #
+ # foo.all.build, foo.all.cross, foo.start.encap, foo.rest.encap,
+ # foo.info, foo.dvi,
+ # foo.install-normal, foo.install-common, foo.install-info, foo.install-man,
+ # foo.uninstall, foo.distdir,
+ # foo.mostlyclean, foo.clean, foo.distclean, foo.extraclean,
+ # foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
+ #
+ # where `foo' is the name of the language.
+ #
+ # It should also provide rules for:
+ #
+ # - making any compiler driver (eg: GCC)
+ # - the compiler proper (eg: treelang)
+ # - define the names for selecting the language in LANGUAGES.
+ #
+ 
+ ## note program-prefix and program-suffix options are not supported
+ ## just program_transform_name which is a sed script to transform the
+ ## names
+ 
+ TREELANGSED = sed
+ TREELANGSEDFLAGS = -n
+ 
+ # back end compiler libraries etc
+ TREE_BE_LIBS = toplev.o libbackend.a $(LIBIBERTY) $(INTLLIBS) $(LIBS) $(LIBDEPS) 
+ TREE_PRE_LIBS = safe-ctype.o
+ GCC_EXTRAS = -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include
+ 
+ # ./xgcc is the just built compiler. See GCC_FOR_TARGET in the GCC Makefile.in.
+ # If this can't be found, you probably have not done a bootstrap of GCC,
+ # which you need to do.
+ 
+ GCC_FOR_TREELANG = ./xgcc $(GCC_EXTRAS)
+ 
+ TREE_GENERATED = $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.c\
+ 	$(srcdir)/treelang/parse.h $(srcdir)/treelang/parse.output $(srcdir)/treelang/TAGS
+ 
+ TREE_SOURCE = ${srcdir}/treelang/parse.y ${srcdir}/treelang/lex.l ${srcdir}/treelang/tree1.c ${srcdir}/treelang/treelang.h ${srcdir}/treelang/treetree.c $(srcdir)/treelang/treetree.h
+ 
+ TREE_EXES = treelang/tree1$(exeext)
+ 
+ #no -Wtraditional warnings, allow long long
+ treelang-warn = $(LOOSE_WARN) -pedantic -Wno-long-long -Wmissing-prototypes -Wmissing-declarations
+ 
+ #
+ # Define the names for selecting treelang in LANGUAGES.
+ 
+ .phony: treelang TREELANG
+ 
+ treelang TREELANG:treelang.done
+ 
+ treelang.done: treelang/tree1$(exeext)
+ 	touch treelang.done
+ 
+ # no preprocessor
+ 
+ # core compiler 
+ treelang/tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o\
+ 	$(TREE_BE_LIBS) c-convert.o
+ 	$(GCC_FOR_TREELANG) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ 	treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o c-convert.o $(TREE_BE_LIBS)
+ 
+ #
+ # Compiling object files from source files.
+ 
+ # object file makes
+ 
+ treelang/tree1.o: $(srcdir)/treelang/tree1.c $(srcdir)/treelang/treelang.h $(srcdir)/treelang/parse.h
+ 	$(GCC_FOR_TREELANG) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< 
+ 
+ treelang/treetree.o: $(srcdir)/treelang/treetree.c $(srcdir)/treelang/treetree.h
+ 	$(GCC_FOR_TREELANG) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< 
+ 
+ treelang/parse.o: $(srcdir)/treelang/parse.c $(srcdir)/treelang/treelang.h $(srcdir)/treelang/treetree.h
+ 	$(GCC_FOR_TREELANG) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< 
+ 
+ treelang/lex.o: $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.h $(srcdir)/treelang/treelang.h
+ 	$(GCC_FOR_TREELANG) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< 
+ 
+ # generated files the files from lex and yacc are put into the source
+ # directory in case someone wants to build but does not have
+ # lex/yacc
+ 
+ $(srcdir)/treelang/lex.c: $(srcdir)/treelang/lex.l
+ 	$(LEX) $(LEXFLAGS) -o$(srcdir)/treelang/lex.c $(srcdir)/treelang/lex.l
+ 
+ $(srcdir)/treelang/parse.c $(srcdir)/treelang/parse.h: $(srcdir)/treelang/parse.y
+ 	$(BISON) $(BISONFLAGS) -v $(srcdir)/treelang/parse.y\
+ 	--output=$(srcdir)/treelang/parse.c --defines
+ # -v
+ 
+ #
+ # Build hooks:
+ 
+ treelang.all.build: treelang
+ treelang.all.cross: 
+ 	_error_not_here_yet - havent even thought about it - it may even work
+ 
+ treelang.start.encap:
+ treelang.rest.encap: 
+ 
+ .phony:treelang.info
+ treelang.info: $(srcdir)/treelang/treelang.info
+ 
+ $(srcdir)/treelang/treelang.info: $(srcdir)/treelang/treelang.texi
+ 	cd $(srcdir)/treelang && $(MAKEINFO) $(MAKEINFOFLAGS) -I../doc/include \
+ 	-o $(srcdir)/treelang/treelang.info $(srcdir)/treelang/treelang.texi
+ 
+ treelang.dvi: $(srcdir)/treelang/treelang.texi
+ 	TEXINPUTS=$(srcdir)/treelang:$(srcdir):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/treelang/treelang.texi; \
+ 	  texindex treelang.??; \
+ 	  TEXINPUTS=$(srcdir)/treelang:$(srcdir):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/treelang/treelang.texi; \
+ 	  mv treelang.dvi treelang;
+ 
+ #
+ # Install hooks:
+ 
+ # Nothing to do here.
+ treelang.install-normal: treelang.install.common
+ 
+ # Install 
+ .phony:treelang.install.common
+ .phony:treelang.install
+ 
+ treelang.install treelang.install.common treelang.install-common: treelang.install.common.done
+ 
+ treelang.install.common.done: treelang.done 
+ 	for name in $(TREE_EXES); \
+ 	do \
+ 	   if [ -f $$name ] ; then \
+ 	    name2="`echo \`basename $$name\` | sed -e '$(program_transform_name)' `"; \
+ 	    rm -f $(bindir)/$$name2$(exeext); \
+ 	    $(INSTALL_PROGRAM) $$name$(exeext) $(bindir)/$$name2$(exeext); \
+ 	    chmod a+x $(bindir)/$$name2$(exeext); \
+ 	  fi ; \
+ 	done
+ 	touch treelang.install.common.done
+ 
+ treelang.install-info: $(srcdir)/treelang/treelang.info
+ 	for name in $(srcdir)/treelang/treelang.info; \
+ 	do \
+ 	   if [ -f $$name ] ; then \
+ 	    name2="`echo \`basename $$name\` | sed -e '$(program_transform_name)' `"; \
+ 	    rm -f $(libsubdir)/$$name2$(exeext); \
+ 	    $(INSTALL_PROGRAM) $$name$(exeext) $(libsubdir)/$$name2$(exeext); \
+ 	    chmod a+x $(libsubdir)/$$name2$(exeext); \
+ 	  fi ; \
+ 	done
+ 
+ treelang.install-man: 
+ 
+ treelang.uninstall:
+ 	for name in $(TREE_EXES); \
+ 	do \
+ 	  echo $$name; \
+ 	  name2="`echo $$name | sed -e '$(program_transform_name)' `"; \
+ 	  echo becomes $$name2; \
+ 	  echo -rm -rf $(bindir)/$$name2$(exeext); \
+ 	  rm -rf $(bindir)/$$name2$(exeext); \
+ 	done
+ 	-rm treelang.install.common.done
+ 
+ #
+ # Clean hooks:
+ # A lot of the ancillary files are deleted by the main makefile.
+ # We just have to delete files specific to us.
+ 
+ treelang.mostlyclean: 
+ 	for name in $(TREE_EXES); \
+ 	do \
+ 	  echo deleting $$name; \
+ 	  if [ -f treelang/$$name$(exeext) ] ; then \
+ 	    rm -f treelang/$$name$(exeext); \
+ 	  fi ; \
+ 	done
+ 	-rm -f treelang/*.o
+ 	-rm treelang.done
+ 
+ 
+ treelang.clean: treelang.mostlyclean
+ 
+ treelang.distclean: treelang.clean
+ 	-rm -f treelang/config.status 
+ 	-rm -f treelang/*.output
+ 
+ treelang.extraclean: treelang.distclean
+ 
+ treelang.maintainer-clean: treelang.extraclean
+ 	for name in $(TREE_GENERATED); \
+ 	do \
+ 	  if [ -f $(srcdir)/treelang/$$name ] ; then \
+              echo deleting $(srcdir)/treelang/$$name; \
+ 	     rm -f $(srcdir)/treelang/$$name; \
+ 	  fi ; \
+ 	done
+ 	-rm -R $(srcdir)/treelang/*~
+ 
+ 
+ #
+ # Stage hooks:
+ # The main makefile has already created stage?/treelang.
+ 
+ treelang.stage1: stage1-start
+ 	-mv treelang/*$(objext) stage1/treelang
+ treelang.stage2: stage2-start
+ 	-mv treelang/*$(objext) stage2/treelang
+ treelang.stage3: stage3-start
+ 	-mv treelang/*$(objext) stage3/treelang
+ treelang.stage4: stage4-start
+ 	-mv treelang/*$(objext) stage4/treelang
+ #
+ # Maintenance hooks:
+ 
+ # This target creates the files that can be rebuilt, but go in the
+ # distribution anyway.  It then copies the files to the distdir directory.
+ treelang.distdir:
+ 	not here yet
+ 
+ # test hook
+ # the other languages are hard coded in the main makefile.in - that seems to be wrong 
+ 
+ check: treelang.check
+ 
+ TESTSUITEDIR = testsuite
+ 
+ treelang.check: treelang.install-normal $(TESTSUITEDIR)/site.exp
+ 	-mkdir testsuite/treelang 
+ # these three files are empty and it diff has trouble generating diff files for new empty files
+ 	touch $(srcdir)/testsuite/treelang/{a01gcco01runpgmerr,a01gcc.out01,a01gcc.out01err}
+ 	-rootme=`pwd`; export rootme; \
+ 	srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ 	cd testsuite; \
+ 	EXPECT=${EXPECT} ; export EXPECT ; \
+ 	TRANSFORM=$(program_transform_name); export TRANSFORM; \
+ 	if [ -f $${rootme}/../expect/expect ] ; then  \
+ 	   TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
+ 	   export TCL_LIBRARY ; fi ; \
+ 	PATH=$(bindir):$$PATH; export PATH; \
+ 	GCC_EXTRAS="$(GCC_EXTRAS)"; export GCC_EXTRAS; \
+ 	$(RUNTEST) --tool treelang $(RUNTESTFLAGS)
+ 	rm $(srcdir)/testsuite/treelang/{a01gcco01runpgmerr,a01gcc.out01,a01gcc.out01err}
+ 
+ # copy the output files from the current test to source ie say the new results are OK
+ treelang.check.fix: force
+ 	srcdir=`cd ${srcdir}; pwd` ; export srcdir ; 
+ 	-cp testsuite/treelang/*.out* t
+ 	-cp testsuite/treelang/*runpgm* t
+ 	-rm -f t/*nofilename
+ 
+ treelang.wc: force
+ 	wc  ${TREE_SOURCE}
+ 
+ #
+ 
+ # Update the tags table for emacs find label (alt-.) function
+ TAGS: treelang.tags
+ 
+ .PHONY: treelang.tags
+ 
+ treelang.tags:
+ 	cd $(srcdir)/treelang;						\
+ 	etags -l c ${TREE_SOURCE}
+ 
+ .PHONY: treelang.html
+ 
+ treelang.html:
+ 	cd $(srcdir)/treelang && texi2html -I ../doc/include -verbose -menu -split_chapter -number treelang.texi
+ #	mv treelang*.html $(srcdir)/treelang
diff -c3prN gcccvs/gcc/gcc/treelang/README newgcc/gcc/treelang/README
*** gcccvs/gcc/gcc/treelang/README	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/README	Sun Jun  3 14:29:45 2001
***************
*** 0 ****
--- 1,15 ----
+ This is a sample language front end for GCC.
+ 
+ This is a replacement for 'toy' which had potential copyright issues,
+ but more importantly it did not exercise very much of GCC. The intent
+ of this language is that it should provide a cookbook of language
+ elements that you can use in any language front end.
+ 
+ To this end, treelang is essentially an implementation of the GCC back
+ end 'tree' interface in syntax.
+ 
+ Thanks to Richard Kenner, Joachim Nadler and many others for helping
+ me to understand enough of GCC to do this.
+ 
+ Tim Josling
+ May 2001
diff -c3prN gcccvs/gcc/gcc/treelang/config-lang.in newgcc/gcc/treelang/config-lang.in
*** gcccvs/gcc/gcc/treelang/config-lang.in	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/config-lang.in	Sat May 26 12:32:14 2001
***************
*** 0 ****
--- 1,36 ----
+ # Top level configure fragment for GNU C++.
+ # Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
+ 
+ #This file is part of GNU CC.
+ 
+ #GNU CC 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, or (at your option)
+ #any later version.
+ 
+ #GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+ #the Free Software Foundation, 59 Temple Place - Suite 330,
+ #Boston, MA 02111-1307, USA.
+ 
+ # Configure looks for the existence of this file to auto-config each language.
+ # We define several parameters used by configure:
+ #
+ # language	- name of language as it would appear in $(LANGUAGES)
+ # compilers	- value to add to $(COMPILERS)
+ # stagestuff	- files to add to $(STAGESTUFF)
+ # diff_excludes	- files to ignore when building diffs between two versions.
+ 
+ language="treelang"
+ 
+ compilers="tree1\$(exeext)"
+ 
+ stagestuff=
+ 
+ diff_excludes="-x lex.c -x parse.c -x parse.h"
+ headers=
diff -c3prN gcccvs/gcc/gcc/treelang/lang-options.h newgcc/gcc/treelang/lang-options.h
*** gcccvs/gcc/gcc/treelang/lang-options.h	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/lang-options.h	Sun Jun 10 18:33:53 2001
***************
*** 0 ****
--- 1,29 ----
+ /* Definitions for switches for TREELANG.
+ 
+    Copyright (C) 1995, 96-98, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+ This file is part of GNU CC.
+ 
+ GNU CC 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, or (at your option)
+ any later version.
+ 
+ GNU CC 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; see the file COPYING.  If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+ 
+ DEFINE_LANG_NAME ("treelang")
+      
+ /* This is the contribution to the `lang_options' array in GCC.c for
+    treelang.  */
+  {"-fparser-trace", N_("(debug) trace parsing process")},
+  {"-flexer-trace", N_("(debug) trace lexical analysis")},
+ 
+ 
diff -c3prN gcccvs/gcc/gcc/treelang/lang-specs.h newgcc/gcc/treelang/lang-specs.h
*** gcccvs/gcc/gcc/treelang/lang-specs.h	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/lang-specs.h	Sat May 26 15:44:43 2001
***************
*** 0 ****
--- 1,63 ----
+ /* Definitions for specs for TREELANG
+ 
+    The format of the specs file is documented in GCC.c
+ 
+    Copyright (C) 1995, 96-98, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+ This file is part of GNU CC.
+ 
+ GNU CC 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, or (at your option)
+ any later version.
+ 
+ GNU CC 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; see the file COPYING.  If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+ 
+ /* 
+    This is the contribution to the `default_compilers' array in GCC.c for
+    treelang.  
+    
+    This file must compile with 'traditional', so no ANSII string continuations 
+    
+ */
+ 
+ {".tree", "@treelang", NULL},
+ {".TREE", "@treelang", NULL},
+ {".tre", "@treelang", NULL},
+ {".TRE", "@treelang", NULL},
+ {"@treelang",
+     "tree1\
+        %{!Q:-quiet}\
+        %{d*}\
+        %{m*}\
+        %{a}\
+        %{g*}\
+        %{O*}\
+        %{W*}\
+        %{w}\
+        %{ansi}\
+        %{v}\
+        %{--help:--help}\
+        %{pg:-p}\
+        %{p}\
+        %{f*}\
+        %{pg|p:%{fomit-frame-pointer:%e-pg or -p and -fomit-frame-pointer are incompatible}}\
+        %{S:%W{o*}%{!o*:-o %b.s}}\
+        %{!S:-o %g.s}\
+        %i\n\
+        %{!S:as %a\
+        %Y\
+        %{c:%W{o*}%{!o*:-o %w%b%O}}\
+        %{!c:-o %d%w%u%O}\
+        %g.s\
+        %A\n}\
+        ", NULL
+ },
diff -c3prN gcccvs/gcc/gcc/treelang/lex.l newgcc/gcc/treelang/lex.l
*** gcccvs/gcc/gcc/treelang/lex.l	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/lex.l	Mon Jun 11 08:52:06 2001
***************
*** 0 ****
--- 1,281 ----
+ %{ /* -*- c -*- = mode for emacs editor
+ /* 
+ 
+    TREELANG lexical analysis
+ 
+    ---------------------------------------------------------------------
+ 
+    Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+    
+    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, 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, 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+    
+    In other words, you are welcome to use, share and improve this program.
+    You are forbidden to forbid anyone else to use, share and improve
+    what you give them.   Help stamp out software-hoarding!  
+    
+    ---------------------------------------------------------------------
+    
+    Written by Tim Josling 1999-2001, based in part on other parts of
+    the GCC compiler. 
+  
+ */
+ 
+ typedef void* tree;
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <memory.h>
+ #include "gansidecl.h"
+ /* Token defs.  */
+ #include "treelang.h"
+ #include "parse.h"
+ 
+ extern int option_lexer_trace;
+ 
+ int yylex (void);
+ void update_yylval (int a); 
+ 
+ static int next_tree_lineno=1;
+ static int next_tree_charno=1;
+  
+ static void update_lineno_charno (void);
+ static void dump_lex_value (int lexret);
+  
+ #define SAVE_RETURN(a) {update_yylval (a); if (option_lexer_trace) {fprintf (stderr, "\nlexer returning"); dump_lex_value (a);} return a;}
+ #define NOT_RETURN(a) {update_yylval (a); if (option_lexer_trace) {fprintf (stderr, "\nlexer swallowing"); \
+                          dump_lex_value (a);}}
+ 
+ %}
+ 
+ %option nostack
+ %option nounput
+ %option noyywrap
+ %option pointer
+ %option nodefault
+ 
+ %%
+ 
+  { 
+    yylval = my_malloc (sizeof (struct token));
+    ((struct token*)yylval)->lineno = next_tree_lineno;
+    ((struct token*)yylval)->charno = next_tree_charno;
+  }
+ 
+ [ \n]+ {
+   update_lineno_charno ();
+     NOT_RETURN (WHITESPACE);
+ }
+   
+ "//".*  {
+   /* Comment.  */
+     update_lineno_charno ();
+     NOT_RETURN (COMMENT);
+ }
+    
+ "{" {
+   update_lineno_charno ();
+   SAVE_RETURN (LEFT_BRACE);
+ }
+   
+ "}" {
+   update_lineno_charno ();
+   SAVE_RETURN (RIGHT_BRACE);
+ }
+   
+ "(" {
+   update_lineno_charno ();
+   SAVE_RETURN (LEFT_PARENTHESIS);
+ }
+   
+ ")" {
+   update_lineno_charno ();
+   SAVE_RETURN (RIGHT_PARENTHESIS);
+ }
+   
+ "," {
+   update_lineno_charno ();
+   SAVE_RETURN (COMMA);
+ }
+   
+ ";" {
+   update_lineno_charno ();
+   SAVE_RETURN (SEMICOLON);
+ }
+   
+ "+" {
+   update_lineno_charno ();
+   SAVE_RETURN (PLUS);
+ }
+   
+ "-" {
+   update_lineno_charno ();
+   SAVE_RETURN (MINUS);
+ }
+   
+ "=" {
+   update_lineno_charno ();
+   SAVE_RETURN (ASSIGN);
+ }
+   
+ "==" {
+   update_lineno_charno ();
+   SAVE_RETURN (EQUALS);
+ }
+   
+ [+-]?[0-9]+ {
+   update_lineno_charno ();
+   SAVE_RETURN (INTEGER);
+ }
+   
+ "external_reference" {
+   update_lineno_charno ();
+   SAVE_RETURN (EXTERNAL_REFERENCE);
+ }
+   
+ "external_definition" {
+   update_lineno_charno ();
+   SAVE_RETURN (EXTERNAL_DEFINITION);
+ }
+   
+ "static" {
+   update_lineno_charno ();
+   SAVE_RETURN (STATIC);
+ }
+   
+ "automatic" {
+   update_lineno_charno ();
+   SAVE_RETURN (STATIC);
+ }
+   
+ "int" {
+   update_lineno_charno ();
+   SAVE_RETURN (INT);
+ }
+   
+ "char" {
+   update_lineno_charno ();
+   SAVE_RETURN (CHAR);
+ }
+   
+ "void" {
+   update_lineno_charno ();
+   SAVE_RETURN (VOID);
+ }
+   
+ "unsigned" {
+   update_lineno_charno ();
+   SAVE_RETURN (UNSIGNED);
+ }
+   
+ "return" {
+   update_lineno_charno ();
+   SAVE_RETURN (RETURN);
+ }
+   
+ "if" {
+   update_lineno_charno ();
+   SAVE_RETURN (IF);
+ }
+   
+ "else" {
+   update_lineno_charno ();
+   SAVE_RETURN (ELSE);
+ }
+   
+ [A-Za-z_]+[A-Za-z_0-9]* {
+   update_lineno_charno ();
+   update_yylval (NAME); 
+   if (option_lexer_trace) 
+     {
+       fprintf (stderr, "\nlexer returning"); 
+       dump_lex_value (NAME);
+     } 
+   return NAME;
+ }
+   
+ [^\n]  {
+   update_lineno_charno ();
+   fprintf (stderr, "%s:%i:%i: Unrecognized character %c\n", in_fname, 
+            ((struct token*)yylval)->lineno, 
+            ((struct token*)yylval)->charno, yytext[0]);
+   errorcount++;
+ }
+ 
+ %%
+ 
+ /* 
+    Update line number (1-) and character number (1-).  Call this
+    before processing the token.  */
+ 
+ static void 
+ update_lineno_charno (void)
+ {
+    /* Update the values we send to caller in case we sometimes don't
+       tell them about all the 'tokens' eg comments etc.  */
+    int yyl;
+    ((struct token*)yylval)->lineno = next_tree_lineno;
+    ((struct token*)yylval)->charno = next_tree_charno;
+    for ( yyl = 0; yyl < yyleng; ++yyl ) 
+       {
+          if ( yytext[yyl] == '\n' ) 
+             {
+                ++next_tree_lineno;
+                next_tree_charno = 1;
+             } 
+          else 
+            next_tree_charno++;
+       }
+ }
+ 
+ /* Fill in the fields of yylval - the value of the token.  The token
+    type is A.  */
+ void 
+ update_yylval (int a)
+ {
+   struct token* tok;
+   tok=yylval;
+   
+   tok->category = token_category;
+   tok->type = a;
+   tok->length = yyleng;
+   /* Have to copy yytext as it is just a ptr into the buffer at the
+      moment.  */
+   tok->chars = my_malloc (yyleng + 1);
+   memcpy (tok->chars, yytext, yyleng);
+ }
+ 
+ /* Trace the value LEXRET and the position and token details being
+    returned by the lexical analyser.  */
+ 
+ static void
+ dump_lex_value (int lexret) 
+ {
+   int ix;
+   fprintf (stderr, " %d l:%d c:%d ln:%d text=", lexret,
+          ((struct token*) yylval)->lineno,
+          ((struct token*) yylval)->charno,
+          ((struct token*) yylval)->length);
+   for (ix = 0; ix < yyleng; ix++) 
+     {
+       fprintf (stderr, "%c", yytext[ix]);
+     }
+   printf (" in hex:");
+   for (ix = 0; ix < yyleng; ix++) 
+     {
+       fprintf (stderr, " %2.2x", yytext[ix]);
+     }
+   fprintf (stderr, "\n");
+ }  
+ 
diff -c3prN gcccvs/gcc/gcc/treelang/parse.y newgcc/gcc/treelang/parse.y
*** gcccvs/gcc/gcc/treelang/parse.y	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/parse.y	Sat Jul 28 12:38:49 2001
***************
*** 0 ****
--- 1,986 ----
+ %{ /* -*- c -*- emacs mode c */
+   /* 
+ 
+      TREELANG Compiler parser.  
+ 
+      ---------------------------------------------------------------------
+ 
+      Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+      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, 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, 59 Temple Place - Suite 330,
+      Boston, MA 02111-1307, USA.
+ 
+      In other words, you are welcome to use, share and improve this program.
+      You are forbidden to forbid anyone else to use, share and improve
+      what you give them.   Help stamp out software-hoarding!  
+ 
+      ---------------------------------------------------------------------
+ 
+      Written by Tim Josling 1999-2001, based in part on other parts of
+      the GCC compiler.
+  
+    */
+ 
+   /* 
+ 
+      Grammar Conflicts
+      *****************
+ 
+      Here are no conflicts in this grammar.  Please keep it that way.
+ 
+    */
+ 
+ typedef void* tree;
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ 
+ #include "gansidecl.h"
+ 
+ #include "treelang.h"
+ #include "treetree.h"
+ 
+ #define YYDEBUG 1
+ #define YYPRINT(file, type, value) print_token (file, type, value) 
+ #define YYERROR_VERBOSE YES
+ 
+ /* Local prototypes.  */
+ 
+ static void yyerror (const char *error_message);
+ int yylex (void);
+ int yyparse (void);
+ void print_token (FILE * file, unsigned int  type ATTRIBUTE_UNUSED, YYSTYPE value);
+ static struct production* reverse_prod_list (struct production* old_first);
+ static void ensure_not_void (unsigned int type, struct token* name);
+ static int check_type_match (int type_num, struct production* exp);
+ static int get_common_type (struct production* type1, struct production* type2);
+ static struct production* make_integer_constant (struct token* value);
+ static void set_storage (struct production* prod);
+ 
+ /* File global variables.  */
+ 
+ static struct production* current_function=NULL;
+ 
+ %}
+ 
+ /* Not %raw - seems to have bugs.  */
+ %token_table
+ 
+ /* Punctuation.  */
+ %token RIGHT_BRACE
+ %token LEFT_BRACE
+ %token RIGHT_SQUARE_BRACKET
+ %token LEFT_SQUARE_BRACKET
+ %token RIGHT_PARENTHESIS
+ %token LEFT_PARENTHESIS
+ %token SEMICOLON
+ %token ASTERISK
+ %token COMMA
+ %right EQUALS
+ %right ASSIGN
+ %left  PLUS
+ %left  MINUS
+ 
+ /* Literals.  */
+ %token INTEGER
+ 
+ /* Keywords.  */
+ %token IF
+ %token ELSE
+ %token RETURN
+ %token CHAR
+ %token INT
+ %token UNSIGNED
+ %token VOID
+ %token TYPEDEF
+ %token NAME
+ %token STATIC
+ %token AUTOMATIC
+ %token EXTERNAL_DEFINITION
+ %token EXTERNAL_REFERENCE
+ 
+ /* Tokens not passed to parser.  */
+ %token WHITESPACE
+ %token COMMENT
+ 
+ /* Pseudo tokens - productions.  */
+ %token PROD_VARIABLE_NAME
+ %token PROD_TYPE_NAME
+ %token PROD_FUNCTION_NAME
+ %token PROD_INTEGER_CONSTANT
+ %token PROD_PLUS_EXPRESSION
+ %token PROD_MINUS_EXPRESSION
+ %token PROD_ASSIGN_EXPRESSION
+ %token PROD_VARIABLE_REFERENCE_EXPRESSION
+ %token PROD_PARAMETER
+ %token PROD_FUNCTION_INVOCATION
+ %expect 0 
+ %% 
+ 
+ file:
+ /* Nil.   */ {
+   /* Nothing to do.  */
+ }
+ declarations {
+   /* Nothing to do.  */
+ }
+ ;
+ 
+ 
+ declarations:
+ declaration {
+   /* Nothing to do.  */
+ }
+ |declarations declaration {
+   /* Nothing to do.  */
+ }
+ ;
+ 
+ declaration:
+ variable_def {
+   /* Nothing to do.  */
+ }
+ |function_prototype {
+   /* Nothing to do.  */
+ }
+ |function {
+   /* Nothing to do.  */
+ }
+ ;
+ 
+ variable_def:
+ storage typename NAME init_opt SEMICOLON {
+   struct token* tok;
+   struct production* prod;
+   tok = $3;
+   prod = make_production (PROD_VARIABLE_NAME, tok);
+   SYMBOL_TABLE_NAME (prod) = tok;
+   EXPRESSION_TYPE (prod) = $2;
+   VAR_INIT (prod) = $4;
+   NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct production*)EXPRESSION_TYPE (prod)));
+   ensure_not_void (NUMERIC_TYPE (prod), tok);
+   if (insert_tree_name (prod))
+     {
+       YYERROR;
+     }
+   STORAGE_CLASS_TOKEN (prod) = $1;
+   set_storage (prod);
+ 
+   if (VAR_INIT (prod))
+     {
+       if (! ((struct production*)VAR_INIT (prod))->code)
+         abort ();
+     if (STORAGE_CLASS (prod) == EXTERNAL_REFERENCE_STORAGE)
+       {
+         fprintf (stderr, "%s:%i:%i: External reference variables may not have initial value\n", in_fname, 
+                 tok->lineno, tok->charno);
+         print_token (stderr, 0, tok);
+         errorcount++;
+         YYERROR;
+       }
+     }
+   prod->code = tree_code_create_variable
+     (STORAGE_CLASS (prod), 
+      ((struct token*)SYMBOL_TABLE_NAME (prod))->chars,
+      ((struct token*)SYMBOL_TABLE_NAME (prod))->length,
+      NUMERIC_TYPE (prod),
+      VAR_INIT (prod)? ((struct production*)VAR_INIT (prod))->code:NULL,
+      in_fname,
+      tok->lineno);
+   if (!prod->code) 
+     abort ();
+ }
+ ;
+ 
+ storage:
+ STATIC
+ |AUTOMATIC
+ |EXTERNAL_DEFINITION
+ |EXTERNAL_REFERENCE
+ ;
+ 
+ parameter:
+ typename NAME {
+   struct token* tok;
+   struct production* prod;
+   struct production* prod2;
+   tok = $2;
+   prod = make_production (PROD_VARIABLE_NAME, tok);
+   SYMBOL_TABLE_NAME (prod) = $2;
+   EXPRESSION_TYPE (prod) = $1;
+   NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct production*)EXPRESSION_TYPE (prod)));
+   ensure_not_void (NUMERIC_TYPE (prod), tok);
+   if (insert_tree_name (prod))
+     {
+       YYERROR;
+     }
+   prod2 = make_production (PROD_PARAMETER, tok);
+   VARIABLE (prod2) = prod;
+   $$ = prod2;
+ }
+ ;
+ 
+ function_prototype:
+ storage typename NAME LEFT_PARENTHESIS parameters RIGHT_PARENTHESIS SEMICOLON {
+   struct token* tok;
+   struct production* prod;
+   struct production* type;
+   struct tree_parameter_list* first_parms;
+   struct tree_parameter_list* last_parms;
+   struct tree_parameter_list* this_parms;
+   struct production* this_parm;
+   struct production* this_parm_var;
+   tok = $3;
+   prod = make_production (PROD_FUNCTION_NAME, $3);
+   SYMBOL_TABLE_NAME (prod) = $3;
+   EXPRESSION_TYPE (prod) = $2;
+   NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct production*)EXPRESSION_TYPE (prod)));
+   PARAMETERS (prod) = reverse_prod_list ($5); 
+   insert_tree_name (prod);
+   STORAGE_CLASS_TOKEN (prod) = $1;
+   set_storage (prod);
+   switch (STORAGE_CLASS (prod))
+     { 
+     case STATIC_STORAGE:
+     case EXTERNAL_DEFINITION_STORAGE:
+       break;
+       
+     case AUTOMATIC_STORAGE:
+       fprintf (stderr, "%s:%i:%i: A function cannot be automatic\n", in_fname, 
+               tok->lineno, tok->charno);
+       print_token (stderr, 0, tok);
+       errorcount++;
+       YYERROR;
+       break;
+ 
+     default:
+       abort ();
+     }
+   type = EXPRESSION_TYPE (prod);
+   /* Create a parameter list in a non-front end specific format.  */
+   for (first_parms = NULL, last_parms = NULL, this_parm = PARAMETERS (prod);
+        this_parm;
+        this_parm = this_parm->next)
+     {
+       if (this_parm->category != production_category)
+         abort ();
+       this_parm_var = VARIABLE (this_parm);
+       if (!this_parm_var)
+         abort ();
+       if (this_parm_var->category != production_category)
+         abort ();
+       this_parms = my_malloc (sizeof (struct tree_parameter_list));
+       if (!this_parm_var->main_token)
+         abort ();
+       this_parms->variable_name = this_parm_var->main_token->chars;
+       this_parms->type = NUMERIC_TYPE (( (struct production*)EXPRESSION_TYPE (this_parm_var)));
+       if (last_parms)
+         {
+           last_parms->next = this_parms;
+           last_parms = this_parms;
+         }
+       else
+         {
+           first_parms = this_parms;
+           last_parms = this_parms;
+         }
+       this_parms->where_to_put_var_tree = & (( (struct production*)VARIABLE (this_parm))->code);
+     }
+   FIRST_PARMS (prod) = first_parms;
+ 
+   prod->code = tree_code_create_function_prototype
+     (tok->chars, STORAGE_CLASS (prod), NUMERIC_TYPE (type),
+      first_parms, in_fname, tok->lineno);
+ 
+ }
+ ;
+ 
+ function:
+ NAME LEFT_BRACE {
+   struct production* proto;
+   struct production search_prod;
+   struct token* tok;
+   struct production* this_parm;
+   tok = $1;
+   push_var_level ();
+   SYMBOL_TABLE_NAME ((&search_prod)) = tok;
+   current_function = proto = lookup_tree_name (&search_prod);
+   if (!proto)
+     {
+       fprintf (stderr, "%s:%i:%i: Function prototype not found\n", in_fname, 
+               tok->lineno, tok->charno);
+       print_token (stderr, 0, tok);
+       errorcount++;
+       YYERROR;
+     }
+   if (!proto->code)
+     abort ();
+   tree_code_create_function_initial
+     (proto->code, in_fname, tok->lineno,
+      FIRST_PARMS (current_function));
+ 
+   /* Check all the parameters have code.  */
+   for (this_parm = PARAMETERS (proto);
+        this_parm;
+        this_parm = this_parm->next)
+     {
+       if (! (struct production*)VARIABLE (this_parm))
+         abort ();
+       if (! (( (struct production*)VARIABLE (this_parm))->code))
+         abort ();
+     }
+ }
+ variable_defs_opt statements_opt RIGHT_BRACE {
+   struct token* tok;
+   tok = $1;
+   tree_code_create_function_wrapup (in_fname, tok->lineno);
+   current_function = NULL;
+   pop_var_level ();
+ }
+ ;
+ 
+ variable_defs_opt:
+ /* Nil.   */ {
+   $$ = 0;
+ }
+ |variable_defs {
+   $$ = $1;
+ }
+ ;
+ 
+ statements_opt:
+ /* Nil.   */ {
+   $$ = 0;
+ }
+ |statements {
+   $$ = $1;
+ }
+ ;
+ 
+ variable_defs:
+ variable_def {
+   /* Nothing to do.  */
+ }
+ |variable_defs variable_def {
+   /* Nothing to do.  */
+ }
+ ;
+ 
+ typename:
+ INT {
+   struct token* tok;
+   struct production* prod;
+   tok = $1;
+   prod = make_production (PROD_TYPE_NAME, tok);
+   NUMERIC_TYPE (prod) = SIGNED_INT;
+   prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+   $$ = prod;
+ }
+ |UNSIGNED INT {
+   struct token* tok;
+   struct production* prod;
+   tok = $1;
+   prod = make_production (PROD_TYPE_NAME, tok);
+   NUMERIC_TYPE (prod) = UNSIGNED_INT;
+   prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+   $$ = prod;
+ }
+ |CHAR {
+   struct token* tok;
+   struct production* prod;
+   tok = $1;
+   prod = make_production (PROD_TYPE_NAME, tok);
+   NUMERIC_TYPE (prod) = SIGNED_CHAR;
+   prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+   $$ = prod;
+ }
+ |UNSIGNED CHAR {
+   struct token* tok;
+   struct production* prod;
+   tok = $1;
+   prod = make_production (PROD_TYPE_NAME, tok);
+   NUMERIC_TYPE (prod) = UNSIGNED_CHAR;
+   prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+   $$ = prod;
+ }
+ |VOID {
+   struct token* tok;
+   struct production* prod;
+   tok = $1;
+   prod = make_production (PROD_TYPE_NAME, tok);
+   NUMERIC_TYPE (prod) = VOID_TYPE;
+   prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+   $$ = prod;
+ }
+ ;
+ 
+ parameters:
+ parameter {
+   /* Nothing to do.  */
+   $$ = $1;
+ }
+ |parameters COMMA parameter {
+   struct production* prod1;
+   prod1 = $3;
+   prod1->next = $1; /* Insert in reverse order.  */
+   $$ = prod1;
+ }
+ ;
+ 
+ statements:
+ statement {
+   /* Nothing to do.  */
+ }
+ |statements statement {
+   /* Nothing to do.  */
+ }
+ ;
+ 
+ statement:
+ expression SEMICOLON {
+   struct production* exp;
+   exp = $1;
+   tree_code_output_expression_statement (exp->code, in_fname, exp->main_token->lineno);
+ }
+ |return SEMICOLON {
+   /* Nothing to do.  */
+ }
+ |if_statement {
+   /* Nothing to do.  */
+ }
+ ;
+ 
+ if_statement:
+ IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS {
+   struct token* tok;
+   struct production* exp;
+   tok = $1;
+   exp = $3;
+   ensure_not_void (NUMERIC_TYPE (exp), exp->main_token);
+   tree_code_if_start (exp->code, in_fname, tok->lineno);
+ }
+ LEFT_BRACE statements_opt RIGHT_BRACE {
+   /* Just let the statements flow.  */
+ }
+ ELSE {
+   struct token* tok;
+   tok = $1;
+   tree_code_if_else (in_fname, tok->lineno);
+ }
+ LEFT_BRACE statements_opt RIGHT_BRACE {
+   struct token* tok;
+   tok = $12;
+   tree_code_if_end (in_fname, tok->lineno);
+ }
+ ;
+ 
+ 
+ return:
+ RETURN expression_opt {
+   struct production* type_prod;
+   struct token* ret_tok;
+   ret_tok = $1;
+   type_prod = EXPRESSION_TYPE (current_function);
+   if (NUMERIC_TYPE (type_prod) == VOID)
+     if ($2 == NULL)
+       tree_code_generate_return (type_prod->code, NULL);
+     else
+       {
+         fprintf (stderr, "%s:%i:%i: Redundant expression in return\n", in_fname, 
+                 ret_tok->lineno, ret_tok->charno);
+         print_token (stderr, 0, ret_tok);
+         errorcount++;
+         tree_code_generate_return (type_prod->code, NULL);
+       }
+   else
+     if ($2 == NULL)
+       {
+         fprintf (stderr, "%s:%i:%i: Expression missing in return\n", in_fname, 
+                 ret_tok->lineno, ret_tok->charno); 
+         print_token (stderr, 0, ret_tok);
+         errorcount++;
+       }
+     else
+       {
+         struct production* exp;
+         exp = $2;
+         /* Check same type.  */
+         if (check_type_match (NUMERIC_TYPE (type_prod), $2))
+           {
+             if (!type_prod->code)
+               abort ();
+             if (!exp->code)
+               abort ();
+             /* Generate the code. */
+             tree_code_generate_return (type_prod->code, exp->code);
+           }
+       }
+ }
+ ;
+ 
+ expression_opt:
+ /* Nil.   */ {
+   $$ = 0;
+ }
+ |expression {
+   struct production* exp;
+   exp = $1;
+   if (!exp->code)
+     abort ();
+   
+   $$ = $1;
+ }
+ ;
+ 
+ expression:
+ INTEGER {
+   $$ = make_integer_constant ($1);
+ }
+ |variable_ref {
+   $$ = $1;
+ }
+ |expression PLUS expression {
+   struct token* tok;
+   struct production* prod;
+   struct production* op1;
+   struct production* op2;
+   tree type;
+   
+   op1 = $1;
+   op2 = $3;
+   tok = $2;
+   ensure_not_void (NUMERIC_TYPE (op1), op1->main_token);
+   ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+   prod = make_production (PROD_PLUS_EXPRESSION, tok);
+   NUMERIC_TYPE (prod) = get_common_type (op1, op2);
+   if (!NUMERIC_TYPE (prod))
+     YYERROR;
+   else 
+     {
+       type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+       if (!type)
+         abort ();
+       OP1 (prod) = $1;
+       OP2 (prod) = $3;
+       
+       prod->code = tree_code_get_expression
+         (EXP_PLUS, type, op1->code, op2->code, NULL);
+     }
+   $$ = prod;
+ }
+ |expression MINUS expression %prec PLUS {
+   struct token* tok;
+   struct production* prod;
+   struct production* op1;
+   struct production* op2;
+   tree type;
+   
+   op1 = $1;
+   op2 = $3;
+   ensure_not_void (NUMERIC_TYPE (op1), op1->main_token);
+   ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+   tok = $2;
+   prod = make_production (PROD_PLUS_EXPRESSION, tok);
+   NUMERIC_TYPE (prod) = get_common_type (op1, op2);
+   if (!NUMERIC_TYPE (prod))
+     YYERROR;
+   else 
+     {
+       type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+       if (!type)
+         abort ();
+       OP1 (prod) = $1;
+       OP2 (prod) = $3;
+       
+       prod->code = tree_code_get_expression (EXP_MINUS, 
+                                           type, op1->code, op2->code, NULL);
+     }
+   $$ = prod;
+ }
+ |expression EQUALS expression {
+   struct token* tok;
+   struct production* prod;
+   struct production* op1;
+   struct production* op2;
+   tree type;
+   
+   op1 = $1;
+   op2 = $3;
+   ensure_not_void (NUMERIC_TYPE (op1), op1->main_token);
+   ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+   tok = $2;
+   prod = make_production (PROD_PLUS_EXPRESSION, tok);
+   NUMERIC_TYPE (prod) = SIGNED_INT;
+   if (!NUMERIC_TYPE (prod))
+     YYERROR;
+   else 
+     {
+       type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+       if (!type)
+         abort ();
+       OP1 (prod) = $1;
+       OP2 (prod) = $3;
+       
+       prod->code = tree_code_get_expression (EXP_EQUALS, 
+                                           type, op1->code, op2->code, NULL);
+     }
+   $$ = prod;
+ }
+ |variable_ref ASSIGN expression {
+   struct token* tok;
+   struct production* prod;
+   struct production* op1;
+   struct production* op2;
+   tree type;
+   
+   op1 = $1;
+   op2 = $3;
+   tok = $2;
+   ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+   prod = make_production (PROD_ASSIGN_EXPRESSION, tok);
+   NUMERIC_TYPE (prod) = NUMERIC_TYPE (op1);
+   if (!NUMERIC_TYPE (prod))
+     YYERROR;
+   else 
+     {
+       type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+       if (!type)
+         abort ();
+       OP1 (prod) = $1;
+       OP2 (prod) = $3;
+       prod->code = tree_code_get_expression (EXP_ASSIGN, 
+                                           type, op1->code, op2->code, NULL);
+     }
+   $$ = prod;
+ }
+ |function_invocation {
+   $$ = $1;
+ }
+ ;
+ 
+ function_invocation:
+ NAME LEFT_PARENTHESIS expressions_with_commas RIGHT_PARENTHESIS {
+   struct production* prod;
+   struct token* tok;
+   struct production search_prod;
+   struct production* proto;
+   struct production* exp;
+   struct production* exp_proto;
+   struct production* var;
+   int exp_proto_count;
+   int exp_count;
+   tree parms;
+   tree type;
+   
+   tok = $1;
+   prod = make_production (PROD_FUNCTION_INVOCATION, tok);
+   SYMBOL_TABLE_NAME (prod) = tok;
+   PARAMETERS (prod) = reverse_prod_list ($3);
+   SYMBOL_TABLE_NAME ((&search_prod)) = tok;
+   proto = lookup_tree_name (&search_prod);
+   if (!proto)
+     {
+       fprintf (stderr, "%s:%i:%i: Function prototype not found\n", in_fname, 
+               tok->lineno, tok->charno);
+       print_token (stderr, 0, tok);
+       errorcount++;
+       YYERROR;
+     }
+   EXPRESSION_TYPE (prod) = EXPRESSION_TYPE (proto);
+   NUMERIC_TYPE (prod) = NUMERIC_TYPE (proto);
+   /* Count the expressions and ensure they match the prototype.  */
+   for (exp_proto_count = 0, exp_proto = PARAMETERS (proto); 
+        exp_proto; exp_proto = exp_proto->next)
+     exp_proto_count++;
+ 
+   for (exp_count = 0, exp = PARAMETERS (prod); exp; exp = exp->next)
+     exp_count++;
+ 
+   if (exp_count !=  exp_proto_count)
+     {
+       fprintf (stderr, "%s:%i:%i: expression count mismatch with prototype\n", in_fname, 
+               tok->lineno, tok->charno);
+       print_token (stderr, 0, tok);
+       errorcount++;
+       YYERROR;
+     }
+   parms = tree_code_init_parameters ();
+   for (exp_proto = PARAMETERS (proto), exp = PARAMETERS (prod);
+        exp_proto;
+        exp = exp->next, exp_proto = exp_proto->next)
+   {
+     if (!exp)
+       abort ();
+     if (!exp_proto)
+       abort ();
+     if (!exp->code)
+       abort ();
+     var = VARIABLE (exp_proto);
+     if (!var)
+       abort ();
+     if (!var->code)
+       abort ();
+     parms = tree_code_add_parameter (parms, var->code, exp->code);
+   }
+   type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+   prod->code = tree_code_get_expression
+     (EXP_FUNCTION_INVOCATION, type, proto->code, parms, NULL);
+   $$ = prod;
+ }
+ ;
+ 
+ expressions_with_commas:
+ expression {
+   struct production* exp;
+   exp = $1;
+   ensure_not_void (NUMERIC_TYPE (exp), exp->main_token);
+   $$ = $1;
+ }
+ |expressions_with_commas COMMA expression {
+   struct production* exp;
+   exp = $3;
+   ensure_not_void (NUMERIC_TYPE (exp), exp->main_token);
+   exp->next = $1; /* Reverse order.  */
+   $$ = exp;
+ }
+ ;
+ 
+ variable_ref:
+ NAME {
+   struct production search_prod;
+   struct production* prod;
+   struct production* symbol_table_entry;
+   struct token* tok;
+   tree type;
+ 
+   tok = $1;
+   SYMBOL_TABLE_NAME ((&search_prod)) = tok;
+   symbol_table_entry = lookup_tree_name (&search_prod);
+   if (!symbol_table_entry)
+     {
+       fprintf (stderr, "%s:%i:%i: Variable referred to but not defined\n", in_fname, 
+               tok->lineno, tok->charno);
+       print_token (stderr, 0, tok);
+       errorcount++;
+       YYERROR;
+     }
+ 
+   prod = make_production (PROD_VARIABLE_REFERENCE_EXPRESSION, tok);
+   NUMERIC_TYPE (prod) = NUMERIC_TYPE (symbol_table_entry);
+   type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+   if (!NUMERIC_TYPE (prod))
+     YYERROR;
+   OP1 (prod) = $1;
+   
+   prod->code = tree_code_get_expression (EXP_REFERENCE, type, 
+                                       symbol_table_entry->code, NULL, NULL);
+   $$ = prod;
+ }
+ ;
+ 
+ init_opt:
+ /* Nil.   */ {
+   $$ = 0;
+ }
+ |init {
+   /* Nothing to do.  */
+ }
+ 
+ init:
+ ASSIGN init_element {
+ }
+ ;
+ 
+ init_element:
+ INTEGER {
+   $$ = make_integer_constant ($1);
+ }
+ ;
+ 
+ %%
+ 
+ /* Print a token VALUE to file FILE.  Ignore TYPE which is the token
+    type. */
+ 
+ void
+ print_token (FILE * file, unsigned int  type ATTRIBUTE_UNUSED, YYSTYPE value) 
+ {
+   struct token *tok;
+   unsigned int  ix;
+ 
+   tok  =  value;
+   fprintf (file, "%d \"", tok->lineno);
+   for (ix  =  0; ix < tok->length; ix++)
+     fprintf (file, "%c", tok->chars[ix]);
+   fprintf (file, "\"");
+ }
+ 
+ /* Output a message ERROR_MESSAGE from the parser.  */
+ void
+ yyerror (const char *error_message)
+ {
+   struct token *tok;
+   
+   tok = yylval;
+   if (tok)
+     {
+       fprintf (stderr, "%s:%i:%i: %s\n", in_fname, tok->lineno, tok->charno, error_message);
+       print_token (stderr, 0, tok);
+     }
+   else
+     fprintf (stderr, "%s\n", error_message);
+   
+   errorcount++;
+ 
+ }
+ 
+ /* Reverse the order of a token list, linked by parse_next, old first
+    token is OLD_FIRST.  */
+ 
+ static struct production*
+ reverse_prod_list (struct production* old_first)
+ {
+   struct production* current;
+   struct production* next;
+   struct production* prev = NULL;
+   
+   current = old_first;
+   prev = NULL;
+ 
+   while (current) 
+     {
+       if (current->category != production_category)
+         abort ();
+       next = current->next;
+       current->next = prev;
+       prev = current;
+       current = next; 
+     }
+   return prev;
+ }
+ 
+ /* Ensure TYPE is not VOID. Use NAME as the token for the error location.  */
+ 
+ static void
+ ensure_not_void (unsigned int type, struct token* name)
+ {
+   if (type == VOID)
+     {
+       fprintf (stderr, "%s:%i:%i: Type must not be void in this context\n", in_fname, 
+               name->lineno, name->charno);
+       print_token (stderr, 0, name);
+       errorcount++;
+     }
+ }
+ 
+ /* Check TYPE1 and TYPE2 which are integral types.  Return the lowest
+    common type (min is signed int).  */
+ 
+ static int 
+ get_common_type (struct production* type1, struct production* type2)
+ {
+   if (NUMERIC_TYPE (type1) == UNSIGNED_INT)
+     return UNSIGNED_INT;
+   if (NUMERIC_TYPE (type2) == UNSIGNED_INT)
+     return UNSIGNED_INT;
+ 
+   return SIGNED_INT;
+ }
+ 
+ /* Check type (TYPE_NUM) and expression (EXP) match.  Return the 1 if
+    OK else 0.  Must be exact match - same name unless it is an
+    integral type.  */
+ 
+ static int 
+ check_type_match (int type_num, struct production* exp)
+ {
+   switch (type_num)
+     {
+     case SIGNED_INT:
+     case UNSIGNED_INT:
+     case SIGNED_CHAR:
+     case UNSIGNED_CHAR:
+       switch (NUMERIC_TYPE (exp))
+         {
+         case SIGNED_INT:
+         case UNSIGNED_INT:
+         case SIGNED_CHAR:
+         case UNSIGNED_CHAR:
+           return 1;
+           
+         case VOID:
+           abort ();
+       
+         default: 
+           abort ();
+         }
+       break;
+       
+     case VOID:
+       abort ();
+       
+     default:
+       abort ();
+       
+     }
+ }
+ 
+ /* Make a production for an integer constant VALUE.  */
+ 
+ static struct production* 
+ make_integer_constant (struct token* value)
+ {
+   struct token* tok;
+   struct production* prod;
+   tok = value;
+   prod = make_production (PROD_INTEGER_CONSTANT, tok);
+   if ((tok->chars[0] == (unsigned char)'-')|| (tok->chars[0] == (unsigned char)'+'))
+     NUMERIC_TYPE (prod) = SIGNED_INT;
+   else
+     NUMERIC_TYPE (prod) = UNSIGNED_INT;
+   prod->code = tree_code_get_integer_value (tok->chars, tok->length);
+   return prod;
+ }
+ 
+ /* Set STORAGE_CLASS in PROD according to CLASS_TOKEN.  */
+ 
+ static void
+ set_storage (struct production* prod)
+ {
+   struct token* stg_class;
+   stg_class = STORAGE_CLASS_TOKEN (prod);
+   switch (stg_class->type)
+     {
+     case STATIC:
+       STORAGE_CLASS (prod) = STATIC_STORAGE;
+       break;
+       
+     case AUTOMATIC:
+       STORAGE_CLASS (prod) = AUTOMATIC_STORAGE;
+       break;
+       
+     case EXTERNAL_DEFINITION:
+       STORAGE_CLASS (prod) = EXTERNAL_DEFINITION_STORAGE;
+       break;
+ 
+     case EXTERNAL_REFERENCE:
+       STORAGE_CLASS (prod) = EXTERNAL_REFERENCE_STORAGE;
+       break;
+ 
+     default:
+       abort ();
+     }
+ }
diff -c3prN gcccvs/gcc/gcc/treelang/tree1.c newgcc/gcc/treelang/tree1.c
*** gcccvs/gcc/gcc/treelang/tree1.c	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/tree1.c	Sat Jul 28 11:24:04 2001
***************
*** 0 ****
--- 1,449 ----
+ /* 
+ 
+     TREELANG Compiler almost main (tree1)
+     Called by GCC's toplev.c
+ 
+     Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+     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, 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, 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ 
+     In other words, you are welcome to use, share and improve this program.
+     You are forbidden to forbid anyone else to use, share and improve
+     what you give them.   Help stamp out software-hoarding!  
+ 
+     ---------------------------------------------------------------------------
+ 
+     Written by Tim Josling 1999, 2000, 2001, based in part on other
+     parts of the GCC compiler.
+ 
+ */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "gansidecl.h"
+ #include "flags.h"
+ #include "output.h"
+ #include "toplev.h"
+ 
+ #include "ggc.h"
+ #include "tree.h"
+ 
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <ctype.h>
+ #include <stdarg.h>
+ #include <string.h>
+ #include <stdio.h>
+ 
+ #include "treelang.h"
+ 
+ /* Each front end provides its own.  */
+ static void tree_init (void);
+ static void tree_finish (void);
+ static void tree_init_options (void);
+ static int tree_decode_option (int, char**);
+ static void tree_post_options (void);
+ 
+ /* Linked list of symbols - all must be unique in treelang.  */
+ 
+ struct production* symbol_table = NULL;
+ 
+ /* Hooks for back end and toplev.c.  */
+ 
+ struct lang_hooks lang_hooks = 
+ {tree_init,
+  tree_finish, 
+  tree_init_options,
+  tree_decode_option,
+  tree_post_options};
+ 
+ /* Language for usage for messages.  */
+ 
+ const char* const language_string = "TREELANG - sample front end for GCC ";
+ 
+ /* Local prototypes.  */
+ 
+ void version (void);
+ 
+ /* Fake parse routine in this module - name dictated by toplev.c.  */
+ int yyparse (void);
+ 
+ /* Real parse module in treeprs.c.  */
+ int tree_parse (void);
+ 
+ /* GC routine for symbol table.  */
+ static void symbol_table_ggc (void* m);
+ 
+ /* Global variables.  */
+ 
+ extern int errorcount; 
+ 
+ extern struct cbl_tree_struct_parse_tree_top* parse_tree_top;
+ 
+ /* 
+    Options. 
+ */
+ 
+ /* Trace the parser.  */
+ 
+ extern int yydebug;
+ unsigned int option_parser_trace = 0;
+ 
+ /* Trace the lexical analysis.  */
+ 
+ unsigned int option_lexer_trace = 0;
+ 
+ /* Warning levels.  */
+ 
+ /* Local variables.  */
+ 
+ unsigned char* in_fname = NULL;	/* Input file name.  */
+ 
+ /* This is 1 if we have output the version string.  */
+ 
+ static int version_done = 0;
+ 
+ /* Variable nesting level.  */
+ 
+ static unsigned int current_nesting_level = 0;
+ 
+ /* Process one switch - called by toplev.c.  */
+ 
+ int
+ tree_decode_option (num_options_left, first_option_left)
+      int num_options_left ATTRIBUTE_UNUSED; 
+      char** first_option_left;
+ {
+   
+   /*
+     Process options - bear in mind I may get options that are really
+     meant for someone else (eg the main compiler) so I have to be very
+     permissive. 
+     
+   */
+   
+   if (first_option_left[0][0] != '-')
+     return 0; 
+   
+   switch (first_option_left[0][1]) 
+     {
+     case '-':
+       if (!strcmp (first_option_left[0],"--help"))
+         {
+           if (!version_done)
+             {
+               fputs (language_string, stdout);
+               fputs (version_string, stdout);
+               fputs ("\n", stdout);
+               version_done = 1;
+             }
+           fprintf (stdout, "Usage: tree1 [switches] -o output input\n");
+           return 1;
+         }
+     case 'v':
+       if (!strcmp (first_option_left[0],"-v"))
+         {
+           if (!version_done)
+             {
+               fputs (language_string, stdout);
+               fputs (version_string, stdout);
+               fputs ("\n", stdout);
+               version_done = 1;
+             }
+           return 1;
+         }
+     case 'f':
+       if (!strcmp (first_option_left[0],"-fparser-trace"))
+         {
+           option_parser_trace = 1;
+           yydebug = 1;
+           return 1;
+         }
+       if (!strcmp (first_option_left[0],"-flexer-trace"))
+         {
+           option_lexer_trace = 1;
+           return 1;
+         }
+       return 0;
+ 
+     case 'w':
+       if (!strcmp (first_option_left[0],"-w"))
+         {
+           /* Tolerate this option but ignore it - we always put out
+              all warnings.  */
+           return 1;
+         }
+       return 0;
+ 
+     case 'W':
+       if (!strcmp (first_option_left[0],"-Wall"))
+         {
+           return 1;
+         }
+       return 0;
+ 
+     default:
+       return 0;
+     }
+ 
+   return 0;
+ 
+ }
+ 
+ /* Initialize options.  */
+ 
+ void 
+ tree_init_options (void)
+ {
+ }
+ 
+ /* Wrap up options.  */
+ 
+ void 
+ tree_post_options (void)
+ {
+ }
+ 
+ /* Performs whatever initialization steps are needed by the
+    language-dependent front end.  */
+ 
+ void
+ tree_init (void)
+ {
+   /* Define my garbage collection routines.  */
+   ggc_add_root (&symbol_table, 1, 
+                 /* Unused size.  */ sizeof (void*), symbol_table_ggc);
+   /* Note: only storage that has to be kept across functions needs to
+      be protected from GC.  */
+ }
+ 
+ /* Performs whatever wrapup steps are needed by the language-dependent
+    front end. */
+ 
+ void
+ tree_finish (void)
+ {
+ }
+ 
+ /* Language dependent parser setup.  */
+ 
+ const char*
+ init_parse (const char* filename)
+ {
+   /* This error will not happen from GCC as it will always create a
+      fake input file.  */
+   if (!filename || (filename[0] == ' ') || (!filename[0])) 
+     {
+       if (!version_done)
+         {
+           fprintf (stderr, "No input file specified, try --help for help\n");
+           exit (1);
+         }
+ 
+       in_fname = NULL;
+       return NULL;
+     }
+   yyin = fopen (filename, "r");
+   if (!yyin)
+     {
+       fprintf (stderr, "Unable to open input file %s\n", filename);
+       exit (1);
+     }
+   return (char*) (in_fname = (unsigned char*)filename);
+ }
+ 
+ /* Language dependent wrapup.  */
+ 
+ void 
+ finish_parse (void)
+ {
+   fclose (yyin);
+ }
+ 
+ /* Return a short string identifying this language to the debugger.  */
+ 
+ const char*
+ lang_identify (void)
+ { 
+   return "treelang";
+ }
+ 
+ /* Print language-specific statistics.  */
+ 
+ void
+ print_lang_statistics (void)
+ {
+ }
+ 
+ /* Scan the symbol table* M, marking storage used.  */
+ 
+ static void
+ symbol_table_ggc (void* m)
+ {
+   struct production* pp;
+   pp = * (struct production**)m;
+   /* Actually it is a pointer to a pointer, to allow reallocation and
+      relinking.  */
+   mark_production_used (pp);
+ }
+ 
+ /* Mark a production PP as used so it wont be garbage collected.  */
+ 
+ void
+ mark_production_used (struct production* pp)
+ {
+   int sub_ix;
+  loop:
+   if (!pp)
+     return;
+   ggc_mark (pp);
+   
+   if (pp->category == token_category)
+     {
+       mark_token_used ((struct token*)pp);
+       return;
+     }
+   if (pp->category != production_category)
+     abort ();
+   mark_token_used (pp->main_token);
+   for (sub_ix = 0; sub_ix < SUB_COUNT; sub_ix++)
+     mark_production_used (pp->sub[sub_ix]);
+   /* The macro tests for NULL so I don't need to.  */
+   ggc_mark_tree (pp->code);
+   pp = pp->next;
+   goto loop;
+ }
+ 
+ /* Mark a token TT as used so it wont be garbage collected.  */
+ 
+ void
+ mark_token_used (struct token* tt)
+ {
+   if (!tt) 
+     return;
+   ggc_mark (tt);
+   if (tt->chars)
+     ggc_mark (tt->chars);
+ }
+ 
+ /* Set debug (-y) option.  */
+ 
+ void
+ set_yydebug (int value ATTRIBUTE_UNUSED)
+ {
+   option_parser_trace = 1;
+   option_lexer_trace = 1;
+ }
+ 
+ /* Allocate SIZE bytes and clear them.  */
+ 
+ void*
+ my_malloc (size_t size)
+ {
+   void* mem;
+   mem = ggc_alloc (size);
+   if (!mem)
+     {
+       fprintf (stderr, "\nOut of memory\n");
+       abort ();
+     }
+   memset (mem,0,size);
+   return mem;
+ }
+ 
+ /* Look up a name in PROD->SYMBOL_TABLE_NAME in the symbol table;
+    return the symbol table entry from the symbol table if found there,
+    else 0.  */
+ 
+ struct production*
+ lookup_tree_name (struct production* prod)
+ {
+   struct production* this;
+   struct token* this_tok;
+   struct token* tok;
+   tok = SYMBOL_TABLE_NAME (prod);
+   for (this = symbol_table; this; this = this->next)
+     {
+       this_tok = this->main_token;
+       if (tok->length != this_tok->length) 
+         continue;
+       if (memcmp (tok->chars, this_tok->chars, this_tok->length))
+         continue;
+       if (option_parser_trace)
+         fprintf (stderr, "Found symbol %s (%i:%i) as %i \n", tok->chars, 
+                 tok->lineno, tok->charno, NUMERIC_TYPE (this));
+       return this;
+     }
+   if (option_parser_trace)
+     fprintf (stderr, "Not found symbol %s (%i:%i) as %i \n", tok->chars, 
+             tok->lineno, tok->charno, tok->type);
+   return NULL;
+ }
+ 
+ /* Insert name PROD into the symbol table.  Return 1 if duplicate, 0 if OK.  */
+ 
+ int
+ insert_tree_name (struct production* prod)
+ {
+   struct token* tok;
+   tok = SYMBOL_TABLE_NAME (prod);
+   if (lookup_tree_name (prod))
+     {
+       fprintf (stderr, "%s:%i:%i duplicate name %s\n", in_fname, tok->lineno, tok->charno, tok->chars);
+       errorcount++;
+       return 1;
+     }
+   prod->next = symbol_table;
+   NESTING_LEVEL (prod) = current_nesting_level;
+   symbol_table = prod;
+   return 0;
+ }
+ 
+ void
+ push_var_level (void)
+ {
+   current_nesting_level++;
+ }
+ 
+ /* Pop variable nesting level and remove those variable from symbol table.  */
+ 
+ void
+ pop_var_level (void)
+ {
+   current_nesting_level--;
+ 
+   while (symbol_table)
+     {
+       if (NESTING_LEVEL (symbol_table) > current_nesting_level)
+         symbol_table = symbol_table->next;
+       else
+         break;
+     }
+ }
+ 
+ 
+ /* Create a struct productions of type TYPE, main token MAIN_TOK.  */
+ 
+ struct production* 
+ make_production (int type, struct token* main_tok)
+ {
+   struct production* prod;
+   prod = my_malloc (sizeof (struct production));
+   prod->category = production_category;
+   prod->type = type;
+   prod->main_token = main_tok;
+   return prod;
+ }
diff -c3prN gcccvs/gcc/gcc/treelang/treelang.h newgcc/gcc/treelang/treelang.h
*** gcccvs/gcc/gcc/treelang/treelang.h	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/treelang.h	Sun Jun 10 21:30:31 2001
***************
*** 0 ****
--- 1,114 ----
+ /* 
+ 
+     TREELANG Compiler common definitions (treelang.h)
+ 
+     Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+     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, 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, 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ 
+     In other words, you are welcome to use, share and improve this program.
+     You are forbidden to forbid anyone else to use, share and improve
+     what you give them.   Help stamp out software-hoarding!  
+ 
+     ---------------------------------------------------------------------------
+ 
+     Written by Tim Josling 1999, 2000, 2001, based in part on other
+     parts of the GCC compiler.
+ 
+ */
+ 
+ /* Parse structure type.  */
+ enum category_enum 
+ {
+   token_category = 111,
+   production_category = 222
+ };
+ 
+ /* Input file name and FILE.  */
+ extern unsigned char* in_fname;
+ extern FILE* yyin;
+ 
+ extern int errorcount; /* In toplev.c.  */
+ 
+ struct token
+ {
+   enum category_enum category; /* Token or production. */
+   unsigned int type; /* Token type.  */
+   /* Prior to this point, production must match token.  */
+   unsigned int lineno;
+   unsigned int charno;
+   unsigned int length; /* The value.  */
+   unsigned char* chars;
+ };
+ 
+ struct production
+ {
+   enum category_enum category; /* Token or Production. */
+   unsigned int type; /* Production type - a fake token name.  */
+   /* Prior to this point, production must match token.  */
+   struct token* main_token; /* Main token for error msgs; variable name token.  */
+ 
+   unsigned int info[2]; /* Extra information.  */
+ #define NESTING_LEVEL(a) a->info[0]  /* Level used for variable definitions.  */
+ #define NUMERIC_TYPE(a)  a->info[1]  /* Numeric type used in type definitions and expressions.  */
+ 
+ 
+ #define SUB_COUNT 5
+   void* sub[SUB_COUNT]; /* Sub productions or tokens.  */
+ 
+ #define SYMBOL_TABLE_NAME(a) (a->sub[0]) /* Name token.  */
+ 
+ #define EXPRESSION_TYPE(a) (a->sub[1]) /* Type identifier.  */
+ 
+ #define OP1(a) (a->sub[2]) /* Exp operand1.  */
+ #define PARAMETERS(a) (a->sub[2]) /* Function parameters.  */
+ #define VARIABLE(a) (a->sub[2]) /* Parameter variable ptr.  */
+ #define VAR_INIT(a) (a->sub[2]) /* Variable init.  */
+ 
+ #define OP2(a) (a->sub[3]) /* Exp operand2.  */
+ #define FIRST_PARMS(a) (a->sub[3]) /* Function parameters linked via struct tree_parameter_list.  */
+ 
+ #define OP3(a) (a->sub[4]) /* Exp operand3.  */
+ #define STORAGE_CLASS_TOKEN(a) (a->sub[4]) /* Storage class token.  */
+ 
+   void* code; /* Back end hook for this item.  */
+   struct production* next; /* Next in chains of various types.  */
+ 
+   unsigned int flag1:2;
+ #define STORAGE_CLASS(a) a->flag1 /* Values in treetree.h.  */
+ 
+   unsigned int flag2:1;
+   unsigned int flag3:1;
+   unsigned int flag4:1;
+   unsigned int flag5:1;
+   unsigned int flag6:1;
+   unsigned int flag7:1;
+ 
+ };
+ 
+ /* For parser. Alternatively you can define it using %union (bison) or
+    union. */
+ #define YYSTYPE void*
+ 
+ void* my_malloc (size_t size);
+ int insert_tree_name (struct production* prod);
+ struct production* lookup_tree_name (struct production* prod);
+ void push_var_level (void);
+ void pop_var_level (void);
+ struct production* make_production (int type, struct token* main_tok);
+ void mark_production_used (struct production * pp);
+ void mark_token_used (struct token* tt);
+ 
diff -c3prN gcccvs/gcc/gcc/treelang/treelang.texi newgcc/gcc/treelang/treelang.texi
*** gcccvs/gcc/gcc/treelang/treelang.texi	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/treelang.texi	Sun Jun 10 18:54:40 2001
***************
*** 0 ****
--- 1,1311 ----
+ \input texinfo  @c -*-texinfo-*-
+ @c %**start of header
+ @setfilename treelang.info
+ 
+ @set last-update 2001-07-30
+ @set copyrights-treelang 1995,1996,1997,1998,1999,2000,2001
+ @c DEVELOPMENT is set to indicate an in-development version,
+ @c as compared to a release version.  When making a release
+ @c (e.g. a release branch in the CVS repository for GCC),
+ @c clear this and set the version information correctly.
+ @clear DEVELOPMENT
+ @set version-treelang 1.0
+ @set version-GCC 3.0
+ 
+ @set email-general gcc@@gcc.gnu.org
+ @set email-bugs gcc-bugs@@gcc.gnu.org or bug-gcc@@gnu.org
+ @set email-patches gcc-patches@@gcc.gnu.org 
+ @set path-treelang gcc/gcc/treelang
+ 
+ @set which-treelang GCC-@value{version-GCC}
+ @set which-GCC GCC
+ 
+ @set email-josling tej@@melbpc.org.au
+ @set www-josling http://www.geocities.com/timjosling
+ 
+ @c This tells @include'd files that they're part of the overall TREELANG doc
+ @c set.  (They might be part of a higher-level doc set too.)
+ @set DOC-TREELANG
+ 
+ @c @setfilename usetreelang.info
+ @c @setfilename maintaintreelang.info
+ @c To produce the full manual, use the "treelang.info" setfilename, and
+ @c make sure the following do NOT begin with '@c' (and the @clear lines DO)
+ @set INTERNALS
+ @set USING
+ @c To produce a user-only manual, use the "usetreelang.info" setfilename, and
+ @c make sure the following does NOT begin with '@c':
+ @c @clear INTERNALS
+ @c To produce a maintainer-only manual, use the "maintaintreelang.info" setfilename,
+ @c and make sure the following does NOT begin with '@c':
+ @c @clear USING
+ 
+ @c 6/27/96 FSF DO wants smallbook fmt for 1st bound edition. (from gcc.texi)
+ @c @smallbook
+ 
+ @c i also commented out the finalout command, so if there *are* any
+ @c overfulls, you'll (hopefully) see the rectangle in the right hand
+ @c margin. -- burley 1999-03-13 (from mew's comment in GCC.texi).
+ @c @finalout
+ 
+ @ifset INTERNALS
+ @ifset USING
+ @settitle Using and Maintaining GNU Treelang
+ @end ifset
+ @end ifset
+ @c seems reasonable to assume at least one of INTERNALS or USING is set...
+ @ifclear INTERNALS
+ @settitle Using GNU Treelang
+ @end ifclear
+ @ifclear USING
+ @settitle Maintaining GNU Treelang
+ @end ifclear
+ @c then again, have some fun
+ @ifclear INTERNALS
+ @ifclear USING
+ @settitle Doing Very Little at all with GNU Treelang
+ @end ifclear
+ @end ifclear
+ 
+ @syncodeindex fn cp
+ @syncodeindex vr cp
+ @c %**end of header
+ 
+ @c Cause even numbered pages to be printed on the left hand side of
+ @c the page and odd numbered pages to be printed on the right hand
+ @c side of the page.  Using this, you can print on both sides of a
+ @c sheet of paper and have the text on the same part of the sheet.
+ 
+ @c The text on right hand pages is pushed towards the right hand
+ @c margin and the text on left hand pages is pushed toward the left
+ @c hand margin.
+ @c (To provide the reverse effect, set bindingoffset to -0.75in.)
+ 
+ @c @tex
+ @c \global\bindingoffset=0.75in
+ @c \global\normaloffset =0.75in
+ @c @end tex
+ 
+ @ifinfo
+ @dircategory Programming
+ @direntry
+ * treelang: (treelang).                  The GNU Treelang compiler.
+ @end direntry
+ @ifset INTERNALS
+ @ifset USING
+ This file documents the use and the internals of the GNU Treelang
+ (@code{treelang}) compiler. At the moment this manual is not
+ incorporated into the main GCC manual as it is too incomplete. It
+ corresponds to the @value{which-treelang} version of @code{treelang}.
+ @end ifset
+ @end ifset
+ @ifclear USING
+ This file documents the internals of the GNU Treelang (@code{treelang}) compiler.
+ It corresponds to the @value{which-treelang} version of @code{treelang}.
+ @end ifclear
+ @ifclear INTERNALS
+ This file documents the use of the GNU Treelang (@code{treelang}) compiler.
+ It corresponds to the @value{which-treelang} version of @code{treelang}.
+ @end ifclear
+ 
+ Published by the Free Software Foundation
+ 59 Temple Place - Suite 330
+ Boston, MA 02111-1307 USA
+ 
+ Copyright (C) @value{copyrights-treelang} Free Software Foundation, Inc.
+ 
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.1 or
+ any later version published by the Free Software Foundation; with the
+ Invariant Sections being ``GNU General Public License'', the Front-Cover
+ texts being (a) (see below), and with the Back-Cover Texts being (b)
+ (see below).  A copy of the license is included in the section entitled
+ ``GNU Free Documentation License''.
+ 
+ (a) The FSF's Front-Cover Text is:
+ 
+      A GNU Manual
+ 
+ (b) The FSF's Back-Cover Text is:
+ 
+      You have freedom to copy and modify this GNU Manual, like GNU
+      software.  Copies published by the Free Software Foundation raise
+      funds for GNU development.
+ @end ifinfo
+ 
+ treelang was Contributed by Tim Josling (@email{@value{email-josling}}).
+ Inspired by and based on the 'toy' language, written by Richard Kenner.
+ 
+ This document was written by Tim Josling, based on the GNU C++
+ documentation.
+ 
+ @setchapternewpage odd
+ @c @finalout
+ @titlepage
+ @ifset INTERNALS
+ @ifset USING
+ @center @titlefont{Using and Maintaining GNU Treelang}
+ 
+ @end ifset
+ @end ifset
+ @ifclear INTERNALS
+ @title Using GNU Treelang
+ @end ifclear
+ @ifclear USING
+ @title Maintaining GNU Treelang
+ @end ifclear
+ @sp 2
+ @center Tim Josling
+ @sp 3
+ @center Last updated @value{last-update}
+ @sp 1
+ @center for version @value{version-treelang}
+ @page
+ @vskip 0pt plus 1filll
+ Copyright @copyright{} @value{copyrights-treelang} Free Software Foundation, Inc.
+ @sp 2
+ For the @value{which-treelang} Version*
+ @sp 1
+ Published by the Free Software Foundation @*
+ 59 Temple Place - Suite 330@*
+ Boston, MA 02111-1307, USA@*
+ @c Last printed ??ber, 19??.@*
+ @c Printed copies are available for $? each.@*
+ @c ISBN ???
+ @sp 1
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.1 or
+ any later version published by the Free Software Foundation; with the
+ Invariant Sections being ``GNU General Public License'', the Front-Cover
+ texts being (a) (see below), and with the Back-Cover Texts being (b)
+ (see below).  A copy of the license is included in the section entitled
+ ``GNU Free Documentation License''.
+ 
+ (a) The FSF's Front-Cover Text is:
+ 
+      A GNU Manual
+ 
+ (b) The FSF's Back-Cover Text is:
+ 
+      You have freedom to copy and modify this GNU Manual, like GNU
+      software.  Copies published by the Free Software Foundation raise
+      funds for GNU development.
+ @end titlepage
+ @page
+ 
+ @ifinfo
+ 
+ @node Top, Copying,, (dir)
+ @top Introduction
+ @cindex Introduction
+ 
+ @ifset INTERNALS
+ @ifset USING
+ This manual documents how to run, install and maintain @code{treelang},
+ as well as its new features and incompatibilities,
+ and how to report bugs.
+ It corresponds to the @value{which-treelang} version of @code{treelang}.
+ @end ifset
+ @end ifset
+ 
+ @ifclear INTERNALS
+ This manual documents how to run and install @code{treelang},
+ as well as its new features and incompatibilities, and how to report
+ bugs.
+ It corresponds to the @value{which-treelang} version of @code{treelang}.
+ @end ifclear
+ @ifclear USING
+ This manual documents how to maintain @code{treelang}, as well as its
+ new features and incompatibilities, and how to report bugs.  It
+ corresponds to the @value{which-treelang} version of @code{treelang}.
+ @end ifclear
+ 
+ @end ifinfo
+ 
+ @ifset DEVELOPMENT
+ @emph{Warning:} This document is still under development, and might not
+ accurately reflect the @code{treelang} code base of which it is a part.
+ @end ifset
+ 
+ @c yes, the "M: " @emph{is} intentional -- bad.def references it (CMPAMBIG)!
+ 
+ @menu
+ * Copying::                     
+ * Contributors::                
+ * GNU Free Documentation License::                
+ * Funding::                     
+ * Getting Started::             
+ * What is GNU Treelang?::       
+ * Lexical Syntax::              
+ * Parsing Syntax::              
+ * Compiler Overview::           
+ * TREELANG and GCC::            
+ * Compiler::                    
+ * Other Languages::             
+ * treelang internals::          
+ * Open Questions::              
+ * Bugs::                        
+ * Service::                     
+ * Projects::                    
+ * Index::                       
+ 
+ @detailmenu
+  --- The Detailed Node Listing ---
+ 
+ Other Languages
+ 
+ * Interoperating with C and C++::  
+ 
+ treelang internals
+ 
+ * treelang files::              
+ * treelang compiler interfaces::  
+ * Hints and tips::              
+ 
+ treelang compiler interfaces
+ 
+ * treelang driver::             
+ * treelang main compiler::      
+ 
+ treelang main compiler
+ 
+ * Interfacing to toplev.c::     
+ * Interfacing to the garbage collection::  
+ * Interfacing to the code generation code. ::  
+ 
+ Reporting Bugs
+ 
+ * Sending Patches::             
+ 
+ @end detailmenu
+ @end menu
+ 
+ @include gpl.texi
+ 
+ @include fdl.texi
+ 
+ @node Contributors
+ 
+ @unnumbered Contributors to GNU Treelang
+ @cindex contributors
+ @cindex credits
+ 
+ Treelang was based on 'toy' by Richard Kenner, and also uses code from
+ the GCC core code tree. Tim Josling first created the language and
+ documentation, based on the GCC fortran compiler's documentation
+ framework.
+ 
+ @itemize @bullet
+ @item
+ The packaging and compiler portions of GNU Treelang are based largely
+ on the GNU CC compiler.
+ @xref{Contributors,,Contributors to GNU CC,GCC,Using and Maintaining GNU CC},
+ for more information.
+ 
+ @item
+ There is no specific run-time library for treelang, other than the
+ standard c runtime.
+ 
+ @item
+ It would have been difficult to build treelang without access to Joachim
+ Nadler's guide to writing a front end to GCC (written in German). A
+ translation of this document into English is available via the
+ CobolForGCC project or via the documentation links from the GCC home
+ page @uref{http://GCC.gnu.org}.
+ @end itemize
+ 
+ @include funding.texi
+ 
+ @node Getting Started
+ @chapter Getting Started
+ @cindex getting started
+ @cindex new users
+ @cindex newbies
+ @cindex beginners
+ 
+ Treelang is a sample language, useful only to help people understand how
+ to implement a new language front end to GCC. It is not a useful
+ language in itself other than as an example or basis for building a new
+ language. Therefore only language developers are likely to have an
+ interest in it.
+ 
+ This manual assumes familiarity with GCC, which you can obtain by using
+ it and by reading the manual @samp{Using and Porting GNU CC}.
+ 
+ To install treelang, follow the GCC installation instructions, taking care to ensure you specify treelang in the configure step.
+ 
+ If you're generally curious about the future of
+ @code{treelang}, see @ref{Projects}.
+ If you're curious about its past,
+ see @ref{Contributors}.
+ 
+ To see a few of the questions maintainers of @code{treelang} have,
+ and that you might be able to answer,
+ see @ref{Open Questions}.
+ 
+ @ifset USING
+ @node What is GNU Treelang?, Lexical Syntax, Getting Started, Top
+ @chapter What is GNU Treelang?
+ @cindex concepts, basic
+ @cindex basic concepts
+ 
+ GNU Treelang, or @code{treelang}, is designed initially as a free
+ replacement for, or alternative to, the 'toy' language, but which is
+ amenable to inclusion within the GCC source tree. 
+ 
+ @code{treelang} is largely a cut down version of C, designed to showcase
+ the features of the GCC code generation back end. Only those features
+ that are directly supported by the GCC code generation back end are
+ implemented. Features are implemented in a manner which is easiest and
+ clearest to implement. Not all or even most code generation back end
+ features are implemented. The intention is to add features incrementally
+ until most features of the GCC back end are implemented in treelang.
+ 
+ The main features missing are structures, arrays and pointers.
+ 
+ A sample program follows:
+ 
+ @example
+ // function prototypes
+ // function 'add' taking two ints and returning an int
+ external_definition int add(int arg1, int arg2);
+ external_definition int subtract(int arg3, int arg4);
+ external_definition int first_nonzero(int arg5, int arg6);
+ external_definition int double_plus_one(int arg7);
+ 
+ // function definition
+ add 
+ @{
+ // return the sum of arg1 and arg2
+   return arg1 + arg2;
+ @}
+ 
+         
+ subtract 
+ @{
+   return arg3 - arg4;
+ @}
+ 
+ double_plus_one
+ @{
+ // aaa is a variable, of type integer and allocated at the start of the function
+   automatic int aaa;
+ // set aaa to the value returned from aaa, when passed arg7 and arg7 as the two parameters
+   aaa=add(arg7, arg7);
+   aaa=add(aaa, aaa);
+   aaa=subtract(subtract(aaa, arg7), arg7) + 1;
+   return aaa;
+ @}
+ 
+ first_nonzero
+ @{
+ // C-like if statement
+   if (arg5)
+     @{
+       return arg5;
+     @}
+   else
+     @{
+     @}
+   return arg6;
+ @}
+ @end example
+ 
+ @node Lexical Syntax, Parsing Syntax, What is GNU Treelang?, Top
+ @chapter Lexical Syntax
+ @cindex Lexical Syntax
+ 
+ Treelang programs consist of whitespace, comments, keywords and names.
+ @itemize @bullet
+ 
+ @item
+ Whitespace consists of the space character and the end of line
+ character. Tabs are not allowed. Only Posix style line terminations are
+ allowed (ie not DOS CRLF). Whitespace is ignored except within comments,
+ and where it separates parts of the program. In the example below, A and
+ B are two separate names separated by whitespace. 
+ 
+ @smallexample
+ A B
+ @end smallexample
+ 
+ @item
+ Comments consist of @samp{//} followed by any characters up to the end
+ of the line. C style comments (/* */) are not supported. For example,
+ the assignment below is followed by a not very helpful comment.
+ 
+ @smallexample
+ x=1; // Set X to 1
+ @end smallexample
+ 
+ @item
+ Keywords consist of any reserved words or symbols as described
+ later. The list of keywords follows:
+ 
+ @smallexample
+ @{ - used to start the statements in a function
+ @} - used to end the statements in a function
+ ( - start list of function arguments, or to change the precedence of operators in an expression
+ ) - end list or prioritised operators in expression
+ , - used to separate parameters in a function prototype or in a function call 
+ ; - used to end a statement
+ + - addition
+ - - subtraction
+ = - assignment
+ == - equality test
+ if - begin IF statement
+ else - begin 'else' portion of IF statement
+ static - indicate variable is permanent, or function has file scope only
+ automatic - indicate that variable is allocated for the life of the function
+ external_reference - indicate that variable or function is defined in another file
+ external_definition - indicate that variable or function is to be accessible from other files
+ int - variable is an integer (same as C int) 
+ char - variable is a character (same as C char)
+ unsigned - variable is unsigned. If this is not present, the variable is signed
+ return - start function return statement
+ void - used as function type to indicate function returns nothing
+ @end smallexample
+ 
+ 
+ @item
+ Names consist of any letter or "_" followed by any number of letters or
+ numbers or "_". "$" is not allowed in a name. All names must be globally
+ unique - the same name may not be used twice in any context - and must
+ not be a keyword. Names and keywords are case sensitive. For example:
+ 
+ @smallexample
+ a A _a a_ IF_X
+ @end smallexample
+ 
+ are all different names.
+ 
+ @end itemize
+ 
+ @node Parsing Syntax, Compiler Overview, Lexical Syntax, Top
+ @chapter Parsing Syntax
+ @cindex Parsing Syntax
+ 
+ Declarations are built up from the lexical elements described above. A
+ file may contain one of more declarations.
+ 
+ @itemize @bullet
+ 
+ @item
+ declaration: variable declaration OR function prototype OR function declaration
+ 
+ @item
+ Function Prototype: storage type NAME ( parameter_list )
+ 
+ @smallexample
+ static int add (int a, int b)
+ @end smallexample
+ 
+ @item
+ variable_declaration: storage type NAME initial;
+ 
+ Example:
+ 
+ @smallexample
+ int temp1=1;
+ @end smallexample
+ 
+ A variable declaration can be outside a function, or at the start of a function.
+ 
+ @item
+ storage: automatic OR static OR external_reference OR external_definition
+ 
+ This defines the scope, duration and visibility of a function or variable
+ 
+ @enumerate 1
+ 
+ @item 
+ automatic: This means a variable is allocated at start of function and
+ released when the function returns. This can only be used for variables
+ within functions. It cannot be used sed for functions.
+ 
+ @item 
+ static: This means a variable is allocated at start of program and
+ remains allocated until the program as a whole ends. For a function, it
+ means that the function is only visible within the current file.
+ 
+ @item
+ external_definition: For a variable, which must be defined outside a
+ function, it means that the variable is visible from other files. For a
+ function, it means that the function is visible from another file.
+ 
+ @item
+ external_reference: For a variable, which must be defined outside a
+ function, it means that the variable is defined in another file. For a
+ function, it means that the function is defined in another file.
+ 
+ @end enumerate
+ 
+ @item
+ type: int OR unsigned int OR char OR unsigned char OR void
+ 
+ This defines the data type of a variable or the return type of a function.
+ 
+ @enumerate a
+ 
+ @item 
+ int: The variable is a signed integer. The function returns a signed integer.
+ 
+ @item 
+ unsigned int: The variable is an unsigned integer. The function returns an unsigned integer.
+ 
+ @item 
+ char: The variable is a signed character. The function returns a signed character.
+ 
+ @item 
+ unsigned char: The variable is an unsigned character. The function returns an unsigned character.
+ 
+ @end enumerate
+ 
+ @item
+ parameter_list OR parameter [, parameter]...
+ 
+ @item
+ parameter: variable_declaration ,
+ 
+ The variable declarations must not have initialisations.
+ 
+ @item 
+ initial: = value
+ 
+ @item
+ value: integer_constant
+ 
+ @smallexample
+ eg 1 +2 -3
+ @end smallexample
+ 
+ @item
+ function_declaration: name @{variable_declarations statements @}
+ 
+ A function consists of the function name then the declarations (if any)
+ and statements (if any) within one pair of braces.
+ 
+ The details of the function arguments come from the function
+ prototype. The function prototype must precede the function declaration
+ in the file.
+ 
+ @item
+ statement: if_statement OR expression_statement OR return_statement
+ 
+ @item
+ if_statement: if (expression) @{ statements @} else @{ statements @}
+ 
+ The first lot of statements is executed if the expression is
+ non-zero. Otherwise the second lot of statements is executed. Either
+ list of statements may be empty, but both sets of braces and the else must be present. 
+ 
+ @smallexample
+ if (a==b) 
+ @{
+ // nothing
+ @}
+ else
+ @{
+ a=b;
+ @}
+ @end smallexample
+ 
+ @item
+ expression_statement: expression;
+ 
+ The expression is executed and any side effects, such 
+ 
+ @item
+ return_statement: return expression_opt;
+ 
+ Returns from the function. If the function is void, the expression must
+ be absent, and if the function is not void the expression must be
+ present.
+ 
+ @item
+ expression: variable OR integer_constant OR expression+expression OR expression-expression
+  OR expression==expression OR (expression) OR variable=expression OR function_call
+ 
+ An expression can be a constant or a variable reference or a
+ function_call. Expressions can be combined as a sum of two expressions
+ or the difference of two expressions, or an equality test of two
+ expresions. An assignment is also an expression. Expresions and operator
+ precedence work as in C.
+ 
+ @item
+ function_call: function_name( comma-seperated_expressions)
+ 
+ This invokes the function, passing to it the values of the expressions
+ as actual parameters.
+ 
+ @end itemize
+ 
+ @cindex compilers
+ @node Compiler Overview, TREELANG and GCC, Parsing Syntax, Top
+ @chapter Compiler Overview
+ treelang is run as part of the @code{GCC} compiler. 
+ 
+ @itemize @bullet
+ @cindex source code
+ @cindex file, source
+ @cindex code, source
+ @cindex source file
+ @item
+ It reads a user's program, stored in a file and containing instructions
+ written in the appropriate language (Treelang, C, and so on).  This file
+ contains @dfn{source code}.
+ 
+ @cindex translation of user programs
+ @cindex machine code
+ @cindex code, machine
+ @cindex mistakes
+ @item
+ It translates the user's program into instructions a computer can carry
+ out more quickly than it takes to translate the instructions in the
+ first place.  These instructions are called @dfn{machine code}---code
+ designed to be efficiently translated and processed by a machine such as
+ a computer.  Humans usually aren't as good writing machine code as they
+ are at writing Treelang or C, because it is easy to make tiny mistakes
+ writing machine code.  When writing Treelang or C, it is easy to make
+ big mistakes. But yoy can only make one mistake, because the compiler
+ stops after it finds any problem.
+ 
+ @cindex debugger
+ @cindex bugs, finding
+ @cindex @code{gdb}, command
+ @cindex commands, @code{gdb}
+ @item
+ It provides information in the generated machine code
+ that can make it easier to find bugs in the program
+ (using a debugging tool, called a @dfn{debugger},
+ such as @code{gdb}).
+ 
+ @cindex libraries
+ @cindex linking
+ @cindex @code{ld} command
+ @cindex commands, @code{ld}
+ @item
+ It locates and gathers machine code already generated to perform actions
+ requested by statements in the user's program.  This machine code is
+ organized into @dfn{libraries} and is located and gathered during the
+ @dfn{link} phase of the compilation process.  (Linking often is thought
+ of as a separate step, because it can be directly invoked via the
+ @code{ld} command.  However, the @code{GCC} command, as with most
+ compiler commands, automatically performs the linking step by calling on
+ @code{ld} directly, unless asked to not do so by the user.)
+ 
+ @cindex language, incorrect use of
+ @cindex incorrect use of language
+ @item
+ It attempts to diagnose cases where the user's program contains
+ incorrect usages of the language.  The @dfn{diagnostics} produced by the
+ compiler indicate the problem and the location in the user's source file
+ where the problem was first noticed.  The user can use this information
+ to locate and fix the problem.
+ 
+ The compiler stops after the first error. There are no plans to fix
+ this, ever, as it would vastly complicate the implementation of treelang
+ to little or no benefit.
+ 
+ @cindex diagnostics, incorrect
+ @cindex incorrect diagnostics
+ @cindex error messages, incorrect
+ @cindex incorrect error messages
+ (Sometimes an incorrect usage of the language leads to a situation where
+ the compiler can not make any sense of what it reads---while a human
+ might be able to---and thus ends up complaining about an incorrect
+ ``problem'' it encounters that, in fact, reflects a misunderstanding of
+ the programmer's intention.)
+ 
+ @cindex warnings
+ @cindex questionable instructions
+ @item
+ There are no warnings in treelang. A program is either correct or in
+ error.
+ @end itemize
+ 
+ @cindex components of treelang
+ @cindex @code{treelang}, components of
+ @code{treelang} consists of several components:
+ 
+ @cindex @code{GCC}, command
+ @cindex commands, @code{GCC}
+ @itemize @bullet
+ @item
+ A modified version of the @code{GCC} command, which also might be
+ installed as the system's @code{cc} command.
+ (In many cases, @code{cc} refers to the
+ system's ``native'' C compiler, which
+ might be a non-GNU compiler, or an older version
+ of @code{GCC} considered more stable or that is
+ used to build the operating system kernel.)
+ 
+ @cindex @code{treelang}, command
+ @cindex commands, @code{treelang}
+ @item
+ The @code{treelang} command itself.
+ 
+ @item
+ The @code{libc} run-time library.  This library contains the machine
+ code needed to support capabilities of the Treelang language that are
+ not directly provided by the machine code generated by the
+ @code{treelang} compilation phase. This is the same library that the
+ main c compiler uses (libc).
+ 
+ @cindex @code{tree1}, program
+ @cindex programs, @code{tree1}
+ @cindex assembler
+ @cindex @code{as} command
+ @cindex commands, @code{as}
+ @cindex assembly code
+ @cindex code, assembly
+ @item
+ The compiler itself, is internally named @code{tree1}.
+ 
+ Note that @code{tree1} does not generate machine code directly---it
+ generates @dfn{assembly code} that is a more readable form
+ of machine code, leaving the conversion to actual machine code
+ to an @dfn{assembler}, usually named @code{as}.
+ @end itemize
+ 
+ @code{GCC} is often thought of as ``the C compiler'' only,
+ but it does more than that.
+ Based on command-line options and the names given for files
+ on the command line, @code{GCC} determines which actions to perform, including
+ preprocessing, compiling (in a variety of possible languages), assembling,
+ and linking.
+ 
+ @cindex driver, GCC command as
+ @cindex @code{GCC}, command as driver
+ @cindex executable file
+ @cindex files, executable
+ @cindex cc1 program
+ @cindex programs, cc1
+ @cindex preprocessor
+ @cindex cpp program
+ @cindex programs, cpp
+ For example, the command @samp{GCC foo.c} @dfn{drives} the file
+ @file{foo.c} through the preprocessor @code{cpp}, then
+ the C compiler (internally named
+ @code{cc1}), then the assembler (usually @code{as}), then the linker
+ (@code{ld}), producing an executable program named @file{a.out} (on
+ UNIX systems).
+ 
+ @cindex treelang program
+ @cindex programs, treelang
+ As another example, the command @samp{GCC foo.tree} would do much the
+ same as @samp{GCC foo.c}, but instead of using the C compiler named
+ @code{cc1}, @code{GCC} would use the treelang compiler (named
+ @code{tree1}). However there is no preprocessor for treelang.
+ 
+ @cindex @code{tree1}, program
+ @cindex programs, @code{tree1}
+ In a GNU Treelang installation, @code{GCC} recognizes Treelang source
+ files by name just like it does C and C++ source files.  It knows to use
+ the Treelang compiler named @code{tree1}, instead of @code{cc1} or
+ @code{cc1plus}, to compile Treelang files. If a file's name ends in
+ @code{.tree} then GCC knows that the program is written in treelang. You
+ can also manually override the language.
+ 
+ @cindex @code{GCC}, not recognizing Treelang source
+ @cindex unrecognized file format
+ @cindex file format not recognized
+ Non-Treelang-related operation of @code{GCC} is generally
+ unaffected by installing the GNU Treelang version of @code{GCC}.
+ However, without the installed version of @code{GCC} being the
+ GNU Treelang version, @code{GCC} will not be able to compile
+ and link Treelang programs.
+ 
+ @cindex printing version information
+ @cindex version information, printing
+ The command @samp{GCC -v x.tree} where @samp{x.tree} is a file which
+ must exist but whose contents are ignored, is a quick way to display
+ version information for the various programs used to compile a typical
+ Treelang source file. 
+ 
+ The @code{tree1} program represents most of what is unique to GNU
+ Treelang; @code{tree1} is a combination of two rather large chunks of
+ code.
+ 
+ @cindex GNU Back End (GBE)
+ @cindex GBE
+ @cindex @code{GCC}, back end
+ @cindex back end, GCC
+ @cindex code generator
+ One chunk is the so-called @dfn{GNU Back End}, or GBE,
+ which knows how to generate fast code for a wide variety of processors.
+ The same GBE is used by the C, C++, and Treelang compiler programs @code{cc1},
+ @code{cc1plus}, and @code{tree1}, plus others.
+ Often the GBE is referred to as the ``GCC back end'' or
+ even just ``GCC''---in this manual, the term GBE is used
+ whenever the distinction is important.
+ 
+ @cindex GNU Treelang Front End (TFE)
+ @cindex tree1
+ @cindex @code{treelang}, front end
+ @cindex front end, @code{treelang}
+ The other chunk of @code{tree1} is the majority of what is unique about
+ GNU Treelang---the code that knows how to interpret Treelang programs to
+ determine what they are intending to do, and then communicate that
+ knowledge to the GBE for actual compilation of those programs.  This
+ chunk is called the @dfn{Treelang Front End} (TFE).  The @code{cc1} and
+ @code{cc1plus} programs have their own front ends, for the C and C++
+ languages, respectively.  These fronts ends are responsible for
+ diagnosing incorrect usage of their respective languages by the programs
+ the process, and are responsible for most of the warnings about
+ questionable constructs as well.  (The GBE in principle handles
+ producing some warnings, like those concerning possible references to
+ undefined variables but these warnings should not occur in treelang
+ programs as the front end is meant to pick them up first).
+ 
+ Because so much is shared among the compilers for various languages,
+ much of the behavior and many of the user-selectable options for these
+ compilers are similar.
+ For example, diagnostics (error messages and
+ warnings) are similar in appearance; command-line
+ options like @samp{-Wall} have generally similar effects; and the quality
+ of generated code (in terms of speed and size) is roughly similar
+ (since that work is done by the shared GBE).
+ 
+ @node TREELANG and GCC, Compiler, Compiler Overview, Top
+ @chapter Compile Treelang, C, or Other Programs
+ @cindex compiling programs
+ @cindex programs, compiling
+ 
+ @cindex @code{GCC}, command
+ @cindex commands, @code{GCC}
+ A GNU Treelang installation includes a modified version of the @code{GCC}
+ command.
+ 
+ In a non-Treelang installation, @code{GCC} recognizes C, C++,
+ and Objective-C source files.
+ 
+ In a GNU Treelang installation, @code{GCC} also recognizes Treelang source
+ files and accepts Treelang-specific command-line options, plus some
+ command-line options that are designed to cater to Treelang users
+ but apply to other languages as well.
+ 
+ @xref{G++ and GCC,,Compile C; C++; or Objective-C,GCC,Using and Porting GNU CC},
+ for information on the way different languages are handled
+ by the GNU CC compiler (@code{GCC}).
+ 
+ You can use this, combined with the output of the @samp{GCC -v x.tree}
+ command to get the options applicable to treelang. Treelang programs
+ must end with the suffix @samp{.tree}.
+ 
+ @cindex preprocessor
+ 
+ Treelang programs are not by default run through the c
+ preprocessor by GCC. There is no reason why they cannot be run through the
+ preprocessor manually, but you would need to prevent the preprocessor
+ fron generating #line directives, using the @samp{-P} option, otherwise
+ tree1 will not accept the input.
+ 
+ @node Compiler, Other Languages, TREELANG and GCC, Top
+ @chapter The GNU Treelang Compiler
+ 
+ The GNU Treelang compiler, @code{treelang}, supports programs written
+ in the GNU Treelang language.
+ 
+ @node Other Languages, treelang internals, Compiler, Top
+ @chapter Other Languages
+ 
+ @menu
+ * Interoperating with C and C++::  
+ @end menu
+ 
+ @node Interoperating with C and C++,  , Other Languages, Other Languages
+ @section Tools and advice for interoperating with C and C++
+ 
+ The output of treelang programs looks like c program code to the linker
+ and everybody else, so you should be able to freely mix treelang and C
+ (and C++) code.
+ 
+ @ifset INTERNALS
+ @node treelang internals, Open Questions, Other Languages, Top
+ @chapter treelang internals
+ 
+ @menu
+ * treelang files::              
+ * treelang compiler interfaces::  
+ * Hints and tips::              
+ @end menu
+ 
+ @node treelang files, treelang compiler interfaces, treelang internals, treelang internals
+ @section treelang files
+ 
+ To create a compiler that integrates into GCC, you need create many
+ files. Some of the files are integrated into the main GCC makefile, to
+ build the various parts of the compiler and to run the test
+ suite. Others are incorporated into various GCC programs such as
+ GCC.c. Finally you must provide the actual programs comprising your
+ compiler. 
+ 
+ @cindex files
+ 
+ The files are:
+ 
+ @enumerate 1
+ 
+ @item
+ COPYING. This is the copyright file, assuming you are going to use the
+ GNU General Public Licence. You probably need to use the GPL because if
+ you use the GCC back end your program and the back end are one program,
+ and the back end is GPLed.
+ 
+ This need not be present if the language is incorporated into the main
+ GCC tree, as the main GCC directory has this file. 
+ 
+ @item
+ COPYING.LIB. This is the copyright file for those parts of your program
+ that are not to be covered by the GPL, but are instead to be covered by
+ the LGPL (Library or Lesser GPL). This licence may be appropriate for
+ the library routines associated with your compiler. These are the
+ routines that are linked with the @emph{output} of the compiler. Using
+ the LGPL for these programs allows programs written using your compiler
+ to be closed source. For example LIBC is under the LGPL. 
+ 
+ This need not be present if the language is incorporated into the main
+ GCC tree, as the main GCC directory has this file. 
+ 
+ @item
+ ChangeLog. Record all the changes to your compiler. Use the same format
+ as used in treelang as it is supported by an emacs editing mode and is
+ part of the FSF coding standard. Normally each directory has its own
+ changelog. The FSF standard allows but does not require a meaningful
+ comment on why the changes were made, above and beyond @emph{why} they
+ were made. In the author's opinion it is useful to provide this
+ information.
+ 
+ @item
+ root.texi. Macros for use in the main manual eg email addresses etc.
+ 
+ @item
+ treelang.texi. The manual, written in texinfo. Your manual would have a
+ different file name. You need not write it in texinfo if you don't want
+ do, but a lot of GNU software does use texinfo. 
+ 
+ @cindex Make-lang.in
+ @item
+ Make-lang.in. This file is part of the make file which in incorporated
+ with the GCC make file skeleton (Makefile.in in the GCC directory) to
+ make Makefile, as part of the configuration process.
+ 
+ Makefile in turn is the main instruction to actually build
+ everything. The build instructions are held in the main GCC manual and
+ web site so they are not repeated here. 
+ 
+ There are some comments at the top which will help you understand what
+ you need to do.
+ 
+ There are make commands to build things, remove generated files with
+ various degrees of thoroughness, count the lines of code (so you know
+ how much progress you are making), build info and html files from the
+ texinfo source, run the tests etc.
+ 
+ @item
+ README. Just a brief informative text file saying what is in this
+ directory. 
+ 
+ @cindex config-lang.in
+ @item
+ config-lang.in. This file is read by the configuration progress and must
+ be present. You specify the name of your language, the name(s) of the
+ compiler(s) incouding preprocessors you are going to build, whether any,
+ usually generated, files should be excluded from diffs (ie when making
+ diff files to send in patches). Whether the equate 'stagestuff' is used
+ is unknown (???).
+ 
+ @cindex lang-options
+ @item
+ lang-options. This file is included into GCC.c, the main GCC driver, and
+ tells it what options your language supports. This is only used to
+ display help (is this true ???).
+ 
+ @cindex lang-specs
+ @item
+ lang-specs. This file is also included in GCC.c. It tells GCC.c when to
+ call your programs and what options to send them. The mini-language
+ 'specs' is documented in the source of GCC.c. Do not attempt to write a
+ specs file from scratch - use an existing one as the base and enhance
+ it. 
+ 
+ @item
+ Your texi files. Texinfo can be used to build documentation in HTML,
+ info, dvi and postscript formats. It is a tagged language, is documented
+ in its own manual, and has its own emacs mode.
+ 
+ @item
+ Your programs. The relationships between all the programs are explained
+ in the next section. You need to write or use the following programs:
+ 
+ @itemize @bullet
+ 
+ @item
+ lexer. This breaks the input into words and passes these to the
+ parser. This is lex.l in treelang, which is passed through flex, a lex
+ variant, to produce C code lex.c. Note there is a school of thought that
+ says real men hand code their own lexers, however you may prefer to
+ write far less code and use flex, as was done with treelang.
+ 
+ @item
+ parser. This breaks the program into recognizable constructs such as
+ expressions, statements etc. This is parse.y in treelang, which is
+ passed through bison, which is a yacc variant, to produce C code parse.c.
+ 
+ @item
+ back end interface. This interfaces to the code generation back end. In
+ treelang, this is tree1.c which mainly interfaces to toplev.c and
+ treetree.c which mainly interfaces to everything else. Many languages
+ mix up the back end interface with the parser, as in the C compiler for
+ example. It is a matter of taste which way to do it, but with treelang
+ it is separated out to make the back end interface cleaner and easier to
+ understand.
+ 
+ @item
+ header files. For function prototypes and common data items. One point
+ to note here is that bison can generate a header files with all the
+ numbers is has assigned to the keywords and symbols, and you can include
+ the same header in your lexer. This technique is demonstrated in
+ treelang.
+ 
+ @item
+ compiler main file. GCC comes with a program toplev.c which is a
+ perfectly serviceable main program for your compiler. treelang uses
+ toplev.c but other languages have been known to replace it with their
+ own main program. Again this is a matter of taste and how much code you
+ want to write. 
+ 
+ @end itemize
+ 
+ @end enumerate
+ 
+ @node treelang compiler interfaces, Hints and tips, treelang files, treelang internals
+ @section treelang compiler interfaces
+ 
+ @cindex driver
+ @cindex toplev.c
+ 
+ @menu
+ * treelang driver::             
+ * treelang main compiler::      
+ @end menu
+ 
+ @node treelang driver, treelang main compiler, treelang compiler interfaces, treelang compiler interfaces
+ @subsection treelang driver
+ 
+ The GCC compiler consists of a driver, which then executes the various
+ compiler phases based on the instructions in the specs files. 
+ 
+ Typically a program's language will be identified from its suffix (eg
+ .tree) for treelang programs.
+ 
+ The driver (gcc.c) will then drive (exec) in turn a preprocessor, the main
+ compiler, the assembler and the link editor. Options to GCC allow you to
+ override all of this. In the case of treelang programs there is no
+ preprocessor, and mostly these days the C preprocessor is run within the
+ main C compiler rather than as a separate process, apparently for reasons of speed.
+ 
+ You will be using the standard assembler and linkage editor so these are
+ ignored from now on. 
+ 
+ You have to write your own preprocessor if you want one. This is usually
+ totally language specific. The main point to be aware of is to ensure
+ that you find some way to pass file name and line number information
+ through to the main compiler so that it can tell the back end this
+ information and so the debugger can find the right source line for each
+ piece of code. That is all there is to say about the preprocessor except
+ that the preprocessor will probably not be the slowest part of the
+ compiler and will probably not use the most memory so don't waste too
+ much time tuning it until you know you need to do so.
+ 
+ @node treelang main compiler,  , treelang driver, treelang compiler interfaces
+ @subsection treelang main compiler
+ 
+ The main compiler for treelang consists of toplev.c from the main GCC
+ compiler, the parser, lexer and back end interface routines, and the
+ back end routines themselves, of which there are many.
+ 
+ toplev.c does a lot of work for you and you should almost certainly use it,
+ 
+ Writing this code is the hard part of creating a compiler using GCC. The
+ back end interface documentation is incomplete and the interface is
+ complex. 
+ 
+ There are three main aspects to interfacing to the other GCC code. 
+ 
+ @menu
+ * Interfacing to toplev.c::     
+ * Interfacing to the garbage collection::  
+ * Interfacing to the code generation code. ::  
+ @end menu
+ 
+ @node Interfacing to toplev.c, Interfacing to the garbage collection, treelang main compiler, treelang main compiler
+ @subsubsection Interfacing to toplev.c
+ 
+ In treelang this is handled mainly in tree1.c
+ and partly in treetree.c. Peruse toplev.c for details of what you need
+ to do.
+ 
+ @node Interfacing to the garbage collection, Interfacing to the code generation code. , Interfacing to toplev.c, treelang main compiler
+ @subsubsection Interfacing to the garbage collection
+ 
+ Interfacing to the garbage collection. In treelang this is mainly in
+ tree1.c. 
+ 
+ Memory allocation in the compiler should be done using the ggc_alloc and
+ kindred routines in ggc*.*. At the end of every 'function' in your language, toplev.c calls
+ the garbage collection several times. The garbage collection calls mark
+ routines which go through the memory which is still used, telling the
+ garbage collection not to free it. Then all the memory not used is
+ freed.
+ 
+ What this means is that you need a way to hook into this marking
+ process. This is done by calling ggc_add_root. This provides the address
+ of a callback routine which will be called duing garbage collection and
+ which can call ggc_mark to save the storage. If storage is only
+ used within the parsing of a function, you do not need to provide a way
+ to mark it. 
+ 
+ Note that you can also call ggc_mark_tree to mark any of the back end
+ internal 'tree' nodes. This routine will follow the branches of the
+ trees and mark all the subordinate structures. This is useful for
+ example when you have created a variable declaaration that will be used
+ across multiple functions, or for a function declaration (from a
+ prototype) that may be used later on. See the next item for more on the
+ tree nodes. 
+ 
+ @node Interfacing to the code generation code. ,  , Interfacing to the garbage collection, treelang main compiler
+ @subsubsection Interfacing to the code generation code. 
+ 
+ In treelang this is done in treetree.c. A typedef called 'tree' which is
+ defined in tree.h and tree.def in the GCC directory and largely
+ implemented in tree.c and stmt.c forms the basic interface to the
+ compiler back end.
+ 
+ In general you call various tree routines to generate code, either
+ directly or through toplev.c. You build up data structures and
+ expressions in similar ways. 
+ 
+ You can read some documentation on this which can be found via the GCC
+ main web page. In particular, the documentation produced by Joachim
+ Nadler and translated by Tim Josling can be quite useful. the C compiler
+ also has documentation in the main GCC manual (particularly the current
+ CVS version) which is useful on a lot of the details.
+ 
+ In time it is hoped to enhance this document to provide a more
+ comprehensive overview of this topic. The main gap is in explaining how
+ it all works together. 
+ 
+ @node Hints and tips,  , treelang compiler interfaces, treelang internals
+ @section Hints and tips
+ 
+ @itemize @bullet
+ 
+ @item
+ TAGS: Use the make ETAGS commands to create TAGS files which can be used in
+ emacs to jump to any symbol quickly. 
+ 
+ @item
+ GREP: grep is also a useful way to find all uses of a symbol.
+ 
+ @item
+ TREE: The main routines to look at are tree.h and tree.def. You will
+ probably want a hardcopy of these. 
+ 
+ @item
+ SAMPLE: look at the sample interfacing code in treetree.c. You can use
+ gdb to trace through the code and learn about how it all works. 
+ 
+ @item
+ GDB: the GCC back end works well with gdb. It traps abort() and allows
+ you to trace back what went wrong. 
+ 
+ @item
+ Error Checking: The compiler back end does some error and consistency
+ checking. Often the result of an error is just no code being
+ generated. You will then need to trace through and find out what is
+ going wrong. The rtl dump files can help here also.
+ 
+ @item
+ rtl dump files: The main compiler documents these files which are dumps
+ of the rtl (intermediate code) which is manipulated doing the code
+ generation process. This can provide useful clues about what is going
+ wrong. The rtl 'language' is documented in the main GCC manual.
+ 
+ @end itemize
+ 
+ @end ifset
+ 
+ @node Open Questions, Bugs, treelang internals, Top
+ @chapter Open Questions
+ 
+ If you know GCC well, please consider looking at the file treetree.c and
+ resolving any questions marked "???".
+ 
+ @node Bugs, Service, Open Questions, Top
+ @chapter Reporting Bugs
+ @cindex bugs
+ @cindex reporting bugs
+ 
+ You can report bugs to @email{@value{email-bugs}}. Please make
+ sure bugs are real before reporting them. Follow the guidelines in the
+ main GCC manual for submitting bug reports.
+ 
+ @menu
+ * Sending Patches::             
+ @end menu
+ 
+ @node Sending Patches,  , Bugs, Bugs
+ @section Sending Patches for GNU Treelang
+ 
+ If you would like to write bug fixes or improvements for the GNU
+ Treelang compiler, that is very helpful.  Send suggested fixes to
+ @email{@value{email-patches}}.
+ 
+ @node Service, Projects, Bugs, Top
+ @chapter How To Get Help with GNU Treelang
+ 
+ If you need help installing, using or changing GNU Treelang, there are two
+ ways to find it:
+ 
+ @itemize @bullet
+ 
+ @item
+ Look in the service directory for someone who might help you for a fee.
+ The service directory is found in the file named @file{SERVICE} in the
+ GNU CC distribution.
+ 
+ @item
+ Send a message to @email{@value{email-general}}.
+ 
+ @end itemize
+ 
+ @end ifset
+ @ifset INTERNALS
+ 
+ @node Projects, Index, Service, Top
+ @chapter Projects
+ @cindex projects
+ 
+ If you want to contribute to @code{treelang} by doing research,
+ design, specification, documentation, coding, or testing,
+ the following information should give you some ideas.
+ 
+ Send a message to @email{@value{email-general}} if you plan to add a
+ feature.
+ 
+ The main requirement for treelang is to add features and to add
+ documentation. Features are things that the GCC back end can do but
+ which are not reflected in treelang. Examples include structures,
+ unions, pointers, arrays.
+ 
+ @end ifset
+ 
+ @node Index,  , Projects, Top
+ @unnumbered Index
+ 
+ @printindex cp
+ @summarycontents
+ @contents
+ @bye
diff -c3prN gcccvs/gcc/gcc/treelang/treetree.c newgcc/gcc/treelang/treetree.c
*** gcccvs/gcc/gcc/treelang/treetree.c	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/treetree.c	Sat Jul 28 12:41:52 2001
***************
*** 0 ****
--- 1,1625 ----
+ /* 
+ 
+     TREELANG Compiler back end interface (treetree.c)
+     Called by the parser.
+ 
+     If you want a working example of how to write a front end to GCC,
+     you are in the right place.
+ 
+     Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+     2001 Free Software Foundation, Inc.
+ 
+     This code is based on toy.c written by Richard Kenner. 
+     
+     It was later modified by Jonathan Bartlett whose changes have all
+     been removed (by Tim Josling).
+ 
+     Various bits and pieces were cloned from the GCC main tree, as
+     GCC evolved, for COBOLForGCC, by Tim Josling.
+ 
+     It was adapted to TREELANG by Tim Josling 2001.
+ 
+     ---------------------------------------------------------------------------
+ 
+     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, 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, 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ 
+     In other words, you are welcome to use, share and improve this program.
+     You are forbidden to forbid anyone else to use, share and improve
+     what you give them.   Help stamp out software-hoarding!  
+ 
+     ---------------------------------------------------------------------------
+ 
+  */
+ 
+ /*
+   Assumption: garbage collection is never called implicitly.  It will
+   not be called 'at any time' when short of memory.  It will only be
+   called explicitly at the end of each function.  This removes the
+   need for a *lot* of bother to ensure everything is in the mark trees
+   at all times.  */
+ 
+   /* Note it is OK to use GCC extensions such as long long in a compiler front end.
+      This is because the GCC front ends are built using GCC. */
+
+ /* Standard/OS headers.  */
+ 
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include "safe-ctype.h"
+ #include <errno.h>
+ #include <stdarg.h>
+ #include <limits.h>
+ #include <string.h>
+ 
+ #include <fcntl.h>
+ #include <getopt.h>
+ #include <stdio.h>
+ 
+ /* GCC headers.  */
+ 
+ #include "gansidecl.h"
+ #include "config.h"
+ #include "system.h"
+ #include "gansidecl.h"
+ #include "tree.h"
+ #include "flags.h"
+ #include "output.h"
+ #include "c-lex.h"
+ #include "c-tree.h"
+ #include "rtl.h"
+ #include "tm_p.h"
+ #include "ggc.h"
+ #include "toplev.h"
+ #include "varray.h"
+ 
+ #include "treetree.h"
+ 
+ extern int option_main;
+ extern char **file_names;
+ 
+ /* Number of bits in int and char - accessed by front end.  */
+ 
+ unsigned int tree_code_int_size = 0;
+ unsigned int tree_code_char_size = 0;
+ 
+ /* Utility types.  */
+ 
+ static tree void_pointer_type_node = NULL;
+ static tree char_pointer_type_node = NULL;
+ 
+ /* Local declarations.  */
+ static long get_int_value (tree t);
+ 
+ /* Decls for builtin functions.  */
+ 
+ /* Get rid of warnings until we use it.  Do not remove.  */
+ #if 0 
+ static tree memset_decl;
+ static tree memcpy_decl;
+ #endif
+ 
+ /* In this case there is very little to keep between functions - we
+    keep the symbol table only and the things that hang off that - see
+    tree1.c.  Garbage collection is only invoked when we call
+    rest_of_compilation at the end of a function. */
+ 
+ #define ADDROOT(where) ggc_add_root (&where, 1, /* Unused size.  */ sizeof (void*), \
+  tree_ggc_storage_always_used);
+ 
+ /* Return the tree stuff for this type TYPE_NUM.  */
+ 
+ tree 
+ tree_code_get_type (int type_num) 
+ {
+   switch (type_num)
+     {
+     case SIGNED_CHAR:
+       return signed_char_type_node;
+       
+     case UNSIGNED_CHAR:
+       return unsigned_char_type_node;
+ 
+     case SIGNED_INT:
+       return integer_type_node;
+ 
+     case UNSIGNED_INT:
+       return unsigned_type_node; 
+ 
+     case VOID_TYPE:
+       return void_type_node; 
+ 
+     default:
+       abort ();
+     }
+ }
+ 
+ /* Output the code for the start of an if statement.  The test
+    expression is EXP (true if not zero), and the stmt occurred at line
+    LINENO in file FILENAME.  */
+ 
+ void
+ tree_code_if_start (tree exp, unsigned char* filename, int lineno)
+ {
+   tree cond_exp;
+   cond_exp = build (NE_EXPR, 
+                  TREE_TYPE (exp), 
+                  exp, 
+                  build1 (CONVERT_EXPR, TREE_TYPE (exp), integer_zero_node));
+   emit_line_note ((char*)filename, lineno); /* Output the line number information.  */
+   expand_start_cond (cond_exp, /* Exit-able if non zero.  */ 0);
+ }
+ 
+ /* Output the code for the else of an if statement.  The else occurred
+    at line LINENO in file FILENAME.  */
+ 
+ void 
+ tree_code_if_else (unsigned char* filename, int lineno)
+ {
+   emit_line_note ((char*)filename, lineno); /* Output the line number information.  */
+   expand_start_else ();
+ }
+ 
+ /* Output the code for the end_if an if statement.  The end_if (final brace) occurred
+    at line LINENO in file FILENAME.  */
+ 
+ void 
+ tree_code_if_end (unsigned char* filename, int lineno)
+ {
+   emit_line_note ((char*)filename, lineno); /* Output the line number information.  */
+   expand_end_cond ();
+ }
+ 
+ /* Create a function.  The prototype name is NAME, storage class is
+    STORAGE_CLASS, type of return variable is RET_TYPE, parameter lists
+    is PARMS, returns decl for this function.  */
+ 
+ tree 
+ tree_code_create_function_prototype (unsigned char* chars,
+                                     unsigned int storage_class,
+                                     unsigned int ret_type,
+                                     struct tree_parameter_list* parms,
+                                     unsigned char* filename,
+                                     int lineno)
+ {
+ 
+   tree id;
+   struct tree_parameter_list* parm;
+   tree type_list = NULL_TREE;
+   tree type_node;
+   tree fn_type;
+   tree fn_decl;
+ 
+   /* Build the type.  */
+   id = get_identifier ((char*)chars);
+   for (parm = parms; parm; parm = parm->next)
+     {
+       type_node = get_type_for_numeric_type (parm->type);
+       type_list = tree_cons (NULL_TREE, type_node, type_list);
+     }
+   /* Last parm if null indicates fixed length list (as opposed to
+      printf style va_* list).  */
+   type_list = tree_cons (NULL_TREE, void_type_node, type_list);
+   /* The back end needs them in reverse order.  */
+   type_list = nreverse (type_list);
+ 
+   type_node = get_type_for_numeric_type (ret_type);
+   fn_type = build_function_type (type_node, type_list);
+ 
+   id = get_identifier ((char*)chars);
+   fn_decl = build_decl (FUNCTION_DECL, id, fn_type);
+ 
+   DECL_CONTEXT (fn_decl) = NULL_TREE; /* Nested functions not supported here.  */
+   DECL_SOURCE_FILE (fn_decl) = (char*)filename;
+   if (lineno > 1000000)
+     ; /* Probably the line # is rubbish because someone forgot to set
+     the line number - and unfortunately impossible line #s are used as
+     magic flags at various times. The longest known function for
+     example is about 550,000 lines (it was written in COBOL).  */
+   DECL_SOURCE_LINE (fn_decl) = lineno;
+ 
+   TREE_USED (fn_decl) = 1;
+   /* Real name (optional).  */
+   SET_DECL_ASSEMBLER_NAME (fn_decl, DECL_NAME (fn_decl));
+   
+   TREE_PUBLIC (fn_decl) = 0;
+   DECL_EXTERNAL (fn_decl) = 0; 
+   TREE_STATIC (fn_decl) = 0; 
+   switch (storage_class)
+     {
+     case STATIC_STORAGE:
+       TREE_PUBLIC (fn_decl) = 0; 
+       break;
+ 
+     case EXTERNAL_DEFINITION_STORAGE:
+       TREE_PUBLIC (fn_decl) = 1;
+       break;
+   
+     case EXTERNAL_REFERENCE_STORAGE:
+       DECL_EXTERNAL (fn_decl) = 1; /* We should set TREE_PUBLIC also according to Justin Ferguson.  */
+       break;
+ 
+ 
+     case AUTOMATIC_STORAGE:
+     default:
+       abort ();
+     }
+ 
+   /* Process declaration of function defined elsewhere.  */
+   rest_of_decl_compilation (fn_decl, NULL_PTR, 1, 0);
+ 
+   return fn_decl;
+ }
+ 
+ 
+ /* Output code for start of function; the decl of the function is in
+     PREV_SAVED (as created by tree_code_create_function_prototype),
+     the function is an line number LINENO in file FILENAME.  The
+     parameter details are in the lists PARMS. Returns nothing.  */
+ void 
+ tree_code_create_function_initial (tree prev_saved, 
+                                   unsigned char* filename,
+                                   int lineno,
+                                   struct tree_parameter_list* parms)
+ {
+   tree fn_decl;
+   tree param_decl;
+   tree next_param;
+   tree first_param;
+   tree parm_decl;
+   tree parm_list;
+   tree resultdecl;
+   struct tree_parameter_list* this_parm; 
+   struct tree_parameter_list* parm;
+ 
+   fn_decl = prev_saved;
+   if (!fn_decl)
+     abort ();
+ 
+   /* Output message if not -quiet.  */
+   announce_function (fn_decl);
+ 
+   /* This has something to do with forcing output also.  */
+   pushdecl (fn_decl);
+ 
+   /* Set current function for error msgs etc.  */
+   current_function_decl = fn_decl;
+   DECL_INITIAL (fn_decl) = error_mark_node;
+ 
+   DECL_SOURCE_FILE (fn_decl) = (char*)filename;
+   DECL_SOURCE_LINE (fn_decl) = lineno;
+ 
+   /* Prepare creation of rtl for a new function.  */
+   
+   resultdecl = DECL_RESULT (fn_decl) = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (TREE_TYPE (fn_decl)));
+   DECL_CONTEXT (DECL_RESULT (fn_decl)) = fn_decl;
+   DECL_SOURCE_FILE (resultdecl) = (char*)filename;
+   DECL_SOURCE_LINE (resultdecl) = lineno;
+   /* Work out the size. ??? is this needed.  */
+   layout_decl (DECL_RESULT (fn_decl), 0);
+ 
+   /* Make the argument variable decls.  */
+   parm_list = NULL_TREE;
+   for (parm = parms; parm; parm = parm->next)
+     {
+       parm_decl = build_decl (PARM_DECL, get_identifier ((char*) (parm->variable_name)), 
+                            get_type_for_numeric_type (parm->type));
+       
+       /* Some languages have different nominal and real types.  */
+       DECL_ARG_TYPE (parm_decl) = TREE_TYPE (parm_decl);
+       if (!DECL_ARG_TYPE (parm_decl))
+         abort ();
+       if (!fn_decl)
+         abort ();
+       DECL_CONTEXT (parm_decl) = fn_decl;
+       DECL_SOURCE_FILE (parm_decl) = (char*)filename;
+       DECL_SOURCE_LINE (parm_decl) = lineno;
+       parm_list = chainon (parm_decl, parm_list);
+     }
+ 
+   /* Back into reverse order as the back end likes them.  */
+   parm_list = nreverse (parm_list);
+   
+   DECL_ARGUMENTS (fn_decl) = parm_list;
+ 
+   /* Save the decls for use when the args are referred to.  */
+   for (param_decl = DECL_ARGUMENTS (fn_decl),
+          this_parm = parms;
+        param_decl;
+        param_decl = TREE_CHAIN (param_decl),
+          this_parm = this_parm->next)
+     {
+       if (!this_parm)
+         abort (); /* Too few.  */
+       *this_parm->where_to_put_var_tree = param_decl;
+     }
+   if (this_parm)
+     abort (); /* Too many.  */
+ 
+   /* Output the decl rtl (not the rtl for the function code).  ???.
+      If the function is not defined in this file, when should you
+      execute this?  */
+   make_decl_rtl (fn_decl, NULL);
+ 
+   /* Use filename/lineno from above.  */
+   init_function_start (fn_decl, (char*)filename, lineno); 
+   
+   /* Ceate rtl for startup code of function, such as saving registers.  */
+   
+   expand_function_start (fn_decl, 0);
+   
+   /* Function.c requires a push at the start of the function. that
+      looks like a bug to me but let's make it happy.  */
+   
+   pushlevel (0);
+   
+   /* Create rtl for the start of a new scope.  */
+   
+   expand_start_bindings (2);
+   
+   /* Put the parameters into the symbol table.  */
+   
+   for (first_param = param_decl = nreverse (DECL_ARGUMENTS (fn_decl));
+        param_decl;
+        param_decl = next_param)
+     {
+       next_param = TREE_CHAIN (param_decl);
+       TREE_CHAIN (param_decl) = NULL;
+       layout_decl (param_decl, 0); 
+       pushdecl (param_decl);
+       if (DECL_CONTEXT (param_decl) != current_function_decl)
+         abort ();
+     }
+ 
+   /* Store back the PARM_DECL nodes.  They appear in the right order.  */
+   DECL_ARGUMENTS (fn_decl) = getdecls ();
+ 
+   /* Force it to be output, else may be solely inlined.  */
+   TREE_ADDRESSABLE (fn_decl) = 1;
+   
+   /* Stop -O3 from deleting it.  */
+   TREE_USED (fn_decl) = 1;
+   
+   /* Add a new level to the debugger symbol table.  */
+   
+   pushlevel (0);
+   
+   /* Create rtl for the start of a new scope.  */
+   
+   expand_start_bindings (0);
+   
+   emit_line_note ((char*)filename, lineno); /* Output the line number information.  */
+ }
+ 
+ /* Wrapup a function.  */
+ void 
+ tree_code_create_function_wrapup (unsigned char* filename,
+                                  int lineno)
+ {
+   tree block;
+   tree fn_decl;
+ 
+   fn_decl = current_function_decl;
+   
+   emit_line_note ((char*)filename, lineno); /* Output the line number information.  */
+ 
+   /* Pop inner level.  */
+   
+   block = poplevel (1,1,0);
+   
+   /* Emit rtl for end of scope.  */
+   
+   expand_end_bindings (block, 1, 1);
+   
+   /* Cleanup tail.  */
+   /* Get completely built level from debugger symbol table.  */
+   
+   block = poplevel (1,0,1);
+   
+   /* And attach it to the function.  */
+   
+   DECL_INITIAL (fn_decl) = block;
+   
+   /* Emit rtl for end of scope.  */
+   
+   expand_end_bindings (block, 0, 1);
+   
+   /* Emit rtl for end of function.  */
+   
+   expand_function_end ((char*)filename, lineno, 0);
+   
+   /* Call optimization and convert optimized rtl to assembly code.  */
+   
+   rest_of_compilation (fn_decl);
+   
+   /* We are not inside of any scope now.  */
+   
+   current_function_decl = NULL_TREE;
+ }
+ 
+ /* 
+    Create a variable. 
+    
+    The storage class is STORAGE_CLASS (eg LOCAL).   
+    The name is CHARS/LENGTH.   
+    The type is EXPRESSION_TYPE (eg UNSIGNED_TYPE).  
+    The init tree is INIT.  
+ */
+ 
+ tree 
+ tree_code_create_variable (unsigned int storage_class,
+                                unsigned char* chars,
+                                unsigned int length,
+                                unsigned int expression_type,
+                                tree init,
+                                unsigned char* filename,
+                                int lineno)
+ {
+   tree var_type;
+   tree var_id;
+   tree var_decl;
+ 
+   /* 1. Build the type.  */
+   var_type = get_type_for_numeric_type (expression_type);
+ 
+   /* 2. Build the name.  */
+   if (chars[length] != 0)
+     abort (); /* Should be null terminated.  */
+ 
+   var_id = get_identifier ((char*)chars);
+ 
+   /* 3. Build the decl and set up init.  */
+   var_decl = build_decl (VAR_DECL, var_id, var_type);
+ 
+   /* 3a. Initialization.  */
+   if (init)
+     DECL_INITIAL (var_decl) = build1 (CONVERT_EXPR, var_type, init);
+   else
+     DECL_INITIAL (var_decl) = NULL_TREE;
+       
+   /* 4. Compute size etc.  */
+   layout_decl (var_decl, 0);
+       
+   if (TYPE_SIZE (var_type) == 0)
+     abort (); /* Did not calculate size.  */
+ 
+   DECL_CONTEXT (var_decl) = current_function_decl;
+ 
+   DECL_SOURCE_FILE (var_decl) = (char*)filename;
+   DECL_SOURCE_LINE (var_decl) = lineno;
+ 
+   /* Set the storage mode and whether only visible in the same file.  */
+   switch (storage_class)
+     {
+     case STATIC_STORAGE:
+       TREE_STATIC (var_decl) = 1;
+       TREE_PUBLIC (var_decl) = 0;
+       break;
+ 
+     case AUTOMATIC_STORAGE:
+       TREE_STATIC (var_decl) = 0;
+       TREE_PUBLIC (var_decl) = 0;
+       break;
+       
+     case EXTERNAL_DEFINITION_STORAGE:
+       TREE_STATIC (var_decl) = 0; 
+       TREE_PUBLIC (var_decl) = 1;
+       break;
+       
+     case EXTERNAL_REFERENCE_STORAGE:
+       DECL_EXTERNAL (var_decl) = 1;
+       break;
+       
+     default:
+       abort ();
+     }
+       
+   /* This should really only be set if the variable is used.  */
+   TREE_USED (var_decl) = 1;
+       
+   /* Expand declaration and initial value if any.  */
+   
+   if (TREE_STATIC (var_decl)) 
+     rest_of_decl_compilation (var_decl, 0, 0, 0);
+   else
+     {
+       expand_decl (var_decl);
+       if (DECL_INITIAL (var_decl))
+         expand_decl_init (var_decl);
+     }
+   
+   return pushdecl (copy_node (var_decl));
+   
+ }
+ 
+ 
+ /* Generate code for return statement.  Type is in TYPE, expression
+    is in EXP if present.  */
+ 
+ void
+ tree_code_generate_return (tree type, tree exp)
+ {
+   tree setret;
+   tree param;
+ 
+   for (param = DECL_ARGUMENTS (current_function_decl);
+        param;
+        param = TREE_CHAIN (param))
+     {
+       if (DECL_CONTEXT (param) != current_function_decl)
+         abort ();
+     }
+ 
+   if (exp)
+     {
+       setret = build (MODIFY_EXPR, type, DECL_RESULT (current_function_decl), 
+                      build1 (CONVERT_EXPR, type, exp));
+       TREE_SIDE_EFFECTS (setret) = 1;
+       TREE_USED (setret) = 1;
+       expand_expr_stmt (setret);
+     }
+   expand_return (DECL_RESULT (current_function_decl));
+ }
+ 
+ /* Output the code for this expression statement CODE.  */
+ 
+ void 
+ tree_code_output_expression_statement (tree code, unsigned char* filename, int lineno)
+ {
+   emit_line_note ((char*)filename, lineno); /* Output the line number information.  */
+   TREE_USED (code) = 1;
+   TREE_SIDE_EFFECTS (code) = 1;
+   expand_expr_stmt (code);
+ }
+ 
+ /* Return a tree for a constant integer value in the token TOK.  No
+    size checking is done.  */
+ 
+ tree 
+ tree_code_get_integer_value (unsigned char* chars, unsigned int length)
+ {
+   long long int val = 0;
+   unsigned int ix;
+   unsigned int start = 0;
+   int negative = 1;
+   switch (chars[0])
+     {
+     case (unsigned char)'-':
+       negative = -1;
+       start = 1;
+       break;
+ 
+     case (unsigned char)'+':
+       start = 1;
+       break;
+ 
+     default:
+       break;
+     }
+   for (ix = start; ix < length; ix++)
+     val = val * 10 + chars[ix] - (unsigned char)'0';
+   val = val*negative;
+   return build_int_2 (val & 0xffffffff, (val >> 32) & 0xffffffff);
+ }
+ 
+ /* Return the tree for an expresssion, type EXP_TYPE (see treetree.h)
+    with tree type TYPE and with operands1 OP1, OP2 (maybe), OP3 (maybe).  */
+ tree 
+ tree_code_get_expression (unsigned int exp_type, tree type, tree op1, tree op2, tree op3)
+ {
+   tree ret1;
+   int operator;
+ 
+   switch (exp_type)
+     {
+     case EXP_ASSIGN:
+       if (!op1 || !op2)
+         abort ();
+       operator = MODIFY_EXPR;
+       ret1 = build (operator, type, 
+                  op1, 
+                  build1 (CONVERT_EXPR, type, op2));
+ 
+       break;
+ 
+     case EXP_PLUS:
+       operator = PLUS_EXPR;
+       goto binary_expression;
+       
+     case EXP_MINUS:
+       operator = MINUS_EXPR;
+       goto binary_expression;
+       
+     case EXP_EQUALS:
+       operator = EQ_EXPR;
+       goto binary_expression;
+       
+       /* Expand a binary expression.  Ensure the operands are the right type.  */
+     binary_expression:
+       if (!op1 || !op2)
+         abort ();
+       ret1  =  build (operator, type, 
+                    build1 (CONVERT_EXPR, type, op1), 
+                    build1 (CONVERT_EXPR, type, op2));
+       break;
+ 
+       /* Reference to a variable.  This is dead easy, just return the
+          decl for the variable.  If the TYPE is different than the
+          variable type, convert it.  */
+     case EXP_REFERENCE:
+       if (!op1)
+         abort ();
+       if (type == TREE_TYPE (op1))
+         ret1 = op1;
+       else
+         ret1 = build1 (CONVERT_EXPR, type, op1);
+       break;
+       
+     case EXP_FUNCTION_INVOCATION:
+       if (!op1 || !op2)
+         abort ();
+       {
+         tree fun_ptr;
+         fun_ptr = build1 (ADDR_EXPR, build_pointer_type (type), op1);
+         ret1 = build (CALL_EXPR, type, fun_ptr, nreverse (op2));
+       }
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+ return ret1;
+ }
+ 
+ /* Init parameter list and return empty list.  */
+ 
+ tree 
+ tree_code_init_parameters (void)
+ {
+   return NULL_TREE;
+ }
+ 
+ /* Add a parameter EXP whose expression type is EXP_PROTO to list
+    LIST, returning the new list.  */
+ 
+ tree 
+ tree_code_add_parameter (tree list, tree proto_exp, tree exp)
+ {
+   tree new_exp;
+   new_exp = tree_cons (NULL_TREE, 
+                     build1 (CONVERT_EXPR, TREE_TYPE (proto_exp), exp),
+                     NULL_TREE);
+   if (!list)
+     return new_exp;
+   return chainon (new_exp, list);
+ }
+ 
+ /* Get the tree type for this type whose number is NUMERIC_TYPE.  */
+ 
+ tree
+ get_type_for_numeric_type (unsigned int numeric_type)
+ {
+   
+   int size1;
+   int sign1;
+   switch (numeric_type)
+     {
+     case VOID_TYPE:
+       return void_type_node;
+       
+     case SIGNED_INT:
+       size1 = tree_code_int_size;
+       sign1 = 1;
+       break;
+       
+     case UNSIGNED_INT:
+       size1 = tree_code_int_size;
+       sign1 = 0;
+       break;
+       
+     case SIGNED_CHAR:
+       size1 = tree_code_char_size;
+       sign1 = 1;
+       break;
+       
+     case UNSIGNED_CHAR:
+       size1 = tree_code_char_size;
+       sign1 = 0;
+       break;
+       
+     default:
+       abort ();
+     }
+ 
+   return tree_code_get_numeric_type (size1, sign1);
+   
+ }
+ 
+ /* Return tree representing a numeric type of size SIZE1 bits and
+    signed if SIGN1 !=  0.  */
+ tree 
+ tree_code_get_numeric_type (unsigned int size1, unsigned int sign1)
+ {
+   tree ret1;
+   if (size1 == tree_code_int_size)
+     {
+       if (sign1)
+         ret1 = integer_type_node;
+       else
+         ret1 = unsigned_type_node;
+     }
+   else
+     if (size1 == tree_code_char_size)
+       {
+         if (sign1)
+           ret1 = signed_char_type_node;
+         else
+           ret1 = unsigned_char_type_node;
+       }
+     else 
+       abort ();
+   
+   return ret1;    
+ }
+ 
+ /*****************************************************************
+  *  This is the swamp of no return - generic tree interfacing and
+  *  setup routines needed to make it all work. 
+  *****************************************************************/
+ 
+ tree global_trees[TI_MAX];
+ 
+ tree current_function_decl;
+ 
+ /* Used by dwarfout.c to determine the language ID output (K&R vs ANSI
+    C).  */
+ int flag_traditional;	
+ 
+ /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
+    that have names.  Here so we can clear out their names' definitions
+    at the end of the function.  */
+ 
+ #define NULL_BINDING_LEVEL (struct binding_level *) NULL
+   
+ /* A chain of binding_level structures awaiting reuse.  */
+ 
+ static struct binding_level *free_binding_level;
+ 
+ /* The elements of `ridpointers' are identifier nodes
+    for the reserved type names and storage classes.
+    It is indexed by a RID_... value.  */
+ tree *ridpointers = NULL;
+ 
+ int flag_short_double = 0;
+ int flag_short_wchar = 0;
+ int flag_no_builtin = 0;
+ int flag_no_nonansi_builtin = 0;
+ 
+ tree c_global_trees[CTI_MAX];
+ 
+ tree listify (tree chain);
+ 
+ /* Routines Expected by GCC.  */
+ 
+ /* These are used to build types for various sizes.  The code below
+    is a simplified version of that of GNAT.  */
+ 
+ #ifndef MAX_BITS_PER_WORD
+ #define MAX_BITS_PER_WORD  BITS_PER_WORD
+ #endif
+ 
+ /* This variable keeps a table for types for each precision so that we
+    only allocate each of them once.  Signed and unsigned types are
+    kept separate.  */
+ static tree signed_and_unsigned_types[MAX_BITS_PER_WORD + 1][2];
+ 
+ /* Return an integer type with the number of bits of precision given
+    by PRECISION.  UNSIGNEDP is nonzero if the type is unsigned;
+    otherwise it is a signed type.  */
+ 
+ tree
+ type_for_size (unsigned int precision, int unsignedp)
+ {
+   tree t;
+ 
+   if (precision <= MAX_BITS_PER_WORD
+       && signed_and_unsigned_types[precision][unsignedp] != 0)
+     return signed_and_unsigned_types[precision][unsignedp];
+ 
+  if (unsignedp)
+     t = signed_and_unsigned_types[precision][1]
+      = make_unsigned_type (precision);
+   else
+     t = signed_and_unsigned_types[precision][0]
+      = make_signed_type (precision);
+ 
+   return t;
+ }
+ 
+ /* Print the extended data in a tree node used by this language.  We
+    don't do that so do nothing.  */
+ void 
+ lang_print_xnode (FILE *file ATTRIBUTE_UNUSED,
+                  tree t ATTRIBUTE_UNUSED,
+                  int i ATTRIBUTE_UNUSED)
+ {
+      return;
+ }
+ 
+ /* Return a data type that has machine mode MODE.  UNSIGNEDP selects
+    an unsigned type; otherwise a signed type is returned.  */
+ 
+ tree
+ type_for_mode (enum machine_mode mode,
+                int unsignedp)
+ {
+   return type_for_size (GET_MODE_BITSIZE (mode), unsignedp);
+ }
+ 
+ /* Return the unsigned version of a TYPE_NODE, a scalar type.  */
+ 
+ tree
+ unsigned_type (tree type_node)
+ {
+   return type_for_size (TYPE_PRECISION (type_node), 1);
+ }
+ 
+ /* Return the signed version of a TYPE_NODE, a scalar type.  */
+ 
+ tree
+ signed_type (tree type_node)
+ {
+   return type_for_size (TYPE_PRECISION (type_node), 0);
+ }
+ 
+ /* Return a type the same as TYPE except unsigned or signed according to
+    UNSIGNEDP.  */
+ 
+ tree
+ signed_or_unsigned_type (int unsignedp,
+                          tree type)
+ {
+   if (!INTEGRAL_TYPE_P (type) || TREE_UNSIGNED (type) == unsignedp)
+     return type;
+   else
+     return type_for_size (TYPE_PRECISION (type), unsignedp);
+ }
+ 
+ 
+ /* These functions and variables deal with binding contours.  We only
+    need these functions for the list of PARM_DECLs, but we leave the
+    functions more general; these are a simplified version of the
+    functions from GNAT.  */
+ 
+ /* For each binding contour we allocate a binding_level structure which records
+    the entities defined or declared in that contour. Contours include:
+ 
+ 	the global one
+ 	one for each subprogram definition
+ 	one for each compound statement (declare block)
+ 
+    Binding contours are used to create GCC tree BLOCK nodes.  */
+ 
+ struct binding_level
+ {
+   /* A chain of ..._DECL nodes for all variables, constants, functions,
+      parameters and type declarations.  These ..._DECL nodes are chained
+      through the TREE_CHAIN field. Note that these ..._DECL nodes are stored
+      in the reverse of the order supplied to be compatible with the
+      back-end.  */
+   tree names;
+   /* For each level (except the global one), a chain of BLOCK nodes for all
+      the levels that were entered and exited one level down from this one.  */
+   tree blocks;
+   /* The back end may need, for its own internal processing, to create a BLOCK
+      node. This field is set aside for this purpose. If this field is non-NULL
+      when the level is popped, i.e. when poplevel is invoked, we will use such
+      block instead of creating a new one from the 'names' field, that is the
+      ..._DECL nodes accumulated so far.  Typically the routine 'pushlevel'
+      will be called before setting this field, so that if the front-end had
+      inserted ..._DECL nodes in the current block they will not be lost.   */
+   tree block_created_by_back_end;
+   /* The binding level containing this one (the enclosing binding level). */
+   struct binding_level *level_chain;
+ };
+ 
+ /* The binding level currently in effect.  */
+ static struct binding_level *current_binding_level = NULL;
+ 
+ /* The outermost binding level. This binding level is created when the
+    compiler is started and it will exist through the entire compilation.  */
+ static struct binding_level *global_binding_level;
+ 
+ /* Binding level structures are initialized by copying this one.  */
+ static struct binding_level clear_binding_level = {NULL, NULL, NULL, NULL};
+ 
+ /* Return non-zero if we are currently in the global binding level.  */
+ 
+ int
+ global_bindings_p (void)
+ {
+   return current_binding_level == global_binding_level ? -1 : 0;
+ }
+ 
+ /* Return the list of declarations in the current level. Note that
+    this list is in reverse order (it has to be so for back-end
+    compatibility).  */
+ 
+ tree
+ getdecls (void)
+ {
+   return current_binding_level->names;
+ }
+ 
+ /* Enter a new binding level. The input parameter is ignored, but has
+    to be specified for back-end compatibility.  */
+ 
+ void
+ pushlevel (int ignore ATTRIBUTE_UNUSED)
+ {
+   struct binding_level *newlevel
+    = (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ 
+   *newlevel = clear_binding_level;
+ 
+   /* Add this level to the front of the chain (stack) of levels that are
+      active.  */
+   newlevel->level_chain = current_binding_level;
+   current_binding_level = newlevel;
+ }
+ 
+ /* Exit a binding level.
+    Pop the level off, and restore the state of the identifier-decl mappings
+    that were in effect when this level was entered.
+ 
+    If KEEP is nonzero, this level had explicit declarations, so
+    and create a "block" (a BLOCK node) for the level
+    to record its declarations and subblocks for symbol table output.
+ 
+    If FUNCTIONBODY is nonzero, this level is the body of a function,
+    so create a block as if KEEP were set and also clear out all
+    label names.
+ 
+    If REVERSE is nonzero, reverse the order of decls before putting
+    them into the BLOCK.  */
+ 
+ tree
+ poplevel (int keep,
+           int reverse,
+           int functionbody)
+ {
+   /* Points to a BLOCK tree node. This is the BLOCK node construted for the
+      binding level that we are about to exit and which is returned by this
+      routine.  */
+   tree block_node = NULL_TREE;
+   tree decl_chain;
+   tree subblock_chain = current_binding_level->blocks;
+   tree subblock_node;
+   tree block_created_by_back_end;
+ 
+   /* Reverse the list of *_DECL nodes if desired.  Note that the ..._DECL
+      nodes chained through the `names' field of current_binding_level are in
+      reverse order except for PARM_DECL node, which are explicitely stored in
+      the right order.  */
+   decl_chain = (reverse) ? nreverse (current_binding_level->names)
+                          : current_binding_level->names;
+ 
+   block_created_by_back_end = current_binding_level->block_created_by_back_end;
+   if (block_created_by_back_end != 0)
+     {
+       block_node = block_created_by_back_end;
+ 
+       /* Check if we are about to discard some information that was gathered
+ 	 by the front-end. Nameley check if the back-end created a new block 
+ 	 without calling pushlevel first. To understand why things are lost
+ 	 just look at the next case (i.e. no block created by back-end.  */
+       if ((keep || functionbody) && (decl_chain || subblock_chain))
+ 	abort ();
+     }
+ 
+   /* If there were any declarations in the current binding level, or if this
+      binding level is a function body, or if there are any nested blocks then
+      create a BLOCK node to record them for the life of this function.  */
+   else if (keep || functionbody)
+     block_node = build_block (keep ? decl_chain : 0, 0, subblock_chain, 0, 0);
+ 
+   /* Record the BLOCK node just built as the subblock its enclosing scope.  */
+   for (subblock_node = subblock_chain; subblock_node;
+        subblock_node = TREE_CHAIN (subblock_node))
+     BLOCK_SUPERCONTEXT (subblock_node) = block_node;
+ 
+   /* Clear out the meanings of the local variables of this level.  */
+ 
+   for (subblock_node = decl_chain; subblock_node;
+        subblock_node = TREE_CHAIN (subblock_node))
+     if (DECL_NAME (subblock_node) != 0)
+       /* If the identifier was used or addressed via a local extern decl,  
+ 	 don't forget that fact.   */
+       if (DECL_EXTERNAL (subblock_node))
+ 	{
+ 	  if (TREE_USED (subblock_node))
+ 	    TREE_USED (DECL_NAME (subblock_node)) = 1;
+ 	  if (TREE_ADDRESSABLE (subblock_node))
+ 	    TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (subblock_node)) = 1;
+ 	}
+ 
+   /* Pop the current level.  */
+   current_binding_level = current_binding_level->level_chain;
+ 
+   if (functionbody)
+     {
+       /* This is the top level block of a function. The ..._DECL chain stored
+ 	 in BLOCK_VARS are the function's parameters (PARM_DECL nodes). Don't
+ 	 leave them in the BLOCK because they are found in the FUNCTION_DECL
+ 	 instead.  */
+       DECL_INITIAL (current_function_decl) = block_node;
+       BLOCK_VARS (block_node) = 0;
+     }
+   else if (block_node)
+     {
+       if (block_created_by_back_end == NULL)
+ 	current_binding_level->blocks
+ 	 = chainon (current_binding_level->blocks, block_node);
+     }
+ 
+   /* If we did not make a block for the level just exited, any blocks made for
+      inner levels (since they cannot be recorded as subblocks in that level)
+      must be carried forward so they will later become subblocks of something
+      else.  */
+   else if (subblock_chain)
+     current_binding_level->blocks
+      = chainon (current_binding_level->blocks, subblock_chain);
+   if (block_node)
+     TREE_USED (block_node) = 1;
+ 
+   return block_node;
+ }
+ 
+ /* Insert BLOCK at the end of the list of subblocks of the
+    current binding level.  This is used when a BIND_EXPR is expanded,
+    to handle the BLOCK node inside the BIND_EXPR.  */
+ 
+ void
+ insert_block (tree block)
+ {
+   TREE_USED (block) = 1;
+   current_binding_level->blocks
+    = chainon (current_binding_level->blocks, block);
+ }
+ 
+ /* Set the BLOCK node for the innermost scope
+    (the one we are currently in).  */
+ 
+ void
+ set_block (tree block)
+ {
+   current_binding_level->block_created_by_back_end = block;
+ }
+ 
+ /* Records a ..._DECL node DECL as belonging to the current lexical
+    scope.  Returns the ..._DECL node.  */
+ 
+ tree
+ pushdecl (tree decl)
+ {
+   /* External objects aren't nested, other objects may be.  */
+   if ((DECL_EXTERNAL (decl)) || (decl == current_function_decl))
+     DECL_CONTEXT (decl) = 0;
+   else
+     DECL_CONTEXT (decl) = current_function_decl;
+ 
+   /* Put the declaration on the list.  The list of declarations is in reverse
+      order. The list will be reversed later if necessary.  This needs to be
+      this way for compatibility with the back-end.  */
+ 
+   TREE_CHAIN (decl) = current_binding_level->names;
+   current_binding_level->names = decl;
+ 
+   /* For the declartion of a type, set its name if it is not already
+      set.  */
+ 
+   if (TREE_CODE (decl) == TYPE_DECL
+       && TYPE_NAME (TREE_TYPE (decl)) == 0)
+     TYPE_NAME (TREE_TYPE (decl)) = DECL_NAME (decl);
+ 
+   return decl;
+ }
+ 
+ #ifndef CHAR_TYPE_SIZE
+ #define CHAR_TYPE_SIZE BITS_PER_UNIT
+ #endif
+ 
+ #ifndef INT_TYPE_SIZE
+ #define INT_TYPE_SIZE BITS_PER_WORD
+ #endif
+ 
+ #undef SIZE_TYPE
+ #define SIZE_TYPE "unsigned int"
+ 
+ /* Create the predefined scalar types of C,
+    and some nodes representing standard constants (0, 1, (void *) 0).
+    Initialize the global binding level.
+    Make definitions for built-in primitive functions.  */
+ 
+   /* `unsigned long' is the standard type for sizeof.
+      Note that stddef.h uses `unsigned long',
+      and this must agree, even if long and int are the same size.  */
+ void
+ init_decl_processing ()
+ {
+   tree array_domain_type;
+ 
+   ggc_add_tree_root (&signed_and_unsigned_types[0][0],
+                      (MAX_BITS_PER_WORD + 1) * 2);
+ 
+   ggc_add_tree_root (c_global_trees, CTI_MAX);
+ 
+   set_identifier_size (sizeof (struct tree_identifier));
+ 
+   current_function_decl = NULL;
+   current_binding_level = NULL_BINDING_LEVEL;
+   free_binding_level = NULL_BINDING_LEVEL;
+   pushlevel (0); /* Make the binding_level structure for global names.  */
+   global_binding_level = current_binding_level;
+ 
+   build_common_tree_nodes (flag_signed_char);
+ 
+   set_sizetype (long_unsigned_type_node);
+ 
+   /* Set standard type names.  */
+ 
+   ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+   ggc_add_tree_root (ridpointers, RID_MAX);
+     
+   ridpointers[ (int) RID_INT] = get_identifier ("int");
+   ridpointers[ (int) RID_CHAR] = get_identifier ("char");
+   ridpointers[ (int) RID_VOID] = get_identifier ("void");
+   ridpointers[ (int) RID_FLOAT] = get_identifier ("float");
+   ridpointers[ (int) RID_DOUBLE] = get_identifier ("double");
+   ridpointers[ (int) RID_SHORT] = get_identifier ("short");
+   ridpointers[ (int) RID_LONG] = get_identifier ("long");
+   ridpointers[ (int) RID_UNSIGNED] = get_identifier ("unsigned");
+   ridpointers[ (int) RID_SIGNED] = get_identifier ("signed");
+   ridpointers[ (int) RID_INLINE] = get_identifier ("inline");
+   ridpointers[ (int) RID_CONST] = get_identifier ("const");
+   ridpointers[ (int) RID_RESTRICT] = get_identifier ("restrict");
+   ridpointers[ (int) RID_VOLATILE] = get_identifier ("volatile");
+   ridpointers[ (int) RID_BOUNDED] = get_identifier ("__bounded");
+   ridpointers[ (int) RID_UNBOUNDED] = get_identifier ("__unbounded");
+   ridpointers[ (int) RID_AUTO] = get_identifier ("auto");
+   ridpointers[ (int) RID_STATIC] = get_identifier ("static");
+   ridpointers[ (int) RID_EXTERN] = get_identifier ("extern");
+   ridpointers[ (int) RID_TYPEDEF] = get_identifier ("typedef");
+   ridpointers[ (int) RID_REGISTER] = get_identifier ("register");
+   /*  ridpointers[ (int) RID_ITERATOR] = get_identifier ("iterator"); */
+   ridpointers[ (int) RID_COMPLEX] = get_identifier ("complex");
+   ridpointers[ (int) RID_ID] = get_identifier ("id");
+   ridpointers[ (int) RID_IN] = get_identifier ("in");
+   ridpointers[ (int) RID_OUT] = get_identifier ("out");
+   ridpointers[ (int) RID_INOUT] = get_identifier ("inout");
+   ridpointers[ (int) RID_BYCOPY] = get_identifier ("bycopy");
+   ridpointers[ (int) RID_BYREF] = get_identifier ("byref");
+   ridpointers[ (int) RID_ONEWAY] = get_identifier ("oneway");
+ 
+   /* Define `int' and `char' first so that dbx will output them first.  */
+ 
+   /* Spec1 ensures that the type's type is itself. Needed for DBX. In
+      C this is done in pushdecl with a kludge.  */
+ 
+ #define spec1(type, id, node)\
+  { \
+    tree decl1; \
+    TREE_TYPE (node) = node; \
+    decl1 = build_decl (type, id, node); \
+    TYPE_NAME (node) = decl1; \
+    pushdecl (decl1);\
+  }
+ 
+  spec1 (TYPE_DECL, ridpointers[ (int) RID_INT], integer_type_node);
+  spec1 (TYPE_DECL, get_identifier ("char"), char_type_node);
+  spec1 (TYPE_DECL, get_identifier ("long int"), long_integer_type_node);
+  spec1 (TYPE_DECL, get_identifier ("unsigned long"), unsigned_type_node);
+  spec1 (TYPE_DECL, get_identifier ("long unsigned"), long_unsigned_type_node);
+  spec1 (TYPE_DECL, get_identifier ("long long int"), long_long_integer_type_node);
+  spec1 (TYPE_DECL, get_identifier ("long long unsigned"), long_long_unsigned_type_node);
+  spec1 (TYPE_DECL, get_identifier ("short int"), short_integer_type_node);
+  spec1 (TYPE_DECL, get_identifier ("short unsigned"), short_unsigned_type_node);
+  spec1 (TYPE_DECL, get_identifier ("signed char"), signed_char_type_node);
+  spec1 (TYPE_DECL, get_identifier ("unsigned char"), unsigned_char_type_node);
+  spec1 (TYPE_DECL, NULL_TREE, intQI_type_node);
+  spec1 (TYPE_DECL, NULL_TREE, intHI_type_node);
+  spec1 (TYPE_DECL, NULL_TREE, intSI_type_node);
+  spec1 (TYPE_DECL, NULL_TREE, intDI_type_node);
+ #if HOST_BITS_PER_WIDE_INT >= 64
+  spec1 (TYPE_DECL, NULL_TREE, intTI_type_node);
+ #endif
+  spec1 (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node);
+  spec1 (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node);
+  spec1 (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node);
+  spec1 (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node);
+ #if HOST_BITS_PER_WIDE_INT >= 64
+  spec1 (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node);
+ #endif
+   
+  /* Create the widest literal types.  */
+   widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+   widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+   spec1 (TYPE_DECL, NULL_TREE, widest_integer_literal_type_node);
+   spec1 (TYPE_DECL, NULL_TREE, widest_unsigned_literal_type_node);
+ 
+   build_common_tree_nodes_2 (flag_short_double); 
+ 
+   spec1 (TYPE_DECL, ridpointers[ (int) RID_FLOAT], float_type_node);
+   spec1 (TYPE_DECL, ridpointers[ (int) RID_DOUBLE], double_type_node);
+   spec1 (TYPE_DECL, get_identifier ("long double"), long_double_type_node);
+   spec1 (TYPE_DECL, ridpointers[ (int) RID_VOID], void_type_node);
+ 
+   void_pointer_type_node = build_pointer_type (void_type_node);
+   ADDROOT (void_pointer_type_node);
+   char_pointer_type_node = build_pointer_type (char_type_node);
+   ADDROOT (char_pointer_type_node);
+ 
+ #ifdef MD_INIT_BUILTINS
+   MD_INIT_BUILTINS;
+ #endif
+ 
+   wchar_type_node = get_identifier (flag_short_wchar ? "short unsigned" : WCHAR_TYPE);
+ 
+   boolean_type_node = integer_type_node;
+   boolean_true_node = integer_one_node;
+   boolean_false_node = integer_zero_node;
+ 
+   string_type_node = build_pointer_type (char_type_node);
+   {
+     tree decl1; 
+     decl1 = build_decl (TYPE_DECL, get_identifier ("string"), string_type_node); 
+     TYPE_NAME (string_type_node) = decl1; 
+     pushdecl (decl1);
+   }
+ 
+   const_string_type_node
+    = build_pointer_type (build_type_variant (char_type_node, 1, 0));
+ 
+   /* Make a type to be the domain of a few array types
+      whose domains don't really matter.
+      200 is small enough that it always fits in size_t
+      and large enough that it can hold most function names for the
+      initializations of __FUNCTION__ and __PRETTY_FUNCTION__.  */
+   array_domain_type = build_index_type (build_int_2 (200, 0));
+ 
+   /* Make a type for arrays of characters.  With luck nothing will
+      ever really depend on the length of this array type.  */
+   char_array_type_node
+      = build_array_type (char_type_node, array_domain_type);
+ 
+   tree_code_int_size = get_int_value (TYPE_SIZE (integer_type_node));
+   tree_code_char_size = get_int_value (TYPE_SIZE (char_type_node));
+ 
+ }
+ 
+ /* Given an integer constant T return its value as a long.  Silently
+    fail if too large.  */
+ 
+ static long
+ get_int_value (tree t)
+ {
+   if (TREE_CODE (t) != INTEGER_CST)
+     abort ();
+   return TREE_INT_CST_LOW (t);
+ }
+ 
+ /* Prevent warnings until we use it - do not remove */
+ #if 0
+ /* Possibly define a builtin function with one or two names.
+    BUILTIN_NAME is an __builtin_-prefixed name; NAME is the ordinary
+    name; one or both of these may be NULL (though both being NULL is
+    useless).  BUILTIN_TYPE is the type of the __builtin_-prefixed
+    function; TYPE is the type of the function with the ordinary name.
+    These may differ if the ordinary name is declared with a looser
+    type to avoid conflicts with headers.  FUNCTION_CODE and CLASS are
+    as for builtin_function.  If LIBRARY_NAME_P is nonzero, NAME is
+    passed as the LIBRARY_NAME parameter to builtin_function when
+    declaring BUILTIN_NAME.  If NONANSI_P is nonzero, the name NAME is
+    treated as a non-ANSI name; if NORETURN_P is nonzero, the function
+    is marked as non-returning.  Returns the declaration of
+    BUILTIN_NAME, if any, otherwise the declaration of NAME.  Does not
+    declare NAME if flag_no_builtin, or if NONANSI_P and
+    flag_no_nonansi_builtin.  */
+ 
+ static tree
+ builtin_function_2 (
+                     const char *builtin_name,
+                     const char *name,
+                     tree builtin_type,
+                     tree type,
+                     int function_code,
+                     enum built_in_class class,
+                     int library_name_p,
+                     int nonansi_p,
+                     int noreturn_p)
+ {
+   tree bdecl = NULL_TREE;
+   tree decl = NULL_TREE;
+   if (builtin_name != 0)
+     {
+       bdecl = builtin_function (builtin_name, builtin_type, function_code,
+ 				class, library_name_p ? name : NULL_PTR);
+       if (noreturn_p)
+ 	{
+ 	  TREE_THIS_VOLATILE (bdecl) = 1;
+ 	  TREE_SIDE_EFFECTS (bdecl) = 1;
+ 	}
+     }
+   if (name != 0 && !flag_no_builtin && ! (nonansi_p && flag_no_nonansi_builtin))
+     {
+       decl = builtin_function (name, type, function_code, class, NULL_PTR);
+       if (nonansi_p)
+ 	DECL_BUILT_IN_NONANSI (decl) = 1;
+       if (noreturn_p)
+ 	{
+ 	  TREE_THIS_VOLATILE (decl) = 1;
+ 	  TREE_SIDE_EFFECTS (decl) = 1;
+ 	}
+     }
+   return (bdecl != 0 ? bdecl : decl);
+ }
+ #endif
+ 
+ 
+ /* If DECL has a cleanup, build and return that cleanup here.
+    This is a callback called by expand_expr.  */
+ 
+ tree
+ maybe_build_cleanup (tree decl ATTRIBUTE_UNUSED)
+ { 
+   return NULL_TREE;
+ }
+ 
+ /* Print an error message for invalid use of an incomplete type.  */
+ 
+ void
+ incomplete_type_error (tree dont_care_1 ATTRIBUTE_UNUSED,
+                        tree dont_care_2 ATTRIBUTE_UNUSED)
+ { 
+   /* Should not happen in treelang - can happen in C.  */
+   abort ();
+ }
+ 
+ /* Not sure what this is about */
+ 
+ tree
+ truthvalue_conversion (tree expr)
+ { 
+   return expr;
+ }
+ 
+ 
+ /* Mark EXP saying that we need to be able to take the
+    address of it; it should not be allocated in a register.
+    Value is 1 if successful.  From c-typeck.c */
+ 
+ int
+ mark_addressable (tree exp)
+ {
+   register tree x = exp;
+   while (1)
+     switch (TREE_CODE (x))
+       {
+       case COMPONENT_REF:
+ 	if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
+ 	  {
+ 	    error ("cannot take address of bitfield `%s'",
+ 		   IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
+ 	    return 0;
+ 	  }
+ 
+ 	/* ... fall through ...  */
+ 
+       case ADDR_EXPR:
+       case ARRAY_REF:
+       case REALPART_EXPR:
+       case IMAGPART_EXPR:
+ 	x = TREE_OPERAND (x, 0);
+ 	break;
+ 
+       case CONSTRUCTOR:
+ 	TREE_ADDRESSABLE (x) = 1;
+ 	return 1;
+ 
+       case VAR_DECL:
+       case CONST_DECL:
+       case PARM_DECL:
+       case RESULT_DECL:
+ 	if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
+ 	    && DECL_NONLOCAL (x))
+ 	  {
+ 	    if (TREE_PUBLIC (x))
+ 	      {
+ 		error ("global register variable `%s' used in nested function",
+ 		       IDENTIFIER_POINTER (DECL_NAME (x)));
+ 		return 0;
+ 	      }
+ 	    pedwarn ("register variable `%s' used in nested function",
+ 		     IDENTIFIER_POINTER (DECL_NAME (x)));
+ 	  }
+ 	else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
+ 	  {
+ 	    if (TREE_PUBLIC (x))
+ 	      {
+ 		error ("address of global register variable `%s' requested",
+ 		       IDENTIFIER_POINTER (DECL_NAME (x)));
+ 		return 0;
+ 	      }
+ 
+ 	    /* If we are making this addressable due to its having
+ 	       volatile components, give a different error message.  Also
+ 	       handle the case of an unnamed parameter by not trying
+ 	       to give the name.  */
+ 
+ 	    else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x)))
+ 	      {
+ 		error ("cannot put object with volatile field into register");
+ 		return 0;
+ 	      }
+ 
+ 	    pedwarn ("address of register variable `%s' requested",
+ 		     IDENTIFIER_POINTER (DECL_NAME (x)));
+ 	  }
+ 	put_var_into_stack (x);
+ 
+ 	/* Drops in.  */
+       case FUNCTION_DECL:
+ 	TREE_ADDRESSABLE (x) = 1;
+ 
+       default:
+ 	return 1;
+     }
+ }
+ 
+ /* Since we don't use the DECL_LANG_SPECIFIC field, this is a no-op.  */
+ 
+ void
+ copy_lang_decl (tree node ATTRIBUTE_UNUSED)
+ {
+ }
+ 
+ /* Hooks for print-tree.c:  */
+ 
+ void
+ print_lang_decl (FILE *file ATTRIBUTE_UNUSED,
+                  tree node ATTRIBUTE_UNUSED,
+                  int indent ATTRIBUTE_UNUSED)
+ {
+ }
+ 
+ void
+ print_lang_type (FILE *file ATTRIBUTE_UNUSED,
+                  tree node ATTRIBUTE_UNUSED,
+                  int indent ATTRIBUTE_UNUSED)
+ {
+ }
+ 
+ void
+ print_lang_identifier (FILE *file ATTRIBUTE_UNUSED,
+                        tree node ATTRIBUTE_UNUSED,
+                        int indent ATTRIBUTE_UNUSED)
+ {
+ }
+ 
+ /* Mark any data hanging off a tree node T as used, for garbage
+    collection */
+ void 
+ lang_mark_tree (union tree_node *t ATTRIBUTE_UNUSED)
+ {
+   /* We have no extras in the tree - nothing to do so return.  */
+   return;
+ }
+ 
+ /* Return the typed-based alias set for T, which may be an expression
+    or a type.  Return -1 if we don't do anything special.  */
+ 
+ HOST_WIDE_INT
+ lang_get_alias_set (tree t ATTRIBUTE_UNUSED)
+ {
+   return -1;
+ }
+ 
+ /* Return a definition for a builtin function named NAME and whose data type
+    is TYPE.  TYPE should be a function type with argument types.
+    FUNCTION_CODE tells later passes how to compile calls to this function.
+    See tree.h for its possible values.
+ 
+    If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
+    the name to be called if we can't opencode the function.  */
+ 
+ tree
+ builtin_function (const char *name,
+                   tree type,
+                   int function_code,
+                   enum built_in_class class,
+                   const char *library_name)
+ {
+   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
+   DECL_EXTERNAL (decl) = 1;
+   TREE_PUBLIC (decl) = 1;
+   if (library_name)
+     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
+   make_decl_rtl (decl, NULL_PTR);
+   pushdecl (decl);
+   DECL_BUILT_IN_CLASS (decl) = class;
+   DECL_FUNCTION_CODE (decl) = function_code;
+ 
+   return decl;
+ }
+ 
+ 
+ /* Build a function call to function FUNCTION with parameters PARAMS.
+    PARAMS is a list--a chain of TREE_LIST nodes--in which the
+    TREE_VALUE of each node is a parameter-expression.
+    FUNCTION's data type may be a function type or a pointer-to-function.  */
+ 
+ tree
+ build_function_call (tree function, tree params)
+ {
+   tree fntype = NULL_TREE, fundecl = 0;
+   tree name = NULL_TREE, assembler_name = NULL_TREE, result;
+ 
+   /* Convert anything with function type to a pointer-to-function.  */
+   if (TREE_CODE (function) == FUNCTION_DECL)
+     {
+       name = DECL_NAME (function);
+       assembler_name = DECL_ASSEMBLER_NAME (function);
+ 
+       /* Differs from default_conversion by not setting TREE_ADDRESSABLE
+ 	 (because calling an inline function does not mean the function
+ 	 needs to be separately compiled).  */
+       fntype = build_type_variant (TREE_TYPE (function),
+ 				   TREE_READONLY (function),
+ 				   TREE_THIS_VOLATILE (function));
+       fundecl = function;
+       function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
+     }
+ 
+   /* fntype now gets the type of function pointed to.  */
+   fntype = TREE_TYPE (function);
+   fntype = TREE_TYPE (fntype);
+ 
+   /* Recognize certain built-in functions so we can make tree-codes
+      other than CALL_EXPR.  We do this when it enables fold-const.c
+      to do something useful.  */
+ 
+   result = build (CALL_EXPR, TREE_TYPE (fntype),
+ 		  function, params, NULL_TREE);
+   TREE_SIDE_EFFECTS (result) = 1;
+ 
+   return result;
+ }
+ 
+ /* End compiler back end stuff.  */
+ 
+ /* Garbage Collection.  */
+ 
+ /* Callback to mark storage M as used always.  */
+ 
+ void
+ tree_ggc_storage_always_used (void * m)
+ {
+   void** mm; /* Actually M is a pointer to a pointer to the memory.  */
+   mm = (void**)m;
+ 
+   if (*mm)
+     ggc_mark (*mm);
+ }
diff -c3prN gcccvs/gcc/gcc/treelang/treetree.h newgcc/gcc/treelang/treetree.h
*** gcccvs/gcc/gcc/treelang/treetree.h	Thu Jan  1 10:00:00 1970
--- newgcc/gcc/treelang/treetree.h	Mon Jun 11 08:45:27 2001
***************
*** 0 ****
--- 1,94 ----
+ /* 
+ 
+     TREELANG Compiler definitions for interfacing to treetree.c
+     (compiler back end interface).
+ 
+     Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+     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, 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, 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ 
+     In other words, you are welcome to use, share and improve this program.
+     You are forbidden to forbid anyone else to use, share and improve
+     what you give them.   Help stamp out software-hoarding!  
+ 
+     ---------------------------------------------------------------------------
+ 
+     Written by Tim Josling 1999, 2000, 2001, based in part on other
+     parts of the GCC compiler.
+ 
+  */
+ 
+ /* Parameter list passed to back end.  */
+ struct tree_parameter_list 
+ {
+   struct tree_parameter_list* next; /* Next entry.  */
+   int   type; /* See numeric types below.  */
+   unsigned char* variable_name; /* Name. */
+   tree* where_to_put_var_tree; /* Where to save decl.  */
+ };
+ 
+ tree tree_code_init_parameters (void);
+ tree tree_code_add_parameter (tree list, tree proto_exp, tree exp);
+ tree tree_code_get_integer_value (unsigned char* chars, unsigned int length);
+ void tree_code_generate_return (tree type, tree exp);
+ void tree_ggc_storage_always_used  (void*  m);
+ tree tree_code_get_expression (unsigned int exp_type, tree type, tree op1, tree op2, tree op3);
+ tree tree_code_get_numeric_type (unsigned int size1, unsigned int sign1);
+ void tree_code_create_function_initial (tree prev_saved,
+                                        unsigned char* filename, int lineno,
+                                        struct tree_parameter_list* parms);
+ void tree_code_create_function_wrapup (unsigned char* filename, int lineno);
+ tree tree_code_create_function_prototype (unsigned char* chars,
+                                          unsigned int storage_class,
+                                          unsigned int ret_type,
+                                          struct tree_parameter_list* parms,                                 
+                                          unsigned char* filename,
+                                          int lineno);
+ tree tree_code_create_variable (unsigned int storage_class,
+                                unsigned char* chars,
+                                unsigned int length,
+                                unsigned int expression_type,
+                                tree init,
+                                unsigned char* filename,
+                                int lineno);
+ void tree_code_output_expression_statement (tree code, unsigned char* filename, int lineno);
+ tree get_type_for_numeric_type (unsigned int numeric_type);
+ void tree_code_if_start (tree exp, unsigned char* filename, int lineno);
+ void tree_code_if_else (unsigned char* filename, int lineno);
+ void tree_code_if_end (unsigned char* filename, int lineno);
+ tree tree_code_get_type (int type_num);
+ 
+ /* Storage modes.  */
+ #define STATIC_STORAGE 0
+ #define AUTOMATIC_STORAGE 1
+ #define EXTERNAL_REFERENCE_STORAGE 2
+ #define EXTERNAL_DEFINITION_STORAGE 3
+ 
+ 
+ /* Numeric types.  */
+ #define SIGNED_CHAR 1
+ #define UNSIGNED_CHAR 2
+ #define SIGNED_INT 3 
+ #define UNSIGNED_INT 4
+ #define VOID_TYPE 5
+ 
+ 
+ #define EXP_PLUS 0 /* Addition expression.  */
+ #define EXP_REFERENCE 1 /* Variable reference.  */
+ #define EXP_ASSIGN 2 /* Assignment.  */
+ #define EXP_FUNCTION_INVOCATION 3  /* Call function.  */
+ #define EXP_MINUS 4  /* Subtraction.  */
+ #define EXP_EQUALS 5  /* Equality test.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]