1 /* web2c-parser.y -- parse some of Pascal, and output C, sort of.
3 This grammar has one shift/reduce conflict, from the
4 if-then[-else] rules, which is unresolvable. */
6 /* The order of some of the tokens here is significant. See the rules
7 for - and + in web2c-lexer.l. */
8 %token array_tok begin_tok case_tok const_tok do_tok downto_tok else_tok
9 end_tok file_tok for_tok function_tok goto_tok if_tok label_tok
10 of_tok procedure_tok program_tok record_tok repeat_tok then_tok
11 to_tok type_tok until_tok var_tok while_tok noreturn_tok
12 others_tok r_num_tok i_num_tok string_literal_tok single_char_tok
13 assign_tok two_dots_tok undef_id_tok var_id_tok
14 proc_id_tok proc_param_tok fun_id_tok fun_param_tok const_id_tok
15 type_id_tok hhb0_tok hhb1_tok field_id_tok define_tok field_tok
18 %nonassoc
'=' not_eq_tok
'<' '>' less_eq_tok great_eq_tok
20 %right unary_plus_tok unary_minus_tok
21 %left
'*' '/' div_tok mod_tok and_tok
29 #define symbol(x) sym_table[x].id
32 static char fn_return_type
[50], for_stack
[300], control_var
[50],
34 static char arg_type
[MAX_ARGS
][30];
35 static int last_type
= -1, ids_typed
;
36 static int proc_is_noreturn
= 0;
37 char my_routine
[100]; /* Name of routine being parsed, if any */
38 static char array_bounds
[80], array_offset
[80];
39 static int uses_mem
, uses_eqtb
, lower_sym
, upper_sym
;
40 static FILE *orig_out
;
41 boolean doing_statements
= false
;
42 static boolean var_formals
= false
;
43 static int param_id_list
[MAX_ARGS
], ids_paramed
=0;
45 extern
char conditional
[], temp
[], *std_header
;
46 extern
int tex
, mf
, strict_for
;
48 extern
char coerce_name
[];
49 extern
string program_name
;
52 static long my_labs
(long);
53 static void compute_array_bounds
(void);
54 static void fixup_var_list
(void);
55 static void do_proc_args
(void);
56 static void gen_function_head
(void);
57 static boolean doreturn
(string);
67 printf
("#define %s\n", uppercasify
(program_name
));
69 printf
("#include \"%s\"\n", std_header
);
71 LABEL_DEC_PART CONST_DEC_PART TYPE_DEC_PART
73 { printf
("\n#include \"%s\"\n", coerce_name
); }
79 /* The @define statements we use to populate the symbol table. */
85 define_tok field_tok undef_id_tok
';'
87 ii
= add_to_table
(last_id
);
88 sym_table
[ii
].typ
= field_id_tok
;
90 | define_tok function_tok undef_id_tok
';'
92 ii
= add_to_table
(last_id
);
93 sym_table
[ii
].typ
= fun_id_tok
;
95 | define_tok const_tok undef_id_tok
';'
97 ii
= add_to_table
(last_id
);
98 sym_table
[ii
].typ
= const_id_tok
;
100 | define_tok function_tok undef_id_tok
'(' ')' ';'
102 ii
= add_to_table
(last_id
);
103 sym_table
[ii
].typ
= fun_param_tok
;
105 | define_tok procedure_tok undef_id_tok
';'
107 ii
= add_to_table
(last_id
);
108 sym_table
[ii
].typ
= proc_id_tok
;
110 | define_tok procedure_tok undef_id_tok
'(' ')' ';'
112 ii
= add_to_table
(last_id
);
113 sym_table
[ii
].typ
= proc_param_tok
;
115 | define_tok type_tok undef_id_tok
';'
117 ii
= add_to_table
(last_id
);
118 sym_table
[ii
].typ
= type_id_tok
;
120 | define_tok type_tok undef_id_tok
'=' SUBRANGE_TYPE
';'
122 ii
= add_to_table
(last_id
);
123 sym_table
[ii
].typ
= type_id_tok
;
124 sym_table
[ii
].val
= lower_bound
;
125 sym_table
[ii
].val_sym
= lower_sym
;
126 sym_table
[ii
].upper
= upper_bound
;
127 sym_table
[ii
].upper_sym
= upper_sym
;
129 | define_tok var_tok undef_id_tok
';'
131 ii
= add_to_table
(last_id
);
132 sym_table
[ii
].typ
= var_id_tok
;
136 /* program statement. Ignore any files. */
138 program_tok undef_id_tok PROGRAM_FILE_PART
';'
142 '(' PROGRAM_FILE_LIST
')'
148 | PROGRAM_FILE_LIST
',' PROGRAM_FILE
152 const_id_tok
/* input and output are constants */
157 { if
(block_level
> 0) my_output
("{\n ");
158 indent
++; block_level
++;
161 CONST_DEC_PART TYPE_DEC_PART
162 { if
(block_level
== 2) {
163 if
(strcmp
(fn_return_type
, "void")) {
164 my_output
("register");
165 my_output
(fn_return_type
);
166 my_output
("Result;");
169 sprintf
(safe_string
, "%s_regmem", my_routine
);
170 my_output
(safe_string
);
176 { doing_statements
= true
; }
179 if
(block_level
== 2) {
180 if
(strcmp
(fn_return_type
,"void")) {
181 my_output
("return Result");
185 if
(uses_mem
&& uses_eqtb
)
187 "#define %s_regmem register memoryword *mem=zmem, *eqtb=zeqtb;\n",
190 fprintf
(coerce
, "#define %s_regmem register memoryword *mem=zmem;\n",
193 fprintf
(coerce
, "#define %s_regmem register memoryword *eqtb=zeqtb;\n",
196 fprintf
(coerce
, "#define %s_regmem\n", my_routine
);
198 my_routine
[0] = '\0';
200 indent
--; block_level
--;
201 my_output
("}"); new_line
();
202 doing_statements
= false
;
206 LABEL_DEC_PART: /* empty */
214 | LABEL_LIST
',' LABEL
218 i_num_tok
{ my_output
(temp
); }
223 | const_tok CONST_DEC_LIST
229 | CONST_DEC_LIST CONST_DEC
233 { /* `#define' must be in column 1 for pcc. */
234 unsigned save
= indent
;
237 my_output
("#define");
241 { ii
= add_to_table
(last_id
);
242 sym_table
[ii
].typ
= const_id_tok
;
245 '=' { my_output
("("); }
246 CONSTANT_EXPRESS
{ my_output
(")"); }
247 ';' { sym_table
[ii
].val
= last_i_num
; new_line
(); }
253 sscanf
(temp
, "%ld", &last_i_num
);
254 if
(my_labs
((long) last_i_num
) > 32767)
259 | r_num_tok
{ my_output
(temp
); $$
= ex_real
; }
261 | CONSTANT_ID
{ $$
= ex_32
; }
265 UNARY_OP CONSTANT_EXPRESS %prec
'*'
267 | CONSTANT_EXPRESS
'+' { my_output
("+"); }
268 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
269 | CONSTANT_EXPRESS
'-' { my_output
("-"); }
270 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
271 | CONSTANT_EXPRESS
'*' { my_output
("*"); }
272 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
273 | CONSTANT_EXPRESS div_tok
{ my_output
("/"); }
274 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
275 | CONSTANT_EXPRESS
'=' { my_output
("=="); }
276 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
277 | CONSTANT_EXPRESS not_eq_tok
{ my_output
("!="); }
278 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
279 | CONSTANT_EXPRESS mod_tok
{ my_output
("%"); }
280 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
281 | CONSTANT_EXPRESS
'<' { my_output
("<"); }
282 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
283 | CONSTANT_EXPRESS
'>' { my_output
(">"); }
284 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
285 | CONSTANT_EXPRESS less_eq_tok
{ my_output
("<="); }
286 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
287 | CONSTANT_EXPRESS great_eq_tok
{ my_output
(">="); }
288 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
289 | CONSTANT_EXPRESS and_tok
{ my_output
("&&"); }
290 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
291 | CONSTANT_EXPRESS or_tok
{ my_output
("||"); }
292 CONSTANT_EXPRESS
{ $$
= max
($1, $4); }
293 | CONSTANT_EXPRESS
'/' { my_output
("/ ((double)"); }
294 CONSTANT_EXPRESS
{ $$
= max
($1, $4); my_output
(")"); }
295 | CONST_FACTOR
{ $$
= $1; }
302 { my_output
(")"); $$
= $1; }
310 get_string_literal
(s
);
322 const_id_tok
{ my_output
(last_id
); }
325 TYPE_DEC_PART: /* empty */
326 | type_tok TYPE_DEF_LIST
329 TYPE_DEF_LIST: TYPE_DEF
330 | TYPE_DEF_LIST TYPE_DEF
334 { my_output
("typedef"); }
337 ii
= add_to_table
(last_id
);
338 sym_table
[ii
].typ
= type_id_tok
;
339 strcpy
(safe_string
, last_id
);
350 yyerror ("Cannot typedef arrays with offsets");
352 my_output
(safe_string
);
353 my_output
(array_bounds
);
369 sym_table
[ii
].val
= lower_bound
;
370 sym_table
[ii
].val_sym
= lower_sym
;
371 sym_table
[ii
].upper
= upper_bound
;
372 sym_table
[ii
].upper_sym
= upper_sym
;
376 /* If the bounds on an integral type are known at
377 translation time, select the smallest ANSI C type which
378 can represent it. We avoid using char as such variables
379 are frequently used as array indices. We avoid using
380 schar and unsigned short where possible, since they are
381 treated differently by different compilers
382 (see also config.h). */
383 if
(lower_sym
== -1 && upper_sym
== -1) {
384 if
(0 <= lower_bound
&& upper_bound
<= UCHAR_MAX
)
385 my_output
("unsigned char");
386 else if
(SCHAR_MIN
<= lower_bound
&& upper_bound
<= SCHAR_MAX
)
388 else if
(SHRT_MIN
<= lower_bound
&& upper_bound
<= SHRT_MAX
)
390 else if
(0 <= lower_bound
&& upper_bound
<= USHRT_MAX
)
391 my_output
("unsigned short");
393 my_output
("integer");
395 my_output
("integer");
402 SUBRANGE_CONSTANT two_dots_tok SUBRANGE_CONSTANT
411 POSSIBLE_PLUS i_num_tok
413 lower_bound
= upper_bound
;
414 lower_sym
= upper_sym
;
415 sscanf
(temp
, "%ld", &upper_bound
);
416 upper_sym
= -1; /* no sym table entry */
420 lower_bound
= upper_bound
;
421 lower_sym
= upper_sym
;
422 upper_bound
= sym_table
[l_s
].val
;
426 { /* We've changed some constants into dynamic variables.
427 To avoid changing all the subrange decls, just use integer.
428 This does not work for arrays, for which we check later. */
429 lower_bound
= upper_bound
;
430 lower_sym
= upper_sym
;
432 upper_sym
= 0; /* Translate to integer. */
435 { /* Same as var_id_tok, to avoid changing type definitions.
436 Should keep track of the variables we use in this way
437 and make sure they're all eventually defined. */
438 lower_bound
= upper_bound
;
439 lower_sym
= upper_sym
;
448 if
(last_type
>= 0) {
449 sym_table
[last_type
].var_not_needed
= sym_table
[l_s
].var_not_needed
;
450 sym_table
[last_type
].upper
= sym_table
[l_s
].upper
;
451 sym_table
[last_type
].upper_sym
= sym_table
[l_s
].upper_sym
;
452 sym_table
[last_type
].val
= sym_table
[l_s
].val
;
453 sym_table
[last_type
].val_sym
= sym_table
[l_s
].val_sym
;
461 { if
(last_type
>= 0)
462 sym_table
[last_type
].var_not_needed
= true
;
466 { if
(last_type
>= 0)
467 sym_table
[last_type
].var_not_needed
= true
;
470 { if
(last_type
>= 0)
471 sym_table
[last_type
].var_not_needed
= true
;
478 if
(last_type
>= 0) {
479 sym_table
[last_type
].var_not_needed
= sym_table
[l_s
].var_not_needed
;
480 sym_table
[last_type
].upper
= sym_table
[l_s
].upper
;
481 sym_table
[last_type
].upper_sym
= sym_table
[l_s
].upper_sym
;
482 sym_table
[last_type
].val
= sym_table
[l_s
].val
;
483 sym_table
[last_type
].val_sym
= sym_table
[l_s
].val_sym
;
491 array_tok
'[' INDEX_TYPE
']' of_tok COMPONENT_TYPE
492 | array_tok
'[' INDEX_TYPE
',' INDEX_TYPE
']' of_tok COMPONENT_TYPE
497 { compute_array_bounds
(); }
500 lower_bound
= sym_table
[l_s
].val
;
501 lower_sym
= sym_table
[l_s
].val_sym
;
502 upper_bound
= sym_table
[l_s
].upper
;
503 upper_sym
= sym_table
[l_s
].upper_sym
;
504 compute_array_bounds
();
508 COMPONENT_TYPE: TYPE
;
512 { my_output
("struct"); my_output
("{"); indent
++; }
514 { indent
--; my_output
("}"); semicolon
(); }
517 FIELD_LIST: RECORD_SECTION
518 | FIELD_LIST
';' RECORD_SECTION
522 { field_list
[0] = 0; }
525 /*array_bounds[0] = 0;
526 array_offset[0] = 0;*/
529 { int i
=0, j
; char ltemp
[80];
530 while
(field_list
[i
++] == '!') {
532 while
(field_list
[i
])
533 ltemp
[j
++] = field_list
[i
++];
535 if
(field_list
[i
] == '!')
545 FIELD_ID_LIST: FIELD_ID
546 | FIELD_ID_LIST
',' FIELD_ID
549 FIELD_ID: undef_id_tok
551 while
(field_list
[i
] == '!')
552 while
(field_list
[i
++]);
553 ii
= add_to_table
(last_id
);
554 sym_table
[ii
].typ
= field_id_tok
;
555 field_list
[i
++] = '!';
557 field_list
[i
++] = last_id
[j
++];
563 while
(field_list
[i
] == '!')
564 while
(field_list
[i
++]);
565 field_list
[i
++] = '!';
567 field_list
[i
++] = last_id
[j
++];
575 { my_output
("text /* of "); }
577 { my_output
("*/"); }
582 | var_tok VAR_DEC_LIST
587 | VAR_DEC_LIST VAR_DEC
604 { fixup_var_list
(); }
607 VAR_ID_DEC_LIST: VAR_ID
608 | VAR_ID_DEC_LIST
',' VAR_ID
613 ii
= add_to_table
(last_id
);
614 sym_table
[ii
].typ
= var_id_tok
;
615 sym_table
[ii
].var_formal
= var_formals
;
616 param_id_list
[ids_paramed
++] = ii
;
617 while
(var_list
[i
] == '!')
618 while
(var_list
[i
++]);
621 var_list
[i
++] = last_id
[j
++];
627 ii
= add_to_table
(last_id
);
628 sym_table
[ii
].typ
= var_id_tok
;
629 sym_table
[ii
].var_formal
= var_formals
;
630 param_id_list
[ids_paramed
++] = ii
;
631 while
(var_list
[i
] == '!')
632 while
(var_list
[i
++]);
635 var_list
[i
++] = last_id
[j
++];
641 ii
= add_to_table
(last_id
);
642 sym_table
[ii
].typ
= var_id_tok
;
643 sym_table
[ii
].var_formal
= var_formals
;
644 param_id_list
[ids_paramed
++] = ii
;
645 while
(var_list
[i
] == '!')
646 while
(var_list
[i
++]);
649 var_list
[i
++] = last_id
[j
++];
658 { my_output
("void mainbody( void ) {");
662 STAT_LIST end_tok
'.'
671 | P_F_DEC_PART P_F_DEC
674 P_F_DEC: PROCEDURE_DEC
';'
675 { new_line
(); remove_locals
(); }
677 { new_line
(); remove_locals
(); }
681 PROCEDURE_HEAD BLOCK
;
686 { proc_is_noreturn
= 1; }
691 PROCEDURE_TOK undef_id_tok
692 { ii
= add_to_table
(last_id
);
694 fprintf
(stderr
, "%3d Procedure %s\n", pf_count
++, last_id
);
695 sym_table
[ii
].typ
= proc_id_tok
;
696 strcpy
(my_routine
, last_id
);
697 uses_eqtb
= uses_mem
= false
;
704 { strcpy
(fn_return_type
, "void");
706 gen_function_head
(); }
707 | procedure_tok DECLARED_PROC
710 fprintf
(stderr
, "%3d Procedure %s\n", pf_count
++, last_id
);
711 strcpy
(my_routine
, last_id
);
716 { strcpy
(fn_return_type
, "void");
725 strcpy
(z_id
, last_id
);
730 { sprintf
(z_id
, "z%s", last_id
);
732 if
(sym_table
[ii
].typ
== proc_id_tok
)
733 sym_table
[ii
].typ
= proc_param_tok
;
734 else if
(sym_table
[ii
].typ
== fun_id_tok
)
735 sym_table
[ii
].typ
= fun_param_tok
;
741 FORM_PAR_SEC_L: FORM_PAR_SEC
742 | FORM_PAR_SEC_L
';' FORM_PAR_SEC
746 { ids_typed
= ids_paramed
; }
747 VAR_ID_DEC_LIST
':' type_id_tok
749 i
= search_table
(last_id
);
750 need_var
= !sym_table
[i
].var_not_needed
;
751 for
(i
=ids_typed
; i
<ids_paramed
; i
++)
753 strcpy
(arg_type
[i
], last_id
);
754 if
(need_var
&& sym_table
[param_id_list
[i
]].var_formal
)
755 strcat
(arg_type
[i
], " *");
757 sym_table
[param_id_list
[i
]].var_formal
= false
;
762 FORM_PAR_SEC: {var_formals
= 0; } FORM_PAR_SEC1
763 | var_tok
{var_formals
= 1; } FORM_PAR_SEC1
771 FUNCTION_DEC: FUNCTION_HEAD BLOCK
;
774 function_tok undef_id_tok
778 ii
= add_to_table
(last_id
);
780 fprintf
(stderr
, "%3d Function %s\n", pf_count
++, last_id
);
781 sym_table
[ii
].typ
= fun_id_tok
;
782 strcpy
(my_routine
, last_id
);
783 uses_eqtb
= uses_mem
= false
;
793 get_result_type
(fn_return_type
);
798 | function_tok DECLARED_FUN
804 fprintf
(stderr
, "%3d Function %s\n", pf_count
++, last_id
);
805 strcpy
(my_routine
, last_id
);
806 uses_eqtb
= uses_mem
= false
;
814 { get_result_type
(fn_return_type
);
821 DECLARED_FUN: fun_id_tok
828 STAT_PART: begin_tok STAT_LIST end_tok
831 COMPOUND_STAT: begin_tok
832 { my_output
("{"); indent
++; new_line
(); }
834 { indent
--; my_output
("}"); new_line
(); }
838 | STAT_LIST
';' STATEMENT
841 STATEMENT: UNLAB_STAT
847 {if
(!doreturn
(temp
)) {
848 sprintf
(safe_string
, "lab%s:", temp
);
849 my_output
(safe_string
);
854 UNLAB_STAT: SIMPLE_STAT
860 SIMPLE_STAT: ASSIGN_STAT
865 { my_output
("break"); }
868 ASSIGN_STAT: VARIABLE assign_tok
871 | FUNC_ID_AS assign_tok
872 { my_output
("Result ="); }
877 { if
(strcmp
(last_id
, "mem") == 0)
879 else if
(strcmp
(last_id
, "eqtb") == 0)
881 if
(sym_table
[l_s
].var_formal
)
888 { if
(sym_table
[l_s
].var_formal
)
890 my_output
(last_id
); $$
= ex_32
; }
893 FUNC_ID_AS: fun_id_tok
899 VAR_DESIG_LIST: VAR_DESIG
900 | VAR_DESIG_LIST VAR_DESIG
909 if
(strcmp
(last_id
, "int")==0)
911 else if
(strcmp
(last_id
, "lh")==0)
913 else if
(strcmp
(last_id
, "rh")==0)
916 sprintf
(safe_string
, ".%s", last_id
);
917 my_output
(safe_string
);
921 sprintf
(safe_string
, ".%s", last_id
);
922 my_output
(safe_string
);
926 { my_output
(".hh.b0"); }
928 { my_output
(".hh.b1"); }
933 { my_output
("]["); }
937 EXPRESS: UNARY_OP EXPRESS %prec
'*'
939 | EXPRESS
'+' { my_output
("+"); } EXPRESS
940 { $$
= max
($1, $4); }
941 | EXPRESS
'-' { my_output
("-"); } EXPRESS
942 { $$
= max
($1, $4); }
943 | EXPRESS
'*' { my_output
("*"); } EXPRESS
944 { $$
= max
($1, $4); }
945 | EXPRESS div_tok
{ my_output
("/"); } EXPRESS
946 { $$
= max
($1, $4); }
947 | EXPRESS
'=' { my_output
("=="); } EXPRESS
948 { $$
= max
($1, $4); }
949 | EXPRESS not_eq_tok
{ my_output
("!="); } EXPRESS
950 { $$
= max
($1, $4); }
951 | EXPRESS mod_tok
{ my_output
("%"); } EXPRESS
952 { $$
= max
($1, $4); }
953 | EXPRESS
'<' { my_output
("<"); } EXPRESS
954 { $$
= max
($1, $4); }
955 | EXPRESS
'>' { my_output
(">"); } EXPRESS
956 { $$
= max
($1, $4); }
957 | EXPRESS less_eq_tok
{ my_output
("<="); } EXPRESS
958 { $$
= max
($1, $4); }
959 | EXPRESS great_eq_tok
{ my_output
(">="); } EXPRESS
960 { $$
= max
($1, $4); }
961 | EXPRESS and_tok
{ my_output
("&&"); } EXPRESS
962 { $$
= max
($1, $4); }
963 | EXPRESS or_tok
{ my_output
("||"); } EXPRESS
964 { $$
= max
($1, $4); }
966 { my_output
("/ ((double)"); }
968 { $$
= max
($1, $4); my_output
(")"); }
976 { my_output
("- (integer)"); }
985 { my_output
(")"); $$
= $1; }
989 { my_output
(last_id
); my_output
("()"); }
991 { my_output
(last_id
); }
996 '(' { my_output
("("); }
997 ACTUAL_PARAM_L
')' { my_output
(")"); }
1002 | ACTUAL_PARAM_L
',' { my_output
(","); }
1008 | type_id_tok
/* So we can pass type names to C macros. */
1009 { my_output
(last_id
); }
1017 PROC_STAT: proc_id_tok
1018 { my_output
(last_id
); my_output
("()"); }
1020 { my_output
(last_id
);
1021 ii
= add_to_table
(last_id
);
1022 sym_table
[ii
].typ
= proc_id_tok
;
1026 { my_output
(last_id
); }
1030 GO_TO_STAT: goto_tok i_num_tok
1031 {if
(doreturn
(temp
)) {
1032 if
(strcmp
(fn_return_type
,"void"))
1033 my_output
("return Result");
1035 my_output
("return");
1037 sprintf
(safe_string
, "goto lab%s",
1039 my_output
(safe_string
);
1044 EMPTY_STAT: /* empty */
1047 STRUCT_STAT: COMPOUND_STAT
1052 CONDIT_STAT: IF_STATEMENT
1056 IF_STATEMENT: if_tok
1057 { my_output
("if"); my_output
("("); }
1061 IF_THEN_ELSE_STAT: EXPRESS
1062 { my_output
(")"); }
1066 THEN_ELSE_STAT: then_tok
1070 { my_output
("{"); indent
++; new_line
();
1071 my_output
("if"); my_output
("("); }
1073 { indent
--; my_output
("}"); new_line
(); }
1077 ELSE_STAT: /* empty */
1079 { my_output
("else"); }
1083 CASE_STATEMENT: case_tok
1084 { my_output
("switch"); my_output
("("); }
1086 { my_output
(")"); new_line
();
1087 my_output
("{"); indent
++;
1089 CASE_EL_LIST END_CASE
1090 { indent
--; my_output
("}"); new_line
(); }
1093 CASE_EL_LIST: CASE_ELEMENT
1094 | CASE_EL_LIST
';' CASE_ELEMENT
1097 CASE_ELEMENT: CASE_LAB_LIST
':' UNLAB_STAT
1098 { my_output
("break"); semicolon
(); }
1101 CASE_LAB_LIST: CASE_LAB
1102 | CASE_LAB_LIST
',' CASE_LAB
1106 { my_output
("case");
1108 my_output
(":"); new_line
();
1111 { my_output
("default:"); new_line
(); }
1118 REPETIT_STAT: WHILE_STATEMENT
1123 WHILE_STATEMENT: while_tok
1124 { my_output
("while");
1128 { my_output
(")"); }
1132 REP_STATEMENT: repeat_tok
1133 { my_output
("do"); my_output
("{"); indent
++; }
1135 { indent
--; my_output
("}");
1136 my_output
("while"); my_output
("( ! (");
1139 { my_output
(") )"); }
1142 FOR_STATEMENT: for_tok
1145 my_output
("register");
1146 my_output
("integer");
1148 my_output
("for_begin,");
1149 my_output
("for_end;");
1151 CONTROL_VAR assign_tok
1153 my_output
("for_begin");
1155 my_output
(control_var
);
1158 { my_output
("; if (");
1159 if
(strict_for
) my_output
("for_begin");
1160 else my_output
(control_var
);
1161 my_output
(relation
);
1162 my_output
("for_end)");
1165 my_output
(control_var
);
1167 my_output
("for_begin");
1176 char *top
= strrchr
(for_stack
, '#');
1179 my_output
("while");
1192 CONTROL_VAR: var_id_tok
1193 { strcpy
(control_var
, last_id
); }
1197 { my_output
(";"); }
1200 strcpy
(relation
, "<=");
1201 my_output
("for_end");
1205 sprintf
(for_stack
+ strlen
(for_stack
),
1206 "#%s++ < for_end", control_var
);
1209 { my_output
(";"); }
1212 strcpy
(relation
, ">=");
1213 my_output
("for_end");
1217 sprintf
(for_stack
+ strlen
(for_stack
),
1218 "#%s-- > for_end", control_var
);
1224 compute_array_bounds
(void)
1229 if
(lower_sym
== 0 || upper_sym
== 0) {
1230 yyerror ("Cannot handle variable subrange in array decl");
1232 else if
(lower_sym
== -1) { /* lower is a constant */
1233 lb
= lower_bound
- 1;
1234 if
(lb
==0) lb
= -1; /* Treat lower_bound==1 as if lower_bound==0 */
1235 if
(upper_sym
== -1) /* both constants */
1236 sprintf
(tmp
, "[%ld]", upper_bound
- lb
);
1237 else
{ /* upper a symbol, lower constant */
1239 sprintf
(tmp
, "[%s + %ld]",
1240 symbol
(upper_sym
), (-lb
));
1242 sprintf
(tmp
, "[%s - %ld]",
1243 symbol
(upper_sym
), lb
);
1245 if
(lower_bound
< 0 || lower_bound
> 1) {
1246 if
(*array_bounds
) {
1247 yyerror ("Cannot handle offset in second dimension");
1249 if
(lower_bound
< 0) {
1250 sprintf
(array_offset
, "+%ld", -lower_bound
);
1252 sprintf
(array_offset
, "-%ld", lower_bound
);
1255 strcat
(array_bounds
, tmp
);
1256 } else
{ /* lower is a symbol */
1257 if
(upper_sym
!= -1) /* both are symbols */
1258 sprintf
(tmp
, "[%s - %s + 1]", symbol
(upper_sym
),
1260 else
{ /* upper constant, lower symbol */
1261 sprintf
(tmp
, "[%ld - %s]", upper_bound
+ 1,
1264 if
(*array_bounds
) {
1265 yyerror ("Cannot handle symbolic offset in second dimension");
1267 sprintf
(array_offset
, "- (int)(%s)", symbol
(lower_sym
));
1268 strcat
(array_bounds
, tmp
);
1273 /* Kludge around negative lower array bounds. */
1276 fixup_var_list
(void)
1279 char output_string
[100], real_symbol
[100];
1281 for
(i
= 0; var_list
[i
++] == '!'; )
1283 for
(j
= 0; (real_symbol
[j
++] = var_list
[i
++]); )
1287 fprintf
(out
, "\n#define %s (%s %s)\n ",
1288 real_symbol
, next_temp
, array_offset
);
1289 strcpy
(real_symbol
, next_temp
);
1290 /* Add the temp to the symbol table, so that change files can
1291 use it later on if necessary. */
1292 j
= add_to_table
(next_temp
);
1293 sym_table
[j
].typ
= var_id_tok
;
1296 sprintf
(output_string
, "%s%s%c", real_symbol
, array_bounds
,
1297 var_list
[i
] == '!' ?
',' : ' ');
1298 my_output
(output_string
);
1304 /* If we're not processing TeX, we return false. Otherwise,
1305 return true if the label is "10" and we're not in one of four TeX
1306 routines where the line labeled "10" isn't the end of the routine.
1307 Otherwise, return 0. */
1310 doreturn
(string label
)
1314 && STREQ
(label
, "10")
1315 && !STREQ
(my_routine
, "macrocall")
1316 && !STREQ
(my_routine
, "hpack")
1317 && !STREQ
(my_routine
, "vpackage")
1318 && !STREQ
(my_routine
, "trybreak");
1322 /* Return the absolute value of a long. */
1326 if
(x
< 0L) return
(-x
);
1331 /* Output current function declaration to coerce file. */
1336 /* If we want ANSI code and one of the parameters is a var
1337 parameter, then use the #define to add the &. We do this by
1338 adding a 'z' at the front of the name. gen_function_head will do
1342 for
(i
= 0; i
< ids_paramed
; ++i
)
1343 var
+= sym_table
[param_id_list
[i
]].var_formal
;
1345 for
(i
= strlen
(z_id
); i
>= 0; --i
)
1346 z_id
[i
+1] = z_id
[i
];
1350 if
(proc_is_noreturn
) {
1351 fprintf
(coerce
, "WEB2C_NORETURN ");
1352 proc_is_noreturn
= 0;
1354 /* We can't use our P?H macros here, since there might be an arbitrary
1355 number of function arguments. */
1356 fprintf
(coerce
, "%s %s (", fn_return_type
, z_id
);
1357 if
(ids_paramed
== 0) fprintf
(coerce
, "void");
1358 for
(i
= 0; i
< ids_paramed
; i
++) {
1361 fprintf
(coerce
, "%s %s", arg_type
[i
], symbol
(param_id_list
[i
]));
1363 fprintf
(coerce
, ");\n");
1367 gen_function_head
(void)
1371 if
(strcmp
(my_routine
, z_id
)) {
1372 fprintf
(coerce
, "#define %s(", my_routine
);
1373 for
(i
=0; i
<ids_paramed
; i
++) {
1375 fprintf
(coerce
, ", %s", symbol
(param_id_list
[i
]));
1377 fprintf
(coerce
, "%s", symbol
(param_id_list
[i
]));
1379 fprintf
(coerce
, ") %s(", z_id
);
1380 for
(i
=0; i
<ids_paramed
; i
++) {
1382 fputs
(", ", coerce
);
1383 fprintf
(coerce
, "(%s) ", arg_type
[i
]);
1384 fprintf
(coerce
, "%s(%s)",
1385 sym_table
[param_id_list
[i
]].var_formal?
"&":"",
1386 symbol
(param_id_list
[i
]));
1388 fprintf
(coerce
, ")\n");
1392 /* We now always use ANSI C prototypes. */
1395 if
(ids_paramed
== 0) my_output
("void");
1396 for
(i
=0; i
<ids_paramed
; i
++) {
1397 if
(i
> 0) my_output
(",");
1398 my_output
(arg_type
[i
]);
1399 my_output
(symbol
(param_id_list
[i
]));