#! /bin/sh
set -k

# usage:  mkparserclass prefix [c-file [h-file]]
# 	where 'prefix' is the name of the grammar.  The generated files
#	will have the name prefix_ParseTable (with 'prefix' replaced).
#	The c-file must exist.  If not named in the arguments, its name
#	must be prefix.tab.c.  If the h-file is not specified, it is 
#	taken to be prefix.tab.h;  the h-file need not exist.
#
# Output: files prefix.C and prefix.H suitable for compilation with CC
#	File prefix.C is compiled as any .C file.  File prefix.H is
#	#included by the client program.

export prefix
prefix=$1

# determine file names
# c-file
#	$2, if specified, otherwise prefix.tab.c
#	if file does not exist, exit with error
export cfile
cfile=${2-$1.tab.c}
if test \! -r $cfile; then echo Missing .c file: $cfile; exit 3
	else echo Reading $cfile.  Creating ${prefix}.C;  fi
# h-file
#	$3, if specified,otherwise prefix.tab.h
#	if file does not exist, set name to ""
export hfile
hfile=${3-$1.tab.h}
if test \! -r $hfile; then 
	echo Found no .h file.  Creating ${prefix}.H
	hfilename=""
else
	hfilename=$hfile
fi

#create name for temporary files
tmpfile=/tmp/makepC$$
trap "rm -f ${tmpfile}*" 0 1 2 15 

#generate class declaration file $tmpfile.classdecl
cat <<EOF > $tmpfile.classdecl
#line 48 "mkparserclass"
#include <parser.H>
class ${prefix} : public parser {
public:
	${prefix}();
EOF
if egrep ErrorGuts $cfile > /dev/null; then
	echo "	virtual void ErrorGuts(int severity, char *severityname, char *msg);" >> $tmpfile.classdecl
fi
echo "};" >> $tmpfile.classdecl


#heading of $prefix.C
cat << EOF > ${prefix}.C
/*  body of class $prefix

	Created by Andrew's mkparserclass from  $cfile
*/

EOF

#copy classdecl   (instead of #include $prefix.H)
#	this avoids multiple declaration when %union is used
cat < $tmpfile.classdecl >> ${prefix}.C

#process $cfile to produce the rest of $prefix.C
cat << EOF > $tmpfile.1
# delete all bison.simple stuff
/#line.*bison/ {deleting = 1; next}
/#line/ {deleting = 0}
/Note some compilers choke/ {next}
# insert declaration of reduceActions in place of Bison's parser
/switch \(yyn\)/  {
	print "#line 81 \"mkparserclass\""
	print "static int retval;"
	print ""
	print "#define YYACCEPT  	parser_ACCEPT"
	print "#define YYABORT   	parser_ABORT"
	print "#define YYERROR  	{return (retval&4) ? 7 : 3;}"
	print "#define yyclearin  	{retval = (retval) ? 6 : 4;}"
	print "#define yyerrok   	{retval = (retval) ? 6 : 5;}"
	print ""
	print ""
	print "#define yyval (*pyyval)"
	print "	static int"
	print "reduceActions(int i, YYSTYPE *pyyval, YYSTYPE *yyvsp,"
	print "		class parser *parser) {"
	print "	retval = 0;"
	print "	switch (i) {"
	print "" 
	deleting = 0
	intables = 0
	next
}

# insert end of reduceActions function
/action file gets copied/ {
	print ""
	print " return retval;"
	print "}"
	print "#undef yyval"
	deleting = 1
	next
}

# remove  '#if...YYDEBUG' ... '#endif'     from tables
#	and add them around  yyprhs, yyrhs, yyrline
#	(but NOT arount yytname)
/stdio\.h/ {intables = 1}
/#if.*YYDEBUG/ {if (intables == 1) {inyydebug = 1; next}}
/#endif/ {if (inyydebug == 1) {inyydebug = 0; next}}
/(short yyprhs)|(short yyrhs)|(short yyrline)/ {
	print "#if YYDEBUG != 0"
	print
	inrhsdebug = 1
	next
}
# (continue below)

# delete YYSTYPE declaration
/#ifndef.*YYSTYPE/,/#endif/ {next}

# pass through all lines not handled above
{if (deleting == 0) {print}}

# (continuation of wrapping rhs stuff with #if YYDEBUG ...)
/};/ {if (inrhsdebug == 1) {print "#endif"; inrhsdebug = 0}}

