diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/msh_function.patch | 350 |
1 files changed, 0 insertions, 350 deletions
diff --git a/shell/msh_function.patch b/shell/msh_function.patch deleted file mode 100644 index 270b9ee..0000000 --- a/shell/msh_function.patch +++ /dev/null @@ -1,350 +0,0 @@ -This is a "function" patch for msh which is in use by some busybox -users. Unfortunately it is far too buggy to be applied, but maybe -it's a useful starting point for future work. - -Function-related code is delimited by comments of the form - //funccode:start - ... - //funccode:end -for ease of grepping - -An example of buggy behavior: - -#f() { -# echo foo -# echo test`echo bar >&2` -# echo END f -#} - -function g { -# echo 2 foo -# echo 2 test`echo 2 bar >&2` -# f - echo END g -# echo "1:'$1' 2:'$2'" -} - -# Even this first block fails - it does not even call functions! -# (replacing "echo END g" above with "echo END" makes it run ok) -echo DRY RUN - echo 2 foo - echo 2 test`echo 2 bar >&2` - echo END g - echo "1:'$1' 2:'$2'" - echo foo - echo test`echo bar >&2` - echo END f -echo END DRY RUN - -exit - -# This would fail too -g "$1-one" "two$2" -echo DONE - - - -diff -d -urpN busybox.7/shell/msh.c busybox.8/shell/msh.c ---- busybox.7/shell/msh.c 2008-06-09 09:34:45.000000000 +0200 -+++ busybox.8/shell/msh.c 2008-06-09 09:38:17.000000000 +0200 -@@ -89,6 +89,14 @@ static char *itoa(int n) - - //#define MSHDEBUG 4 - -+/* Used only in "function" support code */ -+#ifdef KSDBG //funccode:start -+ #define KSDBG_PRINT_FUNCNAME fprintf(stderr, "in %s\n", __FUNCTION__) -+#else -+ #define KSDBG_PRINT_FUNCNAME ((void)0) -+#endif -+//funccode:end -+ - #ifdef MSHDEBUG - static int mshdbg = MSHDEBUG; - -@@ -220,6 +228,9 @@ struct op { - #define TASYNC 16 /* c & */ - /* Added to support "." file expansion */ - #define TDOT 17 -+#define TFUNC 18 //funccode:start -+#define TRETURN 19 -+ //funccode:end - - /* Strings for names to make debug easier */ - #ifdef MSHDEBUG -@@ -319,6 +330,27 @@ struct region { - int area; - }; - -+static int func_finished; //funccode:start -+struct func { -+ char* name; -+ int begin_addr; /* pos in buffer of function */ -+ int end_addr; -+}; -+#define MAX_FUNCS 100 -+ -+static struct func funcs[MAX_FUNCS]; -+ -+/* the max DEPTH of function call */ -+#define MAX_DEPTH 100 -+static struct _frame_s { -+ int argc; -+ char **argv; -+ int saved_return_addr; -+} frame[MAX_DEPTH]; -+ -+static void register_func(int begin, int end); -+static struct func* find_func(char* name); -+static void exec_func(struct func* f); //funccode:end - - /* -------- grammar stuff -------- */ - typedef union { -@@ -347,6 +379,8 @@ typedef union { - #define IN 272 - /* Added for "." file expansion */ - #define DOT 273 -+#define FUNC 274 //funccode:start -+#define RETURN 275 //funccode:end - - #define YYERRCODE 300 - -@@ -1722,6 +1756,40 @@ static struct op *simple(void) - (void) synio(0); - break; - -+ case FUNC: { //funccode:start -+ int stop_flag; -+ int number_brace; -+ int func_begin; -+ int func_end; -+ int c; -+ while ((c = my_getc(0)) == ' ' || c == '\t'|| c == '\n') /* skip whitespace */ -+ continue; -+ stop_flag = 1; -+ number_brace = 0; -+ func_begin = global_env.iobase->argp->afpos; -+ while (stop_flag) { -+ if (c == '{') -+ number_brace++; -+ if (c == '}') -+ number_brace--; -+ if (!number_brace) /* if we reach the brace of most outsite */ -+ stop_flag = 0; -+ c = my_getc(0); -+ } -+ unget(c); -+ unget(c); -+ func_end = global_env.iobase->argp->afpos; -+ register_func(func_begin, func_end); -+ peeksym = 0; -+ t = NULL; -+ return t; -+ } -+ case RETURN: -+ func_finished = 1; -+ peeksym = 0; -+ t = NULL; -+ return t; //funccode:end -+ - case WORD: - if (t == NULL) { - t = newtp(); -@@ -2265,6 +2333,13 @@ static int yylex(int cf) - case ')': - startl = 1; - return c; -+ case '{': //funccode:start -+ c = collect(c, '}'); -+ if (c != '\0') -+ return c; -+ break; -+ case '}': -+ return RETURN; //funccode:end - } - - unget(c); -@@ -2293,9 +2368,172 @@ static int yylex(int cf) - } - - yylval.cp = strsave(line, areanum); -+ /* To identify a subroutine */ //funccode:start -+ c = my_getc(0); -+ if (c && any(c, "(")) { -+ c = my_getc(0); -+ if (c && any(c, ")")) -+ return FUNC; -+ zzerr(); -+ } else -+ unget(c); -+ /* read the first char */ -+ /* To identify a function */ -+ if (strcmp(yylval.cp, "function") == 0) { -+ int ret = yylex(0); -+ /* read the function name after "function" */ -+ if (ret == WORD) -+ return (FUNC); -+ zzerr(); -+ } -+ { -+ struct func* f = find_func(yylval.cp); -+ if (f != NULL) { -+ exec_func(f); -+ return RETURN; -+ } -+ } -+ if (yylval.cp != NULL && strcmp(yylval.cp, "return") == 0) { -+ return RETURN; -+ } //funccode:end - return WORD; - } - -+static void register_func(int begin, int end) //funccode:start -+{ -+ struct func *p; -+ int i; -+ for (i = 0; i < MAX_FUNCS; i++) { -+ if (funcs[i].name == NULL) { -+ p = &funcs[i]; -+ break; -+ } -+ } -+ if (i == MAX_FUNCS) { -+ fprintf(stderr, "Too much functions beyond limit\n"); -+ leave(); -+ } -+ p->name = xstrdup(yylval.cp); -+ //fprintf(stderr, "register function,%d,%d,%s\n", begin, end, p->name); -+ KSDBG_PRINT_FUNCNAME; -+ /* io stream */ -+ p->begin_addr = begin; -+ p->end_addr = end; -+} -+ -+static struct func* find_func(char* name) -+{ -+ int i; -+ for (i = 0; i < MAX_FUNCS; i++) { -+ if (funcs[i].name == NULL) -+ continue; -+ if (!strcmp(funcs[i].name, name)) -+ return &funcs[i]; -+ } -+ KSDBG_PRINT_FUNCNAME; -+ //fprintf(stderr, "not found the function %s\n", name); -+ return NULL; -+ //zzerr(); -+} -+ -+/* Begin to execute the function */ -+static int cur_frame = 0; -+ -+static void exec_func(struct func* f) -+{ -+ int c; -+ int temp_argc; -+ char** temp_argv; -+ struct iobuf *bp; -+ -+ /* create a new frame, save the argument and return address to this frame */ -+ frame[cur_frame].argc = dolc; -+ frame[cur_frame].argv = dolv; -+ -+ cur_frame++; -+ /* do some argument parse and set arguments */ -+ temp_argv = xmalloc(sizeof(char *)); -+ temp_argv[0] = xstrdup(f->name); -+ temp_argc = 0; -+ global_env.iop->argp->afpos--; -+ global_env.iop->argp->afbuf->bufp--; -+// unget(c); -+ while (((c = yylex(0)) != '\n') && (yylval.cp != NULL)) { -+ temp_argc++; -+ temp_argv = xrealloc(temp_argv, sizeof(char *) * (temp_argc+1)); -+ /* parse $ var if passed argument is a variable */ -+ if (yylval.cp[0] == '$') { -+ struct var *arg = lookup(&yylval.cp[1]); -+ temp_argv[temp_argc] = xstrdup(arg->value); -+ //fprintf(stderr, "arg->value=%s\n", arg->value); -+ } else { -+ temp_argv[temp_argc] = xstrdup(yylval.cp); -+ //fprintf(stderr, "ARG:%s\n", yylval.cp); -+ } -+ } -+ /* -+ global_env.iop->argp->afpos--; -+ global_env.iop->argp->afbuf->bufp--; -+ */ -+ dolc = temp_argc; -+ dolv = temp_argv; -+ //unget(c); -+ //while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */ -+ // continue; -+ //unget(c); -+ frame[cur_frame].saved_return_addr = global_env.iop->argp->afpos; -+ -+ /* get function begin address and execute this function */ -+ -+ bp = global_env.iop->argp->afbuf; -+ bp->bufp = &(bp->buf[f->begin_addr]); -+ global_env.iop->argp->afpos = f->begin_addr; -+ -+ /* func_finished=0 means we are in a function and func_finished=1 means we are executing a function */ -+ func_finished = 0; -+ -+ //fprintf(stderr, "exec function %s\n", f->name); -+ KSDBG_PRINT_FUNCNAME; -+ for (;;) { -+ //fprintf(stderr, "afpos=%d,%s\n", global_env.iop->argp->afpos, yylval.cp); -+ if (global_env.iop->argp->afpos == f->end_addr) -+ break; -+ onecommand(); -+ /* we return from a function, when func_finished = 1 */ -+ if (func_finished) -+ break; -+ } -+ -+ { -+ //fprintf(stderr, "%s is finished @%d!\n", f->name, global_env.iop->argp->afpos); -+ int ret = frame[cur_frame].saved_return_addr; -+ /* workaround code for \n */ -+ if (dolc) -+ ret--; -+ /* get return address from current frame and jump to */ -+ global_env.iop->argp->afpos = ret; -+ global_env.iop->argp->afbuf->bufp = &(global_env.iop->argp->afbuf->buf[ret]); -+ } -+ /* -+ fprintf(stderr, "******** after execution ********************\n"); -+ fprintf(stderr, " %s \n############# %d\n", global_env.iop->argp->afbuf->bufp, ret); -+ fprintf(stderr, "*******************************\n"); -+ */ -+ /* we return to previous frame */ -+ cur_frame--; -+ /* free some space occupied by argument */ -+ while (dolc--) -+ free(dolv[dolc]); -+ free(dolv); -+ -+ /* recover argument for last function */ -+ dolv = frame[cur_frame].argv; -+ dolc = frame[cur_frame].argc; -+ /* If we are not in the outest frame, we should set -+ * func_finished to 0 that means we still in some function */ -+ if (cur_frame != 0) -+ func_finished = 0; -+} //funccode:end - - static int collect(int c, int c1) - { -@@ -2601,6 +2839,10 @@ static int execute(struct op *t, int *pi - execute(t->right->right, pin, pout, /* no_fork: */ 0); - } - break; -+ case TFUNC: //funccode:start -+ break; -+ case TRETURN: -+ break; //funccode:end - - case TCASE: - cp = evalstr(t->str, DOSUB | DOTRIM); |