mirror of
https://github.com/tmux/tmux.git
synced 2026-10-11 21:14:21 +00:00
Track allocations in yacc to avoid leaking when parsing commands, GitHub
issue 5632 from Jeong, Heon.
This commit is contained in:
318
cmd-parse.y
318
cmd-parse.y
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-parse.y,v 1.62 2026/10/08 06:29:32 nicm Exp $ */
|
/* $OpenBSD: cmd-parse.y,v 1.63 2026/10/08 06:44:16 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -69,6 +69,22 @@ struct cmd_parse_command {
|
|||||||
};
|
};
|
||||||
TAILQ_HEAD(cmd_parse_commands, cmd_parse_command);
|
TAILQ_HEAD(cmd_parse_commands, cmd_parse_command);
|
||||||
|
|
||||||
|
enum cmd_parse_value_type {
|
||||||
|
CMD_PARSE_VALUE_STRING,
|
||||||
|
CMD_PARSE_VALUE_ARGUMENT,
|
||||||
|
CMD_PARSE_VALUE_ARGUMENTS,
|
||||||
|
CMD_PARSE_VALUE_COMMAND,
|
||||||
|
CMD_PARSE_VALUE_COMMANDS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmd_parse_owned_value {
|
||||||
|
enum cmd_parse_value_type type;
|
||||||
|
void *value;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(cmd_parse_owned_value) entry;
|
||||||
|
};
|
||||||
|
TAILQ_HEAD(cmd_parse_owned_values, cmd_parse_owned_value);
|
||||||
|
|
||||||
struct cmd_parse_state {
|
struct cmd_parse_state {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
@@ -87,10 +103,16 @@ struct cmd_parse_state {
|
|||||||
|
|
||||||
struct cmd_parse_scope *scope;
|
struct cmd_parse_scope *scope;
|
||||||
TAILQ_HEAD(, cmd_parse_scope) stack;
|
TAILQ_HEAD(, cmd_parse_scope) stack;
|
||||||
|
|
||||||
|
struct cmd_parse_owned_values values;
|
||||||
};
|
};
|
||||||
static struct cmd_parse_state parse_state;
|
static struct cmd_parse_state parse_state;
|
||||||
|
|
||||||
static char *cmd_parse_get_error(const char *, u_int, const char *);
|
static char *cmd_parse_get_error(const char *, u_int, const char *);
|
||||||
|
static void *cmd_parse_own(enum cmd_parse_value_type, void *);
|
||||||
|
static struct cmd_parse_commands *cmd_parse_own_commands(void);
|
||||||
|
static void *cmd_parse_take(void *);
|
||||||
|
static void cmd_parse_drop(void *);
|
||||||
static void cmd_parse_free_command(struct cmd_parse_command *);
|
static void cmd_parse_free_command(struct cmd_parse_command *);
|
||||||
static struct cmd_parse_commands *cmd_parse_new_commands(void);
|
static struct cmd_parse_commands *cmd_parse_new_commands(void);
|
||||||
static void cmd_parse_free_commands(struct cmd_parse_commands *);
|
static void cmd_parse_free_commands(struct cmd_parse_commands *);
|
||||||
@@ -139,7 +161,7 @@ lines : /* empty */
|
|||||||
{
|
{
|
||||||
struct cmd_parse_state *ps = &parse_state;
|
struct cmd_parse_state *ps = &parse_state;
|
||||||
|
|
||||||
ps->commands = $1;
|
ps->commands = cmd_parse_take($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
statements : statement '\n'
|
statements : statement '\n'
|
||||||
@@ -150,18 +172,16 @@ statements : statement '\n'
|
|||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
TAILQ_CONCAT($$, $2, entry);
|
TAILQ_CONCAT($$, $2, entry);
|
||||||
free($2);
|
cmd_parse_drop($2);
|
||||||
}
|
}
|
||||||
|
|
||||||
statement : /* empty */
|
statement : /* empty */
|
||||||
{
|
{
|
||||||
$$ = xmalloc (sizeof *$$);
|
$$ = cmd_parse_own_commands();
|
||||||
TAILQ_INIT($$);
|
|
||||||
}
|
}
|
||||||
| hidden_assignment
|
| hidden_assignment
|
||||||
{
|
{
|
||||||
$$ = xmalloc (sizeof *$$);
|
$$ = cmd_parse_own_commands();
|
||||||
TAILQ_INIT($$);
|
|
||||||
}
|
}
|
||||||
| condition
|
| condition
|
||||||
{
|
{
|
||||||
@@ -170,8 +190,8 @@ statement : /* empty */
|
|||||||
if (ps->scope == NULL || ps->scope->flag)
|
if (ps->scope == NULL || ps->scope->flag)
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
else {
|
else {
|
||||||
$$ = cmd_parse_new_commands();
|
$$ = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($1);
|
cmd_parse_drop($1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| commands
|
| commands
|
||||||
@@ -181,8 +201,8 @@ statement : /* empty */
|
|||||||
if (ps->scope == NULL || ps->scope->flag)
|
if (ps->scope == NULL || ps->scope->flag)
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
else {
|
else {
|
||||||
$$ = cmd_parse_new_commands();
|
$$ = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($1);
|
cmd_parse_drop($1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +224,7 @@ expanded : format
|
|||||||
struct cmd_find_state *fsp;
|
struct cmd_find_state *fsp;
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
int flags = FORMAT_NOJOBS;
|
int flags = FORMAT_NOJOBS;
|
||||||
|
char *expanded;
|
||||||
|
|
||||||
if (cmd_find_valid_state(&pi->fs))
|
if (cmd_find_valid_state(&pi->fs))
|
||||||
fsp = &pi->fs;
|
fsp = &pi->fs;
|
||||||
@@ -214,9 +235,10 @@ expanded : format
|
|||||||
ft = format_create(c, pi->item, FORMAT_NONE, flags);
|
ft = format_create(c, pi->item, FORMAT_NONE, flags);
|
||||||
format_defaults(ft, c, fsp->s, fsp->wl, fsp->wp);
|
format_defaults(ft, c, fsp->s, fsp->wl, fsp->wp);
|
||||||
|
|
||||||
$$ = format_expand(ft, $1);
|
expanded = format_expand(ft, $1);
|
||||||
|
$$ = cmd_parse_own(CMD_PARSE_VALUE_STRING, expanded);
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
free($1);
|
cmd_parse_drop($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional_assignment : /* empty */
|
optional_assignment : /* empty */
|
||||||
@@ -241,7 +263,7 @@ assignment : EQUALS
|
|||||||
}
|
}
|
||||||
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
|
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
|
||||||
environ_put(global_environ, $1, 0);
|
environ_put(global_environ, $1, 0);
|
||||||
free($1);
|
cmd_parse_drop($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
hidden_assignment : HIDDEN EQUALS
|
hidden_assignment : HIDDEN EQUALS
|
||||||
@@ -263,7 +285,7 @@ hidden_assignment : HIDDEN EQUALS
|
|||||||
}
|
}
|
||||||
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
|
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
|
||||||
environ_put(global_environ, $2, ENVIRON_HIDDEN);
|
environ_put(global_environ, $2, ENVIRON_HIDDEN);
|
||||||
free($2);
|
cmd_parse_drop($2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if_open : IF expanded
|
if_open : IF expanded
|
||||||
@@ -274,7 +296,7 @@ if_open : IF expanded
|
|||||||
scope = xmalloc(sizeof *scope);
|
scope = xmalloc(sizeof *scope);
|
||||||
$$ = scope->flag = format_true($2);
|
$$ = scope->flag = format_true($2);
|
||||||
scope->taken = scope->flag;
|
scope->taken = scope->flag;
|
||||||
free($2);
|
cmd_parse_drop($2);
|
||||||
|
|
||||||
if (ps->scope != NULL)
|
if (ps->scope != NULL)
|
||||||
TAILQ_INSERT_HEAD(&ps->stack, ps->scope, entry);
|
TAILQ_INSERT_HEAD(&ps->stack, ps->scope, entry);
|
||||||
@@ -303,7 +325,7 @@ if_elif : ELIF expanded
|
|||||||
scope->flag = !ps->scope->taken && format_true($2);
|
scope->flag = !ps->scope->taken && format_true($2);
|
||||||
scope->taken = ps->scope->taken || scope->flag;
|
scope->taken = ps->scope->taken || scope->flag;
|
||||||
$$ = scope->flag;
|
$$ = scope->flag;
|
||||||
free($2);
|
cmd_parse_drop($2);
|
||||||
|
|
||||||
free(ps->scope);
|
free(ps->scope);
|
||||||
ps->scope = scope;
|
ps->scope = scope;
|
||||||
@@ -324,48 +346,48 @@ condition : if_open '\n' statements if_close
|
|||||||
if ($1)
|
if ($1)
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
else {
|
else {
|
||||||
$$ = cmd_parse_new_commands();
|
$$ = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_open '\n' statements if_else '\n' statements if_close
|
| if_open '\n' statements if_else '\n' statements if_close
|
||||||
{
|
{
|
||||||
if ($1) {
|
if ($1) {
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
cmd_parse_free_commands($6);
|
cmd_parse_drop($6);
|
||||||
} else {
|
} else {
|
||||||
$$ = $6;
|
$$ = $6;
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_open '\n' statements elif if_close
|
| if_open '\n' statements elif if_close
|
||||||
{
|
{
|
||||||
if ($1) {
|
if ($1) {
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
cmd_parse_free_commands($4.commands);
|
cmd_parse_drop($4.commands);
|
||||||
} else if ($4.flag) {
|
} else if ($4.flag) {
|
||||||
$$ = $4.commands;
|
$$ = $4.commands;
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
} else {
|
} else {
|
||||||
$$ = cmd_parse_new_commands();
|
$$ = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
cmd_parse_free_commands($4.commands);
|
cmd_parse_drop($4.commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_open '\n' statements elif if_else '\n' statements if_close
|
| if_open '\n' statements elif if_else '\n' statements if_close
|
||||||
{
|
{
|
||||||
if ($1) {
|
if ($1) {
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
cmd_parse_free_commands($4.commands);
|
cmd_parse_drop($4.commands);
|
||||||
cmd_parse_free_commands($7);
|
cmd_parse_drop($7);
|
||||||
} else if ($4.flag) {
|
} else if ($4.flag) {
|
||||||
$$ = $4.commands;
|
$$ = $4.commands;
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
cmd_parse_free_commands($7);
|
cmd_parse_drop($7);
|
||||||
} else {
|
} else {
|
||||||
$$ = $7;
|
$$ = $7;
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
cmd_parse_free_commands($4.commands);
|
cmd_parse_drop($4.commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,8 +398,8 @@ elif : if_elif '\n' statements
|
|||||||
$$.commands = $3;
|
$$.commands = $3;
|
||||||
} else {
|
} else {
|
||||||
$$.flag = 0;
|
$$.flag = 0;
|
||||||
$$.commands = cmd_parse_new_commands();
|
$$.commands = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_elif '\n' statements elif
|
| if_elif '\n' statements elif
|
||||||
@@ -385,16 +407,16 @@ elif : if_elif '\n' statements
|
|||||||
if ($1) {
|
if ($1) {
|
||||||
$$.flag = 1;
|
$$.flag = 1;
|
||||||
$$.commands = $3;
|
$$.commands = $3;
|
||||||
cmd_parse_free_commands($4.commands);
|
cmd_parse_drop($4.commands);
|
||||||
} else if ($4.flag) {
|
} else if ($4.flag) {
|
||||||
$$.flag = 1;
|
$$.flag = 1;
|
||||||
$$.commands = $4.commands;
|
$$.commands = $4.commands;
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
} else {
|
} else {
|
||||||
$$.flag = 0;
|
$$.flag = 0;
|
||||||
$$.commands = cmd_parse_new_commands();
|
$$.commands = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($3);
|
cmd_parse_drop($3);
|
||||||
cmd_parse_free_commands($4.commands);
|
cmd_parse_drop($4.commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,12 +424,13 @@ commands : command
|
|||||||
{
|
{
|
||||||
struct cmd_parse_state *ps = &parse_state;
|
struct cmd_parse_state *ps = &parse_state;
|
||||||
|
|
||||||
$$ = cmd_parse_new_commands();
|
$$ = cmd_parse_own_commands();
|
||||||
if (!TAILQ_EMPTY(&$1->arguments) &&
|
if (!TAILQ_EMPTY(&$1->arguments) &&
|
||||||
(ps->scope == NULL || ps->scope->flag))
|
(ps->scope == NULL || ps->scope->flag)) {
|
||||||
|
cmd_parse_take($1);
|
||||||
TAILQ_INSERT_TAIL($$, $1, entry);
|
TAILQ_INSERT_TAIL($$, $1, entry);
|
||||||
else
|
} else
|
||||||
cmd_parse_free_command($1);
|
cmd_parse_drop($1);
|
||||||
}
|
}
|
||||||
| commands ';'
|
| commands ';'
|
||||||
{
|
{
|
||||||
@@ -417,7 +440,7 @@ commands : command
|
|||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
TAILQ_CONCAT($$, $3, entry);
|
TAILQ_CONCAT($$, $3, entry);
|
||||||
free($3);
|
cmd_parse_drop($3);
|
||||||
}
|
}
|
||||||
| commands ';' command
|
| commands ';' command
|
||||||
{
|
{
|
||||||
@@ -426,9 +449,10 @@ commands : command
|
|||||||
$$ = $1;
|
$$ = $1;
|
||||||
if (!TAILQ_EMPTY(&$3->arguments) &&
|
if (!TAILQ_EMPTY(&$3->arguments) &&
|
||||||
(ps->scope == NULL || ps->scope->flag)) {
|
(ps->scope == NULL || ps->scope->flag)) {
|
||||||
|
cmd_parse_take($3);
|
||||||
TAILQ_INSERT_TAIL($$, $3, entry);
|
TAILQ_INSERT_TAIL($$, $3, entry);
|
||||||
} else
|
} else
|
||||||
cmd_parse_free_command($3);
|
cmd_parse_drop($3);
|
||||||
}
|
}
|
||||||
| condition1
|
| condition1
|
||||||
{
|
{
|
||||||
@@ -442,6 +466,7 @@ command : assignment
|
|||||||
$$ = xcalloc(1, sizeof *$$);
|
$$ = xcalloc(1, sizeof *$$);
|
||||||
$$->line = ps->input->line;
|
$$->line = ps->input->line;
|
||||||
TAILQ_INIT(&$$->arguments);
|
TAILQ_INIT(&$$->arguments);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_COMMAND, $$);
|
||||||
}
|
}
|
||||||
| optional_assignment TOKEN
|
| optional_assignment TOKEN
|
||||||
{
|
{
|
||||||
@@ -454,8 +479,9 @@ command : assignment
|
|||||||
|
|
||||||
arg = xcalloc(1, sizeof *arg);
|
arg = xcalloc(1, sizeof *arg);
|
||||||
arg->type = CMD_PARSE_STRING;
|
arg->type = CMD_PARSE_STRING;
|
||||||
arg->string = $2;
|
arg->string = cmd_parse_take($2);
|
||||||
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
|
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_COMMAND, $$);
|
||||||
}
|
}
|
||||||
| optional_assignment TOKEN arguments
|
| optional_assignment TOKEN arguments
|
||||||
{
|
{
|
||||||
@@ -467,12 +493,13 @@ command : assignment
|
|||||||
TAILQ_INIT(&$$->arguments);
|
TAILQ_INIT(&$$->arguments);
|
||||||
|
|
||||||
TAILQ_CONCAT(&$$->arguments, $3, entry);
|
TAILQ_CONCAT(&$$->arguments, $3, entry);
|
||||||
free($3);
|
cmd_parse_drop($3);
|
||||||
|
|
||||||
arg = xcalloc(1, sizeof *arg);
|
arg = xcalloc(1, sizeof *arg);
|
||||||
arg->type = CMD_PARSE_STRING;
|
arg->type = CMD_PARSE_STRING;
|
||||||
arg->string = $2;
|
arg->string = cmd_parse_take($2);
|
||||||
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
|
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_COMMAND, $$);
|
||||||
}
|
}
|
||||||
|
|
||||||
condition1 : if_open commands if_close
|
condition1 : if_open commands if_close
|
||||||
@@ -480,48 +507,48 @@ condition1 : if_open commands if_close
|
|||||||
if ($1)
|
if ($1)
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
else {
|
else {
|
||||||
$$ = cmd_parse_new_commands();
|
$$ = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_open commands if_else commands if_close
|
| if_open commands if_else commands if_close
|
||||||
{
|
{
|
||||||
if ($1) {
|
if ($1) {
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
cmd_parse_free_commands($4);
|
cmd_parse_drop($4);
|
||||||
} else {
|
} else {
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_open commands elif1 if_close
|
| if_open commands elif1 if_close
|
||||||
{
|
{
|
||||||
if ($1) {
|
if ($1) {
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
cmd_parse_free_commands($3.commands);
|
cmd_parse_drop($3.commands);
|
||||||
} else if ($3.flag) {
|
} else if ($3.flag) {
|
||||||
$$ = $3.commands;
|
$$ = $3.commands;
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
} else {
|
} else {
|
||||||
$$ = cmd_parse_new_commands();
|
$$ = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
cmd_parse_free_commands($3.commands);
|
cmd_parse_drop($3.commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_open commands elif1 if_else commands if_close
|
| if_open commands elif1 if_else commands if_close
|
||||||
{
|
{
|
||||||
if ($1) {
|
if ($1) {
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
cmd_parse_free_commands($3.commands);
|
cmd_parse_drop($3.commands);
|
||||||
cmd_parse_free_commands($5);
|
cmd_parse_drop($5);
|
||||||
} else if ($3.flag) {
|
} else if ($3.flag) {
|
||||||
$$ = $3.commands;
|
$$ = $3.commands;
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
cmd_parse_free_commands($5);
|
cmd_parse_drop($5);
|
||||||
} else {
|
} else {
|
||||||
$$ = $5;
|
$$ = $5;
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
cmd_parse_free_commands($3.commands);
|
cmd_parse_drop($3.commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,8 +559,8 @@ elif1 : if_elif commands
|
|||||||
$$.commands = $2;
|
$$.commands = $2;
|
||||||
} else {
|
} else {
|
||||||
$$.flag = 0;
|
$$.flag = 0;
|
||||||
$$.commands = cmd_parse_new_commands();
|
$$.commands = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| if_elif commands elif1
|
| if_elif commands elif1
|
||||||
@@ -541,16 +568,16 @@ elif1 : if_elif commands
|
|||||||
if ($1) {
|
if ($1) {
|
||||||
$$.flag = 1;
|
$$.flag = 1;
|
||||||
$$.commands = $2;
|
$$.commands = $2;
|
||||||
cmd_parse_free_commands($3.commands);
|
cmd_parse_drop($3.commands);
|
||||||
} else if ($3.flag) {
|
} else if ($3.flag) {
|
||||||
$$.flag = 1;
|
$$.flag = 1;
|
||||||
$$.commands = $3.commands;
|
$$.commands = $3.commands;
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
} else {
|
} else {
|
||||||
$$.flag = 0;
|
$$.flag = 0;
|
||||||
$$.commands = cmd_parse_new_commands();
|
$$.commands = cmd_parse_own_commands();
|
||||||
cmd_parse_free_commands($2);
|
cmd_parse_drop($2);
|
||||||
cmd_parse_free_commands($3.commands);
|
cmd_parse_drop($3.commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,10 +586,13 @@ arguments : argument
|
|||||||
$$ = xcalloc(1, sizeof *$$);
|
$$ = xcalloc(1, sizeof *$$);
|
||||||
TAILQ_INIT($$);
|
TAILQ_INIT($$);
|
||||||
|
|
||||||
|
cmd_parse_take($1);
|
||||||
TAILQ_INSERT_HEAD($$, $1, entry);
|
TAILQ_INSERT_HEAD($$, $1, entry);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_ARGUMENTS, $$);
|
||||||
}
|
}
|
||||||
| argument arguments
|
| argument arguments
|
||||||
{
|
{
|
||||||
|
cmd_parse_take($1);
|
||||||
TAILQ_INSERT_HEAD($2, $1, entry);
|
TAILQ_INSERT_HEAD($2, $1, entry);
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
}
|
}
|
||||||
@@ -571,19 +601,22 @@ argument : TOKEN
|
|||||||
{
|
{
|
||||||
$$ = xcalloc(1, sizeof *$$);
|
$$ = xcalloc(1, sizeof *$$);
|
||||||
$$->type = CMD_PARSE_STRING;
|
$$->type = CMD_PARSE_STRING;
|
||||||
$$->string = $1;
|
$$->string = cmd_parse_take($1);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_ARGUMENT, $$);
|
||||||
}
|
}
|
||||||
| EQUALS
|
| EQUALS
|
||||||
{
|
{
|
||||||
$$ = xcalloc(1, sizeof *$$);
|
$$ = xcalloc(1, sizeof *$$);
|
||||||
$$->type = CMD_PARSE_STRING;
|
$$->type = CMD_PARSE_STRING;
|
||||||
$$->string = $1;
|
$$->string = cmd_parse_take($1);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_ARGUMENT, $$);
|
||||||
}
|
}
|
||||||
| '{' argument_statements
|
| '{' argument_statements
|
||||||
{
|
{
|
||||||
$$ = xcalloc(1, sizeof *$$);
|
$$ = xcalloc(1, sizeof *$$);
|
||||||
$$->type = CMD_PARSE_COMMANDS;
|
$$->type = CMD_PARSE_COMMANDS;
|
||||||
$$->commands = $2;
|
$$->commands = cmd_parse_take($2);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_ARGUMENT, $$);
|
||||||
}
|
}
|
||||||
|
|
||||||
argument_statements : statement '}'
|
argument_statements : statement '}'
|
||||||
@@ -594,7 +627,7 @@ argument_statements : statement '}'
|
|||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
TAILQ_CONCAT($$, $2, entry);
|
TAILQ_CONCAT($$, $2, entry);
|
||||||
free($2);
|
cmd_parse_drop($2);
|
||||||
}
|
}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@@ -683,22 +716,116 @@ cmd_parse_free_commands(struct cmd_parse_commands *cmds)
|
|||||||
free(cmds);
|
free(cmds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
cmd_parse_own(enum cmd_parse_value_type type, void *value)
|
||||||
|
{
|
||||||
|
struct cmd_parse_state *ps = &parse_state;
|
||||||
|
struct cmd_parse_owned_value *v;
|
||||||
|
|
||||||
|
v = xmalloc(sizeof *v);
|
||||||
|
v->type = type;
|
||||||
|
v->value = value;
|
||||||
|
TAILQ_INSERT_TAIL(&ps->values, v, entry);
|
||||||
|
return (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_parse_commands *
|
||||||
|
cmd_parse_own_commands(void)
|
||||||
|
{
|
||||||
|
struct cmd_parse_commands *cmds;
|
||||||
|
|
||||||
|
cmds = cmd_parse_new_commands();
|
||||||
|
return (cmd_parse_own(CMD_PARSE_VALUE_COMMANDS, cmds));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_parse_owned_value *
|
||||||
|
cmd_parse_find_value(void *value)
|
||||||
|
{
|
||||||
|
struct cmd_parse_state *ps = &parse_state;
|
||||||
|
struct cmd_parse_owned_value *v;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_REVERSE(v, &ps->values, cmd_parse_owned_values, entry) {
|
||||||
|
if (v->value == value)
|
||||||
|
return (v);
|
||||||
|
}
|
||||||
|
fatalx("parser value not owned");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
cmd_parse_take(void *value)
|
||||||
|
{
|
||||||
|
struct cmd_parse_state *ps = &parse_state;
|
||||||
|
struct cmd_parse_owned_value *v;
|
||||||
|
|
||||||
|
v = cmd_parse_find_value(value);
|
||||||
|
TAILQ_REMOVE(&ps->values, v, entry);
|
||||||
|
free(v);
|
||||||
|
return (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_parse_free_value(enum cmd_parse_value_type type, void *value)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case CMD_PARSE_VALUE_STRING:
|
||||||
|
free(value);
|
||||||
|
break;
|
||||||
|
case CMD_PARSE_VALUE_ARGUMENT:
|
||||||
|
cmd_parse_free_argument(value);
|
||||||
|
break;
|
||||||
|
case CMD_PARSE_VALUE_ARGUMENTS:
|
||||||
|
cmd_parse_free_arguments(value);
|
||||||
|
free(value);
|
||||||
|
break;
|
||||||
|
case CMD_PARSE_VALUE_COMMAND:
|
||||||
|
cmd_parse_free_command(value);
|
||||||
|
break;
|
||||||
|
case CMD_PARSE_VALUE_COMMANDS:
|
||||||
|
cmd_parse_free_commands(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_parse_drop(void *value)
|
||||||
|
{
|
||||||
|
struct cmd_parse_state *ps = &parse_state;
|
||||||
|
struct cmd_parse_owned_value *v;
|
||||||
|
|
||||||
|
v = cmd_parse_find_value(value);
|
||||||
|
TAILQ_REMOVE(&ps->values, v, entry);
|
||||||
|
cmd_parse_free_value(v->type, v->value);
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
static struct cmd_parse_commands *
|
static struct cmd_parse_commands *
|
||||||
cmd_parse_run_parser(char **cause)
|
cmd_parse_run_parser(char **cause)
|
||||||
{
|
{
|
||||||
struct cmd_parse_state *ps = &parse_state;
|
struct cmd_parse_state *ps = &parse_state;
|
||||||
struct cmd_parse_scope *scope, *scope1;
|
struct cmd_parse_scope *scope, *scope1;
|
||||||
int retval;
|
struct cmd_parse_owned_value *v, *v1;
|
||||||
|
int retval;
|
||||||
|
|
||||||
ps->commands = NULL;
|
ps->commands = NULL;
|
||||||
TAILQ_INIT(&ps->stack);
|
TAILQ_INIT(&ps->stack);
|
||||||
|
TAILQ_INIT(&ps->values);
|
||||||
|
|
||||||
retval = yyparse();
|
retval = yyparse();
|
||||||
TAILQ_FOREACH_SAFE(scope, &ps->stack, entry, scope1) {
|
TAILQ_FOREACH_SAFE(scope, &ps->stack, entry, scope1) {
|
||||||
TAILQ_REMOVE(&ps->stack, scope, entry);
|
TAILQ_REMOVE(&ps->stack, scope, entry);
|
||||||
free(scope);
|
free(scope);
|
||||||
}
|
}
|
||||||
|
free(ps->scope);
|
||||||
|
ps->scope = NULL;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(v, &ps->values, entry, v1) {
|
||||||
|
TAILQ_REMOVE(&ps->values, v, entry);
|
||||||
|
cmd_parse_free_value(v->type, v->value);
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
|
if (ps->commands != NULL)
|
||||||
|
cmd_parse_free_commands(ps->commands);
|
||||||
*cause = ps->error;
|
*cause = ps->error;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@@ -1329,9 +1456,10 @@ yylex(void)
|
|||||||
*/
|
*/
|
||||||
next = yylex_getc();
|
next = yylex_getc();
|
||||||
if (condition && next == '{') {
|
if (condition && next == '{') {
|
||||||
yylval.token = yylex_format();
|
token = yylval.token = yylex_format();
|
||||||
if (yylval.token == NULL)
|
if (token == NULL)
|
||||||
return (ERROR);
|
return (ERROR);
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_STRING, token);
|
||||||
return (FORMAT);
|
return (FORMAT);
|
||||||
}
|
}
|
||||||
while (next != '\n' && next != EOF)
|
while (next != '\n' && next != EOF)
|
||||||
@@ -1348,35 +1476,37 @@ yylex(void)
|
|||||||
* % is a condition unless it is all % or all numbers,
|
* % is a condition unless it is all % or all numbers,
|
||||||
* then it is a token.
|
* then it is a token.
|
||||||
*/
|
*/
|
||||||
yylval.token = yylex_get_word('%');
|
token = yylval.token = yylex_get_word('%');
|
||||||
for (cp = yylval.token; *cp != '\0'; cp++) {
|
for (cp = token; *cp != '\0'; cp++) {
|
||||||
if (*cp != '%' && !isdigit((u_char)*cp))
|
if (*cp != '%' && !isdigit((u_char)*cp))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*cp == '\0')
|
if (*cp == '\0') {
|
||||||
|
cmd_parse_own(CMD_PARSE_VALUE_STRING, token);
|
||||||
return (TOKEN);
|
return (TOKEN);
|
||||||
|
}
|
||||||
ps->condition = 1;
|
ps->condition = 1;
|
||||||
if (strcmp(yylval.token, "%hidden") == 0) {
|
if (strcmp(token, "%hidden") == 0) {
|
||||||
free(yylval.token);
|
free(token);
|
||||||
return (HIDDEN);
|
return (HIDDEN);
|
||||||
}
|
}
|
||||||
if (strcmp(yylval.token, "%if") == 0) {
|
if (strcmp(token, "%if") == 0) {
|
||||||
free(yylval.token);
|
free(token);
|
||||||
return (IF);
|
return (IF);
|
||||||
}
|
}
|
||||||
if (strcmp(yylval.token, "%else") == 0) {
|
if (strcmp(token, "%else") == 0) {
|
||||||
free(yylval.token);
|
free(token);
|
||||||
return (ELSE);
|
return (ELSE);
|
||||||
}
|
}
|
||||||
if (strcmp(yylval.token, "%elif") == 0) {
|
if (strcmp(token, "%elif") == 0) {
|
||||||
free(yylval.token);
|
free(token);
|
||||||
return (ELIF);
|
return (ELIF);
|
||||||
}
|
}
|
||||||
if (strcmp(yylval.token, "%endif") == 0) {
|
if (strcmp(token, "%endif") == 0) {
|
||||||
free(yylval.token);
|
free(token);
|
||||||
return (ENDIF);
|
return (ENDIF);
|
||||||
}
|
}
|
||||||
free(yylval.token);
|
free(token);
|
||||||
return (ERROR);
|
return (ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1386,7 +1516,7 @@ yylex(void)
|
|||||||
token = yylex_token(ch);
|
token = yylex_token(ch);
|
||||||
if (token == NULL)
|
if (token == NULL)
|
||||||
return (ERROR);
|
return (ERROR);
|
||||||
yylval.token = token;
|
yylval.token = cmd_parse_own(CMD_PARSE_VALUE_STRING, token);
|
||||||
|
|
||||||
if (strchr(token, '=') != NULL && yylex_is_var(*token, 1)) {
|
if (strchr(token, '=') != NULL && yylex_is_var(*token, 1)) {
|
||||||
for (cp = token + 1; *cp != '='; cp++) {
|
for (cp = token + 1; *cp != '='; cp++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user