diff --git a/ase/awk/awk.c b/ase/awk/awk.c index 4a041a09..4f26145c 100644 --- a/ase/awk/awk.c +++ b/ase/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.44 2006-04-21 17:24:31 bacon Exp $ + * $Id: awk.c,v 1.45 2006-04-22 13:54:52 bacon Exp $ */ #include @@ -24,7 +24,8 @@ xp_awk_t* xp_awk_open (void) return XP_NULL; } - if (xp_awk_map_open (&awk->tree.funcs, awk, 256, __free_func) == XP_NULL) + /* TODO: initial map size?? */ + if (xp_awk_map_open(&awk->tree.funcs,awk,256,__free_func) == XP_NULL) { xp_str_close (&awk->token.name); xp_free (awk); @@ -61,12 +62,8 @@ xp_awk_t* xp_awk_open (void) awk->opt.parse = 0; awk->opt.run = 0; awk->errnum = XP_AWK_ENOERR; - awk->src_func = XP_NULL; - awk->in_func = XP_NULL; - awk->out_func = XP_NULL; - awk->src_arg = XP_NULL; - awk->in_arg = XP_NULL; - awk->out_arg = XP_NULL; + awk->srcio = XP_NULL; + awk->srcio_arg = XP_NULL; awk->parse.nlocals_max = 0; @@ -109,6 +106,7 @@ void xp_awk_clear (xp_awk_t* awk) xp_awk_tab_clear (&awk->parse.globals); xp_awk_tab_clear (&awk->parse.locals); xp_awk_tab_clear (&awk->parse.params); + awk->parse.nlocals_max = 0; /* clear parse trees */ @@ -135,8 +133,6 @@ void xp_awk_clear (xp_awk_t* awk) awk->tree.chain = next; } awk->tree.chain_tail = XP_NULL; - - /* TODO: destroy function list */ } void xp_awk_setparseopt (xp_awk_t* awk, int opt) @@ -153,14 +149,14 @@ int xp_awk_attsrc (xp_awk_t* awk, xp_awk_io_t src, void* arg) { if (xp_awk_detsrc(awk) == -1) return -1; - xp_assert (awk->src_func == XP_NULL); - if (src(XP_AWK_IO_OPEN, arg, XP_NULL, 0) == -1) { - awk->errnum = XP_AWK_ESRCOP; + xp_assert (awk->srcio == XP_NULL); + if (src(XP_AWK_INPUT_OPEN, arg, XP_NULL, 0) == -1) { + awk->errnum = XP_AWK_ESRCINOPEN; return -1; } - awk->src_func = src; - awk->src_arg = arg; + awk->srcio = src; + awk->srcio_arg = arg; awk->lex.curc = XP_CHAR_EOF; awk->lex.ungotc_count = 0; return 0; @@ -168,13 +164,18 @@ int xp_awk_attsrc (xp_awk_t* awk, xp_awk_io_t src, void* arg) int xp_awk_detsrc (xp_awk_t* awk) { - if (awk->src_func != XP_NULL) { - if (awk->src_func(XP_AWK_IO_CLOSE, awk->src_arg, XP_NULL, 0) == -1) { - awk->errnum = XP_AWK_ESRCCL; + if (awk->srcio != XP_NULL) { + xp_ssize_t n; + + n = awk->srcio (XP_AWK_INPUT_CLOSE, awk->srcio_arg, XP_NULL, 0); + if (n == -1) + { + awk->errnum = XP_AWK_ESRCINCLOSE; return -1; } - awk->src_func = XP_NULL; - awk->src_arg = XP_NULL; + + awk->srcio = XP_NULL; + awk->srcio_arg = XP_NULL; awk->lex.curc = XP_CHAR_EOF; awk->lex.ungotc_count = 0; } diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 9ee26d65..a921a6c3 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.53 2006-04-18 16:04:54 bacon Exp $ + * $Id: awk.h,v 1.54 2006-04-22 13:54:52 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -16,9 +16,15 @@ typedef xp_ssize_t (*xp_awk_io_t) ( /* io function commands */ enum { - XP_AWK_IO_OPEN, - XP_AWK_IO_CLOSE, - XP_AWK_IO_DATA + XP_AWK_INPUT_OPEN = 0, + XP_AWK_INPUT_CLOSE = 1, + XP_AWK_INPUT_NEXT = 2, + XP_AWK_INPUT_DATA = 3, + + XP_AWK_OUTPUT_OPEN = 4, + XP_AWK_OUTPUT_CLOSE = 5, + XP_AWK_OUTPUT_NEXT = 6, + XP_AWK_OUTPUT_DATA = 7 }; /* parse options */ @@ -44,9 +50,13 @@ enum XP_AWK_ENOERR, /* no error */ XP_AWK_ENOMEM, /* out of memory */ - XP_AWK_ESRCOP, - XP_AWK_ESRCCL, - XP_AWK_ESRCDT, /* error in reading source */ + XP_AWK_ESRCINOPEN, + XP_AWK_ESRCINCLOSE, + XP_AWK_ESRCINDATA, /* error in reading source */ + + XP_AWK_ETXTINOPEN, + XP_AWK_ETXTINCLOSE, + XP_AWK_ETXTINDATA, /* error in reading text */ XP_AWK_ELXCHR, /* lexer came accross an wrong character */ XP_AWK_ELXUNG, /* lexer failed to unget a character */ @@ -101,13 +111,10 @@ 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_attin (xp_awk_t* awk, xp_awk_io_t in, void* arg); -int xp_awk_detin (xp_awk_t* awk); -int xp_awk_attout (xp_awk_t* awk, xp_awk_io_t out, void* arg); -int xp_awk_detout (xp_awk_t* awk); +/* TODO: xp_awk_parse (xp_awk_t* awk, xp_awk_io_t src, void* arg)??? */ int xp_awk_parse (xp_awk_t* awk); -int xp_awk_run (xp_awk_t* awk); +int xp_awk_run (xp_awk_t* awk, xp_awk_io_t txtio, void* txtio_arg); /* utility functions exported by awk.h */ xp_long_t xp_awk_strtolong ( diff --git a/ase/awk/awk_i.h b/ase/awk/awk_i.h index d04a6651..3c935aea 100644 --- a/ase/awk/awk_i.h +++ b/ase/awk/awk_i.h @@ -1,5 +1,5 @@ /* - * $Id: awk_i.h,v 1.7 2006-04-21 17:24:31 bacon Exp $ + * $Id: awk_i.h,v 1.8 2006-04-22 13:54:52 bacon Exp $ */ #ifndef _XP_AWK_AWKI_H_ @@ -75,13 +75,8 @@ struct xp_awk_t } opt; /* io functions */ - xp_awk_io_t src_func; - xp_awk_io_t in_func; - xp_awk_io_t out_func; - - void* src_arg; - void* in_arg; - void* out_arg; + xp_awk_io_t srcio; + void* srcio_arg; /* parse tree */ xp_awk_tree_t tree; @@ -136,12 +131,23 @@ struct xp_awk_run_t xp_size_t icache_count; xp_size_t rcache_count; - /* input_stream */ - /* output_stream */ - xp_awk_t* awk; + xp_awk_io_t txtio; + void* txtio_arg; + + struct + { + xp_char_t buf[1024]; + xp_size_t buf_pos; + xp_size_t buf_len; + xp_bool_t eof; + xp_str_t line; + } input; + int opt; + int errnum; xp_awk_tree_t* tree; xp_size_t nglobals; + }; #endif diff --git a/ase/awk/err.c b/ase/awk/err.c index 0c6da985..6e57417e 100644 --- a/ase/awk/err.c +++ b/ase/awk/err.c @@ -1,5 +1,5 @@ /* - * $Id: err.c,v 1.12 2006-04-18 16:04:54 bacon Exp $ + * $Id: err.c,v 1.13 2006-04-22 13:54:52 bacon Exp $ */ #include @@ -15,9 +15,15 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk) { XP_TEXT("no error"), XP_TEXT("out of memory"), - XP_TEXT("cannot open source"), - XP_TEXT("cannot close source"), - XP_TEXT("cannot read source"), + + XP_TEXT("cannot open source input"), + XP_TEXT("cannot close source input"), + XP_TEXT("cannot read source input"), + + XP_TEXT("cannot open text input"), + XP_TEXT("cannot close text input"), + XP_TEXT("cannot read text input"), + XP_TEXT("invalid character"), XP_TEXT("cannot unget character"), diff --git a/ase/awk/parse.c b/ase/awk/parse.c index 8c97172a..bb504608 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.85 2006-04-19 03:42:08 bacon Exp $ + * $Id: parse.c,v 1.86 2006-04-22 13:54:52 bacon Exp $ */ #include @@ -2802,10 +2802,10 @@ static int __get_char (xp_awk_t* awk) return 0; } - n = awk->src_func(XP_AWK_IO_DATA, awk->src_arg, &c, 1); + n = awk->srcio (XP_AWK_INPUT_DATA, awk->srcio_arg, &c, 1); if (n == -1) { - awk->errnum = XP_AWK_ESRCDT; + awk->errnum = XP_AWK_ESRCINDATA; return -1; } awk->lex.curc = (n == 0)? XP_CHAR_EOF: c; diff --git a/ase/awk/run.c b/ase/awk/run.c index 7db25ffd..fe3d7693 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.67 2006-04-21 17:24:31 bacon Exp $ + * $Id: run.c,v 1.68 2006-04-22 13:54:52 bacon Exp $ */ #include @@ -31,14 +31,16 @@ #define EXIT_ABORT 5 #define PANIC(run,code) \ - do { (run)->awk->errnum = (code); return XP_NULL; } while (0) + do { (run)->errnum = (code); return XP_NULL; } while (0) #define PANIC_I(run,code) \ - do { (run)->awk->errnum = (code); return -1; } while (0) + do { (run)->errnum = (code); return -1; } while (0) -static int __open_run (xp_awk_run_t* run, xp_awk_t* awk); +static int __open_run ( + xp_awk_run_t* run, xp_awk_t* awk, xp_awk_io_t txtio, void* txtio_arg); static void __close_run (xp_awk_run_t* run); static int __run_main (xp_awk_run_t* run); +static int __run_pattern_blocks (xp_awk_run_t* run); static int __run_block (xp_awk_run_t* run, xp_awk_nde_blk_t* nde); static int __run_statement (xp_awk_run_t* run, xp_awk_nde_t* nde); static int __run_if_statement (xp_awk_run_t* run, xp_awk_nde_if_t* nde); @@ -126,9 +128,11 @@ static int __raw_push (xp_awk_run_t* run, void* val); static void __raw_pop (xp_awk_run_t* run); static void __raw_pop_times (xp_awk_run_t* run, xp_size_t times); +static int __read_text_input (xp_awk_run_t* run); static int __val_to_num (xp_awk_val_t* v, xp_long_t* l, xp_real_t* r); static xp_char_t* __val_to_str (xp_awk_val_t* v, int* errnum); + typedef xp_awk_val_t* (*binop_func_t) ( xp_awk_run_t* run, xp_awk_val_t* left, xp_awk_val_t* right); typedef xp_awk_val_t* (*eval_expr_t) (xp_awk_run_t* run, xp_awk_nde_t* nde); @@ -142,16 +146,33 @@ static int __printval (xp_awk_pair_t* pair) return 0; } -int xp_awk_run (xp_awk_t* awk) +int xp_awk_run (xp_awk_t* awk, xp_awk_io_t txtio, void* txtio_arg) { - xp_awk_run_t run; + xp_awk_run_t* run; + int n; - if (__open_run (&run, awk) == -1) return -1; - if (__run_main (&run) == -1) return -1; -xp_printf (XP_TEXT("run.icache_count = %d\n"), run.icache_count); - __close_run (&run); + run = (xp_awk_run_t*) xp_malloc (xp_sizeof(xp_awk_run_t)); + if (run == XP_NULL) + { + awk->errnum = XP_AWK_ENOMEM; + return -1; + } - return 0; + if (__open_run (run, awk, txtio, txtio_arg) == -1) + { +/* TODO: find a way to set the errnum into awk object in a thread-safe way */ + awk->errnum = run->errnum; + xp_free (run); + return -1; + } + + n = __run_main (run); + if (n == -1) awk->errnum = run->errnum; + + __close_run (run); + xp_free (run); + + return n; } static void __free_namedval (xp_awk_run_t* run, void* val) @@ -159,25 +180,40 @@ static void __free_namedval (xp_awk_run_t* run, void* val) xp_awk_refdownval (run, val); } -static int __open_run (xp_awk_run_t* run, xp_awk_t* awk) +static int __open_run ( + xp_awk_run_t* run, xp_awk_t* awk, xp_awk_io_t txtio, void* txtio_arg) { run->stack = XP_NULL; run->stack_top = 0; run->stack_base = 0; run->stack_limit = 0; + run->exit_level = 0; + run->icache_count = 0; run->rcache_count = 0; - run->awk = awk; + run->txtio = txtio; + run->txtio_arg = txtio_arg; + run->opt = awk->opt.run; + run->errnum = XP_AWK_ENOERR; run->tree = &awk->tree; run->nglobals = awk->tree.nglobals; + run->input.buf_pos = 0; + run->input.buf_len = 0; + if (xp_str_open (&run->input.line, 256) == XP_NULL) + { + run->errnum = XP_AWK_ENOMEM; + return -1; + } + if (xp_awk_map_open (&run->named, run, 256, __free_namedval) == XP_NULL) { - awk->errnum = XP_AWK_ENOMEM; + xp_str_close (&run->input.line); + run->errnum = XP_AWK_ENOMEM; return -1; } @@ -201,6 +237,9 @@ static void __close_run (xp_awk_run_t* run) /* destroy named variables */ xp_awk_map_close (&run->named); + /* destroy input data */ + xp_str_close (&run->input.line); + /* destroy values in free list */ while (run->icache_count > 0) { @@ -244,6 +283,7 @@ static int __run_main (xp_awk_run_t* run) if (run->opt & XP_AWK_RUNMAIN) { +// TODO: should the main function be user-specifiable? static xp_char_t m_a_i_n[] = { XP_CHAR('m'), @@ -282,6 +322,7 @@ static int __run_main (xp_awk_run_t* run) __raw_pop_times (run, run->nglobals); PANIC_I (run, XP_AWK_ENOMEM); } + if (__raw_push(run,(void*)saved_stack_top) == -1) { run->stack_top = saved_stack_top; @@ -322,16 +363,9 @@ static int __run_main (xp_awk_run_t* run) (xp_awk_nde_blk_t*)run->tree->begin) == -1) n = -1; } - while (run->exit_level != EXIT_GLOBAL && - run->exit_level != EXIT_ABORT) + if (n == 0 && run->txtio != XP_NULL) { - run->exit_level = EXIT_NONE; - - /* - * TODO: execute pattern blocks. - */ - - break; + if (__run_pattern_blocks (run) == -1) n = -1; } if (n == 0 && run->tree->end != XP_NULL) @@ -386,6 +420,52 @@ xp_printf (XP_TEXT("-[END VARIABLES]--------------------------\n")); return n; } +static int __run_pattern_blocks (xp_awk_run_t* run) +{ + xp_ssize_t n; + + xp_assert (run->txtio != XP_NULL); + + n = run->txtio (XP_AWK_INPUT_OPEN, run->txtio_arg, XP_NULL, 0); + if (n == -1) PANIC_I (run, XP_AWK_ETXTINOPEN); + + run->input.buf_pos = 0; + run->input.buf_len = 0; + run->input.eof = xp_false; + + while (run->exit_level != EXIT_GLOBAL && + run->exit_level != EXIT_ABORT) + { + int x; + run->exit_level = EXIT_NONE; + + x = __read_text_input(run); + if (x == -1) + { + /* don't care about the result of input close */ + run->txtio (XP_AWK_INPUT_CLOSE, + run->txtio_arg, XP_NULL, 0); + return -1; + } + + if (x == 0) break; /* end of input */ + + /* + * TODO: execute pattern blocks. + */ + /* for each block { run it } + * handle according if next and nextfile has been called + */ + xp_printf (XP_TEXT("**** line [%s]\n"), XP_STR_BUF(&run->input.line)); + } + + n = run->txtio (XP_AWK_INPUT_CLOSE, run->txtio_arg, XP_NULL, 0); + if (n == -1) PANIC_I (run, XP_AWK_ETXTINCLOSE); + + return 0; +} + + static int __run_block (xp_awk_run_t* run, xp_awk_nde_blk_t* nde) { @@ -2413,6 +2493,48 @@ static void __raw_pop_times (xp_awk_run_t* run, xp_size_t times) } } +static int __read_text_input (xp_awk_run_t* run) +{ + xp_ssize_t n; + xp_char_t c; + + xp_str_clear (&run->input.line); + if (run->input.eof) return 0; + + while (1) + { + if (run->input.buf_pos >= run->input.buf_len) + { + n = run->txtio (XP_AWK_INPUT_DATA, run->txtio_arg, + run->input.buf, xp_countof(run->input.buf)); + if (n == -1) PANIC_I (run, XP_AWK_ETXTINDATA); + if (n == 0) + { + if (XP_STR_LEN(&run->input.line) == 0) return 0; + run->input.eof = xp_true; + break; + } + + run->input.buf_pos = 0; + run->input.buf_len = n; + } + + c = run->input.buf[run->input.buf_pos++]; + + if (xp_str_ccat (&run->input.line, c) == (xp_size_t)-1) + { + PANIC_I (run, XP_AWK_ENOMEM); + } + + /* TODO: use LF instead of this hard coded value */ + /* any better way to tell line terminating with newlines? + * line with new line characters removed or retained? */ + if (c == XP_CHAR('\n')) break; + } + + return 1; +} + static int __val_to_num (xp_awk_val_t* v, xp_long_t* l, xp_real_t* r) { if (v->type == XP_AWK_VAL_NIL) diff --git a/ase/awk/run.h b/ase/awk/run.h index afd6b3ce..b8bbfc77 100644 --- a/ase/awk/run.h +++ b/ase/awk/run.h @@ -1,5 +1,5 @@ /* - * $Id: run.h,v 1.9 2006-04-14 16:26:00 bacon Exp $ + * $Id: run.h,v 1.10 2006-04-22 13:54:52 bacon Exp $ */ #ifndef _XP_AWK_RUN_H_ @@ -9,16 +9,6 @@ #error Never include this file directly. Include instead #endif -typedef struct xp_awk_frm_t xp_awk_frm_t; - -struct xp_awk_frm_t -{ - xp_size_t nparams; - xp_size_t nlocals; - xp_awk_val_t* stack; - xp_awk_frm_t* prev; -}; - enum { /* if you change this, you have to change __assop_str in tree.c */ diff --git a/ase/test/awk/awk.c b/ase/test/awk/awk.c index a80ad49d..4a5b7024 100644 --- a/ase/test/awk/awk.c +++ b/ase/test/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.25 2006-04-19 02:52:53 bacon Exp $ + * $Id: awk.c,v 1.26 2006-04-22 13:54:53 bacon Exp $ */ #include @@ -35,11 +35,12 @@ static xp_ssize_t process_source ( xp_char_t c; switch (cmd) { - case XP_AWK_IO_OPEN: - case XP_AWK_IO_CLOSE: + case XP_AWK_INPUT_OPEN: + case XP_AWK_INPUT_CLOSE: + case XP_AWK_INPUT_NEXT: return 0; - case XP_AWK_IO_DATA: + case XP_AWK_INPUT_DATA: if (size <= 0) return -1; #ifdef XP_CHAR_IS_MCHAR c = fgetc (stdin); @@ -49,11 +50,66 @@ static xp_ssize_t process_source ( if (c == XP_CHAR_EOF) return 0; *data = c; return 1; + + case XP_AWK_OUTPUT_OPEN: + case XP_AWK_OUTPUT_CLOSE: + case XP_AWK_OUTPUT_NEXT: + case XP_AWK_OUTPUT_DATA: + return 0; } return -1; } +struct data_io +{ + const char* input_file; + FILE* input_handle; +}; + +static xp_ssize_t process_data ( + int cmd, void* arg, xp_char_t* data, xp_size_t size) +{ + struct data_io* io = (struct data_io*)arg; + xp_char_t c; + + switch (cmd) { + case XP_AWK_INPUT_OPEN: + io->input_handle = fopen (io->input_file, "r"); + if (io->input_handle == NULL) return -1; + return 0; + + case XP_AWK_INPUT_CLOSE: + fclose (io->input_handle); + io->input_handle = NULL; + return 0; + + case XP_AWK_INPUT_NEXT: + /* input switching not supported for the time being... */ + return -1; + + case XP_AWK_INPUT_DATA: + if (size <= 0) return -1; +#ifdef XP_CHAR_IS_MCHAR + c = fgetc (io->input_handle); +#else + c = fgetwc (io->input_handle); +#endif + if (c == XP_CHAR_EOF) return 0; + *data = c; + return 1; + + case XP_AWK_OUTPUT_OPEN: + case XP_AWK_OUTPUT_CLOSE: + case XP_AWK_OUTPUT_NEXT: + case XP_AWK_OUTPUT_DATA: + return -1; + } + + return -1; + +} + #ifdef __linux #include #endif @@ -65,6 +121,7 @@ int xp_main (int argc, xp_char_t* argv[]) #endif { xp_awk_t* awk; + struct data_io data_io = { "awk.in", NULL }; #ifdef __linux mtrace (); @@ -114,7 +171,7 @@ int xp_main (int argc, xp_char_t* argv[]) return -1; } - if (xp_awk_run(awk) == -1) + if (xp_awk_run (awk, process_data, (void*)&data_io) == -1) { #if defined(__STAND_ALONE) && !defined(_WIN32) && defined(XP_CHAR_IS_WCHAR) xp_printf (