diff options
Diffstat (limited to 'gawkapi.c')
-rw-r--r-- | gawkapi.c | 140 |
1 files changed, 129 insertions, 11 deletions
@@ -25,6 +25,11 @@ #include "awk.h" +/* Declare some globals used by api_get_file: */ +extern IOBUF *curfile; +extern INSTRUCTION *main_beginfile; +extern int currule; + static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted); /* @@ -193,6 +198,20 @@ api_fatal(awk_ext_id_t id, const char *format, ...) va_end(args); } +/* api_nonfatal --- print a non fatal error message */ + +static void +api_nonfatal(awk_ext_id_t id, const char *format, ...) +{ + va_list args; + + (void) id; + + va_start(args, format); + err(false, _("error: "), format, args); + va_end(args); +} + /* api_warning --- print a warning message */ static void @@ -411,24 +430,21 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) val->val_type = AWK_NUMBER; (void) force_number(node); - if ((node->flags & NUMCUR) != 0) { - val->num_value = get_number_d(node); - ret = awk_true; - } + val->num_value = get_number_d(node); + ret = awk_true; break; case AWK_STRING: val->val_type = AWK_STRING; (void) force_string(node); - if ((node->flags & STRCUR) != 0) { - val->str_value.str = node->stptr; - val->str_value.len = node->stlen; - ret = awk_true; - } + val->str_value.str = node->stptr; + val->str_value.len = node->stlen; + ret = awk_true; break; case AWK_SCALAR: + fixtype(node); if ((node->flags & NUMBER) != 0) { val->val_type = AWK_NUMBER; } else if ((node->flags & STRING) != 0) { @@ -440,6 +456,7 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) case AWK_UNDEFINED: /* return true and actual type for request of undefined */ + fixtype(node); if (node == Nnull_string) { val->val_type = AWK_UNDEFINED; ret = awk_true; @@ -668,7 +685,7 @@ api_sym_update_scalar(awk_ext_id_t id, /* make_str_node(s, l, ALREADY_MALLOCED): */ r->numbr = 0; r->flags = (MALLOC|STRING|STRCUR); - r->stfmt = -1; + r->stfmt = STFMT_UNUSED; r->stptr = value->str_value.str; r->stlen = value->str_value.len; return awk_true; @@ -782,7 +799,6 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, tmp = awk_value_to_node(index); aptr = assoc_lookup(array, tmp); - unref(tmp); unref(*aptr); elem = *aptr = awk_value_to_node(value); if (elem->type == Node_var_array) { @@ -790,6 +806,9 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, elem->vname = estrdup(index->str_value.str, index->str_value.len); } + if (array->astore != NULL) + (*array->astore)(array, tmp); + unref(tmp); return awk_true; } @@ -1033,6 +1052,99 @@ api_release_value(awk_ext_id_t id, awk_value_cookie_t value) return awk_true; } +/* api_get_file --- return a handle to an existing or newly opened file */ + +static awk_bool_t +api_get_file(awk_ext_id_t id, const char *name, size_t namelen, const char *filetype, + int fd, const awk_input_buf_t **ibufp, const awk_output_buf_t **obufp) +{ + const struct redirect *f; + int flag; /* not used, sigh */ + enum redirval redirtype; + + if (name == NULL || namelen == 0) { + if (curfile == NULL) { + INSTRUCTION *pc; + int save_rule; + char *save_source; + + if (nextfile(& curfile, false) <= 0) + return awk_false; + + pc = main_beginfile; + /* save execution state */ + save_rule = currule; + save_source = source; + + for (;;) { + if (pc == NULL) + fatal(_("cannot find end of BEGINFILE rule")); + if (pc->opcode == Op_after_beginfile) + break; + pc = pc->nexti; + } + pc->opcode = Op_stop; + (void) (*interpret)(main_beginfile); + pc->opcode = Op_after_beginfile; + after_beginfile(& curfile); + /* restore execution state */ + currule = save_rule; + source = save_source; + } + *ibufp = &curfile->public; + *obufp = NULL; + + return awk_true; + } + + redirtype = redirect_none; + switch (filetype[0]) { + case '<': + if (filetype[1] == '\0') + redirtype = redirect_input; + break; + case '>': + switch (filetype[1]) { + case '\0': + redirtype = redirect_output; + break; + case '>': + if (filetype[2] == '\0') + redirtype = redirect_append; + break; + } + break; + case '|': + if (filetype[2] == '\0') { + switch (filetype[1]) { + case '>': + redirtype = redirect_pipe; + break; + case '<': + redirtype = redirect_pipein; + break; + case '&': + redirtype = redirect_twoway; + break; + } + } + break; + } + + if (redirtype == redirect_none) { + warning(_("cannot open unrecognized file type `%s' for `%s'"), + filetype, name); + return awk_false; + } + + if ((f = redirect_string(name, namelen, 0, redirtype, &flag, fd, false)) == NULL) + return awk_false; + + *ibufp = f->iop ? & f->iop->public : NULL; + *obufp = f->output.fp ? & f->output : NULL; + return awk_true; +} + /* * Register a version string for this extension with gawk. */ @@ -1118,6 +1230,12 @@ gawk_api_t api_impl = { calloc, realloc, free, + + /* Find/open a file */ + api_get_file, + + /* Print nonfatal error message */ + api_nonfatal, }; /* init_ext_api --- init the extension API */ |