diff --git a/src/docode.c b/src/docode.c index 67fbe6f7056338d894ca489239f5da82a56b6435..3b4c414b3d9ce27c0470515ef41e7a9c2ca7a5d1 100644 --- a/src/docode.c +++ b/src/docode.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: docode.c,v 1.21 1997/09/09 03:36:11 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.22 1997/09/19 06:45:31 hubbe Exp $"); #include "las.h" #include "program.h" #include "language.h" @@ -802,11 +802,16 @@ static int do_docode2(node *n,int flags) /* Check for cases inside a range */ for(e=0; e<cases-1; e++) { - if(current_switch_jumptable[ order[e]*2+2 ] != -1) + if(order[e] < cases-1) { - if(current_switch_jumptable[ order[e]*2+2 ] != - current_switch_jumptable[ order[e+1]*2+1 ]) - yyerror("Case inside range."); + int o1=order[e]+1; + if(current_switch_jumptable[o1]==current_switch_jumptable[o1+1] && + current_switch_jumptable[o1]==current_switch_jumptable[o1+2]) + { + if(order[e]+1 != order[e+1]) + yyerror("Case inside range."); + e++; + } } } @@ -852,10 +857,13 @@ static int do_docode2(node *n,int flags) { yyerror("Case outside switch."); }else{ - if(!is_const(CAR(n))) + node *lower=CAR(n); + if(!lower) lower=CDR(n); + + if(!is_const(lower)) yyerror("Case label isn't constant."); - tmp1=eval_low(CAR(n)); + tmp1=eval_low(lower); if(tmp1<1) { yyerror("Error in case label."); @@ -872,27 +880,36 @@ static int do_docode2(node *n,int flags) if(CDR(n)) { - if(!is_const(CDR(n))) - yyerror("Case label isn't constant."); + current_switch_jumptable[current_switch_case]= + current_switch_jumptable[current_switch_case-1]; + current_switch_case++; - current_switch_jumptable[current_switch_case+1]= + if(CAR(n)) + { + if(!is_const(CDR(n))) + yyerror("Case label isn't constant."); + current_switch_jumptable[current_switch_case]= current_switch_jumptable[current_switch_case-1]; - current_switch_case+=2; - tmp1=eval_low(CDR(n)); - if(tmp1<1) - { - yyerror("Error in second half of case label."); - push_int(0); - tmp1=1; + current_switch_case++; + + tmp1=eval_low(CDR(n)); + if(tmp1<1) + { + yyerror("Error in second half of case label."); + push_int(0); + tmp1=1; + } + pop_n_elems(tmp1-1); + current_switch_values_on_stack++; + for(tmp1=current_switch_values_on_stack; tmp1 > 1; tmp1--) + if(is_equal(sp-tmp1, sp-1)) + yyerror("Duplicate case."); + current_switch_jumptable[current_switch_case++]=-1; } - pop_n_elems(tmp1-1); - current_switch_values_on_stack++; - for(tmp1=current_switch_values_on_stack; tmp1 > 1; tmp1--) - if(is_equal(sp-tmp1, sp-1)) - yyerror("Duplicate case."); + }else{ + current_switch_jumptable[current_switch_case++]=-1; } - current_switch_jumptable[current_switch_case++]=-1; } return 0; } diff --git a/src/language.yacc b/src/language.yacc index 1446eff7d1a196be5c43c4a60d19f09aaf087ebb..0f7eb4d4bfbcf4ac7facc0549c218bcc2c53444f 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -156,7 +156,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.48 1997/09/11 19:53:44 grubba Exp $"); +RCSID("$Id: language.yacc,v 1.49 1997/09/19 06:45:32 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -331,6 +331,7 @@ int yylex(YYSTYPE *yylval); %type <n> m_expr_list %type <n> m_expr_list2 %type <n> new_local_name +%type <n> optional_comma_expr %type <n> optional_else_part %type <n> return %type <n> sscanf @@ -1010,9 +1011,9 @@ case: F_CASE comma_expr ':' { $$=mknode(F_CASE,$2,0); } - | F_CASE comma_expr F_DOT_DOT comma_expr ':' + | F_CASE comma_expr F_DOT_DOT optional_comma_expr ':' { - $$=mknode(F_CASE,$2,$4); + $$=mknode(F_CASE,$4?$2:0,$4?$4:$2); } ; @@ -1037,6 +1038,10 @@ unused: { $$=0; } unused2: comma_expr { $$=mkcastnode(void_type_string,$1); } ; +optional_comma_expr: { $$=0; } + | comma_expr + ; + comma_expr: comma_expr2 | type2 {