diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 2489414e..6b6397fa 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.158 2006-12-02 16:26:03 bacon Exp $ + * $Id: awk.h,v 1.159 2006-12-04 06:04:05 bacon Exp $ */ #ifndef _ASE_AWK_AWK_H_ @@ -151,11 +151,11 @@ enum /* support shift operators */ ASE_AWK_SHIFT = (1 << 4), - /* support comments by a hash sign */ - ASE_AWK_HASHSIGN = (1 << 5), + /* enable the idiv operator (double slashes) */ + ASE_AWK_IDIV = (1 << 5), - /* support comments by double slashes */ - ASE_AWK_DBLSLASHES = (1 << 6), + /* support comments by a hash sign */ + ASE_AWK_HASHSIGN = (1 << 6), /* support string concatenation in tokenization. * this option can change the behavior of a certain construct. diff --git a/ase/awk/jni.c b/ase/awk/jni.c index 0bb8e441..f3210419 100644 --- a/ase/awk/jni.c +++ b/ase/awk/jni.c @@ -1,5 +1,5 @@ /* - * $Id: jni.c,v 1.35 2006-12-02 16:26:03 bacon Exp $ + * $Id: jni.c,v 1.36 2006-12-04 06:04:06 bacon Exp $ */ #include @@ -234,8 +234,8 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_open (JNIEnv* env, jobject obj) (*env)->SetLongField (env, obj, fid_handle, (jlong)awk); - opt = ASE_AWK_EXPLICIT | ASE_AWK_UNIQUEAFN | ASE_AWK_DBLSLASHES | - ASE_AWK_SHADING | ASE_AWK_IMPLICIT | ASE_AWK_SHIFT | + opt = ASE_AWK_EXPLICIT | ASE_AWK_UNIQUEAFN | ASE_AWK_SHADING | + ASE_AWK_IMPLICIT | ASE_AWK_SHIFT | ASE_AWK_IDIV | ASE_AWK_EXTIO | ASE_AWK_BLOCKLESS | ASE_AWK_HASHSIGN | ASE_AWK_NEXTOFILE; ase_awk_setopt (awk, opt); diff --git a/ase/awk/parse.c b/ase/awk/parse.c index d7209818..31787346 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.214 2006-11-29 02:54:15 bacon Exp $ + * $Id: parse.c,v 1.215 2006-12-04 06:04:06 bacon Exp $ */ #include @@ -16,6 +16,7 @@ enum TOKEN_MINUS_ASSIGN, TOKEN_MUL_ASSIGN, TOKEN_DIV_ASSIGN, + TOKEN_IDIV_ASSIGN, TOKEN_MOD_ASSIGN, TOKEN_EXP_ASSIGN, @@ -33,6 +34,7 @@ enum TOKEN_MINUSMINUS, TOKEN_MUL, TOKEN_DIV, + TOKEN_IDIV, TOKEN_MOD, TOKEN_LOR, TOKEN_LAND, @@ -1540,68 +1542,6 @@ static ase_awk_nde_t* __parse_binary_expr ( return ASE_NULL; } -#if 0 - /* TODO: enhance constant folding. do it in a better way */ - /* TODO: differentiate different types of numbers ... */ - if (left->type == ASE_AWK_NDE_INT && - right->type == ASE_AWK_NDE_INT) - { - ase_long_t l, r; - - l = ((ase_awk_nde_int_t*)left)->val; - r = ((ase_awk_nde_int_t*)right)->val; - - /* TODO: more operators */ - if (opcode == ASE_AWK_BINOP_PLUS) l += r; - else if (opcode == ASE_AWK_BINOP_MINUS) l -= r; - else if (opcode == ASE_AWK_BINOP_MUL) l *= r; - else if (opcode == ASE_AWK_BINOP_DIV && r != 0) l /= r; - else if (opcode == ASE_AWK_BINOP_MOD && r != 0) l %= r; - else goto skip_constant_folding; - - ase_awk_clrpt (awk, right); - ((ase_awk_nde_int_t*)left)->val = l; - - if (((ase_awk_nde_int_t*)left)->str != ASE_NULL) - { - ASE_AWK_FREE (awk, ((ase_awk_nde_int_t*)left)->str); - ((ase_awk_nde_int_t*)left)->str = ASE_NULL; - ((ase_awk_nde_int_t*)left)->len = 0; - } - - continue; - } - else if (left->type == ASE_AWK_NDE_REAL && - right->type == ASE_AWK_NDE_REAL) - { - ase_real_t l, r; - - l = ((ase_awk_nde_real_t*)left)->val; - r = ((ase_awk_nde_real_t*)right)->val; - - /* TODO: more operators */ - if (opcode == ASE_AWK_BINOP_PLUS) l += r; - else if (opcode == ASE_AWK_BINOP_MINUS) l -= r; - else if (opcode == ASE_AWK_BINOP_MUL) l *= r; - else if (opcode == ASE_AWK_BINOP_DIV) l /= r; - else goto skip_constant_folding; - - ase_awk_clrpt (awk, right); - ((ase_awk_nde_real_t*)left)->val = l; - - if (((ase_awk_nde_real_t*)left)->str != ASE_NULL) - { - ASE_AWK_FREE (awk, ((ase_awk_nde_real_t*)left)->str); - ((ase_awk_nde_real_t*)left)->str = ASE_NULL; - ((ase_awk_nde_real_t*)left)->len = 0; - } - - continue; - } - /* TODO: enhance constant folding more... */ - - skip_constant_folding: -#endif nde = (ase_awk_nde_exp_t*) ASE_AWK_MALLOC ( awk, ASE_SIZEOF(ase_awk_nde_exp_t)); if (nde == ASE_NULL) @@ -1962,9 +1902,10 @@ static ase_awk_nde_t* __parse_multiplicative (ase_awk_t* awk) { static __binmap_t map[] = { - { TOKEN_MUL, ASE_AWK_BINOP_MUL }, - { TOKEN_DIV, ASE_AWK_BINOP_DIV }, - { TOKEN_MOD, ASE_AWK_BINOP_MOD }, + { TOKEN_MUL, ASE_AWK_BINOP_MUL }, + { TOKEN_DIV, ASE_AWK_BINOP_DIV }, + { TOKEN_IDIV, ASE_AWK_BINOP_IDIV }, + { TOKEN_MOD, ASE_AWK_BINOP_MOD }, /* { TOKEN_EXP, ASE_AWK_BINOP_EXP }, */ { TOKEN_EOF, 0 } }; @@ -3781,11 +3722,46 @@ static int __get_token (ase_awk_t* awk) ADD_TOKEN_CHAR (awk, c); GET_CHAR (awk); } + else if ((awk->option & ASE_AWK_IDIV) && c == ASE_T('/')) + { + ADD_TOKEN_CHAR (awk, c); + GET_CHAR_TO (awk, c); + if (c == ASE_T('=')) + { + SET_TOKEN_TYPE (awk, TOKEN_IDIV_ASSIGN); + ADD_TOKEN_CHAR (awk, c); + GET_CHAR (awk); + } + else + { + SET_TOKEN_TYPE (awk, TOKEN_IDIV); + } + } else { SET_TOKEN_TYPE (awk, TOKEN_DIV); } } +#if 0 + /* TODO: is it a good idea to use a back-slash for + * the idiv operator like BASIC? */ + else if ((awk->option & ASE_AWK_IDIV) && c == ASE_T('\\')) + { + ADD_TOKEN_CHAR (awk, c); + GET_CHAR_TO (awk, c); + + if (c == ASE_T('=')) + { + SET_TOKEN_TYPE (awk, TOKEN_IDIV_ASSIGN); + ADD_TOKEN_CHAR (awk, c); + GET_CHAR (awk); + } + else + { + SET_TOKEN_TYPE (awk, TOKEN_IDIV); + } + } +#endif else if (c == ASE_T('%')) { ADD_TOKEN_CHAR (awk, c); @@ -4254,6 +4230,7 @@ static int __skip_comment (ase_awk_t* awk) if (c != ASE_T('/')) return 0; /* not a comment */ GET_CHAR_TO (awk, c); +#if 0 if ((awk->option & ASE_AWK_DBLSLASHES) && c == ASE_T('/')) { do @@ -4265,7 +4242,9 @@ static int __skip_comment (ase_awk_t* awk) GET_CHAR (awk); return 1; /* comment by // */ } - else if (c == ASE_T('*')) + else +#endif + if (c == ASE_T('*')) { do { @@ -4332,6 +4311,7 @@ static int __assign_to_opcode (ase_awk_t* awk) ASE_AWK_ASSOP_MINUS, ASE_AWK_ASSOP_MUL, ASE_AWK_ASSOP_DIV, + ASE_AWK_ASSOP_IDIV, ASE_AWK_ASSOP_MOD, ASE_AWK_ASSOP_EXP }; diff --git a/ase/awk/run.c b/ase/awk/run.c index 7e358c22..fa2e238f 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.289 2006-12-03 15:05:01 bacon Exp $ + * $Id: run.c,v 1.290 2006-12-04 06:04:07 bacon Exp $ */ #include @@ -141,6 +141,8 @@ static ase_awk_val_t* __eval_binop_mul ( ase_awk_run_t* run, ase_awk_val_t* left, ase_awk_val_t* right); static ase_awk_val_t* __eval_binop_div ( ase_awk_run_t* run, ase_awk_val_t* left, ase_awk_val_t* right); +static ase_awk_val_t* __eval_binop_idiv ( + ase_awk_run_t* run, ase_awk_val_t* left, ase_awk_val_t* right); static ase_awk_val_t* __eval_binop_mod ( ase_awk_run_t* run, ase_awk_val_t* left, ase_awk_val_t* right); static ase_awk_val_t* __eval_binop_exp ( @@ -2719,6 +2721,10 @@ static ase_awk_val_t* __eval_assignment (ase_awk_run_t* run, ase_awk_nde_t* nde) { tmp = __eval_binop_div (run, val2, val); } + else if (ass->opcode == ASE_AWK_ASSOP_IDIV) + { + tmp = __eval_binop_idiv (run, val2, val); + } else if (ass->opcode == ASE_AWK_ASSOP_MOD) { tmp = __eval_binop_mod (run, val2, val); @@ -3029,6 +3035,7 @@ static ase_awk_val_t* __eval_binary (ase_awk_run_t* run, ase_awk_nde_t* nde) __eval_binop_minus, __eval_binop_mul, __eval_binop_div, + __eval_binop_idiv, __eval_binop_mod, __eval_binop_exp, @@ -3808,16 +3815,61 @@ static ase_awk_val_t* __eval_binop_div ( } else if (n3 == 1) { - res = ase_awk_makerealval (run, (ase_real_t)r1 / (ase_real_t)l2); + res = ase_awk_makerealval ( + run, (ase_real_t)r1 / (ase_real_t)l2); } else if (n3 == 2) { - res = ase_awk_makerealval (run, (ase_real_t)l1 / (ase_real_t)r2); + res = ase_awk_makerealval ( + run, (ase_real_t)l1 / (ase_real_t)r2); } else { ASE_AWK_ASSERT (run->awk, n3 == 3); - res = ase_awk_makerealval (run, (ase_real_t)r1 / (ase_real_t)r2); + res = ase_awk_makerealval ( + run, (ase_real_t)r1 / (ase_real_t)r2); + } + + if (res == ASE_NULL) PANIC (run, ASE_AWK_ENOMEM); + return res; +} + +static ase_awk_val_t* __eval_binop_idiv ( + ase_awk_run_t* run, ase_awk_val_t* left, ase_awk_val_t* right) +{ + int n1, n2, n3; + ase_long_t l1, l2; + ase_real_t r1, r2, quo; + ase_awk_val_t* res; + + n1 = ase_awk_valtonum (run, left, &l1, &r1); + n2 = ase_awk_valtonum (run, right, &l2, &r2); + + if (n1 == -1 || n2 == -1) PANIC (run, ASE_AWK_EOPERAND); + + n3 = n1 + (n2 << 1); + if (n3 == 0) + { + if (l2 == 0) PANIC (run, ASE_AWK_EDIVBYZERO); + res = ase_awk_makeintval ( + run, (ase_long_t)l1 / (ase_long_t)l2); + } + else if (n3 == 1) + { + quo = (ase_real_t)r1 / (ase_real_t)l2; + res = ase_awk_makeintval (run, (ase_long_t)quo); + } + else if (n3 == 2) + { + quo = (ase_real_t)l1 / (ase_real_t)r2; + res = ase_awk_makeintval (run, (ase_long_t)quo); + } + else + { + ASE_AWK_ASSERT (run->awk, n3 == 3); + + quo = (ase_real_t)r1 / (ase_real_t)r2; + res = ase_awk_makeintval (run, (ase_long_t)quo); } if (res == ASE_NULL) PANIC (run, ASE_AWK_ENOMEM); @@ -3841,7 +3893,8 @@ static ase_awk_val_t* __eval_binop_mod ( if (n3 == 0) { if (l2 == 0) PANIC (run, ASE_AWK_EDIVBYZERO); - res = ase_awk_makeintval (run, (ase_long_t)l1 % (ase_long_t)l2); + res = ase_awk_makeintval ( + run, (ase_long_t)l1 % (ase_long_t)l2); } else PANIC (run, ASE_AWK_EOPERAND); diff --git a/ase/awk/run.h b/ase/awk/run.h index 9e67785e..79d19fb5 100644 --- a/ase/awk/run.h +++ b/ase/awk/run.h @@ -1,5 +1,5 @@ /* - * $Id: run.h,v 1.28 2006-11-24 13:20:49 bacon Exp $ + * $Id: run.h,v 1.29 2006-12-04 06:04:07 bacon Exp $ */ #ifndef _ASE_AWK_RUN_H_ @@ -17,6 +17,7 @@ enum ase_awk_assop_type_t ASE_AWK_ASSOP_MINUS, /* -= */ ASE_AWK_ASSOP_MUL, /* *= */ ASE_AWK_ASSOP_DIV, /* /= */ + ASE_AWK_ASSOP_IDIV, /* //= */ ASE_AWK_ASSOP_MOD, /* %= */ ASE_AWK_ASSOP_EXP /* **= */ }; @@ -47,6 +48,7 @@ enum ase_awk_binop_type_t ASE_AWK_BINOP_MINUS, ASE_AWK_BINOP_MUL, ASE_AWK_BINOP_DIV, + ASE_AWK_BINOP_IDIV, ASE_AWK_BINOP_MOD, ASE_AWK_BINOP_EXP, diff --git a/ase/awk/tree.c b/ase/awk/tree.c index 9fc6138b..b3c16565 100644 --- a/ase/awk/tree.c +++ b/ase/awk/tree.c @@ -1,5 +1,5 @@ /* - * $Id: tree.c,v 1.92 2006-11-29 02:54:16 bacon Exp $ + * $Id: tree.c,v 1.93 2006-12-04 06:04:07 bacon Exp $ */ #include @@ -11,6 +11,7 @@ static const ase_char_t* __assop_str[] = ASE_T("-="), ASE_T("*="), ASE_T("/="), + ASE_T("//="), ASE_T("%="), ASE_T("**=") }; diff --git a/ase/test/awk/awk.c b/ase/test/awk/awk.c index 1aea6040..eca9bfb3 100644 --- a/ase/test/awk/awk.c +++ b/ase/test/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.133 2006-11-30 10:40:40 bacon Exp $ + * $Id: awk.c,v 1.134 2006-12-04 06:04:07 bacon Exp $ */ #include @@ -755,7 +755,7 @@ static int __main (int argc, ase_char_t* argv[]) ASE_AWK_EXPLICIT | ASE_AWK_UNIQUEAFN | ASE_AWK_HASHSIGN | - /*ASE_AWK_DBLSLASHES |*/ + ASE_AWK_IDIV | ASE_AWK_SHADING | ASE_AWK_SHIFT | ASE_AWK_EXTIO |