#!/usr/bin/awk -f
# "yyerror_bison_hack.awk"
#	$Id: yyerror_bison_hack.awk,v 1.4 2005/11/12 08:45:36 fang Exp $

# Bison is a piece of shit.  
# It breaks the old yacc interface where symbolic and semantic stacks
# were global and static, available to the user for useful disgnostics
# and error reporting.  In bison, however, those have become local variables
# in yyparse, and are not directly accessible from a function call such as 
# yyerror... UNTIL NOW.  

# This script is intended to hack (and I use that word in its true meaning)
# the .c[c] source file generated by bison (or yacc), by changing the 
# prototype and function call for yyerror, adding stack pointers and 
# variables to the formals, and passing them as arguments.  

# note: thus far this script will only work on the symbol "yyerror"
# because variable cannot appear in patterns for awk.  
# yyerror also must initially have a prototype with one variable argument, 
# and void return (in one line), for the purposes of pattern matching.  

BEGIN {
	prototype_regex = "void[ \t]+yyerror[ ]?\\(.*\\)";
	call_regex = "yyerror[ ]?\\([^()]+\\)";

	# const - no attempt to modify, just read
	new_formals = ", const short* yyss, const short* yyssp, " \
		"const YYSTYPE* yyvs, const YYSTYPE* yyvsp, " \
		"const YYSTYPE yylval, const int yychar, " \
		"const flex::lexer_stateREFERENCE _lexer_state)";
	new_actuals = ", yyss, yyssp, yyvs, yyvsp, yylval, yychar, _lexer_state)";
}

/yyerror[ ]?\(.*\)/ {
	str = $0;
	# is it a prototype or a function call? (check for void)
	ind = match(str, prototype_regex);
	if (ind) {
		proto = substr(str, ind, RLENGTH);	# length of match
		# assuming there is only one ')' in proto:
		# insert new formal arguments
		gsub("\\)", new_formals, proto);
		gsub(prototype_regex, proto, str);
	} else {
		# is a function call
		ind = match(str, call_regex);
		call = substr(str, ind, RLENGTH);	# length of match
		# assuming there is only one ')' in call:
		gsub("\\)", new_actuals, call);
		gsub(call_regex, call, str);
	}
	print str;
}

!/yyerror[ ]?\(.*\)/ {
	print;			# echo back out
}

