/* web2c.yacc -- parse most of Pascal, and output C. */
%token array_tok begin_tok case_tok const_tok do_tok downto_tok else_tok
end_tok file_tok for_tok function_tok goto_tok if_tok label_tok
of_tok procedure_tok program_tok record_tok repeat_tok then_tok
to_tok type_tok until_tok var_tok while_tok integer_tok real_tok
others_tok r_num_tok i_num_tok string_literal_tok single_char_tok
assign_tok two_dots_tok unknown_tok undef_id_tok var_id_tok
proc_id_tok proc_param_tok fun_id_tok fun_param_tok const_id_tok
type_id_tok hhb0_tok hhb1_tok field_id_tok define_tok field_tok
break_tok
%nonassoc '=' not_eq_tok '<' '>' less_eq_tok great_eq_tok
%left '+' '-' or_tok
%right unary_plus_tok unary_minus_tok
%left '*' '/' div_tok mod_tok and_tok
%right not_tok
%{
#include "web2c.h"
#define symbol(x) sym_table[x].id
#define MAX_ARGS 50
static char fn_return_type[50], for_stack[300], control_var[50],
relation[3];
static char arg_type[MAX_ARGS][30];
static int last_type = -1, ids_typed;
char my_routine[100]; /* Name of routine being parsed, if any */
static char array_bounds[80], array_offset[80];
static int uses_mem, uses_eqtb, lower_sym, upper_sym;
static FILE *orig_std;
boolean doing_statements = FALSE;
static boolean var_formals = FALSE;
static int param_id_list[MAX_ARGS], ids_paramed=0;
extern char conditional[], temp[], *std_header;
extern int tex, mf, strict_for;
extern boolean ansi;
extern FILE *coerce;
extern char coerce_name[];
extern boolean debug;
/* Forward refs */
#ifdef ANSI
static long labs(long x);
static void compute_array_bounds(void);
static void fixup_var_list(void);
static void do_proc_args(void);
static void gen_function_head(void);
static boolean doreturn(char *label);
extern int yylex(void);
#else /* not ANSI */
static long labs();
static void compute_array_bounds(), fixup_var_list();
static void do_proc_args(), gen_function_head();
static boolean doreturn();
#endif /* not ANSI */
/* Type hacking for AIX. */
#ifdef AIX
#define UNSIGNED_SHORT_STRING "int"
#else
#define UNSIGNED_SHORT_STRING "unsigned short"
#endif
%}
%start PROGRAM
%%
PROGRAM: DEFS
PROGRAM_HEAD
{block_level++;
printf("#include \"%s\"\n", std_header);}
LABEL_DEC_PART CONST_DEC_PART TYPE_DEC_PART
VAR_DEC_PART
{printf("\n#include \"%s\"\n", coerce_name); }
P_F_DEC_PART
BODY
{YYACCEPT;}
;
DEFS: /* empty */
| DEFS DEF
;
DEF: define_tok field_tok undef_id_tok ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = field_id_tok;
}
| define_tok function_tok undef_id_tok ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = fun_id_tok;
}
| define_tok const_tok undef_id_tok ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = const_id_tok;
}
| define_tok function_tok undef_id_tok '(' ')' ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = fun_param_tok;
}
| define_tok procedure_tok undef_id_tok ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = proc_id_tok;
}
| define_tok procedure_tok undef_id_tok '(' ')' ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = proc_param_tok;
}
| define_tok type_tok undef_id_tok ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = type_id_tok;
}
| define_tok type_tok undef_id_tok '='
SUBRANGE_TYPE ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = type_id_tok;
sym_table[ii].val = lower_bound;
sym_table[ii].val_sym = lower_sym;
sym_table[ii].upper = upper_bound;
sym_table[ii].upper_sym = upper_sym;
}
| define_tok var_tok undef_id_tok ';'
{
ii = add_to_table(last_id);
sym_table[ii].typ = var_id_tok;
}
;
PROGRAM_HEAD: program_tok undef_id_tok ';'
;
BLOCK:
{ if (block_level > 0) my_output("{");
indent++; block_level++;
}
LABEL_DEC_PART
CONST_DEC_PART TYPE_DEC_PART
{if (block_level == 2) {
if (strcmp(fn_return_type, "void")) {
my_output("register");
my_output(fn_return_type);
my_output("Result;");
}
if (tex) {
(void) sprintf(safe_string, "%s_regmem",
my_routine);
my_output(safe_string);
indent_line();
}
}
}
VAR_DEC_PART
{if (block_level == 1)
puts("\n#include \"coerce.h\"");
doing_statements = TRUE;
}
STAT_PART
{if (block_level == 2) {
if (strcmp(fn_return_type,"void")) {
my_output("return(Result)");
semicolon();
}
if (tex) {
if (uses_mem && uses_eqtb)
(void) fprintf(coerce,
"#define %s_regmem register memoryword *mem=zmem, *eqtb=zeqtb;\n",
my_routine);
else if (uses_mem)
(void) fprintf(coerce,
"#define %s_regmem register memoryword *mem=zmem;\n",
my_routine);
else if (uses_eqtb)
(void) fprintf(coerce,
"#define %s_regmem register memoryword *eqtb=zeqtb;\n",
my_routine);
else
(void) fprintf(coerce,
"#define %s_regmem\n",
my_routine);
}
my_routine[0] = '\0';
}
indent--; block_level--;
my_output("}"); new_line();
doing_statements = FALSE;
}
;
LABEL_DEC_PART: /* empty */
| label_tok
{ my_output("/*"); }
LABEL_LIST ';'
{ my_output("*/"); }
;
LABEL_LIST: LABEL
| LABEL_LIST ',' LABEL
;
LABEL: i_num_tok
{ my_output(temp); }
;
CONST_DEC_PART: /* empty */
| const_tok CONST_DEC_LIST
{ indent_line(); }
;
CONST_DEC_LIST: CONST_DEC
| CONST_DEC_LIST CONST_DEC
;
CONST_DEC:
{ new_line(); my_output("#define"); }
undef_id_tok
{ ii=add_to_table(last_id);
sym_table[ii].typ = const_id_tok;
my_output(last_id);
}
'=' CONSTANT ';'
{ sym_table[ii].val=last_i_num;
new_line(); }
;
CONSTANT: i_num_tok
{
(void) sscanf(temp, "%ld", &last_i_num);
if (labs((long) last_i_num) > 32767)
(void) strcat(temp, "L");
my_output(temp);
$$ = ex_32;
}
| r_num_tok
{ my_output(temp);
$$ = ex_real;
}
| STRING
{ $$ = 0; }
| CONSTANT_ID
{ $$ = ex_32; }
;
STRING: string_literal_tok
{ int i, j; char s[132];
j = 1;
s[0] = '"';
for (i=1; yytext[i-1]!=0; i++) {
if (yytext[i] == '\\' || yytext[i] == '"')
s[j++]='\\';
else if (yytext[i] == '\'') i++;
s[j++] = yytext[i];
}
s[j-1] = '"';
s[j] = 0;
my_output(s);
}
| single_char_tok
{ char s[5];
s[0]='\'';
if (yytext[1] == '\\' || yytext[1] == '\'') {
s[2] = yytext[1];
s[1] = '\\';
s[3] = '\'';
s[4] = '\0';
}
else {
s[1] = yytext[1];
s[2]='\'';
s[3]='\0';
}
my_output(s);
}
;
CONSTANT_ID: const_id_tok
{ my_output(last_id); }
;
TYPE_DEC_PART: /* empty */
| type_tok TYPE_DEF_LIST
;
TYPE_DEF_LIST: TYPE_DEF
| TYPE_DEF_LIST TYPE_DEF
;
TYPE_DEF:
{ my_output("typedef"); }
undef_id_tok
{ ii = add_to_table(last_id);
sym_table[ii].typ = type_id_tok;
(void) strcpy(safe_string, last_id);
last_type = ii;
}
'='
{
array_bounds[0] = 0;
array_offset[0] = 0;
}
TYPE ';'
{ if (*array_offset) {
fprintf(stderr, "Cannot typedef arrays with offsets\n");
exit(1);
}
my_output(safe_string);
my_output(array_bounds);
semicolon();
last_type = -1;
}
;
TYPE: SIMPLE_TYPE
| STRUCTURED_TYPE
;
SIMPLE_TYPE: SUBRANGE_TYPE
{ if (last_type >= 0) {
sym_table[ii].val = lower_bound;
sym_table[ii].val_sym = lower_sym;
sym_table[ii].upper = upper_bound;
sym_table[ii].upper_sym = upper_sym;
ii= -1;
}
/* The following code says: if the bounds are known at translation time
* on an integral type, then we select the smallest type of data which
* can represent it in ANSI C. We only use unsigned types when necessary.
*/
if (lower_sym == -1 && upper_sym == -1) {
if (lower_bound>= -127 && upper_bound<=127)
my_output("schar");
else if (lower_bound >= 0
&& upper_bound <= 255)
my_output("unsigned char");
else if (lower_bound >= -32767
&& upper_bound <= 32767)
my_output("short");
else if (lower_bound >= 0
&& upper_bound <= 65535)
my_output(UNSIGNED_SHORT_STRING);
else my_output("integer");
}
else my_output("integer");
}
| TYPE_ID
;
SUBRANGE_TYPE: SUB_CONSTANT two_dots_tok SUB_CONSTANT
;
POSSIBLE_PLUS: /* empty */
| unary_plus_tok
;
SUB_CONSTANT: POSSIBLE_PLUS i_num_tok
{lower_bound = upper_bound;
lower_sym = upper_sym;
(void) sscanf(temp, "%ld", &upper_bound);
upper_sym = -1; /* no sym table entry */
}
| const_id_tok
{ lower_bound = upper_bound;
lower_sym = upper_sym;
upper_bound = sym_table[l_s].val;
upper_sym = l_s;
}
;
TYPE_ID: type_id_tok
{if (last_type >= 0) {
sym_table[last_type].var_not_needed = sym_table[l_s].var_not_needed;
sym_table[last_type].upper = sym_table[l_s].upper;
sym_table[last_type].upper_sym = sym_table[l_s].upper_sym;
sym_table[last_type].val = sym_table[l_s].val;
sym_table[last_type].val_sym = sym_table[l_s].val_sym;
}
my_output(last_id); }
;
STRUCTURED_TYPE: ARRAY_TYPE
{if (last_type >= 0)
sym_table[last_type].var_not_needed = TRUE;}
| RECORD_TYPE
| FILE_TYPE
{if (last_type >= 0)
sym_table[last_type].var_not_needed = TRUE;}
| POINTER_TYPE
{if (last_type >= 0)
sym_table[last_type].var_not_needed = FALSE;}
;
POINTER_TYPE: '^' type_id_tok
{if (last_type >= 0) {
sym_table[last_type].var_not_needed = sym_table[l_s].var_not_needed;
sym_table[last_type].upper = sym_table[l_s].upper;
sym_table[last_type].upper_sym = sym_table[l_s].upper_sym;
sym_table[last_type].val = sym_table[l_s].val;
sym_table[last_type].val_sym = sym_table[l_s].val_sym;
}
my_output(last_id); my_output("*"); }
| '^' undef_id_tok /* HH for Isitex */
{if (last_type >= 0) {
sym_table[last_type].var_not_needed = sym_table[l_s].var_not_needed;
sym_table[last_type].upper = sym_table[l_s].upper;
sym_table[last_type].upper_sym = sym_table[l_s].upper_sym;
sym_table[last_type].val = sym_table[l_s].val;
sym_table[last_type].val_sym = sym_table[l_s].val_sym;
}
my_output(last_id); my_output("*"); }
;
ARRAY_TYPE: array_tok '[' INDEX_TYPE ']' of_tok COMPONENT_TYPE
| array_tok '[' INDEX_TYPE ',' INDEX_TYPE ']' of_tok
COMPONENT_TYPE
;
INDEX_TYPE: SUBRANGE_TYPE
{ compute_array_bounds(); }
| type_id_tok
{ lower_bound = sym_table[l_s].val;
lower_sym = sym_table[l_s].val_sym;
upper_bound = sym_table[l_s].upper;
upper_sym = sym_table[l_s].upper_sym;
compute_array_bounds();
}
;
COMPONENT_TYPE: TYPE
;
RECORD_TYPE: record_tok
{ my_output("struct"); my_output("{"); indent++;}
FIELD_LIST end_tok
{ indent--; my_output("}"); semicolon(); }
;
FIELD_LIST: RECORD_SECTION
| FIELD_LIST ';' RECORD_SECTION
;
RECORD_SECTION:
{ field_list[0] = 0; }
FIELD_ID_LIST ':'
{
/*array_bounds[0] = 0;
array_offset[0] = 0;*/
}
TYPE
{ int i=0, j; char ltemp[80];
while(field_list[i++] == '!') {
j = 0;
while (field_list[i])
ltemp[j++] = field_list[i++];
i++;
if (field_list[i] == '!')
ltemp[j++] = ',';
ltemp[j] = 0;
my_output(ltemp);
}
semicolon();
}
| /* empty */
;
FIELD_ID_LIST: FIELD_ID
| FIELD_ID_LIST ',' FIELD_ID
;
FIELD_ID: undef_id_tok
{ int i=0, j=0;
while (field_list[i] == '!')
while(field_list[i++]);
ii = add_to_table(last_id);
sym_table[ii].typ = field_id_tok;
field_list[i++] = '!';
while (last_id[j])
field_list[i++] = last_id[j++];
field_list[i++] = 0;
field_list[i++] = 0;
}
| field_id_tok
{ int i=0, j=0;
while (field_list[i] == '!')
while(field_list[i++]);
field_list[i++] = '!';
while (last_id[j])
field_list[i++] = last_id[j++];
field_list[i++] = 0;
field_list[i++] = 0;
}
;
FILE_TYPE: file_tok of_tok
{ my_output("file_ptr /* of "); }
TYPE
{ my_output("*/"); }
;
VAR_DEC_PART: /* empty */
| var_tok VAR_DEC_LIST
;
VAR_DEC_LIST: VAR_DEC
| VAR_DEC_LIST VAR_DEC
;
VAR_DEC:
{ var_list[0] = 0;
array_bounds[0] = 0;
array_offset[0] = 0;
var_formals = FALSE;
ids_paramed = 0;
}
VAR_ID_DEC_LIST ':'
{
array_bounds[0] = 0;
array_offset[0] = 0;
}
TYPE ';'
{ fixup_var_list(); }
;
VAR_ID_DEC_LIST: VAR_ID
| VAR_ID_DEC_LIST ',' VAR_ID
;
VAR_ID: undef_id_tok
{ int i=0, j=0;
ii = add_to_table(last_id);
sym_table[ii].typ = var_id_tok;
sym_table[ii].var_formal = var_formals;
param_id_list[ids_paramed++] = ii;
while (var_list[i] == '!')
while(var_list[i++]);
var_list[i++] = '!';
while (last_id[j])
var_list[i++] = last_id[j++];
var_list[i++] = 0;
var_list[i++] = 0;
}
| var_id_tok
{ int i=0, j=0;
ii = add_to_table(last_id);
sym_table[ii].typ = var_id_tok;
sym_table[ii].var_formal = var_formals;
param_id_list[ids_paramed++] = ii;
while (var_list[i] == '!')
while (var_list[i++]);
var_list[i++] = '!';
while (last_id[j])
var_list[i++] = last_id[j++];
var_list[i++] = 0;
var_list[i++] = 0;
}
| field_id_tok
{ int i=0, j=0;
ii = add_to_table(last_id);
sym_table[ii].typ = var_id_tok;
sym_table[ii].var_formal = var_formals;
param_id_list[ids_paramed++] = ii;
while (var_list[i] == '!')
while(var_list[i++]);
var_list[i++] = '!';
while (last_id[j])
var_list[i++] = last_id[j++];
var_list[i++] = 0;
var_list[i++] = 0;
}
;
BODY: /* empty */
| begin_tok
{ my_output("void main_body() {");
indent++;
new_line();
}
STAT_LIST end_tok '.'
{ indent--; my_output("}"); new_line(); }
;
P_F_DEC_PART: /* empty */
| P_F_DEC
| P_F_DEC_PART P_F_DEC
;
P_F_DEC: PROCEDURE_DEC ';'
{ indent_line(); remove_locals(); }
| FUNCTION_DEC ';'
{ indent_line(); remove_locals(); }
;
PROCEDURE_DEC: PROCEDURE_HEAD BLOCK
;
PROCEDURE_HEAD: procedure_tok undef_id_tok
{ ii = add_to_table(last_id);
if (debug)
(void) fprintf(stderr, "%3d Procedure %s\n",
pf_count++, last_id);
sym_table[ii].typ = proc_id_tok;
(void) strcpy(my_routine, last_id);
uses_eqtb = uses_mem = FALSE;
my_output("void");
orig_std = std;
std = 0;
}
PARAM ';'
{(void) strcpy(fn_return_type, "void");
do_proc_args();
gen_function_head();}
| procedure_tok DECLARED_PROC
{ ii = l_s;
if (debug)
(void) fprintf(stderr, "%3d Procedure %s\n",
pf_count++, last_id);
(void) strcpy(my_routine, last_id);
my_output("void");
}
PARAM ';'
{(void) strcpy(fn_return_type, "void");
do_proc_args();
gen_function_head();}
;
PARAM: /* empty */
{ (void) strcpy(z_id, last_id);
mark();
ids_paramed = 0;
}
| '('
{ if (ansi) (void) strcpy(z_id, last_id);
else (void) sprintf(z_id, "z%s", last_id);
ids_paramed = 0;
if (sym_table[ii].typ == proc_id_tok)
sym_table[ii].typ = proc_param_tok;
else if (sym_table[ii].typ == fun_id_tok)
sym_table[ii].typ = fun_param_tok;
mark();
}
FORM_PAR_SEC_L ')'
;
FORM_PAR_SEC_L: FORM_PAR_SEC
| FORM_PAR_SEC_L ';' FORM_PAR_SEC
;
FORM_PAR_SEC1: { ids_typed = ids_paramed;}
VAR_ID_DEC_LIST ':' type_id_tok
{int i, need_var;
i = search_table(last_id);
need_var = !sym_table[i].var_not_needed;
for (i=ids_typed; i<ids_paramed; i++) {
(void) strcpy(arg_type[i], last_id);
if (need_var && sym_table[param_id_list[i]].var_formal)
(void) strcat(arg_type[i], " *");
else sym_table[param_id_list[i]].var_formal = FALSE;
}
}
;
FORM_PAR_SEC: {var_formals = 0;} FORM_PAR_SEC1
| var_tok {var_formals = 1;} FORM_PAR_SEC1
;
DECLARED_PROC : proc_id_tok
| proc_param_tok
;
FUNCTION_DEC: FUNCTION_HEAD BLOCK
;
FUNCTION_HEAD: function_tok undef_id_tok
{ orig_std = std;
std = 0;
ii = add_to_table(last_id);
if (debug)
(void) fprintf(stderr, "%3d Function %s\n",
pf_count++, last_id);
sym_table[ii].typ = fun_id_tok;
(void) strcpy(my_routine, last_id);
uses_eqtb = uses_mem = FALSE;
}
PARAM ':'
{ normal();
array_bounds[0] = 0;
array_offset[0] = 0;
}
RESULT_TYPE
{(void) strcpy(fn_return_type, yytext);
do_proc_args();
gen_function_head();
}
';'
|
function_tok DECLARED_FUN
{ orig_std = std;
std = 0;
ii = l_s;
if (debug)
(void) fprintf(stderr, "%3d Function %s\n",
pf_count++, last_id);
(void) strcpy(my_routine, last_id);
uses_eqtb = uses_mem = FALSE;
}
PARAM ':'
{ normal();
array_bounds[0] = 0;
array_offset[0] = 0;
}
RESULT_TYPE
{(void) strcpy(fn_return_type, yytext);
do_proc_args();
gen_function_head();
}
';'
;
DECLARED_FUN : fun_id_tok
| fun_param_tok
;
RESULT_TYPE: TYPE
;
STAT_PART: begin_tok STAT_LIST end_tok
;
COMPOUND_STAT: begin_tok
{my_output("{"); indent++; new_line();}
STAT_LIST end_tok
{ indent--; my_output("}"); new_line(); }
;
STAT_LIST: STATEMENT
| STAT_LIST ';' STATEMENT
;
STATEMENT: UNLAB_STAT
| S_LABEL ':'
UNLAB_STAT
;
S_LABEL: i_num_tok
{if (!doreturn(temp)) {
(void) sprintf(safe_string, "lab%s:",
temp);
my_output(safe_string);
}
}
;
UNLAB_STAT: SIMPLE_STAT
{ semicolon(); }
| STRUCT_STAT
{ semicolon(); }
;
SIMPLE_STAT: ASSIGN_STAT
| PROC_STAT
| GO_TO_STAT
| EMPTY_STAT
| break_tok
{my_output("break");}
;
ASSIGN_STAT: VARIABLE assign_tok
{ my_output("="); }
EXPRESS
| FUNC_ID_AS assign_tok
{ my_output("Result ="); }
EXPRESS
;
VARIABLE: var_id_tok
{ if (strcmp(last_id, "mem") == 0)
uses_mem = 1;
else if (strcmp(last_id, "eqtb") == 0)
uses_eqtb = 1;
if (sym_table[l_s].var_formal) {
(void) putchar('(');
(void) putchar('*');
my_output(last_id);
(void) putchar(')');
}
else
my_output(last_id);
$$ = ex_32;
}
VAR_DESIG_LIST
| var_id_tok '^' '.' /* HH for Isitex */
{ if (sym_table[l_s].var_formal) {
(void) putchar('(');
(void) putchar('*');
my_output(last_id);
(void) putchar(')');
}
else
my_output(last_id);
(void) putchar('-');
(void) putchar('>');
$$ = ex_32;
}
FIELD_VARIABLE
| var_id_tok '^'
{ (void) putchar('(');
(void) putchar('*');
if (sym_table[l_s].var_formal) {
(void) putchar('(');
(void) putchar('*');
my_output(last_id);
(void) putchar(')');
}
else
my_output(last_id);
(void) putchar(')');
$$ = ex_32;
}
| var_id_tok
{ if (sym_table[l_s].var_formal) {
(void) putchar('(');
(void) putchar('*');
my_output(last_id);
(void) putchar(')');
}
else
my_output(last_id);
$$ = ex_32; }
;
FIELD_VARIABLE: field_id_tok
{ my_output(last_id); }
VAR_DESIG_LIST
| field_id_tok '^' '.'
{ my_output(last_id);
(void) putchar('-');
(void) putchar('>');
}
FIELD_VARIABLE
| field_id_tok
{ my_output(last_id); }
;
FUNC_ID_AS: fun_id_tok
{ $$ = ex_32; }
| fun_param_tok
{ $$ = ex_32; }
;
VAR_DESIG_LIST: VAR_DESIG
| VAR_DESIG_LIST VAR_DESIG
;
VAR_DESIG: '['
{ my_output("["); }
EXPRESS VAR_DESIG1
{ my_output("]"); }
| '.' field_id_tok
{if (tex || mf) {
if (strcmp(last_id, "int")==0)
my_output(".cint");
else if (strcmp(last_id, "lh")==0)
my_output(".v.LH");
else if (strcmp(last_id, "rh")==0)
my_output(".v.RH");
else {
(void)sprintf(safe_string, ".%s", last_id);
my_output(safe_string);
}
}
else {
(void) sprintf(safe_string, ".%s", last_id);
my_output(safe_string);
}
}
| '.' hhb0_tok
{ my_output(".hh.b0");}
| '.' hhb1_tok
{ my_output(".hh.b1");}
;
VAR_DESIG1: ']'
| ','
{ my_output("][");}
EXPRESS ']'
;
EXPRESS: UNARY_OP EXPRESS %prec '*'
{ $$ = $2; }
| EXPRESS '+' {my_output("+");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS '-' {my_output("-");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS '*' {my_output("*");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS div_tok {my_output("/");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS '=' {my_output("==");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS not_eq_tok {my_output("!=");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS mod_tok {my_output("%");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS '<' {my_output("<");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS '>' {my_output(">");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS less_eq_tok {my_output("<=");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS great_eq_tok {my_output(">=");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS and_tok {my_output("&&");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS or_tok {my_output("||");} EXPRESS
{$$ = max($1, $4);}
| EXPRESS '/'
{ my_output("/ ((double)"); }
EXPRESS
{$$ = max($1, $4); my_output(")"); }
| FACTOR
{ $$ = $1; }
;
UNARY_OP: unary_plus_tok
| unary_minus_tok
{ my_output("- (integer)"); }
| not_tok
{ my_output("!"); }
;
FACTOR: '('
{ my_output("("); }
EXPRESS ')'
{ my_output(")"); $$ = $1; }
| VARIABLE
| CONSTANT
| fun_id_tok
{ my_output(last_id); my_output("()"); }
| fun_param_tok
{ my_output(last_id); }
PARAM_LIST
;
PARAM_LIST: '('
{ my_output("("); }
ACTUAL_PARAM_L ')'
{ my_output(")"); }
;
ACTUAL_PARAM_L: ACTUAL_PARAM
| ACTUAL_PARAM_L ','
{ my_output(","); }
ACTUAL_PARAM
;
ACTUAL_PARAM:
EXPRESS WIDTH_FIELD
;
WIDTH_FIELD: ':' i_num_tok
| /* empty */
;
PROC_STAT: proc_id_tok
{ my_output(last_id); my_output("()"); }
| undef_id_tok
{ my_output(last_id);
ii = add_to_table(last_id);
sym_table[ii].typ = proc_id_tok;
my_output("()");
}
| proc_param_tok
{ my_output(last_id); }
PARAM_LIST
;
GO_TO_STAT: goto_tok i_num_tok
{if (doreturn(temp)) {
if (strcmp(fn_return_type,"void"))
my_output("return(Result)");
else
my_output("return");
} else {
(void) sprintf(safe_string, "goto lab%s",
temp);
my_output(safe_string);
}
}
;
EMPTY_STAT: /* empty */
;
STRUCT_STAT: COMPOUND_STAT
| CONDIT_STAT
| REPETIT_STAT
;
CONDIT_STAT: IF_STATEMENT
| CASE_STATEMENT
;
IF_STATEMENT: BEGIN_IF_STAT
| BEGIN_IF_STAT ELSE_STAT
;
BEGIN_IF_STAT: if_tok
{ my_output("if"); my_output("("); }
EXPRESS
{ my_output(")"); new_line();}
then_tok STATEMENT
;
ELSE_STAT: else_tok
{ my_output("else"); }
STATEMENT
;
CASE_STATEMENT: case_tok
{ my_output("switch"); my_output("("); }
EXPRESS of_tok
{ my_output(")"); indent_line();
my_output("{"); indent++;
}
CASE_EL_LIST END_CASE
{ indent--; my_output("}"); new_line(); }
;
CASE_EL_LIST: CASE_ELEMENT
| CASE_EL_LIST ';' CASE_ELEMENT
;
CASE_ELEMENT: CASE_LAB_LIST ':' UNLAB_STAT
{ my_output("break"); semicolon(); }
;
CASE_LAB_LIST: CASE_LAB
| CASE_LAB_LIST ',' CASE_LAB
;
CASE_LAB: i_num_tok
{ my_output("case");
my_output(temp);
my_output(":"); indent_line();
}
| others_tok
{ my_output("default:"); indent_line(); }
;
END_CASE: end_tok
| ';' end_tok
;
REPETIT_STAT: WHILE_STATEMENT
| REP_STATEMENT
| FOR_STATEMENT
;
WHILE_STATEMENT: while_tok
{ my_output("while");
my_output("(");
}
EXPRESS
{ my_output(")"); }
do_tok STATEMENT
;
REP_STATEMENT: repeat_tok
{ my_output("do"); my_output("{"); indent++; }
STAT_LIST until_tok
{ indent--; my_output("}");
my_output("while"); my_output("( ! (");
}
EXPRESS
{ my_output(") )"); }
;
FOR_STATEMENT: for_tok
{
my_output("{");
my_output("register");
my_output("integer");
if (strict_for)
my_output("for_begin,");
my_output("for_end;");
}
CONTROL_VAR assign_tok
{ if (strict_for)
my_output("for_begin");
else
my_output(control_var);
my_output("="); }
FOR_LIST do_tok
{ my_output("; if (");
if (strict_for) my_output("for_begin");
else my_output(control_var);
my_output(relation);
my_output("for_end)");
if (strict_for) {
my_output("{");
my_output(control_var);
my_output("=");
my_output("for_begin");
semicolon();
}
my_output("do");
indent++;
new_line();}
STATEMENT
{
char *top = rindex(for_stack, '#');
indent--; new_line();
my_output("while");
my_output("(");
my_output(top+1);
my_output(")");
my_output(";");
my_output("}");
if (strict_for)
my_output("}");
*top=0;
new_line();
}
;
CONTROL_VAR: var_id_tok
{(void) strcpy(control_var, last_id); }
;
FOR_LIST: EXPRESS
{ my_output(";"); }
to_tok
{
(void) strcpy(relation, "<=");
my_output("for_end");
my_output("="); }
EXPRESS
{
(void) sprintf(for_stack + strlen(for_stack),
"#%s++ < for_end", control_var);
}
| EXPRESS
{ my_output(";"); }
downto_tok
{
(void) strcpy(relation, ">=");
my_output("for_end");
my_output("="); }
EXPRESS
{
(void) sprintf(for_stack + strlen(for_stack),
"#%s-- > for_end", control_var);
}
;
%%
static void compute_array_bounds()
{
long lb;
char tmp[200];
if (lower_sym == -1) { /* lower is a constant */
lb = lower_bound - 1;
if (lb==0) lb = -1; /* Treat lower_bound==1 as if lower_bound==0 */
if (upper_sym == -1) /* both constants */
(void) sprintf(tmp, "[%ld]", upper_bound - lb);
else { /* upper a symbol, lower constant */
if (lb < 0)
(void) sprintf(tmp, "[%s + %ld]",
symbol(upper_sym), (-lb));
else
(void) sprintf(tmp, "[%s - %ld]",
symbol(upper_sym), lb);
}
if (lower_bound < 0 || lower_bound > 1) {
if (*array_bounds) {
fprintf(stderr, "Cannot handle offset in second dimension\n");
exit(1);
}
if (lower_bound < 0) {
(void) sprintf(array_offset, "+%ld", -lower_bound);
} else {
(void) sprintf(array_offset, "-%ld", lower_bound);
}
}
(void) strcat(array_bounds, tmp);
}
else { /* lower is a symbol */
if (upper_sym != -1) /* both are symbols */
(void) sprintf(tmp, "[%s - %s + 1]", symbol(upper_sym),
symbol(lower_sym));
else { /* upper constant, lower symbol */
(void) sprintf(tmp, "[%ld - %s]", upper_bound + 1,
symbol(lower_sym));
}
if (*array_bounds) {
fprintf(stderr, "Cannot handle symbolic offset in second dimension\n");
exit(1);
}
(void) sprintf(array_offset, "- (int)(%s)", symbol(lower_sym));
(void) strcat(array_bounds, tmp);
}
}
static void fixup_var_list()
{
int i, j;
char output_string[100], real_symbol[100];
for (i=0; var_list[i++] == '!'; ) {
for (j=0; real_symbol[j++] = var_list[i++];);
if (*array_offset) {
(void) fprintf(std, "\n#define %s (%s %s)\n ",
real_symbol, next_temp, array_offset);
(void) strcpy(real_symbol, next_temp);
find_next_temp();
}
(void) sprintf(output_string, "%s%s%c",
real_symbol, array_bounds, (var_list[i]=='!' ? ',' : ' '));
my_output(output_string);
}
semicolon();
}
/*
* If we're not processing TeX, we return 0 (false). Otherwise,
* return 1 if the label is "10" and we're not in one of four TeX
* routines where the line labeled "10" isn't the end of the routine.
* Otherwise, return 0.
*/
static boolean doreturn(label)
char *label;
{
if (!tex) return(FALSE);
if (strcmp(label, "10")) return(FALSE);
if (strcmp(my_routine, "macrocall") == 0) return(FALSE);
if (strcmp(my_routine, "hpack") == 0) return(FALSE);
if (strcmp(my_routine, "vpackage") == 0) return(FALSE);
if (strcmp(my_routine, "trybreak") == 0) return(FALSE);
return(TRUE);
}
/* Return the absolute value of a long */
static long labs(x)
long x;
{
if (x < 0L) return(-x);
return(x);
}
static void do_proc_args()
{
int i, var;
/*
* If we want ANSI code and one of the parameters is a var parameter,
* then use the #define to add the &. We do this by adding a 'z' at
* the front of the name. gen_function_head will do the real work.
*/
if (ansi) {
var = 0;
for (i=0; i<ids_paramed; ++i)
var += sym_table[param_id_list[i]].var_formal;
if (var) {
for (i=strlen(z_id); i>=0; --i)
z_id[i+1] = z_id[i];
z_id[0] = 'z';
}
}
if (ansi) {
fprintf(coerce, "%s %s(", fn_return_type, z_id);
if (ids_paramed == 0) fprintf(coerce, "void");
for (i=0; i<ids_paramed; i++) {
if (i > 0) putc(',', coerce);
fprintf(coerce, "%s %s",
arg_type[i],
symbol(param_id_list[i]));
}
fprintf(coerce, ");\n");
} else
fprintf(coerce, "%s %s();\n", fn_return_type, z_id);
}
static void gen_function_head()
{
int i;
if (strcmp(my_routine, z_id)) {
fprintf(coerce, "#define %s(", my_routine);
for (i=0; i<ids_paramed; i++) {
if (i > 0)
fprintf(coerce, ", %s", symbol(param_id_list[i]));
else
fprintf(coerce, "%s", symbol(param_id_list[i]));
}
fprintf(coerce, ") %s(", z_id);
for (i=0; i<ids_paramed; i++) {
if (i > 0)
fputs(", ", coerce);
if (!ansi) /* ansi doesn't need the cast */
fprintf(coerce, "(%s) ", arg_type[i]);
fprintf(coerce, "%s(%s)",
sym_table[param_id_list[i]].var_formal?"&":"",
symbol(param_id_list[i]));
}
fprintf(coerce, ")\n");
}
std = orig_std;
my_output(z_id);
my_output("(");
if (ansi) {
for (i=0; i<ids_paramed; i++) {
if (i > 0) my_output(",");
my_output(arg_type[i]);
my_output(symbol(param_id_list[i]));
}
my_output(")");
indent_line();
} else { /* Not ansi */
for (i=0; i<ids_paramed; i++) {
if (i > 0) my_output(",");
my_output(symbol(param_id_list[i]));
}
my_output(")");
indent_line();
for (i=0; i<ids_paramed; i++) {
my_output(arg_type[i]);
my_output(symbol(param_id_list[i]));
semicolon();
}
}
}