diff --git a/ase/awk/awk.c b/ase/awk/awk.c index 3bc53fcb..da58a78f 100644 --- a/ase/awk/awk.c +++ b/ase/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.52 2006-06-19 04:38:51 bacon Exp $ + * $Id: awk.c,v 1.53 2006-06-19 09:08:50 bacon Exp $ */ #include @@ -14,6 +14,7 @@ static void __free_func (void* awk, void* func); xp_awk_t* xp_awk_open (void) { xp_awk_t* awk; + xp_size_t i; awk = (xp_awk_t*) xp_malloc (xp_sizeof(xp_awk_t)); if (awk == XP_NULL) return XP_NULL; @@ -84,9 +85,7 @@ xp_awk_t* xp_awk_open (void) awk->lex.line = 1; awk->lex.column = 1; - awk->extio.pipe = XP_NULL; - awk->extio.coproc = XP_NULL; - awk->extio.file = XP_NULL; + for (i = 0; i < xp_countof(awk->extio); i++) awk->extio[i] = XP_NULL; return awk; } @@ -227,9 +226,14 @@ xp_size_t xp_awk_getsrcline (xp_awk_t* awk) /* TODO: redo it */ -int xp_awk_setextio (xp_awk_t* awk, xp_awk_io_t io, void* arg) +int xp_awk_setextio (xp_awk_t* awk, int id, xp_awk_io_t handler, void* arg) { - awk->extio.pipe = io; + if (id < 0 || id >= xp_countof(awk->extio)) + { + awk->errnum = XP_AWK_EINVAL; + return -1; + } + awk->extio[id] = handler; return 0; } diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 8c776ecc..d0464a1b 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.65 2006-06-19 04:38:51 bacon Exp $ + * $Id: awk.h,v 1.66 2006-06-19 09:08:50 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -13,13 +13,13 @@ typedef struct xp_awk_t xp_awk_t; typedef xp_ssize_t (*xp_awk_io_t) ( int cmd, void* arg, xp_char_t* data, xp_size_t count); -typedef struct xp_awk_cmd_t xp_awk_cmd_t; +typedef struct xp_awk_extio_t xp_awk_extio_t; -struct xp_awk_cmd_t +struct xp_awk_extio_t { xp_char_t* name; void* handle; - xp_awk_cmd_t* next; + xp_awk_extio_t* next; }; /* io function commands */ @@ -61,6 +61,7 @@ enum { XP_AWK_ENOERR, /* no error */ XP_AWK_ENOMEM, /* out of memory */ + XP_AWK_EINVAL, /* invalid parameter */ XP_AWK_ENOSRCIO, /* no source io handler set */ XP_AWK_ESRCINOPEN, @@ -112,9 +113,22 @@ enum XP_AWK_ENOTINDEXABLE, /* not indexable value */ XP_AWK_EWRONGINDEX, /* wrong index */ XP_AWK_EPIPE, /* pipe operation error */ + XP_AWK_EIOIMPL, /* wrong implementation of user io handler */ XP_AWK_EINTERNAL /* internal error */ }; +/* extio types */ +enum +{ + /* extio types available */ + XP_AWK_EXTIO_PIPE, + XP_AWK_EXTIO_COPROC, + XP_AWK_EXTIO_FILE, + + /* reserved for internal use only */ + XP_AWK_EXTIO_NUM +}; + #ifdef __cplusplus extern "C" { #endif @@ -132,7 +146,7 @@ void xp_awk_setrunopt (xp_awk_t* awk, int opt); int xp_awk_attsrc (xp_awk_t* awk, xp_awk_io_t src, void* arg); int xp_awk_detsrc (xp_awk_t* awk); -int xp_awk_setextio (xp_awk_t* awk, xp_awk_io_t io, void* arg); +int xp_awk_setextio (xp_awk_t* awk, int id, xp_awk_io_t handler, void* arg); xp_size_t xp_awk_getsrcline (xp_awk_t* awk); /* TODO: xp_awk_parse (xp_awk_t* awk, xp_awk_io_t src, void* arg)??? */ diff --git a/ase/awk/awk_i.h b/ase/awk/awk_i.h index 3438d3ef..cbc0daf9 100644 --- a/ase/awk/awk_i.h +++ b/ase/awk/awk_i.h @@ -1,5 +1,5 @@ /* - * $Id: awk_i.h,v 1.16 2006-06-19 04:38:51 bacon Exp $ + * $Id: awk_i.h,v 1.17 2006-06-19 09:08:50 bacon Exp $ */ #ifndef _XP_AWK_AWKI_H_ @@ -111,12 +111,7 @@ struct xp_awk_t xp_size_t column; } lex; - struct - { - xp_awk_io_t pipe; - xp_awk_io_t coproc; - xp_awk_io_t file; - } extio; + xp_awk_io_t extio[XP_AWK_EXTIO_NUM]; /* token */ struct @@ -168,17 +163,20 @@ struct xp_awk_run_t struct { - xp_awk_cmd_t* incmd; - xp_awk_cmd_t* iocmd; - xp_awk_cmd_t* outcmd; - /*xp_awk_infile_t* infile;*/ + xp_awk_extio_t* in_pipe; + xp_awk_extio_t* in_file; + /* + xp_awk_extio_t* out_pipe; + xp_awk_extio_t* out_file; + xp_awk_extio_t* coproc; + */ } extio; int opt; int errnum; - xp_awk_tree_t* tree; - /*xp_size_t nglobals;*/ + /*xp_awk_tree_t* tree; + xp_size_t nglobals;*/ xp_awk_t* awk; }; diff --git a/ase/awk/err.c b/ase/awk/err.c index 78710be3..5ff856ef 100644 --- a/ase/awk/err.c +++ b/ase/awk/err.c @@ -1,5 +1,5 @@ /* - * $Id: err.c,v 1.20 2006-06-18 10:53:06 bacon Exp $ + * $Id: err.c,v 1.21 2006-06-19 09:08:50 bacon Exp $ */ #include @@ -15,6 +15,7 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk) { XP_T("no error"), XP_T("out of memory"), + XP_T("invalid parameter"), XP_T("no source io handler set"), XP_T("cannot open source input"), @@ -65,6 +66,7 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk) XP_T("value not indexable"), XP_T("wrong index value"), XP_T("pipe operation error"), + XP_T("wrong implementation of user-defined io handler"), XP_T("internal error that should never have happened") }; diff --git a/ase/awk/extio.c b/ase/awk/extio.c index fadcb933..1b39142e 100644 --- a/ase/awk/extio.c +++ b/ase/awk/extio.c @@ -1,5 +1,5 @@ /* - * $Id: extio.c,v 1.4 2006-06-19 04:38:51 bacon Exp $ + * $Id: extio.c,v 1.5 2006-06-19 09:08:50 bacon Exp $ */ #include @@ -10,30 +10,29 @@ #include #endif -/* TODO: a lot of todo's here... */ -#include -#include - -int xp_awk_readcmd (xp_awk_run_t* run, const xp_char_t* cmd, int* errnum) +int xp_awk_readextio (xp_awk_run_t* run, + xp_awk_extio_t** extio, xp_awk_io_t handler, + const xp_char_t* name, int* errnum) { - xp_awk_cmd_t* p = run->extio.incmd; + xp_awk_extio_t* p = *extio; + xp_bool_t extio_created = xp_false; while (p != XP_NULL) { - if (xp_strcmp(p->name,cmd) == 0) break; + if (xp_strcmp(p->name,name) == 0) break; p = p->next; } if (p == XP_NULL) { - p = (xp_awk_cmd_t*) xp_malloc (xp_sizeof(xp_awk_cmd_t)); + p = (xp_awk_extio_t*) xp_malloc (xp_sizeof(xp_awk_extio_t)); if (p == XP_NULL) { *errnum = XP_AWK_ENOMEM; return -1; } - p->name = xp_strdup (cmd); + p->name = xp_strdup (name); if (p->name == XP_NULL) { xp_free (p); @@ -42,40 +41,54 @@ int xp_awk_readcmd (xp_awk_run_t* run, const xp_char_t* cmd, int* errnum) } p->handle = XP_NULL; - p->next = run->extio.incmd; - run->extio.incmd = p; + p->next = XP_NULL; + extio_created = xp_true; } if (p->handle == XP_NULL) { - xp_awk_io_t pipe_io = run->awk->extio.pipe; - - if (pipe_io (XP_AWK_INPUT_OPEN, p, XP_NULL, 0) == -1) + if (handler (XP_AWK_INPUT_OPEN, p, XP_NULL, 0) == -1) { - /* this is treated as pipe open error. - * the return value of getline should be -1 - * set ERRNO as well.... - */ + if (extio_created) + { + xp_free (p->name); + xp_free (p); + } + + /* TODO: set ERRNO */ + *errnum = XP_AWK_ENOERR; return -1; } if (p->handle == XP_NULL) { - /* TODO: break the chain ... */ + if (extio_created) + { + xp_free (p->name); + xp_free (p); + } - - /* *errnum = XP_AWK_EEXTIO; external io handler error */ - *errnum = XP_AWK_EINTERNAL; + /* wrong implementation of user io handler. + * the correct io handler should set p->handle to + * non XP_NULL when it returns 0. */ + *errnum = XP_AWK_EIOIMPL; return -1; } } + /* link it to the extio chain */ + if (extio_created) + { + p->next = *extio; + *extio = p; + } + { xp_char_t buf[1024]; -xp_awk_io_t pipe_io = run->awk->extio.pipe; - if (pipe_io (XP_AWK_INPUT_DATA, p, buf, xp_countof(buf)) == 0) + if (handler (XP_AWK_INPUT_DATA, p, buf, xp_countof(buf)) == 0) { + /* no more data. end of data stream */ return 0; } @@ -85,28 +98,28 @@ xp_printf(XP_TEXT("%s"), buf); return 1; } -int xp_awk_closecmd (xp_awk_run_t* run, const xp_char_t* cmd, int* errnum) +int xp_awk_closeextio (xp_awk_run_t* run, + xp_awk_extio_t** extio, xp_awk_io_t handler, + const xp_char_t* name, int* errnum) { - xp_awk_cmd_t* p = run->extio.incmd, * px = XP_NULL; + xp_awk_extio_t* p = *extio, * px = XP_NULL; while (p != XP_NULL) { - if (xp_strcmp(p->name,cmd) == 0) + if (xp_strcmp(p->name,name) == 0) { - xp_awk_io_t pipe_io = run->awk->extio.pipe; - - if (pipe_io (XP_AWK_INPUT_CLOSE, p, XP_NULL, 0) == -1) + if (handler (XP_AWK_INPUT_CLOSE, p, XP_NULL, 0) == -1) { - /* TODO: how to handle this... */ - p->handle = XP_NULL; + /* this is not a run-time error.*/ + *errnum = XP_AWK_ENOERR; return -1; } p->handle = XP_NULL; - //if (opt_remove_closed_cmd) + //if (opt_remove_closed_extio) // TODO:... //{ if (px != XP_NULL) px->next = p->next; - else run->extio.incmd = p->next; + else *extio = p->next; xp_free (p->name); xp_free (p); @@ -118,5 +131,7 @@ int xp_awk_closecmd (xp_awk_run_t* run, const xp_char_t* cmd, int* errnum) p = p->next; } + /* this is not a run-time error */ + *errnum = XP_AWK_ENOERR; return -1; } diff --git a/ase/awk/makefile.in b/ase/awk/makefile.in index 2b3bba21..9d7a8752 100644 --- a/ase/awk/makefile.in +++ b/ase/awk/makefile.in @@ -1,4 +1,4 @@ -SRCS = awk.c err.c tree.c tab.c map.c parse.c run.c sa.c val.c misc.c extio.c +SRCS = awk.c err.c tree.c tab.c map.c parse.c run.c sa.c val.c func.c misc.c extio.c OBJS = $(SRCS:.c=.o) OUT = libxpawk.a diff --git a/ase/awk/run.c b/ase/awk/run.c index cbd912d3..e4fe395c 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.98 2006-06-19 04:38:51 bacon Exp $ + * $Id: run.c,v 1.99 2006-06-19 09:08:50 bacon Exp $ */ #include @@ -22,7 +22,7 @@ #define STACK_RETVAL(run) STACK_AT(run,2) #define STACK_GLOBAL(run,n) ((run)->stack[(n)]) /*#define STACK_RETVAL_GLOBAL(run) ((run)->stack[(run)->nglobals+2])*/ -#define STACK_RETVAL_GLOBAL(run) ((run)->stack[(run)->tree->nglobals+2]) +#define STACK_RETVAL_GLOBAL(run) ((run)->stack[(run)->awk->tree.nglobals+2]) #define EXIT_NONE 0 #define EXIT_BREAK 1 @@ -212,7 +212,7 @@ static int __open_run ( run->opt = awk->opt.run; run->errnum = XP_AWK_ENOERR; - run->tree = &awk->tree; + /*run->tree = &awk->tree; */ /*run->nglobals = awk->tree.nglobals;*/ run->awk = awk; @@ -233,9 +233,8 @@ static int __open_run ( } /* TODO: */ - run->extio.incmd = XP_NULL; - run->extio.iocmd = XP_NULL; - run->extio.outcmd = XP_NULL; + run->extio.in_pipe = XP_NULL; + run->extio.in_file = XP_NULL; return 0; } @@ -287,7 +286,7 @@ static int __run_main (xp_awk_run_t* run) saved_stack_top = run->stack_top; /*nglobals = run->nglobals;*/ - nglobals = run->tree->nglobals; + nglobals = run->awk->tree.nglobals; while (nglobals > 0) { @@ -342,7 +341,7 @@ static int __run_main (xp_awk_run_t* run) run->stack_top = saved_stack_top; /* pops off global variables in a decent way */ /*__raw_pop_times (run, run->nglobals);*/ - __raw_pop_times (run, run->tree->nglobals); + __raw_pop_times (run, run->awk->tree.nglobals); PANIC_I (run, XP_AWK_ENOMEM); } @@ -350,7 +349,7 @@ static int __run_main (xp_awk_run_t* run) { run->stack_top = saved_stack_top; /*__raw_pop_times (run, run->nglobals);*/ - __raw_pop_times (run, run->tree->nglobals); + __raw_pop_times (run, run->awk->tree.nglobals); PANIC_I (run, XP_AWK_ENOMEM); } @@ -359,7 +358,7 @@ static int __run_main (xp_awk_run_t* run) { run->stack_top = saved_stack_top; /*__raw_pop_times (run, run->nglobals);*/ - __raw_pop_times (run, run->tree->nglobals); + __raw_pop_times (run, run->awk->tree.nglobals); PANIC_I (run, XP_AWK_ENOMEM); } @@ -368,7 +367,7 @@ static int __run_main (xp_awk_run_t* run) { run->stack_top = saved_stack_top; /*__raw_pop_times (run, run->nglobals);*/ - __raw_pop_times (run, run->tree->nglobals); + __raw_pop_times (run, run->awk->tree.nglobals); PANIC_I (run, XP_AWK_ENOMEM); } @@ -379,14 +378,14 @@ static int __run_main (xp_awk_run_t* run) STACK_NARGS(run) = (void*)nargs; /* stack set up properly. ready to exeucte statement blocks */ - if (n == 0 && run->tree->begin != XP_NULL) + if (n == 0 && run->awk->tree.begin != XP_NULL) { - xp_assert (run->tree->begin->type == XP_AWK_NDE_BLK); + xp_assert (run->awk->tree.begin->type == XP_AWK_NDE_BLK); run->exit_level = EXIT_NONE; if (__run_block (run, - (xp_awk_nde_blk_t*)run->tree->begin) == -1) n = -1; + (xp_awk_nde_blk_t*)run->awk->tree.begin) == -1) n = -1; } if (n == 0 && run->txtio != XP_NULL) @@ -394,14 +393,14 @@ static int __run_main (xp_awk_run_t* run) if (__run_pattern_blocks (run) == -1) n = -1; } - if (n == 0 && run->tree->end != XP_NULL) + if (n == 0 && run->awk->tree.end != XP_NULL) { - xp_assert (run->tree->end->type == XP_AWK_NDE_BLK); + xp_assert (run->awk->tree.end->type == XP_AWK_NDE_BLK); run->exit_level = EXIT_NONE; if (__run_block (run, - (xp_awk_nde_blk_t*)run->tree->end) == -1) n = -1; + (xp_awk_nde_blk_t*)run->awk->tree.end) == -1) n = -1; } /* restore stack */ @@ -428,7 +427,7 @@ xp_printf (XP_T("\n")); } /* pops off the global variables */ - nglobals = run->tree->nglobals; /*run->nglobals */ + nglobals = run->awk->tree.nglobals; /*run->nglobals */ while (nglobals > 0) { --nglobals; @@ -483,7 +482,7 @@ xp_printf (XP_T("**** line [%s]\n"), XP_STR_BUF(&run->input.line)); /* for each block { run it } * TODO: handle according if next and nextfile has been called */ - if (__run_pattern_block_chain (run, run->tree->chain) == -1) + if (__run_pattern_block_chain (run, run->awk->tree.chain) == -1) { /* don't care about the result of input close */ run->txtio (XP_AWK_INPUT_CLOSE, @@ -2541,7 +2540,7 @@ static xp_awk_val_t* __eval_call (xp_awk_run_t* run, xp_awk_nde_t* nde) int n; /*xp_printf (XP_T(".....__eval_call\n"));*/ - pair = xp_awk_map_get (&run->tree->funcs, call->name); + pair = xp_awk_map_get (&run->awk->tree.funcs, call->name); if (pair == XP_NULL) PANIC (run, XP_AWK_ENOSUCHFUNC); func = (xp_awk_func_t*)pair->val; @@ -2884,9 +2883,12 @@ 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_readcmd (run, str, &errnum); + n = xp_awk_readextio ( + run, &run->extio.in_pipe, + run->awk->extio[XP_AWK_EXTIO_PIPE], str, &errnum); xp_free (str); + if (n < 0 && errnum != XP_AWK_ENOERR) PANIC (run, errnum); return xp_awk_makeintval (run, n); } else if (p->in_type == XP_AWK_GETLINE_COPROC) @@ -2896,8 +2898,29 @@ static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde) } else if (p->in_type == XP_AWK_GETLINE_FILE) { - xp_printf (XP_T("eval_getline file not properly implemented....\n")); - return XP_NULL; + xp_awk_val_t* in; + xp_char_t* str; + int errnum, n; + + in = __eval_expression (run, p->in); + if (in == XP_NULL) return XP_NULL; + + xp_awk_refupval (in); + str = __val_to_str (in, &errnum, XP_NULL); + if (str == XP_NULL) + { + xp_awk_refdownval (run, in); + PANIC (run, errnum); + } + xp_awk_refdownval (run, in); + + n = xp_awk_readextio ( + run, &run->extio.in_file, + run->awk->extio[XP_AWK_EXTIO_FILE], str, &errnum); + xp_free (str); + + if (n < 0 && errnum != XP_AWK_ENOERR) PANIC (run, errnum); + return xp_awk_makeintval (run, n); } else { diff --git a/ase/test/awk/awk.c b/ase/test/awk/awk.c index 8959861c..266168a8 100644 --- a/ase/test/awk/awk.c +++ b/ase/test/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.37 2006-06-19 04:38:51 bacon Exp $ + * $Id: awk.c,v 1.38 2006-06-19 09:08:50 bacon Exp $ */ #include @@ -137,7 +137,7 @@ static xp_ssize_t process_data ( static xp_ssize_t process_extio_pipe ( int cmd, void* arg, xp_char_t* data, xp_size_t size) { - xp_awk_cmd_t* epa = (xp_awk_cmd_t*)arg; + xp_awk_extio_t* epa = (xp_awk_extio_t*)arg; switch (cmd) { @@ -180,6 +180,53 @@ static xp_ssize_t process_extio_pipe ( } +static xp_ssize_t process_extio_file ( + int cmd, void* arg, xp_char_t* data, xp_size_t size) +{ + xp_awk_extio_t* epa = (xp_awk_extio_t*)arg; + + switch (cmd) + { + case XP_AWK_INPUT_OPEN: + { + FILE* handle; + handle = _tfopen (epa->name, XP_T("r")); + if (handle == NULL) return -1; + epa->handle = (void*)handle; + return 0; + } + + case XP_AWK_INPUT_CLOSE: + { + fclose ((FILE*)epa->handle); + epa->handle = NULL; + return 0; + } + + case XP_AWK_INPUT_DATA: + { + if (_fgetts (data, size, epa->handle) == XP_NULL) + return 0; + return xp_strlen(data); + } + + case XP_AWK_INPUT_NEXT: + { + return -1; + } + + case XP_AWK_OUTPUT_OPEN: + case XP_AWK_OUTPUT_CLOSE: + case XP_AWK_OUTPUT_DATA: + case XP_AWK_OUTPUT_NEXT: + { + return -1; + } + } + +} + + #if defined(__STAND_ALONE) && !defined(_WIN32) static int __main (int argc, char* argv[]) #else @@ -203,10 +250,20 @@ static int __main (int argc, xp_char_t* argv[]) } /* TODO: */ - if (xp_awk_setextio (awk, process_extio_pipe, XP_NULL) == -1) + if (xp_awk_setextio (awk, + XP_AWK_EXTIO_PIPE, process_extio_pipe, XP_NULL) == -1) { xp_awk_close (awk); - xp_printf (XP_T("Error: cannot attach source\n")); + xp_printf (XP_T("Error: cannot set extio pipe\n")); + return -1; + } + +/* TODO: */ + if (xp_awk_setextio (awk, + XP_AWK_EXTIO_FILE, process_extio_file, XP_NULL) == -1) + { + xp_awk_close (awk); + xp_printf (XP_T("Error: cannot set extio file\n")); return -1; }