diff --git a/hawk/bin/main.c b/hawk/bin/main.c index f83ba3a9..978c2437 100644 --- a/hawk/bin/main.c +++ b/hawk/bin/main.c @@ -101,6 +101,7 @@ struct arg_t hawk_parsestd_t* psin; /* input source streams */ hawk_bch_t* osf; /* output source file */ xarg_t icf; /* input console files */ + xarg_t ocf; /* output console files */ gvm_t gvm; /* global variable map */ hawk_bch_t* fs; /* field separator */ hawk_bch_t* call; /* function to call */ @@ -507,8 +508,10 @@ static void print_usage (FILE* out, const hawk_bch_t* argv0) fprintf (out, " -c/--call name call a function instead of entering\n"); fprintf (out, " the pattern-action loop. [datafile]* is\n"); fprintf (out, " passed to the function as parameters\n"); - fprintf (out, " -f/--file sourcefile set the source script file\n"); - fprintf (out, " -d/--deparsed-file deparsedfile set the deparsing output file\n"); + fprintf (out, " -f/--file file set the source script file\n"); + fprintf (out, " -d/--deparsed-file file set the deparsed script file to produce\n"); + fprintf (out, " -t/--console-output file set the console output file\n"); + fprintf (out, " multiple -t options are allowed\n"); fprintf (out, " -F/--field-separator string set a field separator(FS)\n"); fprintf (out, " -v/--assign var=value add a global variable with a value\n"); fprintf (out, " -m/--memory-limit number limit the memory usage (bytes)\n"); @@ -633,6 +636,7 @@ static int process_argv (int argc, hawk_bch_t* argv[], struct arg_t* arg) { ":call", 'c' }, { ":file", 'f' }, { ":deparsed-file", 'd' }, + { ":console-output", 't' }, { ":field-separator", 'F' }, { ":assign", 'v' }, { ":memory-limit", 'm' }, @@ -651,9 +655,9 @@ static int process_argv (int argc, hawk_bch_t* argv[], struct arg_t* arg) static hawk_bcli_t opt = { #if defined(HAWK_BUILD_DEBUG) - "hDc:f:d:F:v:m:wX:", + "hDc:f:d:t:F:v:m:wX:", #else - "hDc:f:d:F:v:m:w", + "hDc:f:d:t:F:v:m:w", #endif lng }; @@ -722,6 +726,20 @@ static int process_argv (int argc, hawk_bch_t* argv[], struct arg_t* arg) break; } + case 't': + { + hawk_bcs_t tmp; + tmp.ptr = opt.arg; + tmp.len = hawk_count_bcstr(opt.arg); + if (collect_into_xarg(&tmp, &arg->ocf) <= -1) + { + print_error ("out of memory\n"); + goto oops; + } + arg->ocf.ptr[arg->ocf.size] = HAWK_NULL; + break; + } + case 'F': { arg->fs = opt.arg; /* field seperator */ @@ -918,6 +936,7 @@ static int process_argv (int argc, hawk_bch_t* argv[], struct arg_t* arg) oops: if (arg->gvm.ptr) free (arg->gvm.ptr); purge_xarg (&arg->icf); + purge_xarg (&arg->ocf); if (isf) { if (arg->incl_conv) free (isf[0].u.bcs.ptr); @@ -936,6 +955,7 @@ static void freearg (struct arg_t* arg) /*if (arg->osf != HAWK_NULL) free (arg->osf);*/ purge_xarg (&arg->icf); + purge_xarg (&arg->ocf); if (arg->gvm.ptr) free (arg->gvm.ptr); } @@ -1163,7 +1183,7 @@ static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) rtx = hawk_rtx_openstdwithbcstr( awk, 0, "hawk", (arg.call? HAWK_NULL: arg.icf.ptr), /* console input */ - HAWK_NULL, /* ocf */ /* console output */ + arg.ocf.ptr, /* console output */ arg.console_cmgr ); #else diff --git a/hawk/lib/run.c b/hawk/lib/run.c index a3c6333b..3530bfcd 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -2860,7 +2860,7 @@ static int run_print (hawk_rtx_t* rtx, hawk_nde_print_t* nde) /* check if destination has been specified. */ if (nde->out) { - hawk_oow_t len; + hawk_oow_t len, i; /* if so, resolve the destination name */ out_v = eval_expression(rtx, nde->out); @@ -2874,24 +2874,17 @@ static int run_print (hawk_rtx_t* rtx, hawk_nde_print_t* nde) if (len <= 0) { /* the destination name is empty */ - SETERR_LOC (rtx, HAWK_EIONMEM, &nde->loc); + hawk_rtx_seterrfmt (rtx, &nde->loc, HAWK_EIONMEM, HAWK_T("empty I/O name")); goto oops; } /* it needs to check if the destination name contains * any invalid characters to the underlying system */ - while (len > 0) + for (i = 0; i < len; i++) { - if (out[--len] == HAWK_T('\0')) + if (out[i] == HAWK_T('\0')) { - /* provide length up to one character before - * the first null not to contains a null - * in an error message */ - SETERR_ARG_LOC ( - rtx, HAWK_EIONMNL, - out, hawk_count_oocstr(out), &nde->loc); - - /* if so, it skips writing */ + hawk_rtx_seterrfmt (rtx, &nde->loc, HAWK_EIONMNL, HAWK_T("invalid I/O name of length %zu containing '\\0'"), len); goto oops_1; } } @@ -3028,7 +3021,7 @@ static int run_printf (hawk_rtx_t* rtx, hawk_nde_print_t* nde) if (nde->out) { - hawk_oow_t len; + hawk_oow_t len, i; out_v = eval_expression(rtx, nde->out); if (!out_v) return -1; @@ -3041,18 +3034,15 @@ static int run_printf (hawk_rtx_t* rtx, hawk_nde_print_t* nde) if (len <= 0) { /* the output destination name is empty. */ - SETERR_LOC (rtx, HAWK_EIONMEM, &nde->loc); + hawk_rtx_seterrfmt (rtx, &nde->loc, HAWK_EIONMEM, HAWK_T("empty I/O name")); goto oops_1; } - while (len > 0) + for (i = 0; i < len; i++) { - if (out[--len] == HAWK_T('\0')) + if (out[i] == HAWK_T('\0')) { - /* provide length up to one character before - * the first null not to contains a null - * in an error message */ - SETERR_ARG_LOC (rtx, HAWK_EIONMNL, out, hawk_count_oocstr(out), &nde->loc); + hawk_rtx_seterrfmt (rtx, &nde->loc, HAWK_EIONMNL, HAWK_T("invalid I/O name of length %zu containing '\\0'"), len); /* the output destination name contains a null * character. */ diff --git a/hawk/lib/std.c b/hawk/lib/std.c index 239074b8..9e07b940 100644 --- a/hawk/lib/std.c +++ b/hawk/lib/std.c @@ -2093,7 +2093,7 @@ static int open_rio_console (hawk_rtx_t* rtx, hawk_rio_arg_t* riod) if (hawk_count_oocstr(as.ptr) < as.len) { /* the name contains one or more '\0' */ - hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_EIONMNL, HAWK_T("invalid I/O name beginning with '%js' of length %zu containing '\\0'"), as.ptr, as.len); + hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_EIONMNL, HAWK_T("invalid I/O name of length %zu containing '\\0'"), as.len); hawk_rtx_freevaloocstr (rtx, v, as.ptr); return -1; }