diff --git a/hawk/bin/main.c b/hawk/bin/main.c index eabb7e6d..122ec66c 100644 --- a/hawk/bin/main.c +++ b/hawk/bin/main.c @@ -1204,9 +1204,20 @@ static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) set_intr_run (); +#if 0 retv = arg.call? hawk_rtx_callwithbcstrarr(rtx, arg.call, (const hawk_bch_t**)arg.icf.ptr, arg.icf.size): - hawk_rtx_loop(rtx); + hawk_rtx_loop(rtx); /* this doesn't support @pragma startup ... */ +#else + /* note about @pragma startup ... + * hawk_rtx_execwithbcstrarr() invokes the specified function is @pragma startup ... is set + * in the source code. becuase arg.icf.ptr has been passed to hawk_rtx_openstdwithbcstr() when + * arg.call is HAWK_NULL, arg.icf.ptr serves as parameters to the startup function and + * affects input consoles */ + retv = arg.call? + hawk_rtx_callwithbcstrarr(rtx, arg.call, (const hawk_bch_t**)arg.icf.ptr, arg.icf.size): + hawk_rtx_execwithbcstrarr(rtx, (const hawk_bch_t**)arg.icf.ptr, arg.icf.size); +#endif unset_intr_run (); diff --git a/hawk/lib/hawk-prv.h b/hawk/lib/hawk-prv.h index 3c7a8334..fee25845 100644 --- a/hawk/lib/hawk-prv.h +++ b/hawk/lib/hawk-prv.h @@ -239,6 +239,7 @@ struct hawk_t { int trait; hawk_oow_t rtx_stack_limit; + hawk_ooch_t startup[128]; } pragma; /* function calls */ diff --git a/hawk/lib/hawk.c b/hawk/lib/hawk.c index 282ac56a..5bda8ecb 100644 --- a/hawk/lib/hawk.c +++ b/hawk/lib/hawk.c @@ -379,8 +379,9 @@ void hawk_clear (hawk_t* awk) awk->parse.depth.loop = 0; awk->parse.depth.expr = 0; awk->parse.depth.incl = 0; - awk->parse.pragma.trait = (awk->opt.trait & HAWK_IMPLICIT); + awk->parse.pragma.trait = (awk->opt.trait & HAWK_IMPLICIT); /* implicit on if you didn't mask it off in awk->opt.trait with hawk_setopt */ awk->parse.pragma.rtx_stack_limit = 0; + awk->parse.pragma.startup[0] = '\0'; awk->parse.incl_hist.count =0; diff --git a/hawk/lib/hawk.h b/hawk/lib/hawk.h index b6c7f5b4..c1914cfb 100644 --- a/hawk/lib/hawk.h +++ b/hawk/lib/hawk.h @@ -2198,12 +2198,45 @@ HAWK_EXPORT hawk_val_t* hawk_rtx_callwithbcstrarr ( hawk_oow_t nargs /**< the number of arguments */ ); +HAWK_EXPORT hawk_val_t* hawk_rtx_callwithooucstrarr ( + hawk_rtx_t* rtx, /**< runtime context */ + const hawk_ooch_t* name, /**< function name */ + const hawk_uch_t* args[], /**< arguments to the function */ + hawk_oow_t nargs /**< the number of arguments */ +); + +HAWK_EXPORT hawk_val_t* hawk_rtx_callwithoobcstrarr ( + hawk_rtx_t* rtx, /**< runtime context */ + const hawk_ooch_t* name, /**< function name */ + const hawk_bch_t* args[], /**< arguments to the function */ + hawk_oow_t nargs /**< the number of arguments */ +); + +/** + * The hawk_rtx_execwithucstrarr() function calls the starup function + * if the @pragma startup directive is found in a top-level source + * code or run hawk_rtx_loop() to enter the standard pattern loop + * otherwise */ +HAWK_EXPORT hawk_val_t* hawk_rtx_execwithucstrarr ( + hawk_rtx_t* rtx, /**< runtime context */ + const hawk_uch_t* args[], /**< arguments to the function */ + hawk_oow_t nargs /**< the number of arguments */ +); + +HAWK_EXPORT hawk_val_t* hawk_rtx_execwithbcstrarr ( + hawk_rtx_t* rtx, /**< runtime context */ + const hawk_bch_t* args[], /**< arguments to the function */ + hawk_oow_t nargs /**< the number of arguments */ +); + #if defined(HAWK_OOCH_IS_UCH) # define hawk_rtx_callwithoocstr hawk_rtx_callwithucstr # define hawk_rtx_callwithoocstrarr hawk_rtx_callwithucstrarr +# define hawk_rtx_execwithoocstrarr hawk_rtx_execwithucstrarr #else # define hawk_rtx_callwithoocstr hawk_rtx_callwithbcstr # define hawk_rtx_callwithoocstrarr hawk_rtx_callwithbcstrarr +# define hawk_rtx_execwithoocstrarr hawk_rtx_execwithbcstrarr #endif /** diff --git a/hawk/lib/parse.c b/hawk/lib/parse.c index fb490346..f30b9f8c 100644 --- a/hawk/lib/parse.c +++ b/hawk/lib/parse.c @@ -902,6 +902,7 @@ oops: static int parse_progunit (hawk_t* awk) { /* + @pragma .... @include "xxxx" @global xxx, xxxx; BEGIN { action } @@ -1016,6 +1017,31 @@ static int parse_progunit (hawk_t* awk) if (sl > awk->parse.pragma.rtx_stack_limit) awk->parse.pragma.rtx_stack_limit = sl; } + else if (hawk_comp_oochars_oocstr(name.ptr, name.len, HAWK_T("startup")) == 0) + { + if (get_token(awk) <= -1) return -1; + if (!MATCH(awk, TOK_IDENT)) + { + hawk_seterrfmt (awk, &awk->ptok.loc, HAWK_EIDENT, HAWK_T("function name expected for 'startup'")); + return -1; + } + + if (HAWK_OOECS_LEN(awk->tok.name) >= HAWK_COUNTOF(awk->parse.pragma.startup)) + { + hawk_seterrfmt (awk, &awk->tok.loc, HAWK_EFUNNAM, HAWK_T("startup function name too long")); + return -1; + } + + if (awk->sio.inp == &awk->sio.arg) + { + /* only the top level source */ + if (awk->parse.pragma.startup[0] == '\0') + { + /* honor the first encounter only */ + hawk_copy_oochars_to_oocstr (awk->parse.pragma.startup, HAWK_COUNTOF(awk->parse.pragma.startup), HAWK_OOECS_PTR(awk->tok.name), HAWK_OOECS_LEN(awk->tok.name)); + } + } + } else { hawk_seterrfmt (awk, &awk->ptok.loc, HAWK_EIDENT, HAWK_T("unknown @pragma identifier - %.*js"), name.len, name.ptr); diff --git a/hawk/lib/run.c b/hawk/lib/run.c index 3ace69b4..0d8ef89f 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -1460,21 +1460,45 @@ static hawk_val_t* run_bpae_loop (hawk_rtx_t* rtx) /* start the BEGIN-pattern block-END loop */ hawk_val_t* hawk_rtx_loop (hawk_rtx_t* rtx) { - hawk_val_t* retv = HAWK_NULL; - - rtx->exit_level = EXIT_NONE; - - if (enter_stack_frame (rtx) == 0) + if (rtx->awk->parse.pragma.startup[0] != '\0') { - retv = run_bpae_loop (rtx); - exit_stack_frame (rtx); + /* @pragma startup xxxx specified. + * divert hawk_rtx_loop() to call the specified function */ + return hawk_rtx_callwithoocstrarr(rtx, rtx->awk->parse.pragma.startup, HAWK_NULL, 0); /* TODO: pass argument */ } + else + { + hawk_val_t* retv = HAWK_NULL; - /* reset the exit level */ - rtx->exit_level = EXIT_NONE; - return retv; + rtx->exit_level = EXIT_NONE; + + if (enter_stack_frame(rtx) == 0) + { + retv = run_bpae_loop(rtx); + exit_stack_frame (rtx); + } + + /* reset the exit level */ + rtx->exit_level = EXIT_NONE; + return retv; + } } +hawk_val_t* hawk_rtx_execwithucstrarr (hawk_rtx_t* rtx, const hawk_uch_t* args[], hawk_oow_t nargs) +{ + return (rtx->awk->parse.pragma.startup[0] != '\0')? + hawk_rtx_callwithooucstrarr(rtx, rtx->awk->parse.pragma.startup, args, nargs): + hawk_rtx_loop(rtx); +} + +hawk_val_t* hawk_rtx_execwithbcstrarr (hawk_rtx_t* rtx, const hawk_bch_t* args[], hawk_oow_t nargs) +{ + return (rtx->awk->parse.pragma.startup[0] != '\0')? + hawk_rtx_callwithoobcstrarr(rtx, rtx->awk->parse.pragma.startup, args, nargs): + hawk_rtx_loop(rtx); +} + + /* find an AWK function by name */ static hawk_fun_t* find_fun (hawk_rtx_t* rtx, const hawk_ooch_t* name) { @@ -1548,7 +1572,7 @@ hawk_val_t* hawk_rtx_callfun (hawk_rtx_t* rtx, hawk_fun_t* fun, hawk_val_t* args { /* this function contains pass-by-reference parameters. * i don't support the call here as it requires variables */ - hawk_rtx_seterrfmt (rtx, HAWK_EPERM, HAWK_NULL, HAWK_T("not allowed to call '%.*js' with pass-by-reference parameters"), fun->name.len, fun->name.ptr); + hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_EPERM, HAWK_T("not allowed to call '%.*js' with pass-by-reference parameters"), fun->name.len, fun->name.ptr); return HAWK_NULL; } #endif @@ -1680,6 +1704,68 @@ oops: return ret; } +hawk_val_t* hawk_rtx_callwithooucstrarr (hawk_rtx_t* rtx, const hawk_ooch_t* name, const hawk_uch_t* args[], hawk_oow_t nargs) +{ + hawk_oow_t i; + hawk_val_t** v, * ret; + + v = hawk_rtx_allocmem(rtx, HAWK_SIZEOF(*v) * nargs); + if (!v) return HAWK_NULL; + + for (i = 0; i < nargs; i++) + { + v[i] = hawk_rtx_makestrvalwithucstr(rtx, args[i]); + if (!v[i]) + { + ret = HAWK_NULL; + goto oops; + } + + hawk_rtx_refupval (rtx, v[i]); + } + + ret = hawk_rtx_callwithoocstr(rtx, name, v, nargs); + +oops: + while (i > 0) + { + hawk_rtx_refdownval (rtx, v[--i]); + } + hawk_rtx_freemem (rtx, v); + return ret; +} + +hawk_val_t* hawk_rtx_callwithoobcstrarr (hawk_rtx_t* rtx, const hawk_ooch_t* name, const hawk_bch_t* args[], hawk_oow_t nargs) +{ + hawk_oow_t i; + hawk_val_t** v, * ret; + + v = hawk_rtx_allocmem(rtx, HAWK_SIZEOF(*v) * nargs); + if (!v) return HAWK_NULL; + + for (i = 0; i < nargs; i++) + { + v[i] = hawk_rtx_makestrvalwithbcstr(rtx, args[i]); + if (!v[i]) + { + ret = HAWK_NULL; + goto oops; + } + + hawk_rtx_refupval (rtx, v[i]); + } + + ret = hawk_rtx_callwithoocstr(rtx, name, v, nargs); + +oops: + while (i > 0) + { + hawk_rtx_refdownval (rtx, v[--i]); + } + hawk_rtx_freemem (rtx, v); + return ret; +} + static int run_pblocks (hawk_rtx_t* rtx) { int n; diff --git a/hawk/samples/hawk51.cpp b/hawk/samples/hawk51.cpp index e7d89fe7..99a4d203 100644 --- a/hawk/samples/hawk51.cpp +++ b/hawk/samples/hawk51.cpp @@ -350,22 +350,22 @@ static int handle_cmdline (MyHawk& awk, int argc, hawk_bch_t* argv[], cmdline_t* } -static int hawk_main (MyHawk& awk, int argc, hawk_bch_t* argv[]) +static int hawk_main (MyHawk& hawk, int argc, hawk_bch_t* argv[]) { MyHawk::Run* run; cmdline_t cmdline; int n; - awk.setTrait (awk.getTrait() | HAWK_FLEXMAP | HAWK_RWPIPE | HAWK_NEXTOFILE); + hawk.setTrait (hawk.getTrait() | HAWK_FLEXMAP | HAWK_RWPIPE | HAWK_NEXTOFILE); // ARGV[0] - if (awk.addArgument(HAWK_T("hawk25")) <= -1) + if (hawk.addArgument(HAWK_T("hawk51")) <= -1) { - print_error (awk); + print_error (hawk); return -1; } - if ((n = handle_cmdline(awk, argc, argv, &cmdline)) <= 0) return n; + if ((n = handle_cmdline(hawk, argc, argv, &cmdline)) <= 0) return n; MyHawk::Source* in, * out; MyHawk::SourceString in_str(cmdline.ins); @@ -374,10 +374,10 @@ static int hawk_main (MyHawk& awk, int argc, hawk_bch_t* argv[]) in = (cmdline.ins)? (MyHawk::Source*)&in_str: (MyHawk::Source*)&in_file; out = (cmdline.outf)? (MyHawk::Source*)&out_file: &MyHawk::Source::NONE; - run = awk.parse (*in, *out); + run = hawk.parse (*in, *out); if (run == HAWK_NULL) { - print_error (awk); + print_error (hawk); return -1; } @@ -386,29 +386,29 @@ static int hawk_main (MyHawk& awk, int argc, hawk_bch_t* argv[]) MyHawk::Value fs (run); if (fs.setStr(cmdline.fs) <= -1) { - print_error (awk); + print_error (hawk); return -1; } - if (awk.setGlobal(HAWK_GBL_FS, fs) <= -1) + if (hawk.setGlobal(HAWK_GBL_FS, fs) <= -1) { - print_error (awk); + print_error (hawk); return -1; } } if (cmdline.outc) { - if (awk.addConsoleOutput(cmdline.outc) <= -1) + if (hawk.addConsoleOutput(cmdline.outc) <= -1) { - print_error (awk); + print_error (hawk); return -1; } } MyHawk::Value ret; - if (awk.loop(&ret) <= -1) + if (hawk.loop(&ret) <= -1) { - print_error (awk); + print_error (hawk); return -1; }