#! /bin/sh
set -k
# usage:  mkparser prefix [c-file [h-file]]
#  		where 'prefix' is the name of the grammar.
#	The generated table 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

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

#generate initial segment of parser declaration in .h file
cat <<EOF > ${prefix}.h
/*  declaration of parser $prefix

	Created by mkparser from  $cfile  $hfilename
*/
#include <cparser.h>

extern struct parser *${prefix}_New();

EOF

#process cfile to produce prefix.c
awkfile=/tmp/makepC$$
trap "rm -f ${awkfile} ${awkfile}.2" 0 1 2 15 

cat<<EOF>$awkfile
BEGIN {
	print "/* produced by mkparser from $cfile */"
	print ""
	print "#include <cparser.h>"
}
# if we see ErrorGuts declared, be sure to call parser_SetErrorFunc
/${prefix}_ErrorGuts.*\(/  {if (sawErrorGuts == 0) {
	sawErrorGuts = 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 ""
	print "#define yyval (*pyyval)"
	print "	static int"
	print "reduceActions(i, pyyval, yyvsp, parser)\nint i;\nYYSTYPE *pyyval;\nYYSTYPE *yyvsp;\n"
	print "		struct parser *parser; {"
	print "	switch (i) {"
	print "" 
	deleting = 0
	next
}

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

# remove all '#if...YYDEBUG' ... '#endif'
#	and add them around  yyprhs, yyrhs, yyrline
#	(but NOT arount yytname)
/#if.*YYDEBUG/ {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 116 \"mkparser\""
	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 YYDEBUG != 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 "struct parser *${prefix}_New() {"
	print "	struct parser *self=parser_New();"
	print "	parser_SetTables(self, &${prefix}_ParseTable);"
	if (sawErrorGuts) {
		print "	parser_SetErrorFunc(self, (parser_errfptr)${prefix}_ErrorGuts);"
	}
	print "	return self;"
	print "}"
}
EOF
awk -f $awkfile $cfile > ${prefix}.c

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

	#process hfile to make prefix.h
	cat<<EOF>$awkfile.2
		#terminate class declaration
		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 $awkfile.2 $hfile >> ${prefix}.h
fi
rm -f $awkfile $awkfile.2

# Copyright 1994 Carnegie Mellon University All rights reserved.
#  $Disclaimer: This software is part of version 7.2 of the 
# Andrew User Interface System and is the 
# property of IBM, Carnegie Mellon University, 
# and the other copyright holders.  The source 
# code of this version is for the sole use of 
# members of the Andrew Consortium with 
# memberships extending into calendar year 
# 1994.  This source code is not to be distributed 
# to non-members of the consortium nor beyond 
# a fifty-mile radius from the membership address.  
# Binary object code compiled or derived from 
# these sources is not to be distributed to non-
# members.  Members may have additional 
# distribution rights granted by prior written 
# permission of Carnegie Mellon University.
# 
# IBM, CARNEGIE MELLON UNIVERSITY, 
# AND THE OTHER COPYRIGHT HOLDERS
#  DISCLAIM ALL WARRANTIES WITH 
# REGARD TO THIS SOFTWARE, INCLUDING 
# ALL IMPLIED WARRANTIES OF MERCHANT-
# ABILITY AND FITNESS. IN 
# NO EVENT SHALL  IBM, CARNEGIE 
# MELLON UNIVERSITY, OR ANY OTHER 
# COPYRIGHT HOLDER BE LIABLE FOR 
# ANY SPECIAL, INDIRECT OR CONSE-
# QUENTIAL 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.
#  $
