OSDN Git Service

Added new sample language treelang.
authortimjosling <timjosling@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 May 2002 04:24:18 +0000 (04:24 +0000)
committertimjosling <timjosling@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 May 2002 04:24:18 +0000 (04:24 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53169 138bc75d-0d04-0410-961f-82ee72b054a4

20 files changed:
gcc/testsuite/lib/treelang.exp [new file with mode: 0644]
gcc/testsuite/treelang/ChangeLog [new file with mode: 0644]
gcc/testsuite/treelang/Makefile.in [new file with mode: 0644]
gcc/testsuite/treelang/a01gcci01.c [new file with mode: 0644]
gcc/testsuite/treelang/a01gcci01.tree [new file with mode: 0644]
gcc/testsuite/treelang/a01gcco01runpgm [new file with mode: 0644]
gcc/testsuite/treelang/treetests.exp [new file with mode: 0644]
gcc/treelang/ChangeLog [new file with mode: 0644]
gcc/treelang/Make-lang.in [new file with mode: 0644]
gcc/treelang/README [new file with mode: 0644]
gcc/treelang/config-lang.in [new file with mode: 0644]
gcc/treelang/lang-options.h [new file with mode: 0644]
gcc/treelang/lang-specs.h [new file with mode: 0644]
gcc/treelang/lex.l [new file with mode: 0644]
gcc/treelang/parse.y [new file with mode: 0644]
gcc/treelang/tree1.c [new file with mode: 0644]
gcc/treelang/treelang.h [new file with mode: 0644]
gcc/treelang/treelang.texi [new file with mode: 0644]
gcc/treelang/treetree.c [new file with mode: 0644]
gcc/treelang/treetree.h [new file with mode: 0644]

diff --git a/gcc/testsuite/lib/treelang.exp b/gcc/testsuite/lib/treelang.exp
new file mode 100644 (file)
index 0000000..e3d6c49
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright (C) 1988, 90, 91, 92, 95, 96, 1997, 1999, 2000, 2001, 2002 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 --git a/gcc/testsuite/treelang/ChangeLog b/gcc/testsuite/treelang/ChangeLog
new file mode 100644 (file)
index 0000000..d7f7c78
--- /dev/null
@@ -0,0 +1,40 @@
+2002-04-13  Tim Josling  <tej@melbpc.org.au>
+      * treetree.c (tree_code_create_function_initial)
+      Remove duplicate call to layout_decl
+
+2001-12-02  Tim Josling  <tej@melbpc.org.au>
+      * Make-lang.in
+      Ensure directory is built during install (installdirs dependency)
+
+      * lex.l
+      Work around poisoned malloc (undef IN_GCC)
+      Remove fake definition of tree.
+
+      * parse.y
+      Work around poisoned malloc (undef IN_GCC)
+
+      * tree1.c
+      New front end interface. 
+      (top level) New structure lang_hooks.
+      (tree_post_options) Remove. 
+      errorcount now a macro so do not define it.
+      current_nesting_level => work_nesting_level due to clash. 
+
+      * treelang.h
+      errorcount now a macro so do not reference it.
+
+      * treetree.c
+      Replace NULL_PTR by NULL.
+      (tree_code_get_expression) Mark op3 unused.
+      Do not init builtins.
+
+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 --git a/gcc/testsuite/treelang/Makefile.in b/gcc/testsuite/treelang/Makefile.in
new file mode 100644 (file)
index 0000000..908131b
--- /dev/null
@@ -0,0 +1,9 @@
+# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+all: 
+
+clean:
+       -rm -f *.o *.diff *~ *.bad core *.x
+
+distclean:     clean
+       -rm -f Makefile config.status
diff --git a/gcc/testsuite/treelang/a01gcci01.c b/gcc/testsuite/treelang/a01gcci01.c
new file mode 100644 (file)
index 0000000..69ab63d
--- /dev/null
@@ -0,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 --git a/gcc/testsuite/treelang/a01gcci01.tree b/gcc/testsuite/treelang/a01gcci01.tree
new file mode 100644 (file)
index 0000000..e1e1ac1
--- /dev/null
@@ -0,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 --git a/gcc/testsuite/treelang/a01gcco01runpgm b/gcc/testsuite/treelang/a01gcco01runpgm
new file mode 100644 (file)
index 0000000..3c2c743
--- /dev/null
@@ -0,0 +1,8 @@
+2:2
+7:7
+-1:-1
+1:1
+3:3
+0:0
+1:1
+15:15
diff --git a/gcc/testsuite/treelang/treetests.exp b/gcc/testsuite/treelang/treetests.exp
new file mode 100644 (file)
index 0000000..10e6f84
--- /dev/null
@@ -0,0 +1,289 @@
+
+# Tests for treelang; run from gcc/treelang/Make-lang.in => gcc/Makefile
+
+# Copyright (C) 1999, 2000, 2001, 2002 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
+    global path
+# 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 "
+    set real_pgm_actual ${pgm_actual}
+
+    if  {${tree1} > 0} {
+        if {"${pgm_actual}" == "gcc"} {
+            set real_pgm_actual "xgcc"
+            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 ${real_pgm_actual} ${temp_extras} ${parms} ${mainfile} ${infile} ${outfile} >${testdd}/${basefile} 2>${testdd}/${basefile}err" 2
+    set run_rc [catch {eval exec ${real_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. ${real_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 C 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 --git a/gcc/treelang/ChangeLog b/gcc/treelang/ChangeLog
new file mode 100644 (file)
index 0000000..18b7e08
--- /dev/null
@@ -0,0 +1,24 @@
+2002-05-05  Tim Josling  <tej@melbpc.org.au>
+
+       * Updated for gcc3.2 experimental. Major changes throughout.
+
+2002-03-31  Tim Josling  <tej@melbpc.org.au>
+
+       * Make-lang.in: Changes so build and check work more reliably
+
+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 --git a/gcc/treelang/Make-lang.in b/gcc/treelang/Make-lang.in
new file mode 100644 (file)
index 0000000..bd6f7e3
--- /dev/null
@@ -0,0 +1,297 @@
+# Top level makefile fragment for TREELANG For GCC. -*- makefile -*-
+
+#   Copyright (C) 1994, 1995, 1997, 1998, 1999 2000, 2001, 2002 Free
+#   Software Foundation, Inc.
+
+#This file is part of GCC.
+
+#GCC 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.
+
+#GCC 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 GCC; 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.
+#\f
+
+## 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 = $(BACKEND) $(LIBIBERTY) $(INTLLIBS) $(LIBS) $(LIBDEPS) 
+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 = tree1$(exeext)
+
+#no -Wtraditional warnings, allow long long
+treelang-warn = $(LOOSE_WARN) -pedantic -Wno-long-long -Wmissing-prototypes -Wmissing-declarations
+
+#\f
+# Define the names for selecting treelang in LANGUAGES.
+
+.phony: treelang TREELANG
+
+treelang TREELANG:treelang.done
+
+treelang.done: tree1$(exeext)
+       $(STAMP) treelang.done
+
+# no preprocessor
+
+# core compiler 
+tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o\
+       $(TREE_BE_LIBS) c-convert.o c-typeck.o c-common.o c-decl.o attribs.o
+       $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+       treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o c-convert.o\
+       c-typeck.o c-common.o c-decl.o attribs.o $(TREE_BE_LIBS)
+
+#\f
+# Compiling object files from source files.
+
+# object file makes
+
+treelang/tree1.o: $(srcdir)/treelang/tree1.c $(srcdir)/treelang/treelang.h $(srcdir)/treelang/parse.h
+       $(CC) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< 
+
+treelang/treetree.o: $(srcdir)/treelang/treetree.c $(srcdir)/treelang/treetree.h
+       $(CC) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< 
+
+treelang/parse.o: $(srcdir)/treelang/parse.c $(srcdir)/treelang/treelang.h $(srcdir)/treelang/treetree.h
+       $(CC) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< 
+
+treelang/lex.o: $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.h $(srcdir)/treelang/treelang.h
+       $(CC) -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
+
+#\f
+# 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;
+
+#\f
+# 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:  installdirs 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
+       $(STAMP) 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
+
+#\f
+# 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/*~
+
+
+#\f
+# 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
+#\f
+# 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 sorry not sure if this is needed or not???
+
+# 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: $(TESTSUITEDIR)/site.exp
+       -mkdir testsuite/treelang 
+
+# these three files are empty and it seems diff has trouble generating
+# patch files for new empty files as required for cvs.
+# STAMP does not cut it here as I need an empty file.
+       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=`cd ..;pwd`:$$PATH; export PATH; \
+       gcc_extras="-B`cd ..;pwd` -B`cd ..;pwd`/treelang"; export gcc_extras; \
+       $(RUNTEST) --tool treelang $(RUNTESTFLAGS)
+       rm $(srcdir)/testsuite/treelang/{a01gcco01runpgmerr,a01gcc.out01,a01gcc.out01err}
+#      GCC_EXTRAS="$(GCC_EXTRAS)"; export GCC_EXTRAS; \
+
+# 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}
+
+#\f
+
+# 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 --git a/gcc/treelang/README b/gcc/treelang/README
new file mode 100644 (file)
index 0000000..f16eafc
--- /dev/null
@@ -0,0 +1,16 @@
+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 a subset 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 --git a/gcc/treelang/config-lang.in b/gcc/treelang/config-lang.in
new file mode 100644 (file)
index 0000000..6cf1f45
--- /dev/null
@@ -0,0 +1,37 @@
+# Top level configure fragment for GNU C++.
+# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+#This file is part of GCC.
+
+#GCC 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.
+
+#GCC 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 GCC; 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=
+build_by_default="no"
diff --git a/gcc/treelang/lang-options.h b/gcc/treelang/lang-options.h
new file mode 100644 (file)
index 0000000..2d60c3e
--- /dev/null
@@ -0,0 +1,29 @@
+/* Definitions for switches for TREELANG.
+
+   Copyright (C) 1995, 96-98, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 --git a/gcc/treelang/lang-specs.h b/gcc/treelang/lang-specs.h
new file mode 100644 (file)
index 0000000..4bf8e5d
--- /dev/null
@@ -0,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, 2002 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 ANSI string concatenations
+   
+*/
+
+{".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 --git a/gcc/treelang/lex.l b/gcc/treelang/lex.l
new file mode 100644 (file)
index 0000000..97b06a6
--- /dev/null
@@ -0,0 +1,294 @@
+%{ /* -*- c -*- = mode for emacs editor
+/* 
+
+   TREELANG lexical analysis
+
+   ---------------------------------------------------------------------
+
+   Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 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. 
+*/
+
+/* Avoid poisoned malloc problem.  */
+#undef IN_GCC
+
+#if 0
+/* tree is defined as void* here to avoid any knowledge of tree stuff in this file.  */
+typedef void *tree;
+#endif
+#include <stdio.h>
+#if 0
+#include <ctype.h>
+#endif
+#include <memory.h>
+#include "ansidecl.h"
+#include "config.h"
+#include "system.h"
+#include "diagnostic.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]);
+    }
+  fprintf (stderr, " in hex:");
+  for (ix = 0; ix < yyleng; ix++) 
+    {
+      fprintf (stderr, " %2.2x", yytext[ix]);
+    }
+  fprintf (stderr, "\n");
+}  
+
diff --git a/gcc/treelang/parse.y b/gcc/treelang/parse.y
new file mode 100644 (file)
index 0000000..f0c0cef
--- /dev/null
@@ -0,0 +1,1001 @@
+%{ /* -*- c -*- emacs mode c */
+  /* 
+
+     TREELANG Compiler parser.  
+
+     ---------------------------------------------------------------------
+
+     Copyright (C) 1999, 2000, 2001, 2002 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
+     *****************
+
+     There are no conflicts in this grammar.  Please keep it that way.
+
+   */
+
+#undef IN_GCC
+
+typedef void *tree;
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ansidecl.h"
+#include "config.h"
+#include "system.h"
+#include "diagnostic.h"
+
+#include "treelang.h"
+#include "treetree.h"
+
+#define YYDEBUG 1
+#define YYPRINT(file, type, value) print_token (file, type, value) 
+#define YYERROR_VERBOSE YES
+
+
+extern int option_parser_trace;
+
+/* 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;
+  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;
+}
+;
+
+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 ();
+    }
+}
+
+/* Set parse trace.  */
+
+void
+treelang_debug (void)
+{
+  if (option_parser_trace)
+    yydebug = 1;
+}
diff --git a/gcc/treelang/tree1.c b/gcc/treelang/tree1.c
new file mode 100644 (file)
index 0000000..5067bea
--- /dev/null
@@ -0,0 +1,382 @@
+  /* 
+
+    TREELANG Compiler almost main (tree1)
+    Called by GCC's toplev.c
+
+    Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 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 "ansidecl.h"
+#include "flags.h"
+#include "output.h"
+#include "toplev.h"
+
+#include "ggc.h"
+#include "tree.h"
+#include "diagnostic.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "treelang.h"
+#include "treetree.h"
+
+extern int yyparse (void);
+/* Linked list of symbols - all must be unique in treelang.  */
+
+struct production *symbol_table = NULL;
+
+/* Language for usage for messages.  */
+
+const char *const language_string = "TREELANG - sample front end for GCC ";
+
+/* Local prototypes.  */
+
+void version (void);
+
+/* GC routine for symbol table.  */
+static void symbol_table_ggc (void *m);
+
+/* Global variables.  */
+
+extern struct cbl_tree_struct_parse_tree_top* parse_tree_top;
+
+/* 
+   Options. 
+*/
+
+/* Trace the parser.  */
+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 work_nesting_level = 0;
+
+/* Process one switch - called by toplev.c.  */
+
+int
+treelang_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 'y':
+      if (!strcmp (first_option_left[0],"-y"))
+        {
+          option_lexer_trace = 1;
+          option_parser_trace = 1;
+          return 1;
+        }
+    case 'f':
+      if (!strcmp (first_option_left[0],"-fparser-trace"))
+        {
+          option_parser_trace = 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;
+
+}
+
+/* Language dependent parser setup.  */
+
+const char*
+treelang_init (const char* filename)
+{
+
+  /* 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.  */
+  /* 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.  */
+
+  /* Set up the declarations needed for this front end.  */
+
+  input_filename = "";
+  lineno = 0;
+
+  treelang_init_decl_processing ();
+
+  /* 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);
+    }
+  input_filename = filename;
+  return (char*) (in_fname = (unsigned char*)filename);
+}
+
+/* Language dependent wrapup.  */
+
+void 
+treelang_finish (void)
+{
+  fclose (yyin);
+}
+
+/* Parse a file.  Debug flag doesn't seem to work. */
+
+void
+treelang_parse_file (int debug_flag ATTRIBUTE_UNUSED)
+{
+  treelang_debug ();
+  yyparse ();
+}
+
+
+/* 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);
+}
+
+/* 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) = work_nesting_level;
+  symbol_table = prod;
+  return 0;
+}
+
+/* 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 --git a/gcc/treelang/treelang.h b/gcc/treelang/treelang.h
new file mode 100644 (file)
index 0000000..a265738
--- /dev/null
@@ -0,0 +1,116 @@
+/* 
+
+    TREELANG Compiler common definitions (treelang.h)
+
+    Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 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 
+{ /* These values less likely to be there by chance unlike 0/1,
+      make checks more meaningful */
+  token_category = 111,
+  production_category = 222
+};
+
+/* Input file name and FILE.  */
+extern unsigned char* in_fname;
+extern FILE* yyin;
+
+#if 0
+extern int errorcount; /* In toplev.c.  */
+#endif
+
+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);
+struct production *make_production (int type, struct token* main_tok);
+void mark_production_used (struct production * pp);
+void mark_token_used (struct token* tt);
+void treelang_debug (void);
+
diff --git a/gcc/treelang/treelang.texi b/gcc/treelang/treelang.texi
new file mode 100644 (file)
index 0000000..499f160
--- /dev/null
@@ -0,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,2002
+@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
+
+@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 GCC compiler.
+@xref{Contributors,,Contributors to GCC,GCC,Using and Maintaining GCC},
+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 GCC}.
+
+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. Line terminations are as defined by the
+standard C library. 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 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_separated_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 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 you 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 GCC 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 GCC},
+for information on the way different languages are handled
+by the GCC 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 @code{gcc}. There is no reason why they cannot be run through the
+preprocessor manually, but you would need to prevent the preprocessor
+from 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, with one proviso.
+
+C promotes small integer types to 'int' when used as function parameters and 
+return values. The treelang compiler does not do this, so if you want to interface
+to C, you need to specify the promoted value, not the nominal value. 
+
+@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
+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
+GCC 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 --git a/gcc/treelang/treetree.c b/gcc/treelang/treetree.c
new file mode 100644 (file)
index 0000000..07cb1a5
--- /dev/null
@@ -0,0 +1,1288 @@
+/* 
+
+    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, 2002 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 "ansidecl.h"
+#include "config.h"
+#include "system.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 "langhooks-def.h"
+#include "langhooks.h"
+
+#include "treetree.h"
+
+extern int option_main;
+extern char **file_names;
+
+/* Flags etc required by c code.  */
+
+int warn_format = 0;
+int warn_format_y2k = 0;
+int warn_format_extra_args = 0;
+int warn_format_nonliteral = 0;
+int warn_format_security = 0;
+
+/* The front end language hooks (addresses of code for this front
+   end).  Mostly just use the C routines.  */
+
+#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
+#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion
+#undef LANG_HOOKS_MARK_ADDRESSABLE
+#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable
+#undef LANG_HOOKS_SIGNED_TYPE
+#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type
+#undef LANG_HOOKS_UNSIGNED_TYPE
+#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type
+#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
+#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE treelang_parse_file
+
+/* Hook routines and data unique to treelang.  */
+
+#undef LANG_HOOKS_INIT
+#define LANG_HOOKS_INIT treelang_init
+#undef LANG_HOOKS_NAME
+#define LANG_HOOKS_NAME        "GNU treelang"
+#undef LANG_HOOKS_FINISH 
+#define LANG_HOOKS_FINISH              treelang_finish
+#undef LANG_HOOKS_DECODE_OPTION        
+#define LANG_HOOKS_DECODE_OPTION treelang_decode_option
+const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+
+/* Tree code type/name/code tables.  */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
+
+const char tree_code_type[] = {
+#include "tree.def"
+  'x'
+};
+#undef DEFTREECODE
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
+
+const unsigned char tree_code_length[] = {
+#include "tree.def"
+  0
+};
+#undef DEFTREECODE
+
+#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
+
+const char *const tree_code_name[] = {
+#include "tree.def"
+  "@@dummy"
+};
+#undef DEFTREECODE
+
+/* 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;
+
+/* 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 ((const 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 ((const 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 ((const 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 ((const 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 ((const 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) = (const 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;
+      TREE_STATIC (fn_decl) = 0; 
+      DECL_EXTERNAL (fn_decl) = 0;
+      break;
+  
+    case EXTERNAL_REFERENCE_STORAGE:
+      TREE_PUBLIC (fn_decl) = 0; 
+      DECL_EXTERNAL (fn_decl) = 1;
+      break;
+
+
+    case AUTOMATIC_STORAGE:
+    default:
+      abort ();
+    }
+
+  /* Process declaration of function defined elsewhere.  */
+  rest_of_decl_compilation (fn_decl, NULL, 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 at 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) = (const 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) = (const 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 ((const 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) = (const 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, (const char *)filename, lineno); 
+  
+  /* Create 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.  */
+  
+  (*lang_hooks.decls.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);  Already done in build_decl tej 13/4/2002.  */
+      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.  */
+  
+  (*lang_hooks.decls.pushlevel) (0);
+  
+  /* Create rtl for the start of a new scope.  */
+  
+  expand_start_bindings (0);
+  
+  emit_line_note ((const char *)filename, lineno); /* Output the line number information.  */
+}
+
+/* Wrapup a function contained in file FILENAME, ending at line LINENO.  */
+void 
+tree_code_create_function_wrapup (unsigned char* filename,
+                                 int lineno)
+{
+  tree block;
+  tree fn_decl;
+
+  fn_decl = current_function_decl;
+  
+  emit_line_note ((const char *)filename, lineno); /* Output the line number information.  */
+
+  /* Get completely built level from debugger symbol table.  */
+  
+  block = (*lang_hooks.decls.poplevel) (1, 0, 0);
+  
+  /* Emit rtl for end of scope.  */
+  
+  expand_end_bindings (block, 0, 1);
+  
+  /* Emit rtl for end of function.  */
+  
+  expand_function_end ((const char *)filename, lineno, 0);
+  
+  /* Pop the level.  */
+
+  block = (*lang_hooks.decls.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);
+  
+  /* 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 ((const 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) = (const 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;
+      TREE_PUBLIC (var_decl) = 0;
+      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)
+{
+  /* Output the line number information.  */
+  emit_line_note ((const char *)filename, lineno); 
+  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 ATTRIBUTE_UNUSED)
+{
+  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;    
+}
+
+/* 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);
+} 
+
+/* Following  from c-lang.c.  */
+
+/* Tell the c code we are not objective C.  */
+
+int
+maybe_objc_comptypes (tree lhs ATTRIBUTE_UNUSED,
+                      tree rhs ATTRIBUTE_UNUSED,
+                      int reflexive ATTRIBUTE_UNUSED)
+{
+  return -1;
+}
+
+/* Used by c-typeck.c (build_external_ref), but only for objc.  */
+
+tree
+lookup_objc_ivar (tree id ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+/* Dummy routines called from c code. Save copying c-decl.c, c-common.c etc.  */
+
+void
+check_function_format (int *status ATTRIBUTE_UNUSED,
+                       tree attrs ATTRIBUTE_UNUSED,
+                       tree params ATTRIBUTE_UNUSED)
+{
+  return;
+}
+
+/* Tell the c code we are not objective C.  */
+
+tree
+maybe_building_objc_message_expr ()
+{
+  return 0;
+}
+
+/* Should not be called for treelang.   */
+
+tree
+build_stmt VPARAMS ((enum tree_code code  ATTRIBUTE_UNUSED, ...))
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+tree
+add_stmt (tree t ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+tree
+build_return_stmt (tree expr ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* C warning, ignore.  */
+
+void
+pedwarn_c99 VPARAMS ((const char *msgid ATTRIBUTE_UNUSED, ...))
+{
+  return;
+}
+
+/* Should not be called for treelang.   */
+
+tree
+build_case_label (tree low_value ATTRIBUTE_UNUSED,
+                  tree high_value ATTRIBUTE_UNUSED,
+                  tree label_decl ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+emit_local_var (tree decl ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+expand_stmt (tree t ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+cpp_reader *
+cpp_create_reader (enum c_lang lang ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+cpp_post_options (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+cpp_preprocess_file (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+const char *
+init_c_lex (const char *filename ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void init_pragma (void);
+
+void
+init_pragma ()
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+cpp_finish (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+unsigned int
+cpp_errors (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+tree
+handle_format_attribute (tree *node ATTRIBUTE_UNUSED,
+                         tree name ATTRIBUTE_UNUSED,
+                         tree args ATTRIBUTE_UNUSED,
+                         int flags ATTRIBUTE_UNUSED,
+                         bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+tree
+handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED,
+     tree name ATTRIBUTE_UNUSED,
+     tree args ATTRIBUTE_UNUSED,
+     int flags ATTRIBUTE_UNUSED,
+     bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+int
+cpp_handle_option (cpp_reader *pfile ATTRIBUTE_UNUSED,
+     int argc ATTRIBUTE_UNUSED,
+     char **argv ATTRIBUTE_UNUSED,
+     int ignore ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+set_Wformat (int setting ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+maybe_objc_check_decl (tree decl ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+gen_aux_info_record (tree fndecl ATTRIBUTE_UNUSED,
+                     int is_definition ATTRIBUTE_UNUSED,
+                     int is_implicit ATTRIBUTE_UNUSED,
+                     int is_prototyped ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang, but it is.   */
+
+void
+c_parse_init ()
+{
+  return;
+}
+
+/* Should not be called for treelang.   */
+
+void maybe_apply_pragma_weak (tree decl);
+
+void
+maybe_apply_pragma_weak (tree decl ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+add_decl_stmt (tree decl ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+tree
+maybe_apply_renaming_pragma (tree decl, tree asmname);
+
+/* Should not be called for treelang.   */
+
+tree
+maybe_apply_renaming_pragma (tree decl ATTRIBUTE_UNUSED, tree asmname ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+begin_stmt_tree (tree *t ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+void
+finish_stmt_tree (tree *t ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+/* Should not be called for treelang.   */
+
+int
+defer_fn (tree fn ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
+
+/* 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.  */
+
+/* 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.  */
+
+tree integer_types[itk_none] = { NULL_TREE};
+
+/* The reserved keyword table.  */
+struct resword
+{
+  const char *word;
+  ENUM_BITFIELD(rid) rid : 16;
+  unsigned int disable   : 16;
+};
+
+static const struct resword reswords[] =
+{
+  { "_Bool",           RID_BOOL,       0 },
+  { "_Complex",                RID_COMPLEX,    0 },
+  { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
+  { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
+  { "__alignof",       RID_ALIGNOF,    0 },
+  { "__alignof__",     RID_ALIGNOF,    0 },
+  { "__asm",           RID_ASM,        0 },
+  { "__asm__",         RID_ASM,        0 },
+  { "__attribute",     RID_ATTRIBUTE,  0 },
+  { "__attribute__",   RID_ATTRIBUTE,  0 },
+  { "__bounded",       RID_BOUNDED,    0 },
+  { "__bounded__",     RID_BOUNDED,    0 },
+  { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
+  { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
+  { "__builtin_va_arg",        RID_VA_ARG,     0 },
+  { "__complex",       RID_COMPLEX,    0 },
+  { "__complex__",     RID_COMPLEX,    0 },
+  { "__const",         RID_CONST,      0 },
+  { "__const__",       RID_CONST,      0 },
+  { "__extension__",   RID_EXTENSION,  0 },
+  { "__func__",                RID_C99_FUNCTION_NAME, 0 },
+  { "__imag",          RID_IMAGPART,   0 },
+  { "__imag__",                RID_IMAGPART,   0 },
+  { "__inline",                RID_INLINE,     0 },
+  { "__inline__",      RID_INLINE,     0 },
+  { "__label__",       RID_LABEL,      0 },
+  { "__ptrbase",       RID_PTRBASE,    0 },
+  { "__ptrbase__",     RID_PTRBASE,    0 },
+  { "__ptrextent",     RID_PTREXTENT,  0 },
+  { "__ptrextent__",   RID_PTREXTENT,  0 },
+  { "__ptrvalue",      RID_PTRVALUE,   0 },
+  { "__ptrvalue__",    RID_PTRVALUE,   0 },
+  { "__real",          RID_REALPART,   0 },
+  { "__real__",                RID_REALPART,   0 },
+  { "__restrict",      RID_RESTRICT,   0 },
+  { "__restrict__",    RID_RESTRICT,   0 },
+  { "__signed",                RID_SIGNED,     0 },
+  { "__signed__",      RID_SIGNED,     0 },
+  { "__typeof",                RID_TYPEOF,     0 },
+  { "__typeof__",      RID_TYPEOF,     0 },
+  { "__unbounded",     RID_UNBOUNDED,  0 },
+  { "__unbounded__",   RID_UNBOUNDED,  0 },
+  { "__volatile",      RID_VOLATILE,   0 },
+  { "__volatile__",    RID_VOLATILE,   0 },
+  { "asm",             RID_ASM,        0 },
+  { "auto",            RID_AUTO,       0 },
+  { "break",           RID_BREAK,      0 },
+  { "case",            RID_CASE,       0 },
+  { "char",            RID_CHAR,       0 },
+  { "const",           RID_CONST,      0 },
+  { "continue",                RID_CONTINUE,   0 },
+  { "default",         RID_DEFAULT,    0 },
+  { "do",              RID_DO,         0 },
+  { "double",          RID_DOUBLE,     0 },
+  { "else",            RID_ELSE,       0 },
+  { "enum",            RID_ENUM,       0 },
+  { "extern",          RID_EXTERN,     0 },
+  { "float",           RID_FLOAT,      0 },
+  { "for",             RID_FOR,        0 },
+  { "goto",            RID_GOTO,       0 },
+  { "if",              RID_IF,         0 },
+  { "inline",          RID_INLINE,     0 },
+  { "int",             RID_INT,        0 },
+  { "long",            RID_LONG,       0 },
+  { "register",                RID_REGISTER,   0 },
+  { "restrict",                RID_RESTRICT,   0 },
+  { "return",          RID_RETURN,     0 },
+  { "short",           RID_SHORT,      0 },
+  { "signed",          RID_SIGNED,     0 },
+  { "sizeof",          RID_SIZEOF,     0 },
+  { "static",          RID_STATIC,     0 },
+  { "struct",          RID_STRUCT,     0 },
+  { "switch",          RID_SWITCH,     0 },
+  { "typedef",         RID_TYPEDEF,    0 },
+  { "typeof",          RID_TYPEOF,     0 },
+  { "union",           RID_UNION,      0 },
+  { "unsigned",                RID_UNSIGNED,   0 },
+  { "void",            RID_VOID,       0 },
+  { "volatile",                RID_VOLATILE,   0 },
+  { "while",           RID_WHILE,      0 },
+};
+#define N_reswords (sizeof reswords / sizeof (struct resword))
+
+/* Init enough to allow the C decl code to work, then clean up
+   afterwards.  */
+
+void
+treelang_init_decl_processing ()
+{
+  unsigned int i;
+  tree id;
+
+  /* It is not necessary to register ridpointers as a GC root, because
+     all the trees it points to are permanently interned in the
+     get_identifier hash anyway.  */
+  ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+  
+  for (i = 0; i < N_reswords; i++)
+    {
+      id = get_identifier (reswords[i].word);
+      C_RID_CODE (id) = reswords[i].rid;
+      C_IS_RESERVED_WORD (id) = 1;
+      ridpointers [(int) reswords[i].rid] = id;
+    }
+
+  c_init_decl_processing ();
+
+  /* ix86_return_pops_args takes the type of these so need to patch
+     their own type as themselves.  */
+
+  for (i = 0; i < itk_none; i++)
+    {
+      if (integer_types[i])
+        TREE_TYPE (integer_types [i]) = integer_types[i];
+    }
+
+  /* Probably these ones too.  */
+  TREE_TYPE (float_type_node) = float_type_node;
+  TREE_TYPE (double_type_node) = double_type_node;
+  TREE_TYPE (long_double_type_node) = long_double_type_node;
+
+}
+
+/* Save typing debug_tree all the time. Dump a tree T pretty and
+   concise.  */
+
+void dt (tree t);
+
+void
+dt (tree t)
+{
+  debug_tree (t);
+}
diff --git a/gcc/treelang/treetree.h b/gcc/treelang/treetree.h
new file mode 100644 (file)
index 0000000..24b72e3
--- /dev/null
@@ -0,0 +1,101 @@
+/* 
+
+    TREELANG Compiler definitions for interfacing to treetree.c
+    (compiler back end interface).
+
+    Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 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);
+void treelang_init_decl_processing (void);
+void treelang_finish (void);
+const char * treelang_init (const char* filename);
+int treelang_decode_option (int, char **);
+void treelang_parse_file (int debug_flag);
+void push_var_level (void);
+void pop_var_level (void);
+
+/* 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.  */