diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 365c4c59..6d1bf9c2 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.73 2006-06-26 15:09:28 bacon Exp $ + * $Id: awk.h,v 1.74 2006-06-28 14:19:01 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -18,8 +18,19 @@ typedef xp_ssize_t (*xp_awk_io_t) ( struct xp_awk_extio_t { int type; + xp_char_t* name; void* handle; + + /* input buffer */ + struct + { + xp_char_t buf[2048]; + xp_size_t pos; + xp_size_t len; + xp_bool_t eof; + } in; + xp_awk_extio_t* next; }; diff --git a/ase/awk/extio.c b/ase/awk/extio.c index 29998f8b..cd2ec74a 100644 --- a/ase/awk/extio.c +++ b/ase/awk/extio.c @@ -1,5 +1,5 @@ /* - * $Id: extio.c,v 1.14 2006-06-28 10:40:24 bacon Exp $ + * $Id: extio.c,v 1.15 2006-06-28 14:19:01 bacon Exp $ */ #include @@ -11,7 +11,8 @@ #endif int xp_awk_readextio ( - xp_awk_run_t* run, int in_type, const xp_char_t* name, int* errnum) + xp_awk_run_t* run, int in_type, + const xp_char_t* name, xp_str_t* buf, int* errnum) { xp_awk_extio_t* p = run->extio; xp_awk_io_t handler; @@ -76,6 +77,12 @@ int xp_awk_readextio ( p->type = in_type; p->handle = XP_NULL; + + p->in.buf[0] = XP_C('\0'); + p->in.pos = 0; + p->in.len = 0; + p->in.eof = xp_false; + p->next = XP_NULL; if (handler (XP_AWK_IO_OPEN, extio_opt, p, XP_NULL, 0) == -1) @@ -105,16 +112,52 @@ int xp_awk_readextio ( run->extio = p; } - { -xp_char_t buf[1024]; + /* read a line */ + xp_str_clear (buf); - if (handler (XP_AWK_IO_READ, 0, p, buf, xp_countof(buf)) == 0) + while (1) { - /* no more data. end of data stream */ - return 0; - } + xp_char_t c; -xp_printf(XP_TEXT("%s"), buf); + if (p->in.pos >= p->in.len) + { + xp_ssize_t n; + + if (p->in.eof) + { + if (XP_STR_LEN(buf) == 0) return 0; + break; + } + + n = handler (XP_AWK_IO_READ, 0, + p, p->in.buf, xp_countof(p->in.buf)); + if (n == -1) + { + /* handler error. getline should return -1 */ + /* TODO: set ERRNO */ + *errnum = XP_AWK_ENOERR; + return -1; + } + + if (n == 0) + { + p->in.eof = xp_true; + if (XP_STR_LEN(buf) == 0) return 0; + break; + } + + p->in.len = n; + p->in.pos = 0; + } + + c = p->in.buf[p->in.pos++]; + if (c == XP_C('\n')) break; + + if (xp_str_ccat (buf, c) == (xp_size_t)-1) + { + *errnum = XP_AWK_ENOMEM; + return -1; + } } return 1; diff --git a/ase/awk/extio.h b/ase/awk/extio.h index 2cf08ae2..acd61f84 100644 --- a/ase/awk/extio.h +++ b/ase/awk/extio.h @@ -1,3 +1,7 @@ +/* + * $Id: extio.h,v 1.5 2006-06-28 14:19:01 bacon Exp $ + */ + #ifndef _XP_AWK_EXTIO_H_ #define _XP_AWK_EXTIO_H_ @@ -5,16 +9,16 @@ #error Never include this file directly. Include instead #endif - #ifdef __cplusplus extern "C" #endif int xp_awk_readextio ( - xp_awk_run_t* run, int type, const xp_char_t* name, int* errnum); + xp_awk_run_t* run, int in_type, + const xp_char_t* name, xp_str_t* buf, int* errnum); int xp_awk_writeextio ( - xp_awk_run_t* run, int type, + xp_awk_run_t* run, int out_type, const xp_char_t* name, xp_awk_val_t* v, int* errnum); int xp_awk_closeextio ( diff --git a/ase/awk/run.c b/ase/awk/run.c index ee09568b..bd87e443 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.112 2006-06-28 10:40:24 bacon Exp $ + * $Id: run.c,v 1.113 2006-06-28 14:19:01 bacon Exp $ */ #include @@ -1608,6 +1608,8 @@ static xp_awk_val_t* __eval_binop_lor ( } xp_awk_refdownval (run, lv); + + if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM); return res; } @@ -1652,6 +1654,8 @@ static xp_awk_val_t* __eval_binop_land ( } xp_awk_refdownval (run, lv); + + if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM); return res; } @@ -1844,6 +1848,7 @@ static xp_awk_val_t* __eval_binop_eq ( res = xp_awk_makeintval (run, r); if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM); + return res; } @@ -3060,11 +3065,14 @@ static xp_awk_val_t* __eval_pos (xp_awk_run_t* run, xp_awk_nde_t* nde) static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde) { - xp_awk_nde_getline_t* p = (xp_awk_nde_getline_t*)nde; - xp_awk_val_t* in; + xp_awk_nde_getline_t* p; + xp_awk_val_t* in, * res; xp_char_t* str; + xp_str_t buf; int errnum, n; + p = (xp_awk_nde_getline_t*)nde; + xp_assert (p->in_type == XP_AWK_IN_PIPE || p->in_type == XP_AWK_IN_COPROC || p->in_type == XP_AWK_IN_FILE); @@ -3082,14 +3090,56 @@ static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde) } xp_awk_refdownval (run, in); - n = xp_awk_readextio (run, p->in_type, str, &errnum); + /* TODO: optimization in line buffer management */ + if (xp_str_open (&buf, 256) == XP_NULL) + { + xp_free (str); + PANIC (run, XP_AWK_ENOMEM); + } + + n = xp_awk_readextio (run, p->in_type, str, &buf, &errnum); xp_free (str); - /* TODO: set the value to var if it is not null */ - /* TODO: set $0 if var is null */ + if (n < 0 && errnum != XP_AWK_ENOERR) + { + xp_str_close (&buf); + PANIC (run, errnum); + } - if (n < 0 && errnum != XP_AWK_ENOERR) PANIC (run, errnum); - return xp_awk_makeintval (run, n); + if (n > 0) + { + if (p->var == XP_NULL) + { + /* TODO: set $0 if var is null */ + xp_printf (XP_T("set %s to $0\n"), XP_STR_BUF(&buf)); + xp_str_close (&buf); + } + else + { + xp_awk_val_t* v; + + v = xp_awk_makestrval ( + XP_STR_BUF(&buf), XP_STR_LEN(&buf)); + + xp_str_close (&buf); + + if (v == XP_NULL) PANIC (run, XP_AWK_ENOMEM); + xp_awk_refupval (v); + + if (__do_assignment(run, + (xp_awk_nde_var_t*)p->var, v) == XP_NULL) + { + xp_awk_refdownval (run, v); + return XP_NULL; + } + xp_awk_refdownval (run, v); + } + } + + res = xp_awk_makeintval (run, n); + if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM); + + return res; } static int __raw_push (xp_awk_run_t* run, void* val) @@ -3100,7 +3150,7 @@ static int __raw_push (xp_awk_run_t* run, void* val) xp_size_t n; n = run->stack_limit + STACK_INCREMENT; - tmp = (void**)xp_realloc (run->stack, n * xp_sizeof(void*)); + tmp = (void**) xp_realloc (run->stack, n * xp_sizeof(void*)); if (tmp == XP_NULL) return -1; run->stack = tmp; diff --git a/ase/awk/tree.h b/ase/awk/tree.h index c11a54c9..26aa43c0 100644 --- a/ase/awk/tree.h +++ b/ase/awk/tree.h @@ -1,5 +1,5 @@ /* - * $Id: tree.h,v 1.53 2006-06-28 10:40:24 bacon Exp $ + * $Id: tree.h,v 1.54 2006-06-28 14:19:01 bacon Exp $ */ #ifndef _XP_AWK_TREE_H_ @@ -208,6 +208,7 @@ struct xp_awk_nde_rex_t xp_size_t len; }; +/* XP_AWK_NDE_ARG, XP_AWK_NDE_VAR, ... */ struct xp_awk_nde_var_t { XP_AWK_NDE_HDR; diff --git a/ase/test/awk/t12.awk b/ase/test/awk/t12.awk index 9559b66a..239218a9 100644 --- a/ase/test/awk/t12.awk +++ b/ase/test/awk/t12.awk @@ -7,4 +7,6 @@ BEGIN print "line 4" >> "2"; print "line 4" >> "3"; print "line 4" >> "4"; + + while ((getline x < "abc") > 0) print x; }