# Newyacc -- front end to YACC to go with the new yaccpar (version 1.0)
#		by Eric S. Raymond <esr@snark.thyrsus.com)
#
# This should really be done inside YACC.

# trap 'rm -f /tmp/newyacc$$ /tmp/tabh$$ /tmp/tabc$$ /tmp/yout$$' 0 1 2 15

OLDYACC=/usr/bin/yacc

#
# We have to parse the arguments in order to know what the name of
# the generated parser is.
#
opts=$OLDYACC
for x in $*
do
	case $x in
	-b) oldstyle=y ;;
	-*) opts="$opts $x" ;;
	*)  opts="$opts $x" stem=`expr $x : "\(.*\)\.y"` ;;
	esac
done

#
# Unless we selected old style, move old y.tab.[ch] files out of harm's way
#
if [ "$oldstyle"X = "X" ]
then
	if [ -f y.tab.h ]
	then
		mv y.tab.h /tmp/tabh$$
	fi
	if [ -f y.tab.c ]
	then
		mv y.tab.c /tmp/tabc$$
	fi
	if [ -f y.output ]
	then
		mv y.output /tmp/yout$$
	fi
fi

eval "$opts"	# There goes YACC

#
# Now postprocess the output to do the following:
#
#	1. Make the state and reduction tables private. There's no way anyone
#	   should be looking at those.
#
#	2. Make the visible declarations of generated globals conditional on
#	   whether yyparse() is to use the new control structure or not. Also,
#	   insert compatibility macros at the right place to have scope over
#	   all the user code in the parser.
#
sed <y.tab.c \
	-e "/^yytabelem/s//static yytabelem/" \
	-e "/^yytoktype/s//static yytoktype/" \
	-e "/^char \* yyreds/s//static char *yyreds/" \
| awk >/tmp/newyacc$$ '
/^YYSTYPE yylval, yyval/ {
	print "#ifndef YYPARSE";
	print "YYSTYPE yylval, yyval;";
	print "#else";
	print "yyparse_t *yyctl;"
	print "#define yylex()	(*(yyctl->yylex))()";
	print "#define yydebug	yyctl->yydebug";
	print "#define yyv	(yyctl->yyv)";
	print "#define yys	(yyctl->yys)";
	print "#define yypv	(yyctl->yypv)";
	print "#define yyps	(yyctl->yyps)";
	print "#define yystate	yyctl->yystate";
	print "#define yytmp	yyctl->yytmp";
	print "#define yynerrs	yyctl->yynerrs";
	print "#define yyerrflag	yyctl->yyerrflag";
	print "#define yychar	yyctl->yychar";
	print "#define yyval	yyctl->yyval";
	print "#define yylval	yyctl->yylval";
	print "#endif /* YYPARSE */";
	continue;
}
/^extern int yychar;/ {
	print "#ifndef YYPARSE";
	print "extern int yychar;";
	print "#endif /* YYPARSE */";
	continue;
}
/^extern int yyerrflag;/ {
	print "#ifndef YYPARSE";
	print "extern int yyerrflag;";
	print "#endif /* YYPARSE */";
	continue;
}
			{print $0;}
'

#
# If we selected old style, we want the output in y.tab.c
#
if [ "$oldstyle"X != "X" ]
then
	mv /tmp/newyacc$$ y.tab.c
else
	mv /tmp/newyacc$$ ${stem}.c
	if [ -f y.tab.h ]
	then
		mv y.tab.h ${stem}.h
	fi
	if [ -f y.output ]
	then
		mv y.output ${stem}.d
	fi
fi

#
# Unless we selected old style, restore old y.tab.[ch] files
#
if [ "$oldstyle"X = "X" ]
then
	if [ -f /tmp/tabh$$ ]
	then
		mv /tmp/tabh$$ y.tab.h
	fi
	if [ -f /tmp/tabc$$ ]
	then
		mv /tmp/tabc$$ y.tab.c
	fi
	if [ -f /tmp/yout$$ ]
	then
		mv /tmp/yout$$ y.output 
	fi
fi