# at end, append the table and class declaration
END {
	print "#line 138 \"mkparserclass\""
	print ""
	print "static struct parser_tables ${prefix}_ParseTable = {"
	print "	YYNTOKENS,	/* num_tokens */"
	print "	YYNNTS,		/* num_nt */"
	print "	YYMAXUTOK,	/* max_user_token */"
	print "	YYNRULES,	/* num_rules */"
	print "	YYNSTATES,	/* num_states */"
	print "	YYFINAL,	/* final_state */"
	print ""
	print "	sizeof(YYSTYPE),	/* eltsz */"
	print ""
	print "	YYFLAG,		/* defflag */"
	print "	YYLAST,		/* table_max */"
	print ""
	print "	(char **)yytname,	/* name */"
	print "	(char *)yytranslate,	/* translate */"
	print ""
	print "	(short *)yyr1,		/* lhs */"
	print "#if YYDDBUG != 0"
	print "	(short *)yyprhs,	/* rhsx */"
	print "	(short *)yyr2,		/* rhssz */"
	print "	(short *)yyrhs,		/* rhs */"
	print "#else"
	print "	(short *)NULL,		/* rhsx */"
	print "	(short *)yyr2,		/* rhssz */"
	print "	(short *)NULL,		/* rhs */"
	print "#endif"
	print "	(short *)yytable,	/* table */"
	print "	(short *)yycheck,	/* valid */"
	print ""
	print "	(short *)yydefact,	/* defred */"
	print "	(short *)yypact,	/* actx */"
	print "	(short *)yydefgoto,	/* defnext */"
	print "	(short *)yypgoto, 	/* nextx */"
	print "	(parser_semfptr)reduceActions	/* actions */"
	print "};"
	print ""
	print "$prefix::$prefix() {"
	print "	(this)->SetTables(&${prefix}_ParseTable);"
	print "}"
}
EOF
awk -f $tmpfile.1 $cfile >> ${prefix}.C


#generate  $prefix.H  file
cat << EOF > ${prefix}.H
/*  declaration of class $prefix
	Created by mkparserclass from  $cfile  $hfilename
*/
EOF
cat < $tmpfile.classdecl >> ${prefix}.H

if  test -r $hfile; then 
	echo Reading $hfile.  Creating ${prefix}.H

	#process hfile to make prefix.H 
	cat<<EOF>$tmpfile.2
		BEGIN {print ""}
		# delete YYSTYPE declaration
		/#ifndef.*YYSTYPE/,/#endif/ {next}
		# delete declaration of yylval
		/yylval/ {next}
		# otherwise, just copy the whole thing
		{print}
EOF
	awk -f $tmpfile.2 $hfile >> ${prefix}.H
fi

rm -f $tmpfile*


# Copyright 1994 Carnegie Mellon University All rights reserved.
#  $Disclaimer: Andrew User Interface System - Binary Distribution 7.5
# 
# Permission to use, copy, modify, and distribute this software for any 
# purpose is hereby granted, provided (a) that no fee is charged for the 
# software, for the medium on which it is distributed, for the 
# distribution process, or for effort involved in making the distribution;  
# (b) that all copyright notices, this permission notice, and the 
# following disclaimer remain in these files and appear in supporting 
# documentation;  (c) that you do not translate, reverse engineer, 
# decompile, or disassemble the software; and (d) that the names of 
# IBM, Carnegie Mellon University, and other copyright holders not 
# be used in advertising or publicity pertaining to distribution of the 
# software.
# 
# CARNEGIE MELLON UNIVERSITY, IBM, AND THE OTHER 
# COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES 
# WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 
# IMPLIED WARRANTIES OF MERCHANTABILITY AND 
# FITNESS.  IN NO EVENT SHALL CARNEGIE MELLON 
# UNIVERSITY, IBM, OR ANY OTHER COPYRIGHT HOLDER 
# BE LIABLE FOR ANY SPECIAL, INDIRECT OR 
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 
# PROFITS, WHETHER IN AN ACTION OF CONTRACT, 
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 
# OUT OF OR IN CONNECTION WITH THE USE OR 
# PERFORMANCE OF THIS SOFTWARE.
#  $
