| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- --- 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;
|