aboutsummaryrefslogtreecommitdiffstats
path: root/gawkapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'gawkapi.c')
-rw-r--r--gawkapi.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/gawkapi.c b/gawkapi.c
index 06f31929..e2c0b1a0 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -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);
/*
@@ -1035,6 +1040,90 @@ 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, size_t typelen, 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) {
+ if (nextfile(& curfile, false) <= 0)
+ return awk_false;
+ {
+ INSTRUCTION *pc = main_beginfile;
+ /* save execution state */
+ int save_rule = currule;
+ char *save_source = source;
+
+ while (1) {
+ if (!pc)
+ 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 (typelen) {
+ case 1:
+ switch (*filetype) {
+ case '<':
+ redirtype = redirect_input;
+ break;
+ case '>':
+ redirtype = redirect_output;
+ break;
+ }
+ break;
+ case 2:
+ switch (*filetype) {
+ case '>':
+ if (filetype[1] == '>')
+ redirtype = redirect_append;
+ break;
+ case '|':
+ 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)) == 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.
*/
@@ -1120,6 +1209,9 @@ gawk_api_t api_impl = {
calloc,
realloc,
free,
+
+ /* Find/open a file */
+ api_get_file,
};
/* init_ext_api --- init the extension API */