hush: ifdef out parts which are not needed
if neither loops nor ifs are supported. Code savings: function old new delta parse_stream 1758 1757 -1 checkjobs 335 318 -17 done_pipe 74 52 -22 expand_variables 1437 1407 -30 run_list 1232 1189 -43 parse_and_run_stream 328 267 -61 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/6 up/down: 0/-174) Total: -174 bytes
This commit is contained in:
parent
003f9fb213
commit
5ec6132c98
105
shell/hush.c
105
shell/hush.c
@ -150,9 +150,6 @@
|
|||||||
#define debug_printf_subst(...) fprintf(stderr, __VA_ARGS__)
|
#define debug_printf_subst(...) fprintf(stderr, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Keep unconditionally on for now */
|
|
||||||
#define ENABLE_HUSH_DEBUG 1
|
|
||||||
|
|
||||||
#ifndef debug_printf_clean
|
#ifndef debug_printf_clean
|
||||||
/* broken, of course, but OK for testing */
|
/* broken, of course, but OK for testing */
|
||||||
static const char *indenter(int i)
|
static const char *indenter(int i)
|
||||||
@ -176,7 +173,6 @@ static void debug_print_strings(const char *prefix, char **vv)
|
|||||||
#define debug_print_strings(prefix, vv) ((void)0)
|
#define debug_print_strings(prefix, vv) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Leak hunting. Use hush_leaktool.sh for post-processing.
|
* Leak hunting. Use hush_leaktool.sh for post-processing.
|
||||||
*/
|
*/
|
||||||
@ -216,6 +212,20 @@ void xxfree(void *ptr)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Keep unconditionally on for now */
|
||||||
|
#define HUSH_DEBUG 1
|
||||||
|
/* Do we support ANY keywords? */
|
||||||
|
#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS
|
||||||
|
#define HAS_KEYWORDS 1
|
||||||
|
#define IF_HAS_KEYWORDS(...) __VA_ARGS__
|
||||||
|
#define IF_HAS_NO_KEYWORDS(...)
|
||||||
|
#else
|
||||||
|
#define HAS_KEYWORDS 0
|
||||||
|
#define IF_HAS_KEYWORDS(...)
|
||||||
|
#define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define SPECIAL_VAR_SYMBOL 3
|
#define SPECIAL_VAR_SYMBOL 3
|
||||||
#define PARSEFLAG_EXIT_FROM_LOOP 1
|
#define PARSEFLAG_EXIT_FROM_LOOP 1
|
||||||
|
|
||||||
@ -276,18 +286,20 @@ struct p_context {
|
|||||||
struct pipe *list_head;
|
struct pipe *list_head;
|
||||||
struct pipe *pipe;
|
struct pipe *pipe;
|
||||||
struct redir_struct *pending_redirect;
|
struct redir_struct *pending_redirect;
|
||||||
smallint res_w;
|
#if HAS_KEYWORDS
|
||||||
smallint ctx_inverted; /* "! cmd | cmd" */
|
smallint ctx_res_w;
|
||||||
int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */
|
smallint ctx_inverted; /* "! cmd | cmd" */
|
||||||
|
int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */
|
||||||
struct p_context *stack;
|
struct p_context *stack;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct redir_struct {
|
struct redir_struct {
|
||||||
struct redir_struct *next;
|
struct redir_struct *next;
|
||||||
smallint /*redir_type*/ rd_type;
|
char *rd_filename; /* filename */
|
||||||
int fd; /* file descriptor being redirected */
|
int fd; /* file descriptor being redirected */
|
||||||
int dup; /* -1, or file descriptor being duplicated */
|
int dup; /* -1, or file descriptor being duplicated */
|
||||||
char *rd_filename; /* filename */
|
smallint /*enum redir_type*/ rd_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct child_prog {
|
struct child_prog {
|
||||||
@ -317,9 +329,9 @@ struct pipe {
|
|||||||
char *cmdtext; /* name of job */
|
char *cmdtext; /* name of job */
|
||||||
#endif
|
#endif
|
||||||
struct child_prog *progs; /* array of commands in pipe */
|
struct child_prog *progs; /* array of commands in pipe */
|
||||||
smallint pi_inverted; /* "! cmd | cmd" */
|
|
||||||
smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
|
smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
|
||||||
smallint res_word; /* needed for if, for, while, until... */
|
IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
|
||||||
|
IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* On program start, environ points to initial environment.
|
/* On program start, environ points to initial environment.
|
||||||
@ -1629,8 +1641,7 @@ static int checkjobs(struct pipe* fg_pipe)
|
|||||||
if (i == fg_pipe->num_progs - 1) {
|
if (i == fg_pipe->num_progs - 1) {
|
||||||
/* last process gives overall exitstatus */
|
/* last process gives overall exitstatus */
|
||||||
rcode = WEXITSTATUS(status);
|
rcode = WEXITSTATUS(status);
|
||||||
if (fg_pipe->pi_inverted)
|
IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;)
|
||||||
rcode = !rcode;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fg_pipe->progs[i].is_stopped = 1;
|
fg_pipe->progs[i].is_stopped = 1;
|
||||||
@ -1757,8 +1768,7 @@ static int run_pipe(struct pipe *pi)
|
|||||||
rcode = run_list(child->group) & 0xff;
|
rcode = run_list(child->group) & 0xff;
|
||||||
restore_redirects(squirrel);
|
restore_redirects(squirrel);
|
||||||
debug_printf_exec("run_pipe return %d\n", rcode);
|
debug_printf_exec("run_pipe return %d\n", rcode);
|
||||||
if (pi->pi_inverted)
|
IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
|
||||||
rcode = !rcode;
|
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1801,8 +1811,7 @@ static int run_pipe(struct pipe *pi)
|
|||||||
free(argv_expanded);
|
free(argv_expanded);
|
||||||
restore_redirects(squirrel);
|
restore_redirects(squirrel);
|
||||||
debug_printf_exec("run_pipe return %d\n", rcode);
|
debug_printf_exec("run_pipe return %d\n", rcode);
|
||||||
if (pi->pi_inverted)
|
IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
|
||||||
rcode = !rcode;
|
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1819,8 +1828,7 @@ static int run_pipe(struct pipe *pi)
|
|||||||
free(argv_expanded);
|
free(argv_expanded);
|
||||||
restore_redirects(squirrel);
|
restore_redirects(squirrel);
|
||||||
debug_printf_exec("run_pipe return %d\n", rcode);
|
debug_printf_exec("run_pipe return %d\n", rcode);
|
||||||
if (pi->pi_inverted)
|
IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
|
||||||
rcode = !rcode;
|
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2003,8 +2011,7 @@ static int run_list(struct pipe *pi)
|
|||||||
#else
|
#else
|
||||||
enum { if_code = 0, next_if_code = 0 };
|
enum { if_code = 0, next_if_code = 0 };
|
||||||
#endif
|
#endif
|
||||||
// TODO: rword and ->res_word are not needed if !LOOPS and !IF
|
reserved_style rword IF_HAS_NO_KEYWORDS(= RES_NONE);
|
||||||
reserved_style rword;
|
|
||||||
reserved_style skip_more_for_this_rword = RES_XXXX;
|
reserved_style skip_more_for_this_rword = RES_XXXX;
|
||||||
|
|
||||||
debug_printf_exec("run_list start lvl %d\n", run_list_level + 1);
|
debug_printf_exec("run_list start lvl %d\n", run_list_level + 1);
|
||||||
@ -2075,7 +2082,8 @@ static int run_list(struct pipe *pi)
|
|||||||
#endif /* JOB */
|
#endif /* JOB */
|
||||||
|
|
||||||
for (; pi; pi = flag_restore ? rpipe : pi->next) {
|
for (; pi; pi = flag_restore ? rpipe : pi->next) {
|
||||||
rword = pi->res_word;
|
IF_HAS_KEYWORDS(rword = pi->res_word;)
|
||||||
|
IF_HAS_NO_KEYWORDS(rword = RES_NONE;)
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) {
|
if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) {
|
||||||
flag_restore = 0;
|
flag_restore = 0;
|
||||||
@ -2272,7 +2280,9 @@ static int free_pipe_list(struct pipe *head, int indent)
|
|||||||
struct pipe *pi, *next;
|
struct pipe *pi, *next;
|
||||||
|
|
||||||
for (pi = head; pi; pi = next) {
|
for (pi = head; pi; pi = next) {
|
||||||
|
#if HAS_KEYWORDS
|
||||||
debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word);
|
debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word);
|
||||||
|
#endif
|
||||||
rcode = free_pipe(pi, indent);
|
rcode = free_pipe(pi, indent);
|
||||||
debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup);
|
debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup);
|
||||||
next = pi->next;
|
next = pi->next;
|
||||||
@ -2548,7 +2558,7 @@ static char *expand_string_to_string(const char *str)
|
|||||||
argv[0] = (char*)str;
|
argv[0] = (char*)str;
|
||||||
argv[1] = NULL;
|
argv[1] = NULL;
|
||||||
list = expand_variables(argv, 0x80); /* 0x80: make one-element expansion */
|
list = expand_variables(argv, 0x80); /* 0x80: make one-element expansion */
|
||||||
if (ENABLE_HUSH_DEBUG)
|
if (HUSH_DEBUG)
|
||||||
if (!list[0] || list[1])
|
if (!list[0] || list[1])
|
||||||
bb_error_msg_and_die("BUG in varexp2");
|
bb_error_msg_and_die("BUG in varexp2");
|
||||||
/* actually, just move string 2*sizeof(char*) bytes back */
|
/* actually, just move string 2*sizeof(char*) bytes back */
|
||||||
@ -2567,7 +2577,7 @@ static char* expand_strvec_to_string(char **argv)
|
|||||||
if (list[0]) {
|
if (list[0]) {
|
||||||
int n = 1;
|
int n = 1;
|
||||||
while (list[n]) {
|
while (list[n]) {
|
||||||
if (ENABLE_HUSH_DEBUG)
|
if (HUSH_DEBUG)
|
||||||
if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
|
if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
|
||||||
bb_error_msg_and_die("BUG in varexp3");
|
bb_error_msg_and_die("BUG in varexp3");
|
||||||
list[n][-1] = ' '; /* TODO: or to ifs[0]? */
|
list[n][-1] = ' '; /* TODO: or to ifs[0]? */
|
||||||
@ -2747,8 +2757,7 @@ static struct pipe *new_pipe(void)
|
|||||||
struct pipe *pi;
|
struct pipe *pi;
|
||||||
pi = xzalloc(sizeof(struct pipe));
|
pi = xzalloc(sizeof(struct pipe));
|
||||||
/*pi->followup = 0; - deliberately invalid value */
|
/*pi->followup = 0; - deliberately invalid value */
|
||||||
if (RES_NONE)
|
/*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
|
||||||
pi->res_word = RES_NONE;
|
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2769,7 +2778,7 @@ static void initialize_context(struct p_context *ctx)
|
|||||||
* Handles if, then, elif, else, fi, for, while, until, do, done.
|
* Handles if, then, elif, else, fi, for, while, until, do, done.
|
||||||
* case, function, and select are obnoxious, save those for later.
|
* case, function, and select are obnoxious, save those for later.
|
||||||
*/
|
*/
|
||||||
#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS
|
#if HAS_KEYWORDS
|
||||||
static int reserved_word(const o_string *word, struct p_context *ctx)
|
static int reserved_word(const o_string *word, struct p_context *ctx)
|
||||||
{
|
{
|
||||||
struct reserved_combo {
|
struct reserved_combo {
|
||||||
@ -2828,18 +2837,18 @@ static int reserved_word(const o_string *word, struct p_context *ctx)
|
|||||||
debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
|
debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
|
||||||
if (r->flag == 0) { /* '!' */
|
if (r->flag == 0) { /* '!' */
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
if (ctx->res_w == RES_IN) {
|
if (ctx->ctx_res_w == RES_IN) {
|
||||||
/* 'for a in ! a b c; ...' - ! isn't a keyword here */
|
/* 'for a in ! a b c; ...' - ! isn't a keyword here */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ctx->ctx_inverted /* bash doesn't accept '! ! true' */
|
if (ctx->ctx_inverted /* bash doesn't accept '! ! true' */
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
|| ctx->res_w == RES_FOR /* example: 'for ! a' */
|
|| ctx->ctx_res_w == RES_FOR /* example: 'for ! a' */
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
syntax(NULL);
|
syntax(NULL);
|
||||||
ctx->res_w = RES_SNTX;
|
IF_HAS_KEYWORDS(ctx->ctx_res_w = RES_SNTX;)
|
||||||
}
|
}
|
||||||
ctx->ctx_inverted = 1;
|
ctx->ctx_inverted = 1;
|
||||||
return 1;
|
return 1;
|
||||||
@ -2848,9 +2857,9 @@ static int reserved_word(const o_string *word, struct p_context *ctx)
|
|||||||
struct p_context *new;
|
struct p_context *new;
|
||||||
debug_printf("push stack\n");
|
debug_printf("push stack\n");
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
|
if (ctx->ctx_res_w == RES_IN || ctx->ctx_res_w == RES_FOR) {
|
||||||
syntax("malformed for"); /* example: 'for if' */
|
syntax("malformed for"); /* example: 'for if' */
|
||||||
ctx->res_w = RES_SNTX;
|
ctx->ctx_res_w = RES_SNTX;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2858,12 +2867,12 @@ static int reserved_word(const o_string *word, struct p_context *ctx)
|
|||||||
*new = *ctx; /* physical copy */
|
*new = *ctx; /* physical copy */
|
||||||
initialize_context(ctx);
|
initialize_context(ctx);
|
||||||
ctx->stack = new;
|
ctx->stack = new;
|
||||||
} else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->res))) {
|
} else if (ctx->ctx_res_w == RES_NONE || !(ctx->old_flag & (1 << r->res))) {
|
||||||
syntax(NULL);
|
syntax(NULL);
|
||||||
ctx->res_w = RES_SNTX;
|
ctx->ctx_res_w = RES_SNTX;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ctx->res_w = r->res;
|
ctx->ctx_res_w = r->res;
|
||||||
ctx->old_flag = r->flag;
|
ctx->old_flag = r->flag;
|
||||||
if (ctx->old_flag & FLAG_END) {
|
if (ctx->old_flag & FLAG_END) {
|
||||||
struct p_context *old;
|
struct p_context *old;
|
||||||
@ -2879,8 +2888,6 @@ static int reserved_word(const o_string *word, struct p_context *ctx)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define reserved_word(word, ctx) ((int)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Word is complete, look at it and update parsing context.
|
/* Word is complete, look at it and update parsing context.
|
||||||
@ -2914,15 +2921,17 @@ static int done_word(o_string *word, struct p_context *ctx)
|
|||||||
debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
|
debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#if HAS_KEYWORDS
|
||||||
if (!child->argv) { /* if it's the first word... */
|
if (!child->argv) { /* if it's the first word... */
|
||||||
debug_printf_parse(": checking '%s' for reserved-ness\n", word->data);
|
debug_printf_parse(": checking '%s' for reserved-ness\n", word->data);
|
||||||
if (reserved_word(word, ctx)) {
|
if (reserved_word(word, ctx)) {
|
||||||
o_reset(word);
|
o_reset(word);
|
||||||
word->o_assignment = NOT_ASSIGNMENT;
|
word->o_assignment = NOT_ASSIGNMENT;
|
||||||
debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX));
|
debug_printf_parse("done_word return %d\n", (ctx->ctx_res_w == RES_SNTX));
|
||||||
return (ctx->res_w == RES_SNTX);
|
return (ctx->ctx_res_w == RES_SNTX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (word->nonnull /* we saw "xx" or 'xx' */
|
if (word->nonnull /* we saw "xx" or 'xx' */
|
||||||
/* optimization: and if it's ("" or '') or ($v... or `cmd`...): */
|
/* optimization: and if it's ("" or '') or ($v... or `cmd`...): */
|
||||||
&& (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL)
|
&& (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL)
|
||||||
@ -2942,7 +2951,7 @@ static int done_word(o_string *word, struct p_context *ctx)
|
|||||||
|
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
/* Force FOR to have just one word (variable name) */
|
/* Force FOR to have just one word (variable name) */
|
||||||
if (ctx->res_w == RES_FOR)
|
if (ctx->ctx_res_w == RES_FOR)
|
||||||
done_pipe(ctx, PIPE_SEQ);
|
done_pipe(ctx, PIPE_SEQ);
|
||||||
#endif
|
#endif
|
||||||
debug_printf_parse("done_word return 0\n");
|
debug_printf_parse("done_word return 0\n");
|
||||||
@ -2993,9 +3002,9 @@ static void done_pipe(struct p_context *ctx, pipe_style type)
|
|||||||
debug_printf_parse("done_pipe entered, followup %d\n", type);
|
debug_printf_parse("done_pipe entered, followup %d\n", type);
|
||||||
not_null = done_command(ctx); /* implicit closure of previous command */
|
not_null = done_command(ctx); /* implicit closure of previous command */
|
||||||
ctx->pipe->followup = type;
|
ctx->pipe->followup = type;
|
||||||
ctx->pipe->res_word = ctx->res_w;
|
IF_HAS_KEYWORDS(ctx->pipe->res_word = ctx->ctx_res_w;)
|
||||||
ctx->pipe->pi_inverted = ctx->ctx_inverted;
|
IF_HAS_KEYWORDS(ctx->pipe->pi_inverted = ctx->ctx_inverted;)
|
||||||
ctx->ctx_inverted = 0;
|
IF_HAS_KEYWORDS(ctx->ctx_inverted = 0;)
|
||||||
/* Without this check, even just <enter> on command line generates
|
/* Without this check, even just <enter> on command line generates
|
||||||
* tree of three NOPs (!). Which is harmless but annoying.
|
* tree of three NOPs (!). Which is harmless but annoying.
|
||||||
* IOW: it is safe to do it unconditionally.
|
* IOW: it is safe to do it unconditionally.
|
||||||
@ -3480,7 +3489,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
//err chk?
|
//err chk?
|
||||||
done_pipe(ctx, PIPE_SEQ);
|
done_pipe(ctx, PIPE_SEQ);
|
||||||
}
|
}
|
||||||
if (ctx->res_w == RES_NONE) {
|
if (!HAS_KEYWORDS IF_HAS_KEYWORDS(|| ctx->ctx_res_w == RES_NONE)) {
|
||||||
debug_printf_parse("parse_stream return 0: end_trigger char found\n");
|
debug_printf_parse("parse_stream return 0: end_trigger char found\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3650,7 +3659,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
debug_printf_parse("parse_stream return 1: unexpected '}'\n");
|
debug_printf_parse("parse_stream return 1: unexpected '}'\n");
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
if (ENABLE_HUSH_DEBUG)
|
if (HUSH_DEBUG)
|
||||||
bb_error_msg_and_die("BUG: unexpected %c\n", ch);
|
bb_error_msg_and_die("BUG: unexpected %c\n", ch);
|
||||||
}
|
}
|
||||||
} /* while (1) */
|
} /* while (1) */
|
||||||
@ -3706,10 +3715,12 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
|
|||||||
* Example: "sleep 9999; echo TEST" + ctrl-C:
|
* Example: "sleep 9999; echo TEST" + ctrl-C:
|
||||||
* TEST should be printed */
|
* TEST should be printed */
|
||||||
rcode = parse_stream(&temp, &ctx, inp, ";\n");
|
rcode = parse_stream(&temp, &ctx, inp, ";\n");
|
||||||
|
#if HAS_KEYWORDS
|
||||||
if (rcode != 1 && ctx.old_flag != 0) {
|
if (rcode != 1 && ctx.old_flag != 0) {
|
||||||
syntax(NULL);
|
syntax(NULL);
|
||||||
}
|
}
|
||||||
if (rcode != 1 && ctx.old_flag == 0) {
|
#endif
|
||||||
|
if (rcode != 1 IF_HAS_KEYWORDS(&& ctx.old_flag == 0)) {
|
||||||
done_word(&temp, &ctx);
|
done_word(&temp, &ctx);
|
||||||
done_pipe(&ctx, PIPE_SEQ);
|
done_pipe(&ctx, PIPE_SEQ);
|
||||||
debug_print_tree(ctx.list_head, 0);
|
debug_print_tree(ctx.list_head, 0);
|
||||||
@ -3717,10 +3728,12 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
|
|||||||
run_and_free_list(ctx.list_head);
|
run_and_free_list(ctx.list_head);
|
||||||
} else {
|
} else {
|
||||||
/* We arrive here also if rcode == 1 (error in parse_stream) */
|
/* We arrive here also if rcode == 1 (error in parse_stream) */
|
||||||
|
#if HAS_KEYWORDS
|
||||||
if (ctx.old_flag != 0) {
|
if (ctx.old_flag != 0) {
|
||||||
free(ctx.stack);
|
free(ctx.stack);
|
||||||
o_reset(&temp);
|
o_reset(&temp);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/*temp.nonnull = 0; - o_free does it below */
|
/*temp.nonnull = 0; - o_free does it below */
|
||||||
/*temp.o_quote = 0; - o_free does it below */
|
/*temp.o_quote = 0; - o_free does it below */
|
||||||
free_pipe_list(ctx.list_head, /* indent: */ 0);
|
free_pipe_list(ctx.list_head, /* indent: */ 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user