🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gcc.help
Article #42245

Re: Writing a new front-end for the gcc code generation

#42245
From: Fergus Henderson
Date: Thu, 04 Jan 1996 00:00
2006 lines
58403 bytes
Nicora William <wnicora@is2.ulb.ac.be> writes:

>I would like to write a gcc front-end for an OO language developed at my 
>university.
>
>Does anybody know where to find documentation and wich support can be 
>obtained from GNU ??

There is not a lot of documentation around.  Richard Kenner
<kenner@vlsi1.ultra.nyu.edu> has an example of a "toy" front-end that
you can use to start with.  Here's a copy - but it may require
some tweaking to work with recent versions of gcc.  You could try
asking Richard Kenner if he has a more recent version of it.

From Mon Jun 19 21:02:18 1995
Received: from VLSI1.ULTRA.NYU.EDU by mulga.cs.mu.OZ.AU with SMTP (5.83--+1.3.1+0.50); id AA28373
	Mon, 19 Jun 1995 21:02:18 +1000 (from kenner@vlsi1.ultra.nyu.edu)
Return-Path: <kenner@vlsi1.ultra.nyu.edu>
Received: by vlsi1.ultra.nyu.edu (5.61/1.34)
	id AA08221; Mon, 19 Jun 95 07:02:35 -0400
Date: Mon, 19 Jun 95 07:02:35 -0400
From: kenner@vlsi1.ultra.nyu.edu (Richard Kenner)
Message-Id: <9506191102.AA08221@vlsi1.ultra.nyu.edu>

#!/bin/sh
# This is a shell archive (shar 3.43)
# made 06/07/1995 14:36 UTC by kenner@vlsi1
# Source directory /g/gcc/gcc2/toy
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   2015 -rw-rw-r-- Make-lang.in
#   5373 -rw-rw-r-- Makefile.in
#    447 -rw-rw-r-- config-lang.in
#  22030 -rw-rw-r-- parse.c
#   1713 -rw-rw-r-- parse.y
#  19095 -rw-rw-r-- toy.c
#
# ============= Make-lang.in ==============
if test -f 'Make-lang.in' -a X"$1" != X"-c"; then
	echo 'x - skipping Make-lang.in (File already exists)'
