bug-gawk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug-gawk] Gawk debug command 'eval'


From: arnold
Subject: Re: [bug-gawk] Gawk debug command 'eval'
Date: Sun, 17 Feb 2019 08:08:47 -0700
User-agent: Heirloom mailx 12.5 7/5/10

Hi.

Lothar Langer <address@hidden> wrote:

> Hi,
>
> i didn't read anything in the 'Gawk User's Guide' that it is not
> possible to evaluate user defined functions with the command 'eval' in
> the debugger.
>
> Example:
>
> function isnumeric(x) {
>     return (length(x) && x == x+0)
> }
>
> ...
>
> gawk> eval "print isnumeric(\"hello\")"
> error: `return' not allowed in current context; statement ignored
>
> ... but ...
>
> gawk> eval "print length(\"hello\")"
> 5
>
> ... which is expected ...
>
> My version is:
> GNU Awk 4.2.60, API: 2.0

This turned out to be not so hard to fix.  Please apply this patch, rebuild,
and let me know if you find any other problems. I plan to push this to
master soon.

Thanks for the report!

Arnold
------------------------------------------
diff --git a/awk.h b/awk.h
index a8a37f60..e90f83d5 100644
--- a/awk.h
+++ b/awk.h
@@ -664,6 +664,7 @@ typedef enum opcodeval {
        Op_K_next,
        Op_K_exit,
        Op_K_return,
+       Op_K_return_from_eval,
        Op_K_delete,
        Op_K_delete_loop,
        Op_K_getline_redir,
@@ -1402,7 +1403,7 @@ extern unsigned long (*hash)(const char *s, size_t len, 
unsigned long hsize, siz
 extern void init_env_array(NODE *env_node);
 /* awkgram.c */
 extern NODE *variable(int location, char *name, NODETYPE type);
-extern int parse_program(INSTRUCTION **pcode);
+extern int parse_program(INSTRUCTION **pcode, bool from_eval);
 extern void track_ext_func(const char *name);
 extern void dump_funcs(void);
 extern void dump_vars(const char *fname);
diff --git a/awkgram.y b/awkgram.y
index 9f2b4d3c..87570dfa 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -176,6 +176,7 @@ static INSTRUCTION *ip_end;
 static INSTRUCTION *ip_endfile;
 static INSTRUCTION *ip_beginfile;
 INSTRUCTION *main_beginfile;
+static bool called_from_eval = false;
 
 static inline INSTRUCTION *list_create(INSTRUCTION *x);
 static inline INSTRUCTION *list_append(INSTRUCTION *l, INSTRUCTION *x);
@@ -1093,6 +1094,9 @@ non_compound_stmt
                if (! in_function)
                        yyerror(_("`return' used outside function context"));
          } opt_exp statement_term {
+               if (called_from_eval)
+                       $1->opcode = Op_K_return_from_eval;
+
                if ($3 == NULL) {
                        $$ = list_create($1);
                        (void) list_prepend($$, instruction(Op_push_i));
@@ -2732,10 +2736,12 @@ out:
 /* parse_program --- read in the program and convert into a list of 
instructions */
 
 int
-parse_program(INSTRUCTION **pcode)
+parse_program(INSTRUCTION **pcode, bool from_eval)
 {
        int ret;
 
+       called_from_eval = from_eval;
+
        /* pre-create non-local jump targets
         * ip_end (Op_no_op) -- used as jump target for `exit'
         * outside an END block.
diff --git a/debug.c b/debug.c
index 452b6b6f..19874284 100644
--- a/debug.c
+++ b/debug.c
@@ -5522,7 +5522,7 @@ pre_execute_code(INSTRUCTION **pi)
                                op2str(ei->opcode));
                *pi = ei->nexti;
                break;
-       case Op_K_return:
+       case Op_K_return_from_eval:
                if (ei->nexti != NULL) {        /* not an implicit return */
                        NODE *r;
                        d_error(_("`return' not allowed in current context;"
@@ -5600,7 +5600,7 @@ do_eval(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
        push_context(ctxt);
        the_source = add_srcfile(SRC_CMDLINE, arg->a_string, srcfiles, NULL, 
NULL);
        do_flags = false;
-       ret = parse_program(&code);
+       ret = parse_program(&code, true);
        do_flags = save_flags;
        remove_params(this_func);
        if (ret != 0) {
@@ -5783,7 +5783,7 @@ parse_condition(int type, int num, char *expr)
        push_context(ctxt);
        (void) add_srcfile(SRC_CMDLINE, expr, srcfiles, NULL, NULL);
        do_flags = false;
-       ret = parse_program(&code);
+       ret = parse_program(&code, true);
        do_flags = save_flags;
        remove_params(this_func);
        pop_context();
diff --git a/eval.c b/eval.c
index aa78d3e6..4858fa69 100644
--- a/eval.c
+++ b/eval.c
@@ -325,6 +325,7 @@ static struct optypetab {
        { "Op_K_next", "next" },
        { "Op_K_exit", "exit" },
        { "Op_K_return", "return" },
+       { "Op_K_return_from_eval", "return" },
        { "Op_K_delete", "delete" },
        { "Op_K_delete_loop", NULL },
        { "Op_K_getline_redir", "getline" },
diff --git a/interpret.h b/interpret.h
index c16da88f..cc6e02af 100644
--- a/interpret.h
+++ b/interpret.h
@@ -1199,6 +1199,10 @@ match_re:
                        JUMPTO(ni);     /* Op_func */
                }
 
+               case Op_K_return_from_eval:
+                       cant_happen();
+                       break;
+
                case Op_K_return:
                        m = POP_SCALAR();       /* return value */
 
diff --git a/main.c b/main.c
index d42d1f43..5800231c 100644
--- a/main.c
+++ b/main.c
@@ -465,7 +465,7 @@ main(int argc, char **argv)
        setlocale(LC_NUMERIC, "C");
 #endif
        /* Read in the program */
-       if (parse_program(& code_block) != 0 || dash_v_errs > 0)
+       if (parse_program(& code_block, false) != 0 || dash_v_errs > 0)
                exit(EXIT_FAILURE);
 
        if (do_intl)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]