version 1.32, 2020/12/01 10:48:03 |
version 1.33, 2021/08/18 10:15:08 |
|
|
TAILQ_ENTRY (cmd_parse_scope) entry; |
TAILQ_ENTRY (cmd_parse_scope) entry; |
}; |
}; |
|
|
|
enum cmd_parse_argument_type { |
|
CMD_PARSE_STRING, |
|
CMD_PARSE_COMMANDS |
|
}; |
|
|
|
struct cmd_parse_argument { |
|
enum cmd_parse_argument_type type; |
|
char *string; |
|
struct cmd_parse_commands *commands; |
|
|
|
TAILQ_ENTRY(cmd_parse_argument) entry; |
|
}; |
|
TAILQ_HEAD(cmd_parse_arguments, cmd_parse_argument); |
|
|
struct cmd_parse_command { |
struct cmd_parse_command { |
u_int line; |
u_int line; |
|
struct cmd_parse_arguments arguments; |
|
|
int argc; |
int argc; |
char **argv; |
char **argv; |
|
|
TAILQ_ENTRY(cmd_parse_command) entry; |
TAILQ_ENTRY(cmd_parse_command) entry; |
}; |
}; |
TAILQ_HEAD(cmd_parse_commands, cmd_parse_command); |
TAILQ_HEAD(cmd_parse_commands, cmd_parse_command); |
|
|
|
|
static char *cmd_parse_commands_to_string(struct cmd_parse_commands *); |
static char *cmd_parse_commands_to_string(struct cmd_parse_commands *); |
static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, |
static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, |
struct cmd_list *); |
struct cmd_list *); |
|
static void cmd_parse_flatten_command(struct cmd_parse_command *); |
|
|
%} |
%} |
|
|
%union |
%union |
{ |
{ |
char *token; |
char *token; |
struct { |
struct cmd_parse_arguments *arguments; |
int argc; |
struct cmd_parse_argument *argument; |
char **argv; |
|
} arguments; |
|
int flag; |
int flag; |
struct { |
struct { |
int flag; |
int flag; |
|
|
%token ENDIF |
%token ENDIF |
%token <token> FORMAT TOKEN EQUALS |
%token <token> FORMAT TOKEN EQUALS |
|
|
%type <token> argument expanded format |
%type <token> expanded format |
%type <arguments> arguments |
%type <arguments> arguments |
|
%type <argument> argument |
%type <flag> if_open if_elif |
%type <flag> if_open if_elif |
%type <elif> elif elif1 |
%type <elif> elif elif1 |
%type <commands> argument_statements statements statement |
%type <commands> argument_statements statements statement |
|
|
struct cmd_parse_state *ps = &parse_state; |
struct cmd_parse_state *ps = &parse_state; |
|
|
$$ = cmd_parse_new_commands(); |
$$ = cmd_parse_new_commands(); |
if ($1->argc != 0 && |
if (!TAILQ_EMPTY(&$1->arguments) && |
(ps->scope == NULL || ps->scope->flag)) |
(ps->scope == NULL || ps->scope->flag)) |
TAILQ_INSERT_TAIL($$, $1, entry); |
TAILQ_INSERT_TAIL($$, $1, entry); |
else |
else |
|
|
{ |
{ |
struct cmd_parse_state *ps = &parse_state; |
struct cmd_parse_state *ps = &parse_state; |
|
|
if ($3->argc != 0 && |
if (!TAILQ_EMPTY(&$3->arguments) && |
(ps->scope == NULL || ps->scope->flag)) { |
(ps->scope == NULL || ps->scope->flag)) { |
$$ = $1; |
$$ = $1; |
TAILQ_INSERT_TAIL($$, $3, entry); |
TAILQ_INSERT_TAIL($$, $3, entry); |
|
|
|
|
$$ = xcalloc(1, sizeof *$$); |
$$ = xcalloc(1, sizeof *$$); |
$$->line = ps->input->line; |
$$->line = ps->input->line; |
|
TAILQ_INIT(&$$->arguments); |
} |
} |
| optional_assignment TOKEN |
| optional_assignment TOKEN |
{ |
{ |
struct cmd_parse_state *ps = &parse_state; |
struct cmd_parse_state *ps = &parse_state; |
|
struct cmd_parse_argument *arg; |
|
|
$$ = xcalloc(1, sizeof *$$); |
$$ = xcalloc(1, sizeof *$$); |
$$->line = ps->input->line; |
$$->line = ps->input->line; |
|
TAILQ_INIT(&$$->arguments); |
|
|
cmd_prepend_argv(&$$->argc, &$$->argv, $2); |
arg = xcalloc(1, sizeof *arg); |
|
arg->type = CMD_PARSE_STRING; |
|
arg->string = xstrdup($2); |
|
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry); |
} |
} |
| optional_assignment TOKEN arguments |
| optional_assignment TOKEN arguments |
{ |
{ |
struct cmd_parse_state *ps = &parse_state; |
struct cmd_parse_state *ps = &parse_state; |
|
struct cmd_parse_argument *arg; |
|
|
$$ = xcalloc(1, sizeof *$$); |
$$ = xcalloc(1, sizeof *$$); |
$$->line = ps->input->line; |
$$->line = ps->input->line; |
|
TAILQ_INIT(&$$->arguments); |
|
|
$$->argc = $3.argc; |
TAILQ_CONCAT(&$$->arguments, $3, entry); |
$$->argv = $3.argv; |
free($3); |
cmd_prepend_argv(&$$->argc, &$$->argv, $2); |
|
|
arg = xcalloc(1, sizeof *arg); |
|
arg->type = CMD_PARSE_STRING; |
|
arg->string = xstrdup($2); |
|
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry); |
} |
} |
|
|
condition1 : if_open commands if_close |
condition1 : if_open commands if_close |
|
|
|
|
arguments : argument |
arguments : argument |
{ |
{ |
$$.argc = 1; |
$$ = xcalloc(1, sizeof *$$); |
$$.argv = xreallocarray(NULL, 1, sizeof *$$.argv); |
TAILQ_INIT($$); |
|
|
$$.argv[0] = $1; |
TAILQ_INSERT_HEAD($$, $1, entry); |
} |
} |
| argument arguments |
| argument arguments |
{ |
{ |
cmd_prepend_argv(&$2.argc, &$2.argv, $1); |
TAILQ_INSERT_HEAD($2, $1, entry); |
free($1); |
|
$$ = $2; |
$$ = $2; |
} |
} |
|
|
argument : TOKEN |
argument : TOKEN |
{ |
{ |
$$ = $1; |
$$ = xcalloc(1, sizeof *$$); |
|
$$->type = CMD_PARSE_STRING; |
|
$$->string = xstrdup($1); |
} |
} |
| EQUALS |
| EQUALS |
{ |
{ |
$$ = $1; |
$$ = xcalloc(1, sizeof *$$); |
|
$$->type = CMD_PARSE_STRING; |
|
$$->string = xstrdup($1); |
} |
} |
| '{' argument_statements |
| '{' argument_statements |
{ |
{ |
$$ = cmd_parse_commands_to_string($2); |
$$ = xcalloc(1, sizeof *$$); |
cmd_parse_free_commands($2); |
$$->type = CMD_PARSE_COMMANDS; |
|
$$->commands = $2; |
} |
} |
|
|
argument_statements : statement '}' |
argument_statements : statement '}' |
|
|
} |
} |
|
|
static void |
static void |
|
cmd_parse_free_arguments(struct cmd_parse_arguments *args) |
|
{ |
|
struct cmd_parse_argument *arg, *arg1; |
|
|
|
TAILQ_FOREACH_SAFE(arg, args, entry, arg1) { |
|
switch (arg->type) { |
|
case CMD_PARSE_STRING: |
|
free(arg->string); |
|
break; |
|
case CMD_PARSE_COMMANDS: |
|
cmd_parse_free_commands(arg->commands); |
|
break; |
|
} |
|
TAILQ_REMOVE(args, arg, entry); |
|
free(arg); |
|
} |
|
} |
|
|
|
static void |
cmd_parse_free_command(struct cmd_parse_command *cmd) |
cmd_parse_free_command(struct cmd_parse_command *cmd) |
{ |
{ |
cmd_free_argv(cmd->argc, cmd->argv); |
cmd_free_argv(cmd->argc, cmd->argv); |
|
cmd_parse_free_arguments(&cmd->arguments); |
free(cmd); |
free(cmd); |
} |
} |
|
|
|
|
struct cmd_parse_commands *cmds; |
struct cmd_parse_commands *cmds; |
|
|
cmds = xmalloc(sizeof *cmds); |
cmds = xmalloc(sizeof *cmds); |
TAILQ_INIT (cmds); |
TAILQ_INIT(cmds); |
return (cmds); |
return (cmds); |
} |
} |
|
|
|
|
free(cmds); |
free(cmds); |
} |
} |
|
|
static char * |
|
cmd_parse_commands_to_string(struct cmd_parse_commands *cmds) |
|
{ |
|
struct cmd_parse_command *cmd; |
|
char *string = NULL, *s, *line; |
|
|
|
TAILQ_FOREACH(cmd, cmds, entry) { |
|
line = cmd_stringify_argv(cmd->argc, cmd->argv); |
|
if (string == NULL) |
|
s = line; |
|
else { |
|
xasprintf(&s, "%s ; %s", s, line); |
|
free(line); |
|
} |
|
|
|
free(string); |
|
string = s; |
|
} |
|
if (string == NULL) |
|
string = xstrdup(""); |
|
log_debug("%s: %s", __func__, string); |
|
return (string); |
|
} |
|
|
|
static struct cmd_parse_commands * |
static struct cmd_parse_commands * |
cmd_parse_run_parser(char **cause) |
cmd_parse_run_parser(char **cause) |
{ |
{ |
|
|
return (cmd_parse_run_parser(cause)); |
return (cmd_parse_run_parser(cause)); |
} |
} |
|
|
|
static void |
|
cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix) |
|
{ |
|
struct cmd_parse_command *cmd; |
|
struct cmd_parse_argument *arg; |
|
u_int i, j; |
|
char *s; |
|
|
|
i = 0; |
|
TAILQ_FOREACH(cmd, cmds, entry) { |
|
j = 0; |
|
TAILQ_FOREACH(arg, &cmd->arguments, entry) { |
|
switch (arg->type) { |
|
case CMD_PARSE_STRING: |
|
log_debug("%s %u:%u: %s", prefix, i, j, |
|
arg->string); |
|
break; |
|
case CMD_PARSE_COMMANDS: |
|
xasprintf(&s, "%s %u:%u", prefix, i, j); |
|
cmd_parse_log_commands(arg->commands, s); |
|
free(s); |
|
break; |
|
} |
|
j++; |
|
} |
|
i++; |
|
} |
|
} |
|
|
|
static char * |
|
cmd_parse_commands_to_string(struct cmd_parse_commands *cmds) |
|
{ |
|
struct cmd_parse_command *cmd; |
|
char *string = NULL, *s, *line; |
|
|
|
TAILQ_FOREACH(cmd, cmds, entry) { |
|
cmd_parse_flatten_command(cmd); |
|
|
|
line = cmd_stringify_argv(cmd->argc, cmd->argv); |
|
if (string == NULL) |
|
s = line; |
|
else { |
|
xasprintf(&s, "%s ; %s", s, line); |
|
free(line); |
|
} |
|
|
|
free(string); |
|
string = s; |
|
} |
|
if (string == NULL) |
|
string = xstrdup(""); |
|
log_debug("%s: %s", __func__, string); |
|
return (string); |
|
} |
|
|
|
static void |
|
cmd_parse_flatten_command(struct cmd_parse_command *cmd) |
|
{ |
|
struct cmd_parse_argument *arg; |
|
char *s; |
|
|
|
cmd->argc = 0; |
|
cmd->argv = NULL; |
|
|
|
TAILQ_FOREACH(arg, &cmd->arguments, entry) { |
|
switch (arg->type) { |
|
case CMD_PARSE_STRING: |
|
cmd_append_argv(&cmd->argc, &cmd->argv, arg->string); |
|
break; |
|
case CMD_PARSE_COMMANDS: |
|
s = cmd_parse_commands_to_string(arg->commands); |
|
cmd_append_argv(&cmd->argc, &cmd->argv, s); |
|
free(s); |
|
break; |
|
} |
|
} |
|
} |
|
|
static struct cmd_parse_result * |
static struct cmd_parse_result * |
cmd_parse_build_commands(struct cmd_parse_commands *cmds, |
cmd_parse_build_commands(struct cmd_parse_commands *cmds, |
struct cmd_parse_input *pi) |
struct cmd_parse_input *pi) |
|
|
return (&pr); |
return (&pr); |
} |
} |
|
|
|
/* Flatten command arguments. */ |
|
cmd_parse_log_commands(cmds, __func__); |
|
TAILQ_FOREACH(cmd, cmds, entry) |
|
cmd_parse_flatten_command(cmd); |
|
|
/* |
/* |
* Walk the commands and expand any aliases. Each alias is parsed |
* Walk the commands and expand any aliases. Each alias is parsed |
* individually to a new command list, any trailing arguments appended |
* individually to a new command list, any trailing arguments appended |
|
|
return (cmd_parse_build_commands(cmds, pi)); |
return (cmd_parse_build_commands(cmds, pi)); |
} |
} |
|
|
|
static void |
|
cmd_parse_add_command(struct cmd_parse_commands *cmds, |
|
struct cmd_parse_input *pi, int argc, char **argv) |
|
{ |
|
struct cmd_parse_command *cmd; |
|
struct cmd_parse_argument *arg; |
|
int i; |
|
|
|
cmd_log_argv(argc, argv, "%s", __func__); |
|
|
|
cmd = xcalloc(1, sizeof *cmd); |
|
cmd->line = pi->line; |
|
|
|
TAILQ_INIT(&cmd->arguments); |
|
for (i = 0; i < argc; i++) { |
|
arg = xcalloc(1, sizeof *arg); |
|
arg->type = CMD_PARSE_STRING; |
|
arg->string = xstrdup(argv[i]); |
|
TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry); |
|
} |
|
|
|
TAILQ_INSERT_TAIL(cmds, cmd, entry); |
|
} |
|
|
struct cmd_parse_result * |
struct cmd_parse_result * |
cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) |
cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi) |
{ |
{ |
struct cmd_parse_input input; |
struct cmd_parse_input input; |
struct cmd_parse_commands *cmds; |
struct cmd_parse_commands *cmds; |
struct cmd_parse_command *cmd; |
|
char **copy, **new_argv; |
char **copy, **new_argv; |
size_t size; |
size_t size; |
int i, last, new_argc; |
int i, last, new_argc; |
|
|
if (size != 0) |
if (size != 0) |
new_argc++; |
new_argc++; |
|
|
if (new_argc != 0) { |
if (new_argc != 0) |
cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__, |
cmd_parse_add_command(cmds, pi, new_argc, new_argv); |
i); |
|
|
|
cmd = xcalloc(1, sizeof *cmd); |
|
cmd->line = pi->line; |
|
|
|
cmd->argc = new_argc; |
|
cmd->argv = cmd_copy_argv(new_argc, new_argv); |
|
|
|
TAILQ_INSERT_TAIL(cmds, cmd, entry); |
|
} |
|
|
|
last = i + 1; |
last = i + 1; |
} |
} |
if (last != argc) { |
if (last != argc) { |
new_argv = copy + last; |
new_argv = copy + last; |
new_argc = argc - last; |
new_argc = argc - last; |
|
|
if (new_argc != 0) { |
if (new_argc != 0) |
cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__, |
cmd_parse_add_command(cmds, pi, new_argc, new_argv); |
last); |
|
|
|
cmd = xcalloc(1, sizeof *cmd); |
|
cmd->line = pi->line; |
|
|
|
cmd->argc = new_argc; |
|
cmd->argv = cmd_copy_argv(new_argc, new_argv); |
|
|
|
TAILQ_INSERT_TAIL(cmds, cmd, entry); |
|
} |
|
} |
} |
|
|
cmd_free_argv(argc, copy); |
cmd_free_argv(argc, copy); |