else
echo 'x - extracting Make-lang.in (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Make-lang.in' &&
# 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.realclean,
# 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: g++)
# - the compiler proper (eg: cc1plus)
# - define the names for selecting the language in LANGUAGES.
X
X
X
# Extra flags to pass to recursive makes.
TOY_FLAGS_TO_PASS = \
X	"TOY_FOR_BUILD=$(TOY_FOR_BUILD)" \
X	"TOYFLAGS=$(TOYFLAGS)" \
X	"TOY_FOR_TARGET=$(TOY_FOR_TARGET)"
X
TOY_SRCS = $(srcdir)/toy/parse.y $(srcdir)/toy/toy.c
X
toy: cc1toy
X
cc1toy: $(LIBDEPS) stamp-objlist $(TOY_SRCS)
X	cd toy; $(MAKE) $(FLAGS_TO_PASS) $(TOY_FLAGS_TO_PASS) ../cc1toy
X
X
# Build hooks:
X
toy.all.build: 
toy.all.cross: 
toy.start.encap:
toy.rest.encap:
toy.info:
toy.dvi:
X
X
# Install hooks:
# cc1toy is installed elsewhere as part of $(COMPILERS).
X
toy.install-normal:
toy.install-common:
toy.install-info:
toy.install-man:
X
toy.uninstall:
X
X
# Clean hooks:
# A lot of the ancillary files are deleted by the main makefile.
# We just have to delete files specific to us.
X
toy.mostlyclean:
X	-rm -f toy/*.o
toy.clean:
toy.distclean:
X	-rm -f toy/Makefile
toy.extraclean:
toy.realclean:
X	-rm -f toy/parse.c
X
X
# Stage hooks:
# The main makefile has already created stage?/toy
X
toy.stage1:
X	-mv toy/*.o stage1/toy
toy.stage2:
X	-mv toy/*.o stage2/toy
toy.stage3:
X	-mv toy/*.o stage3/toy
toy.stage4:
X	-mv toy/*.o stage4/toy
X
X
# Maintenance hooks:
X
# This target creates the files that can be rebuilt, but go in the
# distribution anyway.  It then copies the files to the distdir directory.
toy.distdir:
X	mdkdir tmp/toy
X	cd toy; \
X	for file in *[0-9a-zA-Z+]; do \
X	  ln $$file ../tmp/toy >/dev/null 2>&1 || cp $$file ../tmp/toy; \
X	done
SHAR_EOF
chmod 0664 Make-lang.in ||
echo 'restore of Make-lang.in failed'
Wc_c="`wc -c < 'Make-lang.in'`"
test 2015 -eq "$Wc_c" ||
	echo 'Make-lang.in: original size 2015, current size' "$Wc_c"
fi
# ============= Makefile.in ==============
if test -f 'Makefile.in' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile.in (File already exists)'
else
echo 'x - extracting Makefile.in (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile.in' &&
# The makefile built from this file lives in the language subdirectory.
# It's purpose is to provide support for:
#
# 1) recursion where necessary, and only then (building .o's), and
# 2) building and debugging cc1 from the language subdirectory, and
# 3) nothing else.
#
# The parent makefile handles all other chores, with help from the
# language makefile fragment, of course.
#
# The targets for external use are:
# all, TAGS, ???mostlyclean, ???clean.
X
# Suppress smart makes who think they know how to automake Yacc files
.y.c:
X
# Variables that exist for you to override.
# See below for how to change them for certain systems.
X
ALLOCA =
X
# Various ways of specifying flags for compilations:  
# CFLAGS is for the user to override to, e.g., do a bootstrap with -O2.
# BOOT_CFLAGS is the value of CFLAGS to pass
# to the stage2 and stage3 compilations
# XCFLAGS is used for most compilations but not when using the GCC just built.
XXCFLAGS =
CFLAGS = -g
BOOT_CFLAGS = -O $(CFLAGS)
# These exists to be overridden by the x-* and t-* files, respectively.
XX_CFLAGS =
T_CFLAGS =
X
XX_CPPFLAGS =
T_CPPFLAGS =
X
CC = cc
BISON = bison
BISONFLAGS =
LEX = flex
LEXFLAGS =
AR = ar
AR_FLAGS = rc
SHELL = /bin/sh
MAKEINFO = makeinfo
TEXI2DVI = texi2dvi
X
# Define this as & to perform parallel make on a Sequent.
# Note that this has some bugs, and it seems currently necessary 
# to compile all the gen* files first by hand to avoid erroneous results.
P =
X
# This is used in the definition of SUBDIR_USE_ALLOCA.
# ??? Perhaps it would be better if it just looked for *gcc*.
OLDCC = cc
X
# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
# It omits XCFLAGS, and specifies -B./.
# It also specifies -B$(tooldir)/ to find as and ld for a cross compiler.
GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS)
X
# Tools to use when building a cross-compiler.
# These are used because `configure' appends `cross-make'
# to the makefile when making a cross-compiler.
X
target= ... `configure' substitutes actual target name here.
xmake_file= ... `configure' substitutes actual x- file name here.
tmake_file= ... `configure' substitutes actual t- file name here.
#version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c`
#mainversion=`sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/' < $(srcdir)/version.c`
X
# Directory where sources are, from where we are.
srcdir = .
X
# Additional system libraries to link with.
CLIB=
X
# Change this to a null string if obstacks are installed in the
# system library.
OBSTACK=obstack.o
X
# Choose the real default target.
ALL=all
X
# End of variables for you to override.
X
# Definition of `all' is here so that new rules inserted by sed
# do not specify the default target.
all: all.indirect
X
# This tells GNU Make version 3 not to put all variables in the environment.
.NOEXPORT:
X
# sed inserts variable overrides after the following line.
####target overrides
####host overrides
####cross overrides
####build overrides
X
X
# Now figure out from those variables how to compile and link.
X
all.indirect: Makefile ../cc1toy
X
# IN_GCC tells obstack.h that we are using gcc's <stddef.h> file.
INTERNAL_CFLAGS = $(CROSS) -DIN_GCC
X
# This is the variable actually used when we compile.
ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS)
X
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
X
# Even if ALLOCA is set, don't use it if compiling with GCC.
X
SUBDIR_OBSTACK = `if [ x$(OBSTACK) != x ]; then echo ../$(OBSTACK); else true; fi`
SUBDIR_USE_ALLOCA = `case "${CC}" in "${OLDCC}") if [ x$(ALLOCA) != x ]; then echo ../$(ALLOCA); else true; fi ;; esac`
SUBDIR_MALLOC = `if [ x$(MALLOC) != x ]; then echo ../$(MALLOC); else true; fi`
X
# How to link with both our special library facilities
# and the system's installed libraries.
LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) $(CLIB)
X
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
# so that tm.h and config.h will be found in the compilation
# subdirectory rather than in the source directory.
INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
X
# Always use -I$(srcdir)/config when compiling.
.c.o:
X	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
X
# This tells GNU make version 3 not to export all the variables
# defined in this file into the environment.
.NOEXPORT:
X
X
# Lists of files for various purposes.
X
# Language-specific object files for our toy compiler.
X
TOY_OBJS = parse.o toy.o
X
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-convert.o
OBJDEPS = ../stamp-objlist ../c-convert.o
X
compiler: ../cc1toy
../cc1toy: $(P) $(TOY_OBJS) $(OBJDEPS) $(LIBDEPS)
X	$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o ../cc1toy \
X	      $(TOY_OBJS) $(OBJS) $(LIBS)
X
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
X	cd ..; $(SHELL) config.status
X
native: config.status ../cc1toy
X
# Compiling object files from source files.
X
# Note that dependencies on obstack.h are not written
# because that file is not part of GCC.
X
TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \
X	$(srcdir)/../machmode.h $(srcdir)/../machmode.def
X
parse.o : parse.c $(CONFIG_H) $(TREE_H)
X
$(srcdir)/parse.c: $(srcdir)/parse.y
X	cd $(srcdir); $(BISON) $(BISONFLAGS) -o parse.c parse.y
X
toy.o : toy.c $(CONFIG_H) $(TREE_H) ../flags.h
SHAR_EOF
chmod 0664 Makefile.in ||
echo 'restore of Makefile.in failed'
Wc_c="`wc -c < 'Makefile.in'`"
test 5373 -eq "$Wc_c" ||
	echo 'Makefile.in: original size 5373, current size' "$Wc_c"
fi
# ============= config-lang.in ==============
if test -f 'config-lang.in' -a X"$1" != X"-c"; then
	echo 'x - skipping config-lang.in (File already exists)'
else
echo 'x - extracting config-lang.in (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'config-lang.in' &&
# 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.
X
language="toy"
X
compilers="cc1toy"
X
stagestuff="cc1toy"
X
diff_excludes="-x parse.c"
X
X
SHAR_EOF
chmod 0664 config-lang.in ||
echo 'restore of config-lang.in failed'
Wc_c="`wc -c < 'config-lang.in'`"
test 447 -eq "$Wc_c" ||
	echo 'config-lang.in: original size 447, current size' "$Wc_c"
fi
# ============= parse.c ==============
if test -f 'parse.c' -a X"$1" != X"-c"; then
	echo 'x - skipping parse.c (File already exists)'
else
echo 'x - extracting parse.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parse.c' &&
X
/*  A Bison parser, made from parse.y with Bison version GNU Bison version 1.22
X  */
X
#define YYBISON 1  /* Identify Bison output.  */
X
#define	NUM	258
#define	NAME	259
X
#line 3 "parse.y"
X
#include "config.h"
#include "tree.h"
X
extern void build_function	PROTO((tree, tree));
extern tree build_function_decl	PROTO((char, int));
extern tree get_arg_decl	PROTO((int));
X
#line 12 "parse.y"
typedef union {
tree exp;			/* Tree node representing value. */
int ival;			/* Integer value for constant or arg */
char character;			/* Name of function */
} YYSTYPE;
X
#ifndef YYLTYPE
typedef
X  struct yyltype
X    {
X      int timestamp;
X      int first_line;
X      int first_column;
X      int last_line;
X      int last_column;
X      char *text;
X   }
X  yyltype;
X
#define YYLTYPE yyltype
#endif
X
#include <stdio.h>
X
#ifndef __cplusplus
#ifndef __STDC__
#define const
#endif
#endif
X
X
X
#define	YYFINAL		28
#define	YYFLAG		-32768
#define	YYNTBASE	14
X
#define YYTRANSLATE(x) ((unsigned)(x) <= 259 ? yytranslate[x] : 18)
X
static const char yytranslate[] = {     0,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,    13,     2,     2,     2,    11,
X    12,     7,     6,     2,     5,     2,     8,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     9,    10,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
X     2,     2,     2,     2,     2,     1,     2,     3,     4
};
X
#if YYDEBUG != 0
static const short yyprhs[] = {     0,
X     0,     1,     4,     6,    11,    16,    18,    21,    25,    29,
X    33,    37,    41
};
X
static const short yyrhs[] = {    -1,
X    14,    15,     0,     1,     0,    16,     9,    17,    10,     0,
X     4,    11,     3,    12,     0,     3,     0,    13,     3,     0,
X    17,     6,    17,     0,    17,     5,    17,     0,    17,     7,
X    17,     0,    17,     8,    17,     0,    11,    17,    12,     0,
X     1,     0
};
X
#endif
X
#if YYDEBUG != 0
static const short yyrline[] = { 0,
X    28,    29,    30,    32,    34,    36,    37,    38,    39,    40,
X    41,    42,    43
};
X
static const char * const yytname[] = {   "$","error","$illegal.","NUM","NAME",
"'-'","'+'","'*'","'/'","':'","';'","'('","')'","'$'","input","function","fndef",
"exp",""
};
#endif
X
static const short yyr1[] = {     0,
X    14,    14,    14,    15,    16,    17,    17,    17,    17,    17,
X    17,    17,    17
};
X
static const short yyr2[] = {     0,
X     0,     2,     1,     4,     4,     1,     2,     3,     3,     3,
X     3,     3,     1
};
X
static const short yydefact[] = {     0,
X     3,     0,     0,     2,     0,     0,     0,     0,    13,     6,
X     0,     0,     0,     5,     0,     7,     0,     0,     0,     0,
X     4,    12,     9,     8,    10,    11,     0,     0
};
X
static const short yydefgoto[] = {     2,
X     4,     5,    13
};
X
static const short yypact[] = {    21,
-32768,    23,   -10,-32768,     0,     8,    -1,    14,-32768,-32768,
X    -1,    25,    -2,-32768,    12,-32768,    -1,    -1,    -1,    -1,
-32768,-32768,    22,    22,-32768,-32768,    31,-32768
};
X
static const short yypgoto[] = {-32768,
-32768,-32768,    -4
};
X
X
#define	YYLAST		31
X
X
static const short yytable[] = {     9,
X     6,    10,    17,    18,    19,    20,    15,    21,     7,    11,
X     8,    12,    23,    24,    25,    26,    17,    18,    19,    20,
X    -1,     1,    27,    22,    -1,    14,     3,    16,    19,    20,
X    28
};
X
static const short yycheck[] = {     1,
X    11,     3,     5,     6,     7,     8,    11,    10,     9,    11,
X     3,    13,    17,    18,    19,    20,     5,     6,     7,     8,
X     0,     1,     0,    12,     4,    12,     4,     3,     7,     8,
X     0
};
/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
#line 3 "/usr/local/lib/bison.simple"
X
/* Skeleton output parser for bison,
X   Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
X
X   This program is free software; you can redistribute it and/or modify
X   it under the terms of the GNU General Public License as published by
X   the Free Software Foundation; either version 1, or (at your option)
X   any later version.
X
X   This program is distributed in the hope that it will be useful,
X   but WITHOUT ANY WARRANTY; without even the implied warranty of
X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X   GNU General Public License for more details.
X
X   You should have received a copy of the GNU General Public License
X   along with this program; if not, write to the Free Software
X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
X
X
#ifndef alloca
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not GNU C.  */
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
#include <alloca.h>
#else /* not sparc */
#if defined (MSDOS) && !defined (__TURBOC__)
#include <malloc.h>
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
#include <malloc.h>
#pragma alloca
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
#endif /* not sparc.  */
#endif /* not GNU C.  */
#endif /* alloca not defined.  */
X
/* This is the parser code that is written into each bison parser
X  when the %semantic_parser declaration is not specified in the grammar.
X  It was written by Richard Stallman by simplifying the hairy parser
X  used when %semantic_parser is specified.  */
X
/* Note: there must be only one dollar sign in this file.
X   It is replaced by the list of actions, each action
X   as one case of the switch.  */
X
#define yyerrok		(yyerrstatus = 0)
#define yyclearin	(yychar = YYEMPTY)
#define YYEMPTY		-2
#define YYEOF		0
#define YYACCEPT	return(0)
#define YYABORT 	return(1)
#define YYERROR		goto yyerrlab1
/* Like YYERROR except do call yyerror.
X   This remains here temporarily to ease the
X   transition to the new meaning of YYERROR, for GCC.
X   Once GCC version 2 has supplanted version 1, this can go.  */
#define YYFAIL		goto yyerrlab
#define YYRECOVERING()  (!!yyerrstatus)
#define YYBACKUP(token, value) \
do								\
X  if (yychar == YYEMPTY && yylen == 1)				\
X    { yychar = (token), yylval = (value);			\
X      yychar1 = YYTRANSLATE (yychar);				\
X      YYPOPSTACK;						\
X      goto yybackup;						\
X    }								\
X  else								\
X    { yyerror ("syntax error: cannot back up"); YYERROR; }	\
while (0)
X
#define YYTERROR	1
#define YYERRCODE	256
X
#ifndef YYPURE
#define YYLEX		yylex()
#endif
X
#ifdef YYPURE
#ifdef YYLSP_NEEDED
#define YYLEX		yylex(&yylval, &yylloc)
#else
#define YYLEX		yylex(&yylval)
#endif
#endif
X
/* If nonreentrant, generate the variables here */
X
#ifndef YYPURE
X
int	yychar;			/*  the lookahead symbol		*/
YYSTYPE	yylval;			/*  the semantic value of the		*/
X				/*  lookahead symbol			*/
X
#ifdef YYLSP_NEEDED
YYLTYPE yylloc;			/*  location data for the lookahead	*/
X				/*  symbol				*/
#endif
X
int yynerrs;			/*  number of parse errors so far       */
#endif  /* not YYPURE */
X
#if YYDEBUG != 0
int yydebug;			/*  nonzero means print parse trace	*/
/* Since this is uninitialized, it does not stop multiple parsers
X   from coexisting.  */
#endif
X
/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/
X
#ifndef	YYINITDEPTH
#define YYINITDEPTH 200
#endif
X
/*  YYMAXDEPTH is the maximum size the stacks can grow to
X    (effective only if the built-in stack extension method is used).  */
X
#if YYMAXDEPTH == 0
#undef YYMAXDEPTH
#endif
X
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif
X
#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
#define __yy_bcopy(FROM,TO,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
#else				/* not GNU C or C++ */
#ifndef __cplusplus
X
/* This is the most reliable way to avoid incompatibilities
X   in available built-in functions on various systems.  */
static void
__yy_bcopy (from, to, count)
X     char *from;
X     char *to;
X     int count;
{
X  register char *f = from;
X  register char *t = to;
X  register int i = count;
X
X  while (i-- > 0)
X    *t++ = *f++;
}
X
#else /* __cplusplus */
X
/* This is the most reliable way to avoid incompatibilities
X   in available built-in functions on various systems.  */
static void
__yy_bcopy (char *from, char *to, int count)
{
X  register char *f = from;
X  register char *t = to;
X  register int i = count;
X
X  while (i-- > 0)
X    *t++ = *f++;
}
X
#endif
#endif
X
#line 169 "/usr/local/lib/bison.simple"
int
yyparse()
{
X  register int yystate;
X  register int yyn;
X  register short *yyssp;
X  register YYSTYPE *yyvsp;
X  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
X  int yychar1;		/*  lookahead token as an internal (translated) token number */
X
X  short	yyssa[YYINITDEPTH];	/*  the state stack			*/
X  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/
X
X  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
X  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */
X
#ifdef YYLSP_NEEDED
X  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
X  YYLTYPE *yyls = yylsa;
X  YYLTYPE *yylsp;
X
#define YYPOPSTACK   (yyvsp--, yysp--, yylsp--)
#else
#define YYPOPSTACK   (yyvsp--, yysp--)
#endif
X
X  int yystacksize = YYINITDEPTH;
X
#ifdef YYPURE
X  int yychar;
X  YYSTYPE yylval;
X  int yynerrs;
#ifdef YYLSP_NEEDED
X  YYLTYPE yylloc;
#endif
#endif
X
X  YYSTYPE yyval;		/*  the variable used to return		*/
X				/*  semantic values from the action	*/
X				/*  routines				*/
X
X  int yylen;
X
#if YYDEBUG != 0
X  if (yydebug)
X    fprintf(stderr, "Starting parse\n");
#endif
X
X  yystate = 0;
X  yyerrstatus = 0;
X  yynerrs = 0;
X  yychar = YYEMPTY;		/* Cause a token to be read.  */
X
X  /* Initialize stack pointers.
X     Waste one element of value and location stack
X     so that they stay on the same level as the state stack.  */
X
X  yyssp = yyss - 1;
X  yyvsp = yyvs;
#ifdef YYLSP_NEEDED
X  yylsp = yyls;
#endif
X
/* Push a new state, which is found in  yystate  .  */
/* In all cases, when you get here, the value and location stacks
X   have just been pushed. so pushing a state here evens the stacks.  */
yynewstate:
X
X  *++yyssp = yystate;
X
X  if (yyssp >= yyss + yystacksize - 1)
X    {
X      /* Give user a chance to reallocate the stack */
X      /* Use copies of these so that the &'s don't force the real ones into memory. */
X      YYSTYPE *yyvs1 = yyvs;
X      short *yyss1 = yyss;
#ifdef YYLSP_NEEDED
X      YYLTYPE *yyls1 = yyls;
#endif
X
X      /* Get the current used size of the three stacks, in elements.  */
X      int size = yyssp - yyss + 1;
X
#ifdef yyoverflow
X      /* Each stack pointer address is followed by the size of
X	 the data in use in that stack, in bytes.  */
X      yyoverflow("parser stack overflow",
X		 &yyss1, size * sizeof (*yyssp),
X		 &yyvs1, size * sizeof (*yyvsp),
#ifdef YYLSP_NEEDED
X		 &yyls1, size * sizeof (*yylsp),
#endif
X		 &yystacksize);
X
X      yyss = yyss1; yyvs = yyvs1;
#ifdef YYLSP_NEEDED
X      yyls = yyls1;
#endif
#else /* no yyoverflow */
X      /* Extend the stack our own way.  */
X      if (yystacksize >= YYMAXDEPTH)
X	{
X	  yyerror("parser stack overflow");
X	  return 2;
X	}
X      yystacksize *= 2;
X      if (yystacksize > YYMAXDEPTH)
X	yystacksize = YYMAXDEPTH;
X      yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
X      __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
X      yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
X      __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
X      yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
X      __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
#endif
#endif /* no yyoverflow */
X
X      yyssp = yyss + size - 1;
X      yyvsp = yyvs + size - 1;
#ifdef YYLSP_NEEDED
X      yylsp = yyls + size - 1;
#endif
X
#if YYDEBUG != 0
X      if (yydebug)
X	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
#endif
X
X      if (yyssp >= yyss + yystacksize - 1)
X	YYABORT;
X    }
X
#if YYDEBUG != 0
X  if (yydebug)
X    fprintf(stderr, "Entering state %d\n", yystate);
#endif
X
X yybackup:
X
/* Do appropriate processing given the current state.  */
/* Read a lookahead token if we need one and don't already have one.  */
/* yyresume: */
X
X  /* First try to decide what to do without reference to lookahead token.  */
X
X  yyn = yypact[yystate];
X  if (yyn == YYFLAG)
X    goto yydefault;
X
X  /* Not known => get a lookahead token if don't already have one.  */
X
X  /* yychar is either YYEMPTY or YYEOF
X     or a valid token in external form.  */
X
X  if (yychar == YYEMPTY)
X    {
#if YYDEBUG != 0
X      if (yydebug)
X	fprintf(stderr, "Reading a token: ");
#endif
X      yychar = YYLEX;
X    }
X
X  /* Convert token to internal form (in yychar1) for indexing tables with */
X
X  if (yychar <= 0)		/* This means end of input. */
X    {
X      yychar1 = 0;
X      yychar = YYEOF;		/* Don't call YYLEX any more */
X
#if YYDEBUG != 0
X      if (yydebug)
X	fprintf(stderr, "Now at end of input.\n");
#endif
X    }
X  else
X    {
X      yychar1 = YYTRANSLATE(yychar);
X
#if YYDEBUG != 0
X      if (yydebug)
X	{
X	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
X	  /* Give the individual parser a way to print the precise meaning
X	     of a token, for further debugging info.  */
#ifdef YYPRINT
X	  YYPRINT (stderr, yychar, yylval);
#endif
X	  fprintf (stderr, ")\n");
X	}
#endif
X    }
X
X  yyn += yychar1;
X  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
X    goto yydefault;
X
X  yyn = yytable[yyn];
X
X  /* yyn is what to do for this token type in this state.
X     Negative => reduce, -yyn is rule number.
X     Positive => shift, yyn is new state.
X       New state is final state => don't bother to shift,
X       just return success.
X     0, or most negative number => error.  */
X
X  if (yyn < 0)
X    {
X      if (yyn == YYFLAG)
X	goto yyerrlab;
X      yyn = -yyn;
X      goto yyreduce;
X    }
X  else if (yyn == 0)
X    goto yyerrlab;
X
X  if (yyn == YYFINAL)
X    YYACCEPT;
X
X  /* Shift the lookahead token.  */
X
#if YYDEBUG != 0
X  if (yydebug)
X    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
#endif
X
X  /* Discard the token being shifted unless it is eof.  */
X  if (yychar != YYEOF)
X    yychar = YYEMPTY;
X
X  *++yyvsp = yylval;
#ifdef YYLSP_NEEDED
X  *++yylsp = yylloc;
#endif
X
X  /* count tokens shifted since error; after three, turn off error status.  */
X  if (yyerrstatus) yyerrstatus--;
X
X  yystate = yyn;
X  goto yynewstate;
X
/* Do the default action for the current state.  */
yydefault:
X
X  yyn = yydefact[yystate];
X  if (yyn == 0)
X    goto yyerrlab;
X
/* Do a reduction.  yyn is the number of a rule to reduce with.  */
yyreduce:
X  yylen = yyr2[yyn];
X  yyval = yyvsp[1-yylen]; /* implement default value of the action */
X
#if YYDEBUG != 0
X  if (yydebug)
X    {
X      int i;
X
X      fprintf (stderr, "Reducing via rule %d (line %d), ",
X	       yyn, yyrline[yyn]);
X
X      /* Print the symboles being reduced, and their result.  */
X      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
X	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
X      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
X    }
#endif
X
X
X  switch (yyn) {
X
case 4:
#line 32 "parse.y"
{ build_function (yyvsp[-3].exp, yyvsp[-1].exp); ;
X    break;}
case 5:
#line 34 "parse.y"
{ yyval.exp = build_function_decl (yyvsp[-3].character, yyvsp[-1].ival); ;
X    break;}
case 6:
#line 36 "parse.y"
{ yyval.exp = build_int_2 (yyvsp[0].ival, yyvsp[0].ival >= 0 ? 0 : -1); ;
X    break;}
case 7:
#line 37 "parse.y"
{ yyval.exp = get_arg_decl (yyvsp[0].ival); ;
X    break;}
case 8:
#line 38 "parse.y"
{ yyval.exp = build (PLUS_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X    break;}
case 9:
#line 39 "parse.y"
{ yyval.exp = build (MINUS_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X    break;}
case 10:
#line 40 "parse.y"
{ yyval.exp = build (MULT_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X    break;}
case 11:
#line 41 "parse.y"
{ yyval.exp = build (TRUNC_DIV_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X    break;}
case 12:
#line 42 "parse.y"
{ yyval.exp = yyvsp[-1].exp; ;
X    break;}
case 13:
#line 43 "parse.y"
{ yyval.exp = error_mark_node; ;
X    break;}
}
X   /* the action file gets copied in in place of this dollarsign */
#line 440 "/usr/local/lib/bison.simple"
X
X  yyvsp -= yylen;
X  yyssp -= yylen;
#ifdef YYLSP_NEEDED
X  yylsp -= yylen;
#endif
X
#if YYDEBUG != 0
X  if (yydebug)
X    {
X      short *ssp1 = yyss - 1;
X      fprintf (stderr, "state stack now");
X      while (ssp1 != yyssp)
X	fprintf (stderr, " %d", *++ssp1);
X      fprintf (stderr, "\n");
X    }
#endif
X
X  *++yyvsp = yyval;
X
#ifdef YYLSP_NEEDED
X  yylsp++;
X  if (yylen == 0)
X    {
X      yylsp->first_line = yylloc.first_line;
X      yylsp->first_column = yylloc.first_column;
X      yylsp->last_line = (yylsp-1)->last_line;
X      yylsp->last_column = (yylsp-1)->last_column;
X      yylsp->text = 0;
X    }
X  else
X    {
X      yylsp->last_line = (yylsp+yylen-1)->last_line;
X      yylsp->last_column = (yylsp+yylen-1)->last_column;
X    }
#endif
X
X  /* Now "shift" the result of the reduction.
X     Determine what state that goes to,
X     based on the state we popped back to
X     and the rule number reduced by.  */
X
X  yyn = yyr1[yyn];
X
X  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
X  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
X    yystate = yytable[yystate];
X  else
X    yystate = yydefgoto[yyn - YYNTBASE];
X
X  goto yynewstate;
X
yyerrlab:   /* here on detecting error */
X
X  if (! yyerrstatus)
X    /* If not already recovering from an error, report this error.  */
X    {
X      ++yynerrs;
X
#ifdef YYERROR_VERBOSE
X      yyn = yypact[yystate];
X
X      if (yyn > YYFLAG && yyn < YYLAST)
X	{
X	  int size = 0;
X	  char *msg;
X	  int x, count;
X
X	  count = 0;
X	  for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
X	    if (yycheck[x + yyn] == x)
X	      size += strlen(yytname[x]) + 15, count++;
X	  msg = (char *) xmalloc(size + 15);
X	  strcpy(msg, "parse error");
X
X	  if (count < 5)
X	    {
X	      count = 0;
X	      for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
X		if (yycheck[x + yyn] == x)
X		  {
X		    strcat(msg, count == 0 ? ", expecting `" : " or `");
X		    strcat(msg, yytname[x]);
X		    strcat(msg, "'");
X		    count++;
X		  }
X	    }
X	  yyerror(msg);
X	  free(msg);
X	}
X      else
#endif /* YYERROR_VERBOSE */
X	yyerror("parse error");
X    }
X
yyerrlab1:   /* here on error raised explicitly by an action */
X
X  if (yyerrstatus == 3)
X    {
X      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
X
X      /* return failure if at end of input */
X      if (yychar == YYEOF)
X	YYABORT;
X
#if YYDEBUG != 0
X      if (yydebug)
X	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
#endif
X
X      yychar = YYEMPTY;
X    }
X
X  /* Else will try to reuse lookahead token
X     after shifting the error token.  */
X
X  yyerrstatus = 3;		/* Each real token shifted decrements this */
X
X  goto yyerrhandle;
X
yyerrdefault:  /* current state does not do anything special for the error token. */
X
#if 0
X  /* This is wrong; only states that explicitly want error tokens
X     should shift them.  */
X  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
X  if (yyn) goto yydefault;
#endif
X
yyerrpop:   /* pop the current state because it cannot handle the error token */
X
X  if (yyssp == yyss) YYABORT;
X  yyvsp--;
X  yystate = *--yyssp;
#ifdef YYLSP_NEEDED
X  yylsp--;
#endif
X
#if YYDEBUG != 0
X  if (yydebug)
X    {
X      short *ssp1 = yyss - 1;
X      fprintf (stderr, "Error: state stack now");
X      while (ssp1 != yyssp)
X	fprintf (stderr, " %d", *++ssp1);
X      fprintf (stderr, "\n");
X    }
#endif
X
yyerrhandle:
X
X  yyn = yypact[yystate];
X  if (yyn == YYFLAG)
X    goto yyerrdefault;
X
X  yyn += YYTERROR;
X  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
X    goto yyerrdefault;
X
X  yyn = yytable[yyn];
X  if (yyn < 0)
X    {
X      if (yyn == YYFLAG)
X	goto yyerrpop;
X      yyn = -yyn;
X      goto yyreduce;
X    }
X  else if (yyn == 0)
X    goto yyerrpop;
X
X  if (yyn == YYFINAL)
X    YYACCEPT;
X
#if YYDEBUG != 0
X  if (yydebug)
X    fprintf(stderr, "Shifting error token, ");
#endif
X
X  *++yyvsp = yylval;
#ifdef YYLSP_NEEDED
X  *++yylsp = yylloc;
#endif
X
X  yystate = yyn;
X  goto yynewstate;
}
#line 45 "parse.y"
X
X
#include <stdio.h>
#include <ctype.h>
X
extern FILE *finput;
X
int
yylex ()
{
X  int c;
X
X  /* Ignore whitespace, get first character.  */
X  while (isspace (c = getc (finput)))
X    ;
X
X  /* If a digit, get the number.  */
X  if (isdigit (c))
X    {
X      ungetc (c, finput);
X      fscanf (finput, "%i", &yylval.ival);
X      return NUM;
X    }
X
X  /* Otherwise return the letter to use as the function name.  */
X  else if (isalpha (c))
X    {
X      yylval.character = c;
X      return NAME;
X    }
X
X  return c;
}
SHAR_EOF
chmod 0664 parse.c ||
echo 'restore of parse.c failed'
Wc_c="`wc -c < 'parse.c'`"
test 22030 -eq "$Wc_c" ||
	echo 'parse.c: original size 22030, current size' "$Wc_c"
fi
# ============= parse.y ==============
if test -f 'parse.y' -a X"$1" != X"-c"; then
	echo 'x - skipping parse.y (File already exists)'
else
echo 'x - extracting parse.y (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parse.y' &&
/* Grammer file for compiler for toy language.  */
X
%{
#include "config.h"
#include "tree.h"
X
extern void build_function	PROTO((tree, tree));
extern tree build_function_decl	PROTO((char, int));
extern tree get_arg_decl	PROTO((int));
%}
X
%union {
tree exp;			/* Tree node representing value. */
int ival;			/* Integer value for constant or arg */
char character;			/* Name of function */
}
X
%token <ival> NUM		/* Decimal constant. */
%token <character> NAME		/* Function name.  */
X
%left '-' '+'
%left '*' '/'
X
%type <exp> exp fndef
X
%%
X
input: /* empty */
X  | input function
X  | error ;
X
function: fndef ':' exp ';' { build_function ($1, $3); } ;
X
fndef: NAME '(' NUM ')' { $$ = build_function_decl ($1, $3); } ;
X
exp:  NUM	    { $$ = build_int_2 ($1, $1 >= 0 ? 0 : -1); }
X     | '$' NUM      { $$ = get_arg_decl ($2); }
X     | exp '+' exp  { $$ = build (PLUS_EXPR, integer_type_node, $1, $3); }
X     | exp '-' exp  { $$ = build (MINUS_EXPR, integer_type_node, $1, $3); }
X     | exp '*' exp  { $$ = build (MULT_EXPR, integer_type_node, $1, $3); }
X     | exp '/' exp  { $$ = build (TRUNC_DIV_EXPR, integer_type_node, $1, $3); }
X     | '(' exp ')'  { $$ = $2; }
X     | error        { $$ = error_mark_node; } ;
X
%%
X
#include <stdio.h>
#include <ctype.h>
X
extern FILE *finput;
X
int
yylex ()
{
X  int c;
X
X  /* Ignore whitespace, get first character.  */
X  while (isspace (c = getc (finput)))
X    ;
X
X  /* If a digit, get the number.  */
X  if (isdigit (c))
X    {
X      ungetc (c, finput);
X      fscanf (finput, "%i", &yylval.ival);
X      return NUM;
X    }
X
X  /* Otherwise return the letter to use as the function name.  */
X  else if (isalpha (c))
X    {
X      yylval.character = c;
X      return NAME;
X    }
X
X  return c;
}
SHAR_EOF
chmod 0664 parse.y ||
echo 'restore of parse.y failed'
Wc_c="`wc -c < 'parse.y'`"
test 1713 -eq "$Wc_c" ||
	echo 'parse.y: original size 1713, current size' "$Wc_c"
fi
# ============= toy.c ==============
if test -f 'toy.c' -a X"$1" != X"-c"; then
	echo 'x - skipping toy.c (File already exists)'
else
echo 'x - extracting toy.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'toy.c' &&
#include "config.h"
#include "tree.h"
#include "flags.h"
#include <stdio.h>
X
/* Global Variables for the various types and nodes we create.  */ 
X
tree error_mark_node;
tree integer_type_node;
tree char_type_node;
tree void_type_node;
X
tree integer_zero_node;
tree integer_one_node;
tree current_function_decl;
X
/* Global Variables Expected by gcc: */
X
char *language_string = "Demo language";
int flag_traditional;		/* Used by dwarfout.c.  */
X
/* Here are the three functions needed to compile out language and the
X   variables they use.  */
X
/* Number of arguments to the current function and the decls for the args.  */
static int num_args;
static tree *arg_decls;
X
/* Make a FUNCTION_DECL for a function whose single-character name is
X   NAME, that has NARGS integer operands, and returns integer.  */
X
tree
build_function_decl (name, nargs)
X     char name;
X     int nargs;
{
X  tree param_list = NULL_TREE;
X  tree param_type_list = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
X  tree parm_decl;
X  tree fntype;
X  tree fndecl;
X  char *p;
X  int i;
X
X  /* Allocate space for our PARM_DECLS and create them.  */
X
X  num_args = nargs;
X  arg_decls = (tree *) xmalloc (nargs * sizeof (tree));
X  for (i = nargs - 1; i >= 0; i--)
X    {
X      p = xmalloc (2);
X      p[0] = 'a' + i;
X      p[1] = '\0';
X      parm_decl = build_decl (PARM_DECL, get_identifier (p),
X			      integer_type_node);
X      DECL_ARG_TYPE (parm_decl) = integer_type_node;
X      arg_decls[i] = parm_decl;
X      param_list = chainon (parm_decl, param_list);
X      param_type_list = tree_cons (NULL_TREE, integer_type_node,
X				   param_type_list);
X    }
X
X  /* The function type depends on the return type and type of args.  */
X  fntype = build_function_type (integer_type_node, param_type_list);
X
X  /* Now make the function decl.  */
X  p = xmalloc (2);
X  p[0] = name;
X  p[1] = '\0';
X
X  fndecl = build_decl (FUNCTION_DECL, get_identifier (p), fntype);
X  DECL_EXTERNAL (fndecl) = 0;
X  TREE_PUBLIC (fndecl) = 1;
X  TREE_STATIC (fndecl) = 1;
X  DECL_ARGUMENTS (fndecl) = param_list;
X  DECL_RESULT (fndecl)
X    = build_decl (RESULT_DECL, NULL_TREE, integer_type_node);
X  DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
X
X  rest_of_decl_compilation (fndecl, NULL_PTR, 1, 0);
X  return fndecl;
}
X
/* Get the PARM_DECL for the Nth operand.  */
X
tree
get_arg_decl (n)
X     int n;
{
X  if (n >= num_args)
X    {
X      fprintf (stderr, "arg number too high\n");
X      n = 0;
X    }
X
X  return arg_decls[n];
}
X
/* Generate code for FNDECL that returns EXP.  */
X
void
build_function (fndecl, exp)
X     tree fndecl;
X     tree exp;
{
X  tree param_decl, next_param;
X
X  /* Set line number information; everything is line 1 for us.  */
X  DECL_SOURCE_FILE (fndecl) = input_filename;
X  DECL_SOURCE_LINE (fndecl) = 1;
X
X  /* Announce we are compiling this function.  */
X  announce_function (fndecl);
X
X  /* Set up to compile the function and enter it.  */
X  current_function_decl = fndecl;
X  DECL_INITIAL (fndecl) = error_mark_node;
X
X  temporary_allocation ();
X  pushlevel (0);
X  make_function_rtl (fndecl);
X
X  /* Push all the PARM_DECL nodes onto the current scope (i.e. the scope of the
X     subprogram body) so that they can be recognized as local variables in the
X     subprogram.   */
X
X  for (param_decl = nreverse (DECL_ARGUMENTS (fndecl));
X       param_decl; param_decl = next_param)
X    {
X      next_param = TREE_CHAIN (param_decl);
X      TREE_CHAIN (param_decl) = NULL;
X      pushdecl (param_decl);
X    }
X
X  /* Store back the PARM_DECL nodes. They appear in the right order. */
X  DECL_ARGUMENTS (fndecl) = getdecls ();
X
X  init_function_start (fndecl, input_filename, 1);
X  expand_function_start (fndecl, 0);
X  expand_start_bindings (0);
X
X  /* The only thing in this function is a single return statement, which
X     we now generate.  Note that EXP will have been allocated in
X     permanent_obstack.  To do this properly, we need to enter the function 
X     ontext before parsing the expression, but then error recovery is more
X     complex, so we don't do that here.  */
X
X  expand_return (build (MODIFY_EXPR, void_type_node,
X			DECL_RESULT (fndecl), exp));
X
X  /* Now get back out of the function and compile it.  */
X  expand_end_bindings (NULL_TREE, 1, 0);
X  poplevel (1, 0, 1);
X  expand_function_end (fndecl, 1, 0);
X  rest_of_compilation (fndecl);
X  current_function_decl = 0;
X  permanent_allocation (1);
}
X
/* Routines Expected by gcc:  */
X
/* These are used to build types for various sizes.  The code below
X   is a simplified version of that of GNAT.  */
X
#ifndef MAX_BITS_PER_WORD
#define MAX_BITS_PER_WORD  BITS_PER_WORD
#endif
X
/* This variable keeps a table for types for each precision so that we only 
X   allocate each of them once. Signed and unsigned types are kept separate.  */
static tree signed_and_unsigned_types[MAX_BITS_PER_WORD + 1][2];
X
/* Return an integer type with the number of bits of precision given by  
X   PRECISION.  UNSIGNEDP is nonzero if the type is unsigned; otherwise
X   it is a signed type.  */
X
tree
type_for_size (precision, unsignedp)
X     unsigned precision;
X     int unsignedp;
{
X  tree t;
X  int moment;
X
X  if (precision <= MAX_BITS_PER_WORD
X      && signed_and_unsigned_types[precision][unsignedp] != 0)
X    return signed_and_unsigned_types[precision][unsignedp];
X
X  /* Since we will keep these types around, they must be permanent.  */
X  moment = suspend_momentary ();
X  push_obstacks_nochange ();
X  end_temporary_allocation ();
X
X if (unsignedp)
X    t = signed_and_unsigned_types[precision][1]
X      = make_unsigned_type (precision);
X  else
X    t = signed_and_unsigned_types[precision][0]
X      = make_signed_type (precision);
X
X  pop_obstacks ();
X  resume_momentary (moment);
X
X  return t;
}
X
/* Return a data type that has machine mode MODE.  UNSIGNEDP selects
X   an unsigned type; otherwise a signed type is returned.  */
X
tree
type_for_mode (mode, unsignedp)
X     enum machine_mode mode;
X     int unsignedp;
{
X  return type_for_size (GET_MODE_BITSIZE (mode), unsignedp);
}
X
/* Return the unsigned version of a TYPE_NODE, a scalar type.  */
X
tree
unsigned_type (type_node)
X     tree type_node;
{
X  return type_for_size (TYPE_PRECISION (type_node), 1);
}
X
/* Return the signed version of a TYPE_NODE, a scalar type.  */
X
tree
signed_type (type_node)
X     tree type_node;
{
X  return type_for_size (TYPE_PRECISION (type_node), 0);
}
X
/* Return a type the same as TYPE except unsigned or signed according to
X   UNSIGNEDP.  */
X
tree
signed_or_unsigned_type (unsignedp, type)
X     int unsignedp;
X     tree type;
{
X  if (! INTEGRAL_TYPE_P (type) || TREE_UNSIGNED (type) == unsignedp)
X    return type;
X  else
X    return type_for_size (TYPE_PRECISION (type), unsignedp);
}
X
/* These functions and variables deal with binding contours.  We only
X   need these functions for the list of PARM_DECLs, but we leave the
X   functions more general; these are a simplified version of the
X   functions from GNAT.  */
X
/* For each binding contour we allocate a binding_level structure which records
X   the entities defined or declared in that contour. Contours include:
X
X	the global one
X	one for each subprogram definition
X	one for each compound statement (declare block)
X
X   Binding contours are used to create GCC tree BLOCK nodes.  */
X
struct binding_level
{
X  /* A chain of ..._DECL nodes for all variables, constants, functions,
X     parameters and type declarations.  These ..._DECL nodes are chained
X     through the TREE_CHAIN field. Note that these ..._DECL nodes are stored
X     in the reverse of the order supplied to be compatible with the
X     back-end.  */
X  tree names;
X  /* For each level (except the global one), a chain of BLOCK nodes for all
X     the levels that were entered and exited one level down from this one.  */
X  tree blocks;
X  /* The back end may need, for its own internal processing, to create a BLOCK
X     node. This field is set aside for this purpose. If this field is non-null
X     when the level is popped, i.e. when poplevel is invoked, we will use such
X     block instead of creating a new one from the 'names' field, that is the
X     ..._DECL nodes accumulated so far.  Typically the routine 'pushlevel'
X     will be called before setting this field, so that if the front-end had
X     inserted ..._DECL nodes in the current block they will not be lost.   */
X  tree block_created_by_back_end;
X  /* The binding level containing this one (the enclosing binding level). */
X  struct binding_level *level_chain;
};
X
/* The binding level currently in effect.  */
static struct binding_level *current_binding_level = NULL;
X
/* The outermost binding level. This binding level is created when the
X   compiler is started and it will exist through the entire compilation.  */
static struct binding_level *global_binding_level;
X
/* Binding level structures are initialized by copying this one.  */
static struct binding_level clear_binding_level = {NULL, NULL, NULL, NULL};
X
/* Return non-zero if we are currently in the global binding level.  */
X
int
global_bindings_p ()
{
X  return current_binding_level == global_binding_level ? -1 : 0;
}
X
/* Return the list of declarations in the current level. Note that this list
X   is in reverse order (it has to be so for back-end compatibility).  */
X
tree
getdecls ()
{
X  return current_binding_level->names;
}
X
/* Nonzero if the current level needs to have a BLOCK made.  */
X
int
kept_level_p ()
{
X  return (current_binding_level->names != 0);
}
X
/* Enter a new binding level. The input parameter is ignored, but has to be
X   specified for back-end compatibility.  */
X
void
pushlevel (ignore)
X     int ignore;
{
X  struct binding_level *newlevel
X    = (struct binding_level *) xmalloc (sizeof (struct binding_level));
X
X  *newlevel = clear_binding_level;
X
X  /* Add this level to the front of the chain (stack) of levels that are
X     active.  */
X  newlevel->level_chain = current_binding_level;
X  current_binding_level = newlevel;
}
X
/* Exit a binding level.
X   Pop the level off, and restore the state of the identifier-decl mappings
X   that were in effect when this level was entered.
X
X   If KEEP is nonzero, this level had explicit declarations, so
X   and create a "block" (a BLOCK node) for the level
X   to record its declarations and subblocks for symbol table output.
X
X   If FUNCTIONBODY is nonzero, this level is the body of a function,
X   so create a block as if KEEP were set and also clear out all
X   label names.
X
X   If REVERSE is nonzero, reverse the order of decls before putting
X   them into the BLOCK.  */
X
tree
poplevel (keep, reverse, functionbody)
X     int keep;
X     int reverse;
X     int functionbody;
{
X  /* Points to a BLOCK tree node. This is the BLOCK node construted for the
X     binding level that we are about to exit and which is returned by this
X     routine.  */
X  tree block_node = NULL_TREE;
X  tree decl_chain;
X  tree decl_node;
X  tree subblock_chain = current_binding_level->blocks;
X  tree subblock_node;
X  tree block_created_by_back_end;
X
X  /* Reverse the list of XXXX_DECL nodes if desired.  Note that the ..._DECL
X     nodes chained through the `names' field of current_binding_level are in
X     reverse order except for PARM_DECL node, which are explicitely stored in
X     the right order.  */
X  decl_chain = (reverse) ? nreverse (current_binding_level->names)
X                         : current_binding_level->names;
X
X  block_created_by_back_end = current_binding_level->block_created_by_back_end;
X  if (block_created_by_back_end != 0)
X    {
X      block_node = block_created_by_back_end;
X
X      /* Check if we are about to discard some information that was gathered
X	 by the front-end. Nameley check if the back-end created a new block 
X	 without calling pushlevel first. To understand why things are lost
X	 just look at the next case (i.e. no block created by back-end.  */
X      if ((keep || functionbody) && (decl_chain || subblock_chain))
X	abort ();
X    }
X
X  /* If there were any declarations in the current binding level, or if this
X     binding level is a function body, or if there are any nested blocks then
X     create a BLOCK node to record them for the life of this function.  */
X  else if (keep || functionbody)
X    block_node = build_block (keep ? decl_chain : 0, 0, subblock_chain, 0, 0);
X
X  /* Record the BLOCK node just built as the subblock its enclosing scope.  */
X  for (subblock_node = subblock_chain; subblock_node;
X       subblock_node = TREE_CHAIN (subblock_node))
X    BLOCK_SUPERCONTEXT (subblock_node) = block_node;
X
X  /* Clear out the meanings of the local variables of this level.  */
X
X  for (subblock_node = decl_chain; subblock_node;
X       subblock_node = TREE_CHAIN (subblock_node))
X    if (DECL_NAME (subblock_node) != 0)
X      /* If the identifier was used or addressed via a local extern decl,  
X	 don't forget that fact.   */
X      if (DECL_EXTERNAL (subblock_node))
X	{
X	  if (TREE_USED (subblock_node))
X	    TREE_USED (DECL_NAME (subblock_node)) = 1;
X	  if (TREE_ADDRESSABLE (subblock_node))
X	    TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (subblock_node)) = 1;
X	}
X
X  /* Pop the current level.  */
X  current_binding_level = current_binding_level->level_chain;
X
X  if (functionbody)
X    {
X      /* This is the top level block of a function. The ..._DECL chain stored
X	 in BLOCK_VARS are the function's parameters (PARM_DECL nodes). Don't
X	 leave them in the BLOCK because they are found in the FUNCTION_DECL
X	 instead.  */
X      DECL_INITIAL (current_function_decl) = block_node;
X      BLOCK_VARS (block_node) = 0;
X    }
X  else if (block_node)
X    {
X      if (block_created_by_back_end == NULL)
X	current_binding_level->blocks
X	  = chainon (current_binding_level->blocks, block_node);
X    }
X
X  /* If we did not make a block for the level just exited, any blocks made for
X     inner levels (since they cannot be recorded as subblocks in that level)
X     must be carried forward so they will later become subblocks of something
X     else.  */
X  else if (subblock_chain)
X    current_binding_level->blocks
X      = chainon (current_binding_level->blocks, subblock_chain);
X  if (block_node)
X    TREE_USED (block_node) = 1;
X
X  return block_node;
}
X
/* Insert BLOCK at the end of the list of subblocks of the
X   current binding level.  This is used when a BIND_EXPR is expanded,
X   to handle the BLOCK node inside the BIND_EXPR.  */
X
void
insert_block (block)
X     tree block;
{
X  TREE_USED (block) = 1;
X  current_binding_level->blocks
X    = chainon (current_binding_level->blocks, block);
}
X
/* Set the BLOCK node for the innermost scope
X   (the one we are currently in).  */
X
void
set_block (block)
X     tree block;
{
X  current_binding_level->block_created_by_back_end = block;
}
X
/* Records a ..._DECL node DECL as belonging to the current lexical scope.
X   Returns the ..._DECL node. */
X
tree
pushdecl (decl)
X     tree decl;
{
X  /* External objects aren't nested, other objects may be.  */
X  if (DECL_EXTERNAL (decl))
X    DECL_CONTEXT (decl) = 0;
X  else
X    DECL_CONTEXT (decl) = current_function_decl;
X
X  /* Put the declaration on the list.  The list of declarations is in reverse
X     order. The list will be reversed later if necessary.  This needs to be
X     this way for compatibility with the back-end.  */
X
X  TREE_CHAIN (decl) = current_binding_level->names;
X  current_binding_level->names = decl;
X
X  /* For the declartion of a type, set its name if it is not already set. */
X
X  if (TREE_CODE (decl) == TYPE_DECL
X      && TYPE_NAME (TREE_TYPE (decl)) == 0)
X    TYPE_NAME (TREE_TYPE (decl)) = DECL_NAME (decl);
X
X  return decl;
}
X
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
X
#ifndef INT_TYPE_SIZE
#define INT_TYPE_SIZE BITS_PER_WORD
#endif
X
#undef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
X
/* Create the predefined scalar types such as `integer_type_node' needed 
X   in the gcc back-end and initialize the global binding level.  */
X
void
init_decl_processing ()
{
X  tree endlink;
X
X  /* The structure `tree_identifier' is the GCC tree data structure that holds
X     IDENTIFIER_NODE nodes. We need to call `set_identifier_size' to tell GCC
X     that we have not added any language specific fields to IDENTIFIER_NODE
X     nodes.  */
X  set_identifier_size (sizeof (struct tree_identifier));
X  lineno = 0;
X
X  /* Make the binding_level structure for global names.  */
X  pushlevel (0);
X  global_binding_level = current_binding_level;
X
X  sizetype = type_for_size (GET_MODE_BITSIZE (Pmode), 1);
X  pushdecl (build_decl (TYPE_DECL, get_identifier (SIZE_TYPE), sizetype));
X
X  integer_type_node = type_for_size (INT_TYPE_SIZE, 0) ;
X  pushdecl (build_decl (TYPE_DECL, get_identifier ("int"), integer_type_node));
X
X  char_type_node = type_for_size (CHAR_TYPE_SIZE, 1);
X  pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
X			char_type_node));
X
X  integer_zero_node = build_int_2 (0, 0);
X  integer_one_node = build_int_2 (1, 0);
X
X  size_zero_node = build_int_2 (0, 0);
X  TREE_TYPE (size_zero_node) = sizetype;
X  size_one_node = build_int_2 (1, 0);
X  TREE_TYPE (size_one_node) = sizetype;
X
X  error_mark_node = make_node (ERROR_MARK);
X  TREE_TYPE (error_mark_node) = error_mark_node;
X  void_type_node = make_node (VOID_TYPE);
X  layout_type (void_type_node);
X  TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
}
X
/* Decode all the language specific options that cannot be decoded by GCC. The
X   option decoding phase of GCC calls this routine on the flags that it cannot
X   decode.  Return 1 if successful, otherwise return 0. */
X
int
lang_decode_option (p)
X     char *p;
{ return 0; }
X
/* Perform all the initialization steps that are language-specific.  */
X
void
lang_init ()
{}
X
/* Perform all the finalization steps that are language-specific.  */
X
void
lang_finish ()
{}
X
/* Return a short string identifying this language to the debugger.  */
X
char *
lang_identify ()
{ return "toy"; }
X
/* If DECL has a cleanup, build and return that cleanup here.
X   This is a callback called by expand_expr.  */
X
tree
maybe_build_cleanup (decl)
X     tree decl;
{ return NULL_TREE; }
X
/* Print an error message for invalid use of an incomplete type.  */
X
void
incomplete_type_error (dont_care_1, dont_care_2)
X     tree dont_care_1, dont_care_2;
{ abort (); }
X
tree
truthvalue_conversion (expr)
X     tree expr;
{ return expr;}
X
void
mark_addressable (expr)
X     tree expr;
{}
X
/* Print any language-specific compilation statistics.  */
X
void
print_lang_statistics ()
{}
X
/* Since we don't use the DECL_LANG_SPECIFIC field, this is a no-op.  */
X
void
copy_lang_decl (node)
X     tree node;
{}
X
/* Hooks for print-tree.c:  */
X
void
print_lang_decl (file, node, indent)
X     FILE *file;
X     tree node;
X     int indent;
{}
X
void
print_lang_type (file, node, indent)
X     FILE *file;
X     tree node;
X     int indent;
{}
X
void
print_lang_identifier (file, node, indent)
X     FILE *file;
X     tree node;
X     int indent;
{}
X
/* Performs whatever initialization steps are needed by the language-dependent
X   lexical analyzer.  */
X
void
init_lex ()
{}
X
/* Sets some debug flags for the parser. It does nothing here.  */
X
void
set_yydebug (value)
X     int value;
{}
X
/* Routine to print parse error message.  */
X
void
yyerror (str)
X     char *str;
{
X  fprintf (stderr, "%s\n", str);
}
SHAR_EOF
chmod 0664 toy.c ||
echo 'restore of toy.c failed'
Wc_c="`wc -c < 'toy.c'`"
test 19095 -eq "$Wc_c" ||
	echo 'toy.c: original size 19095, current size' "$Wc_c"
fi
exit 0
Technical Details
Message-ID: <9600416.23942@mulga.cs.mu.OZ.AU>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <4cdpm5$6gh@news.Belgium.EU.net>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 11318c,ff1cf4523271e6d
X-Google-Attributes: gid11318c,public
From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Subject: Re: Writing a new front-end for the gcc code generation
Date: 1996/01/04
Message-ID: <9600416.23942@mulga.cs.mu.OZ.AU>
X-Deja-AN: 133957227
sender: news@cs.mu.OZ.AU (CS-Usenet)
references: <4cdpm5$6gh@news.Belgium.EU.net>
organization: Computer Science, University of Melbourne, Australia
newsgroups: gnu.gcc.help