SVN-Revision: 13081master
parent
9b75b9e35c
commit
5a97325e73
@ -0,0 +1,212 @@ |
||||
--- a/editors/awk.c
|
||||
+++ b/editors/awk.c
|
||||
@@ -53,9 +53,14 @@ typedef struct chain_s {
|
||||
} chain;
|
||||
|
||||
/* Function */
|
||||
+typedef var *(*awk_cfunc)(var *res, var *args, int nargs);
|
||||
typedef struct func_s {
|
||||
unsigned nargs;
|
||||
+ enum { AWKFUNC, CFUNC } type;
|
||||
+ union {
|
||||
+ awk_cfunc cfunc;
|
||||
struct chain_s body;
|
||||
+ } x;
|
||||
} func;
|
||||
|
||||
/* I/O stream */
|
||||
@@ -1395,7 +1400,8 @@ static void parse_program(char *p)
|
||||
next_token(TC_FUNCTION);
|
||||
g_pos++;
|
||||
f = newfunc(t_string);
|
||||
- f->body.first = NULL;
|
||||
+ f->type = AWKFUNC;
|
||||
+ f->x.body.first = NULL;
|
||||
f->nargs = 0;
|
||||
while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
|
||||
v = findvar(ahash, t_string);
|
||||
@@ -1404,7 +1410,7 @@ static void parse_program(char *p)
|
||||
if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
|
||||
break;
|
||||
}
|
||||
- seq = &(f->body);
|
||||
+ seq = &(f->x.body);
|
||||
chain_group();
|
||||
clear_array(ahash);
|
||||
|
||||
@@ -2367,7 +2373,8 @@ static var *evaluate(node *op, var *res)
|
||||
break;
|
||||
|
||||
case XC( OC_FUNC ):
|
||||
- if (!op->r.f->body.first)
|
||||
+ if ((op->r.f->type == AWKFUNC) &&
|
||||
+ !op->r.f->x.body.first)
|
||||
syntax_error(EMSG_UNDEF_FUNC);
|
||||
|
||||
X.v = R.v = nvalloc(op->r.f->nargs+1);
|
||||
@@ -2384,7 +2391,10 @@ static var *evaluate(node *op, var *res)
|
||||
fnargs = X.v;
|
||||
|
||||
L.s = g_progname;
|
||||
- res = evaluate(op->r.f->body.first, res);
|
||||
+ if (op->r.f->type == AWKFUNC)
|
||||
+ res = evaluate(op->r.f->x.body.first, res);
|
||||
+ else if (op->r.f->type == CFUNC)
|
||||
+ res = op->r.f->x.cfunc(res, fnargs, op->r.f->nargs);
|
||||
g_progname = L.s;
|
||||
|
||||
nvfree(fnargs);
|
||||
@@ -2747,6 +2757,143 @@ static rstream *next_input_file(void)
|
||||
#undef files_happen
|
||||
}
|
||||
|
||||
+/* read the contents of an entire file */
|
||||
+static char *get_file(const char *fname)
|
||||
+{
|
||||
+ FILE *F;
|
||||
+ char *s = NULL;
|
||||
+ int i, j, flen;
|
||||
+
|
||||
+ F = fopen(fname, "r");
|
||||
+ if (!F) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (fseek(F, 0, SEEK_END) == 0) {
|
||||
+ flen = ftell(F);
|
||||
+ s = (char *)xmalloc(flen+4);
|
||||
+ fseek(F, 0, SEEK_SET);
|
||||
+ i = 1 + fread(s+1, 1, flen, F);
|
||||
+ } else {
|
||||
+ for (i=j=1; j>0; i+=j) {
|
||||
+ s = (char *)xrealloc(s, i+4096);
|
||||
+ j = fread(s+i, 1, 4094, F);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ s[i] = '\0';
|
||||
+ fclose(F);
|
||||
+ return s;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* parse_include():
|
||||
+ *
|
||||
+ * taken from parse_program from awk.c
|
||||
+ * END{} is not parsed here, and BEGIN{} is executed immediately
|
||||
+ */
|
||||
+static void parse_include(char *p)
|
||||
+{
|
||||
+ uint32_t tclass;
|
||||
+ chain *initseq = NULL;
|
||||
+ chain tmp;
|
||||
+ func *f;
|
||||
+ var *v, *tv;
|
||||
+
|
||||
+ tv = nvalloc(1);
|
||||
+ memset(&tmp, 0, sizeof(tmp));
|
||||
+ g_pos = p;
|
||||
+ t_lineno = 1;
|
||||
+ while ((tclass = next_token(TC_EOF | TC_OPSEQ |
|
||||
+ TC_OPTERM | TC_BEGIN | TC_FUNCDECL)) != TC_EOF) {
|
||||
+ if (tclass & TC_OPTERM)
|
||||
+ continue;
|
||||
+
|
||||
+ seq = &tmp;
|
||||
+ if (tclass & TC_BEGIN) {
|
||||
+ initseq = xzalloc(sizeof(chain));
|
||||
+ seq = initseq;
|
||||
+ chain_group();
|
||||
+ } else if (tclass & TC_FUNCDECL) {
|
||||
+ next_token(TC_FUNCTION);
|
||||
+ g_pos++;
|
||||
+ f = newfunc(t_string);
|
||||
+ f->type = AWKFUNC;
|
||||
+ f->x.body.first = NULL;
|
||||
+ f->nargs = 0;
|
||||
+ while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
|
||||
+ v = findvar(ahash, t_string);
|
||||
+ v->x.aidx = (f->nargs)++;
|
||||
+
|
||||
+ if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
|
||||
+ break;
|
||||
+ }
|
||||
+ seq = &(f->x.body);
|
||||
+ chain_group();
|
||||
+ clear_array(ahash);
|
||||
+ }
|
||||
+ }
|
||||
+ if (initseq && initseq->first)
|
||||
+ tv = evaluate(initseq->first, tv);
|
||||
+ nvfree(tv);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* include an awk file and run its BEGIN{} section */
|
||||
+static xhash *includes = NULL;
|
||||
+static void include_file(const char *filename)
|
||||
+{
|
||||
+ char *s;
|
||||
+ var *v;
|
||||
+ int oldlnr = g_lineno;
|
||||
+ const char *oldprg = g_progname;
|
||||
+
|
||||
+ if (!includes)
|
||||
+ includes = hash_init();
|
||||
+
|
||||
+ /* find out if the file has been included already */
|
||||
+ v = findvar(includes, filename);
|
||||
+ if (istrue(v))
|
||||
+ return;
|
||||
+ setvar_s(v, "1");
|
||||
+
|
||||
+ /* read include file */
|
||||
+ s = get_file(filename);
|
||||
+ if (!s) {
|
||||
+ fprintf(stderr, "Could not open file.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ g_lineno = 1;
|
||||
+ g_progname = xstrdup(filename);
|
||||
+ parse_include(s+1);
|
||||
+ free(s);
|
||||
+ g_lineno = oldlnr;
|
||||
+ g_progname = oldprg;
|
||||
+}
|
||||
+
|
||||
+static var *include(var *res, var *args, int nargs)
|
||||
+{
|
||||
+ const char *s;
|
||||
+
|
||||
+ nargs = nargs; /* shut up, gcc */
|
||||
+ s = getvar_s(args);
|
||||
+ if (s && (strlen(s) > 0))
|
||||
+ include_file(s);
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+/* registers a global c function for the awk interpreter */
|
||||
+static void register_cfunc(const char *name, awk_cfunc cfunc, int nargs)
|
||||
+{
|
||||
+ func *f;
|
||||
+
|
||||
+ f = newfunc(name);
|
||||
+ f->type = CFUNC;
|
||||
+ f->x.cfunc = cfunc;
|
||||
+ f->nargs = nargs;
|
||||
+}
|
||||
+
|
||||
int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int awk_main(int argc, char **argv)
|
||||
{
|
||||
@@ -2812,6 +2959,9 @@ int awk_main(int argc, char **argv)
|
||||
*s1 = '=';
|
||||
}
|
||||
}
|
||||
+
|
||||
+ register_cfunc("include", include, 1);
|
||||
+
|
||||
opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
|
||||
opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);
|
||||
argv += optind;
|
Loading…
Reference in new issue