diff --git a/ase/awk/awk.h b/ase/awk/awk.h index de607fa0..10859729 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.43 2006-04-06 16:25:37 bacon Exp $ + * $Id: awk.h,v 1.44 2006-04-07 04:23:11 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -28,7 +28,8 @@ enum XP_AWK_EXPLICIT = (1 << 1), /* variable requires explicit declaration */ XP_AWK_UNIQUE = (1 << 2), /* a function name should not coincide to be a variable name */ XP_AWK_SHADING = (1 << 3), /* allow variable shading */ - XP_AWK_SHIFT = (1 << 4) /* support shift operators */ + XP_AWK_SHIFT = (1 << 4), /* support shift operators */ + XP_AWK_HASHSIGN = (1 << 5) /* support comments by a hash sign */ }; /* error code */ @@ -45,6 +46,7 @@ enum XP_AWK_ELXUNG, /* lexer failed to unget a character */ XP_AWK_EENDSRC, /* unexpected end of source */ + XP_AWK_EENDSTR, /* unexpected end of a string */ XP_AWK_ELBRACE, /* left brace expected */ XP_AWK_ELPAREN, /* left parenthesis expected */ XP_AWK_ERPAREN, /* right parenthesis expected */ diff --git a/ase/awk/err.c b/ase/awk/err.c index ff2f8879..f43b3128 100644 --- a/ase/awk/err.c +++ b/ase/awk/err.c @@ -1,5 +1,5 @@ /* - * $Id: err.c,v 1.5 2006-04-06 16:25:37 bacon Exp $ + * $Id: err.c,v 1.6 2006-04-07 04:23:11 bacon Exp $ */ #include @@ -20,7 +20,9 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk) XP_TEXT("cannot read source"), XP_TEXT("invalid character"), XP_TEXT("cannot unget character"), + XP_TEXT("unexpected end of source"), + XP_TEXT("unexpected end of a string"), XP_TEXT("left brace expected"), XP_TEXT("left parenthesis expected"), XP_TEXT("right parenthesis expected"), diff --git a/ase/awk/parse.c b/ase/awk/parse.c index 40af3404..06632d1b 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.72 2006-04-05 15:56:20 bacon Exp $ + * $Id: parse.c,v 1.73 2006-04-07 04:23:11 bacon Exp $ */ #include @@ -55,7 +55,7 @@ enum TOKEN_INT, TOKEN_REAL, - TOKEN_STRING, + TOKEN_STR, TOKEN_REGEX, TOKEN_IDENT, @@ -144,6 +144,7 @@ static xp_awk_nde_t* __parse_nextfile (xp_awk_t* awk); static int __get_token (xp_awk_t* awk); static int __get_number (xp_awk_t* awk); +static int __get_string (xp_awk_t* awk); static int __get_char (xp_awk_t* awk); static int __unget_char (xp_awk_t* awk, xp_cint_t c); static int __skip_spaces (xp_awk_t* awk); @@ -1516,7 +1517,7 @@ static xp_awk_nde_t* __parse_primary (xp_awk_t* awk) return (xp_awk_nde_t*)nde; } - else if (MATCH(awk,TOKEN_STRING)) + else if (MATCH(awk,TOKEN_STR)) { xp_awk_nde_str_t* nde; @@ -2165,10 +2166,12 @@ static int __get_token (xp_awk_t* awk) xp_cint_t c; int n; - do { + do + { if (__skip_spaces(awk) == -1) return -1; if ((n = __skip_comment(awk)) == -1) return -1; - } while (n == 1); + } + while (n == 1); xp_str_clear (&awk->token.name); c = awk->lex.curc; @@ -2184,25 +2187,34 @@ static int __get_token (xp_awk_t* awk) else if (xp_isalpha(c) || c == XP_CHAR('_')) { /* identifier */ - do { + do + { ADD_TOKEN_CHAR (awk, c); GET_CHAR_TO (awk, c); - } while (xp_isalpha(c) || c == XP_CHAR('_') || xp_isdigit(c)); + } + while (xp_isalpha(c) || c == XP_CHAR('_') || xp_isdigit(c)); SET_TOKEN_TYPE (awk, __classify_ident(awk, XP_STR_BUF(&awk->token.name))); } else if (c == XP_CHAR('\"')) { - /* string */ - GET_CHAR_TO (awk, c); - do { - ADD_TOKEN_CHAR (awk, c); - GET_CHAR_TO (awk, c); - } while (c != XP_CHAR('\"')); + SET_TOKEN_TYPE (awk, TOKEN_STR); - SET_TOKEN_TYPE (awk, TOKEN_STRING); - GET_CHAR_TO (awk, c); -// TODO: enhance string handling including escaping + if (__get_string(awk) == -1) return -1; + while (1) + { + do + { + if (__skip_spaces(awk) == -1) return -1; + if ((n = __skip_comment(awk)) == -1) return -1; + } + while (n == 1); + + c = awk->lex.curc; + if (c != XP_CHAR('\"')) break; + + if (__get_string(awk) == -1) return -1; + } } else if (c == XP_CHAR('=')) { @@ -2333,10 +2345,6 @@ static int __get_token (xp_awk_t* awk) ADD_TOKEN_STR (awk, XP_TEXT("+=")); GET_CHAR_TO (awk, c); } - else if (xp_isdigit(c)) - { - // read_number (XP_CHAR('+')); - } else { SET_TOKEN_TYPE (awk, TOKEN_PLUS); @@ -2358,11 +2366,6 @@ static int __get_token (xp_awk_t* awk) ADD_TOKEN_STR (awk, XP_TEXT("-=")); GET_CHAR_TO (awk, c); } - else if (xp_isdigit(c)) - { -// TODO... - // read_number (XP_CHAR('-')); - } else { SET_TOKEN_TYPE (awk, TOKEN_MINUS); @@ -2472,7 +2475,8 @@ static int __get_number (xp_awk_t* awk) { ADD_TOKEN_CHAR (awk, c); GET_CHAR_TO (awk, c); - } while (xp_isxdigit(c)); + } + while (xp_isxdigit(c)); return 0; } @@ -2483,7 +2487,8 @@ static int __get_number (xp_awk_t* awk) { ADD_TOKEN_CHAR (awk, c); GET_CHAR_TO (awk, c); - } while (c == XP_CHAR('0') || c == XP_CHAR('1')); + } + while (c == XP_CHAR('0') || c == XP_CHAR('1')); return 0; } @@ -2544,6 +2549,49 @@ static int __get_number (xp_awk_t* awk) return 0; } +static int __get_string (xp_awk_t* awk) +{ + xp_cint_t c; + xp_bool_t escaped = xp_false; + + GET_CHAR_TO (awk, c); + while (1) + { + if (c == XP_CHAR_EOF) + { + awk->errnum = XP_AWK_EENDSTR; + return -1; + } + + if (escaped == xp_false && c == XP_CHAR('\"')) + { + GET_CHAR_TO (awk, c); + break; + } + + if (escaped == xp_false && c == XP_CHAR('\\')) + { + GET_CHAR_TO (awk, c); + escaped = xp_true; + continue; + } + + if (escaped == xp_true) + { + if (c == XP_CHAR('n')) c = XP_CHAR('\n'); + else if (c == XP_CHAR('r')) c = XP_CHAR('\r'); + else if (c == XP_CHAR('t')) c = XP_CHAR('\t'); + /* TODO: more escape characters */ + escaped = xp_false; + } + + ADD_TOKEN_CHAR (awk, c); + GET_CHAR_TO (awk, c); + } + + return 0; +} + static int __get_char (xp_awk_t* awk) { xp_ssize_t n; @@ -2589,20 +2637,36 @@ static int __skip_comment (xp_awk_t* awk) { xp_cint_t c = awk->lex.curc; - if (c != XP_CHAR('/')) return 0; + if ((awk->opt.parse & XP_AWK_HASHSIGN) && c == XP_CHAR('#')) + { + do + { + GET_CHAR_TO (awk, c); + } + while (c != '\n' && c != XP_CHAR_EOF); + + GET_CHAR (awk); + return 1; /* comment by # */ + } + + if (c != XP_CHAR('/')) return 0; /* not a comment */ GET_CHAR_TO (awk, c); if (c == XP_CHAR('/')) { - do { + do + { GET_CHAR_TO (awk, c); - } while (c != '\n' && c != XP_CHAR_EOF); + } + while (c != '\n' && c != XP_CHAR_EOF); + GET_CHAR (awk); - return 1; + return 1; /* comment by // */ } else if (c == XP_CHAR('*')) { - do { + do + { GET_CHAR_TO (awk, c); if (c == XP_CHAR('*')) { @@ -2613,11 +2677,13 @@ static int __skip_comment (xp_awk_t* awk) break; } } - } while (0); - return 1; + } + while (1); + + return 1; /* c-style comment */ } - if (__unget_char(awk, c) == -1) return -1; + if (__unget_char(awk,c) == -1) return -1; /* error */ awk->lex.curc = XP_CHAR('/'); return 0; diff --git a/ase/awk/run.c b/ase/awk/run.c index 3f83dea2..a0037f14 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.36 2006-04-06 16:25:37 bacon Exp $ + * $Id: run.c,v 1.37 2006-04-07 04:23:11 bacon Exp $ */ #include @@ -271,7 +271,7 @@ static int __run_if_statement (xp_awk_t* awk, xp_awk_nde_if_t* nde) if (test == XP_NULL) return -1; xp_awk_refupval (test); - if (xp_awk_isvaltrue(test)) + if (xp_awk_boolval(test)) { n = __run_statement (awk, nde->then_part); } @@ -297,7 +297,7 @@ static int __run_while_statement (xp_awk_t* awk, xp_awk_nde_while_t* nde) xp_awk_refupval (test); - if (xp_awk_isvaltrue(test)) + if (xp_awk_boolval(test)) { // TODO: break.... continue...., global exit, return... run-time abortion... if (__run_statement(awk,nde->body) == -1) @@ -351,7 +351,7 @@ static int __run_while_statement (xp_awk_t* awk, xp_awk_nde_while_t* nde) if (test == XP_NULL) return -1; xp_awk_refupval (test); - if (!xp_awk_isvaltrue(test)) + if (!xp_awk_boolval(test)) { xp_awk_refdownval (awk, test); break; @@ -381,7 +381,7 @@ static int __run_for_statement (xp_awk_t* awk, xp_awk_nde_for_t* nde) if (test == XP_NULL) return -1; xp_awk_refupval (test); - if (xp_awk_isvaltrue(test)) + if (xp_awk_boolval(test)) { if (__run_statement(awk,nde->body) == -1) { @@ -576,7 +576,7 @@ static xp_awk_val_t* __eval_expression (xp_awk_t* awk, xp_awk_nde_t* nde) default: /* somthing wrong. internal error */ /* TODO: set the error code instead of assertion below */ - xp_assert (XP_TEXT("should never happen") == XP_NULL); + xp_assert (!"should never happen"); return XP_NULL; } @@ -730,19 +730,9 @@ static xp_awk_val_t* __eval_binop_lor ( { xp_awk_val_t* res = XP_NULL; - if (left->type == XP_AWK_VAL_INT && - right->type == XP_AWK_VAL_INT) - { - xp_long_t r = - ((xp_awk_val_int_t*)left)->val || - ((xp_awk_val_int_t*)right)->val; - res = xp_awk_makeintval (awk, r); - // TOOD: error handling - } - else - { - /* TODO: trigger error */ - } + res = xp_awk_makeintval (awk, + xp_awk_boolval(left) || xp_awk_boolval(right)); + if (res == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); return res; } @@ -752,19 +742,9 @@ static xp_awk_val_t* __eval_binop_land ( { xp_awk_val_t* res = XP_NULL; - if (left->type == XP_AWK_VAL_INT && - right->type == XP_AWK_VAL_INT) - { - xp_long_t r = - ((xp_awk_val_int_t*)left)->val && - ((xp_awk_val_int_t*)right)->val; - res = xp_awk_makeintval (awk, r); - // TOOD: error handling - } - else - { - // TODO: trigger error - } + res = xp_awk_makeintval (awk, + xp_awk_boolval(left) && xp_awk_boolval(right)); + if (res == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); return res; } @@ -781,9 +761,13 @@ static xp_awk_val_t* __eval_binop_bor ( ((xp_awk_val_int_t*)left)->val | ((xp_awk_val_int_t*)right)->val; res = xp_awk_makeintval (awk, r); - // TOOD: error handling + } + else + { + PANIC (awk, XP_AWK_EOPERAND); } + if (res == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); return res; } @@ -799,9 +783,13 @@ static xp_awk_val_t* __eval_binop_bxor ( ((xp_awk_val_int_t*)left)->val ^ ((xp_awk_val_int_t*)right)->val; res = xp_awk_makeintval (awk, r); - // TOOD: error handling + } + else + { + PANIC (awk, XP_AWK_EOPERAND); } + if (res == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); return res; } @@ -817,9 +805,13 @@ static xp_awk_val_t* __eval_binop_band ( ((xp_awk_val_int_t*)left)->val & ((xp_awk_val_int_t*)right)->val; res = xp_awk_makeintval (awk, r); - // TOOD: error handling + } + else + { + PANIC (awk, XP_AWK_EOPERAND); } + if (res == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); return res; } diff --git a/ase/awk/val.c b/ase/awk/val.c index fddfd1d8..a34364b6 100644 --- a/ase/awk/val.c +++ b/ase/awk/val.c @@ -1,5 +1,5 @@ /* - * $Id: val.c,v 1.16 2006-04-06 16:25:37 bacon Exp $ + * $Id: val.c,v 1.17 2006-04-07 04:23:11 bacon Exp $ */ #include @@ -232,7 +232,7 @@ xp_awk_val_t* xp_awk_cloneval (xp_awk_t* awk, xp_awk_val_t* val) return XP_NULL; } -xp_bool_t xp_awk_isvaltrue (xp_awk_val_t* val) +xp_bool_t xp_awk_boolval (xp_awk_val_t* val) { if (val == XP_NULL) return xp_false; @@ -241,15 +241,14 @@ xp_bool_t xp_awk_isvaltrue (xp_awk_val_t* val) case XP_AWK_VAL_NIL: return xp_false; case XP_AWK_VAL_INT: - return (((xp_awk_val_int_t*)val)->val == 0)? xp_false: xp_true; + return ((xp_awk_val_int_t*)val)->val != 0; case XP_AWK_VAL_REAL: - return (((xp_awk_val_real_t*)val)->val == 0.0)? xp_false: xp_true; + return ((xp_awk_val_real_t*)val)->val != 0.0; case XP_AWK_VAL_STR: - /* TODO: decide what to do */ - return (((xp_awk_val_str_t*)val)->len == 0)? xp_false: xp_true; + return ((xp_awk_val_str_t*)val)->len > 0; } - /* this should never happen */ + xp_assert (!"should never happen"); return xp_false; } diff --git a/ase/awk/val.h b/ase/awk/val.h index 66b62315..b49b22de 100644 --- a/ase/awk/val.h +++ b/ase/awk/val.h @@ -1,5 +1,5 @@ /* - * $Id: val.h,v 1.13 2006-04-06 16:25:37 bacon Exp $ + * $Id: val.h,v 1.14 2006-04-07 04:23:11 bacon Exp $ */ #ifndef _XP_AWK_VAL_H_ @@ -90,7 +90,7 @@ void xp_awk_refdownval (xp_awk_t* awk, xp_awk_val_t* val); void xp_awk_refdownval_nofree (xp_awk_t* awk, xp_awk_val_t* val); xp_awk_val_t* xp_awk_cloneval (xp_awk_t* awk, xp_awk_val_t* val); -xp_bool_t xp_awk_isvaltrue (xp_awk_val_t* val); +xp_bool_t xp_awk_boolval (xp_awk_val_t* val); void xp_awk_printval (xp_awk_val_t* val); #ifdef __cplusplus