Bug Summary

File:src/usr.bin/tmux/obj/cmd-parse.c
Warning:line 1505, column 13
Attempt to free released memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cmd-parse.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/tmux/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/tmux -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/tmux/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c cmd-parse.c
1#include <stdlib.h>
2#include <string.h>
3#define YYBYACC1 1
4#define YYMAJOR1 1
5#define YYMINOR9 9
6#define YYLEXyylex() yylex()
7#define YYEMPTY-1 -1
8#define yyclearin(yychar=(-1)) (yychar=(YYEMPTY-1))
9#define yyerrok(yyerrflag=0) (yyerrflag=0)
10#define YYRECOVERING()(yyerrflag!=0) (yyerrflag!=0)
11#define YYPREFIX"yy" "yy"
12#line 20 "/usr/src/usr.bin/tmux/cmd-parse.y"
13
14#include <sys/types.h>
15
16#include <ctype.h>
17#include <errno(*__errno()).h>
18#include <pwd.h>
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22#include <wchar.h>
23
24#include "tmux.h"
25
26static int yylex(void);
27static int yyparse(void);
28static int printflike(1,2)__attribute__ ((format (printf, 1, 2))) yyerror(const char *, ...);
29
30static char *yylex_token(int);
31static char *yylex_format(void);
32
33struct cmd_parse_scope {
34 int flag;
35 TAILQ_ENTRY (cmd_parse_scope)struct { struct cmd_parse_scope *tqe_next; struct cmd_parse_scope
**tqe_prev; }
entry;
36};
37
38enum cmd_parse_argument_type {
39 CMD_PARSE_STRING,
40 CMD_PARSE_COMMANDS,
41 CMD_PARSE_PARSED_COMMANDS
42};
43
44struct cmd_parse_argument {
45 enum cmd_parse_argument_type type;
46 char *string;
47 struct cmd_parse_commands *commands;
48 struct cmd_list *cmdlist;
49
50 TAILQ_ENTRY(cmd_parse_argument)struct { struct cmd_parse_argument *tqe_next; struct cmd_parse_argument
**tqe_prev; }
entry;
51};
52TAILQ_HEAD(cmd_parse_arguments, cmd_parse_argument)struct cmd_parse_arguments { struct cmd_parse_argument *tqh_first
; struct cmd_parse_argument **tqh_last; }
;
53
54struct cmd_parse_command {
55 u_int line;
56 struct cmd_parse_arguments arguments;
57
58 TAILQ_ENTRY(cmd_parse_command)struct { struct cmd_parse_command *tqe_next; struct cmd_parse_command
**tqe_prev; }
entry;
59};
60TAILQ_HEAD(cmd_parse_commands, cmd_parse_command)struct cmd_parse_commands { struct cmd_parse_command *tqh_first
; struct cmd_parse_command **tqh_last; }
;
61
62struct cmd_parse_state {
63 FILE *f;
64
65 const char *buf;
66 size_t len;
67 size_t off;
68
69 int condition;
70 int eol;
71 int eof;
72 struct cmd_parse_input *input;
73 u_int escapes;
74
75 char *error;
76 struct cmd_parse_commands *commands;
77
78 struct cmd_parse_scope *scope;
79 TAILQ_HEAD(, cmd_parse_scope)struct { struct cmd_parse_scope *tqh_first; struct cmd_parse_scope
**tqh_last; }
stack;
80};
81static struct cmd_parse_state parse_state;
82
83static char *cmd_parse_get_error(const char *, u_int, const char *);
84static void cmd_parse_free_command(struct cmd_parse_command *);
85static struct cmd_parse_commands *cmd_parse_new_commands(void);
86static void cmd_parse_free_commands(struct cmd_parse_commands *);
87static void cmd_parse_build_commands(struct cmd_parse_commands *,
88 struct cmd_parse_input *, struct cmd_parse_result *);
89static void cmd_parse_print_commands(struct cmd_parse_input *,
90 struct cmd_list *);
91
92#line 101 "/usr/src/usr.bin/tmux/cmd-parse.y"
93#ifndef YYSTYPE_DEFINED
94#define YYSTYPE_DEFINED
95typedef union
96{
97 char *token;
98 struct cmd_parse_arguments *arguments;
99 struct cmd_parse_argument *argument;
100 int flag;
101 struct {
102 int flag;
103 struct cmd_parse_commands *commands;
104 } elif;
105 struct cmd_parse_commands *commands;
106 struct cmd_parse_command *command;
107} YYSTYPE;
108#endif /* YYSTYPE_DEFINED */
109#line 110 "cmd-parse.c"
110#define ERROR257 257
111#define HIDDEN258 258
112#define IF259 259
113#define ELSE260 260
114#define ELIF261 261
115#define ENDIF262 262
116#define FORMAT263 263
117#define TOKEN264 264
118#define EQUALS265 265
119#define YYERRCODE256 256
120const short yylhs[] =
121 { -1,
122 0, 0, 10, 10, 11, 11, 11, 11, 2, 2,
123 1, 17, 17, 18, 16, 5, 19, 6, 20, 13,
124 13, 13, 13, 7, 7, 12, 12, 12, 12, 12,
125 15, 15, 15, 14, 14, 14, 14, 8, 8, 3,
126 3, 4, 4, 4, 9, 9,
127};
128const short yylen[] =
129 { 2,
130 0, 1, 2, 3, 0, 1, 1, 1, 1, 1,
131 1, 0, 1, 1, 2, 2, 1, 2, 1, 4,
132 7, 5, 8, 3, 4, 1, 2, 3, 3, 1,
133 1, 2, 3, 3, 5, 4, 6, 2, 3, 1,
134 2, 1, 1, 2, 2, 3,
135};
136const short yydefred[] =
137 { 0,
138 0, 0, 14, 0, 0, 0, 0, 0, 7, 30,
139 26, 6, 0, 0, 15, 9, 10, 16, 11, 0,
140 0, 0, 0, 3, 0, 0, 0, 17, 0, 19,
141 0, 0, 0, 34, 4, 28, 29, 42, 43, 0,
142 33, 0, 0, 0, 0, 20, 18, 0, 0, 36,
143 0, 44, 0, 0, 41, 0, 0, 22, 0, 39,
144 0, 35, 0, 45, 0, 0, 0, 37, 46, 25,
145 0, 21, 23,
146};
147const short yydgoto[] =
148 { 4,
149 18, 19, 41, 42, 5, 31, 44, 32, 52, 6,
150 7, 8, 9, 10, 11, 12, 13, 14, 33, 34,
151};
152const short yysindex[] =
153 { -175,
154 -227, -172, 0, 0, -10, -175, 46, 10, 0, 0,
155 0, 0, -205, 0, 0, 0, 0, 0, 0, -175,
156 -238, -56, 53, 0, -238, -118, -228, 0, -172, 0,
157 -238, -234, -238, 0, 0, 0, 0, 0, 0, -175,
158 0, -118, 63, -234, 66, 0, 0, -52, -238, 0,
159 -55, 0, -175, 3, 0, -175, 68, 0, -175, 0,
160 -55, 0, 4, 0, -208, -175, -219, 0, 0, 0,
161 -219, 0, 0,};
162const short yyrindex[] =
163 { 1,
164 0, 0, 0, 0, -184, 2, 0, 5, 0, 0,
165 0, 0, 0, -4, 0, 0, 0, 0, 0, 6,
166 -184, 0, 0, 0, 7, 12, 6, 0, 0, 0,
167 -184, 0, -184, 0, 0, 0, 0, 0, 0, -2,
168 0, 15, 0, 0, 0, 0, 0, -215, -184, 0,
169 0, 0, -2, 0, 0, 6, 0, 0, 6, 0,
170 0, 0, 0, 0, -1, 6, 6, 0, 0, 0,
171 6, 0, 0,};
172const short yygindex[] =
173 { 0,
174 57, 0, 40, 0, 39, -17, 28, 47, 0, 9,
175 14, 56, 0, 69, 71, 0, 0, 0, -8, -9,
176};
177#define YYTABLESIZE277 277
178const short yytable[] =
179 { 20,
180 1, 2, 25, 25, 40, 31, 25, 5, 5, 43,
181 5, 5, 24, 35, 8, 5, 27, 46, 45, 23,
182 2, 32, 50, 49, 40, 28, 3, 30, 27, 1,
183 2, 28, 29, 30, 58, 57, 3, 15, 1, 2,
184 23, 62, 30, 21, 38, 3, 38, 43, 53, 1,
185 2, 68, 29, 54, 31, 24, 3, 72, 26, 21,
186 22, 73, 35, 21, 65, 27, 63, 67, 25, 21,
187 32, 21, 56, 40, 71, 59, 22, 66, 23, 12,
188 23, 55, 1, 2, 23, 47, 48, 21, 51, 3,
189 16, 17, 70, 36, 60, 37, 0, 0, 0, 0,
190 0, 0, 0, 0, 61, 0, 0, 0, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 31, 0, 5, 0, 0, 0, 0, 64, 69, 8,
193 0, 27, 0, 0, 0, 0, 32, 0, 0, 40,
194 0, 0, 0, 0, 0, 38, 39, 0, 0, 0,
195 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
196 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
197 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 28, 29, 30, 30, 0, 29, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
205 0, 0, 0, 0, 3, 31, 31, 31, 24, 13,
206 24, 12, 12, 0, 12, 12, 27, 27, 27, 12,
207 12, 32, 32, 32, 40, 40, 40,
208};
209const short yycheck[] =
210 { 10,
211 0, 0, 59, 59, 123, 10, 59, 10, 10, 27,
212 10, 10, 10, 10, 10, 10, 10, 27, 27, 6,
213 259, 10, 32, 32, 10, 260, 265, 262, 20, 258,
214 259, 260, 261, 262, 44, 44, 265, 265, 258, 259,
215 27, 51, 262, 5, 260, 265, 262, 65, 40, 258,
216 259, 61, 261, 40, 59, 10, 265, 67, 264, 21,
217 5, 71, 10, 25, 56, 59, 53, 59, 59, 31,
218 59, 33, 10, 59, 66, 10, 21, 10, 65, 264,
219 67, 42, 258, 259, 71, 29, 31, 49, 33, 265,
220 263, 264, 65, 25, 48, 25, -1, -1, -1, -1,
221 -1, -1, -1, -1, 49, -1, -1, -1, -1, -1,
222 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
223 125, -1, 125, -1, -1, -1, -1, 125, 125, 125,
224 -1, 125, -1, -1, -1, -1, 125, -1, -1, 125,
225 -1, -1, -1, -1, -1, 264, 265, -1, -1, -1,
226 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
228 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
229 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
230 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
231 -1, -1, -1, 260, 261, 262, 262, -1, 261, -1,
232 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
233 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
235 -1, -1, -1, -1, -1, -1, -1, -1, 259, -1,
236 -1, -1, -1, -1, 265, 260, 261, 262, 260, 264,
237 262, 264, 264, -1, 264, 264, 260, 261, 262, 264,
238 264, 260, 261, 262, 260, 261, 262,
239};
240#define YYFINAL4 4
241#ifndef YYDEBUG0
242#define YYDEBUG0 0
243#endif
244#define YYMAXTOKEN265 265
245#if YYDEBUG0
246const char * const yyname[] =
247 {
248"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2490,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"';'",0,0,0,0,0,0,0,0,0,
2500,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2510,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2520,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2530,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2540,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"ERROR",
255"HIDDEN","IF","ELSE","ELIF","ENDIF","FORMAT","TOKEN","EQUALS",
256};
257const char * const yyrule[] =
258 {"$accept : lines",
259"lines :",
260"lines : statements",
261"statements : statement '\\n'",
262"statements : statements statement '\\n'",
263"statement :",
264"statement : hidden_assignment",
265"statement : condition",
266"statement : commands",
267"format : FORMAT",
268"format : TOKEN",
269"expanded : format",
270"optional_assignment :",
271"optional_assignment : assignment",
272"assignment : EQUALS",
273"hidden_assignment : HIDDEN EQUALS",
274"if_open : IF expanded",
275"if_else : ELSE",
276"if_elif : ELIF expanded",
277"if_close : ENDIF",
278"condition : if_open '\\n' statements if_close",
279"condition : if_open '\\n' statements if_else '\\n' statements if_close",
280"condition : if_open '\\n' statements elif if_close",
281"condition : if_open '\\n' statements elif if_else '\\n' statements if_close",
282"elif : if_elif '\\n' statements",
283"elif : if_elif '\\n' statements elif",
284"commands : command",
285"commands : commands ';'",
286"commands : commands ';' condition1",
287"commands : commands ';' command",
288"commands : condition1",
289"command : assignment",
290"command : optional_assignment TOKEN",
291"command : optional_assignment TOKEN arguments",
292"condition1 : if_open commands if_close",
293"condition1 : if_open commands if_else commands if_close",
294"condition1 : if_open commands elif1 if_close",
295"condition1 : if_open commands elif1 if_else commands if_close",
296"elif1 : if_elif commands",
297"elif1 : if_elif commands elif1",
298"arguments : argument",
299"arguments : argument arguments",
300"argument : TOKEN",
301"argument : EQUALS",
302"argument : '{' argument_statements",
303"argument_statements : statement '}'",
304"argument_statements : statements statement '}'",
305};
306#endif
307#ifdef YYSTACKSIZE10000
308#undef YYMAXDEPTH10000
309#define YYMAXDEPTH10000 YYSTACKSIZE10000
310#else
311#ifdef YYMAXDEPTH10000
312#define YYSTACKSIZE10000 YYMAXDEPTH10000
313#else
314#define YYSTACKSIZE10000 10000
315#define YYMAXDEPTH10000 10000
316#endif
317#endif
318#define YYINITSTACKSIZE200 200
319/* LINTUSED */
320int yydebug;
321int yynerrs;
322int yyerrflag;
323int yychar;
324short *yyssp;
325YYSTYPE *yyvsp;
326YYSTYPE yyval;
327YYSTYPE yylval;
328short *yyss;
329short *yysslim;
330YYSTYPE *yyvs;
331unsigned int yystacksize;
332int yyparse(void);
333#line 575 "/usr/src/usr.bin/tmux/cmd-parse.y"
334
335static char *
336cmd_parse_get_error(const char *file, u_int line, const char *error)
337{
338 char *s;
339
340 if (file == NULL((void *)0))
341 s = xstrdup(error);
342 else
343 xasprintf(&s, "%s:%u: %s", file, line, error);
344 return (s);
345}
346
347static void
348cmd_parse_print_commands(struct cmd_parse_input *pi, struct cmd_list *cmdlist)
349{
350 char *s;
351
352 if (pi->item == NULL((void *)0) || (~pi->flags & CMD_PARSE_VERBOSE0x8))
353 return;
354 s = cmd_list_print(cmdlist, 0);
355 if (pi->file != NULL((void *)0))
356 cmdq_print(pi->item, "%s:%u: %s", pi->file, pi->line, s);
357 else
358 cmdq_print(pi->item, "%u: %s", pi->line, s);
359 free(s);
360}
361
362static void
363cmd_parse_free_argument(struct cmd_parse_argument *arg)
364{
365 switch (arg->type) {
366 case CMD_PARSE_STRING:
367 free(arg->string);
368 break;
369 case CMD_PARSE_COMMANDS:
370 cmd_parse_free_commands(arg->commands);
371 break;
372 case CMD_PARSE_PARSED_COMMANDS:
373 cmd_list_free(arg->cmdlist);
374 break;
375 }
376 free(arg);
377}
378
379static void
380cmd_parse_free_arguments(struct cmd_parse_arguments *args)
381{
382 struct cmd_parse_argument *arg, *arg1;
383
384 TAILQ_FOREACH_SAFE(arg, args, entry, arg1)for ((arg) = ((args)->tqh_first); (arg) != ((void *)0) &&
((arg1) = ((arg)->entry.tqe_next), 1); (arg) = (arg1))
{
385 TAILQ_REMOVE(args, arg, entry)do { if (((arg)->entry.tqe_next) != ((void *)0)) (arg)->
entry.tqe_next->entry.tqe_prev = (arg)->entry.tqe_prev;
else (args)->tqh_last = (arg)->entry.tqe_prev; *(arg)->
entry.tqe_prev = (arg)->entry.tqe_next; ; ; } while (0)
;
386 cmd_parse_free_argument(arg);
387 }
388}
389
390static void
391cmd_parse_free_command(struct cmd_parse_command *cmd)
392{
393 cmd_parse_free_arguments(&cmd->arguments);
394 free(cmd);
395}
396
397static struct cmd_parse_commands *
398cmd_parse_new_commands(void)
399{
400 struct cmd_parse_commands *cmds;
401
402 cmds = xmalloc(sizeof *cmds);
403 TAILQ_INIT(cmds)do { (cmds)->tqh_first = ((void *)0); (cmds)->tqh_last =
&(cmds)->tqh_first; } while (0)
;
404 return (cmds);
405}
406
407static void
408cmd_parse_free_commands(struct cmd_parse_commands *cmds)
409{
410 struct cmd_parse_command *cmd, *cmd1;
411
412 TAILQ_FOREACH_SAFE(cmd, cmds, entry, cmd1)for ((cmd) = ((cmds)->tqh_first); (cmd) != ((void *)0) &&
((cmd1) = ((cmd)->entry.tqe_next), 1); (cmd) = (cmd1))
{
413 TAILQ_REMOVE(cmds, cmd, entry)do { if (((cmd)->entry.tqe_next) != ((void *)0)) (cmd)->
entry.tqe_next->entry.tqe_prev = (cmd)->entry.tqe_prev;
else (cmds)->tqh_last = (cmd)->entry.tqe_prev; *(cmd)->
entry.tqe_prev = (cmd)->entry.tqe_next; ; ; } while (0)
;
414 cmd_parse_free_command(cmd);
415 }
416 free(cmds);
417}
418
419static struct cmd_parse_commands *
420cmd_parse_run_parser(char **cause)
421{
422 struct cmd_parse_state *ps = &parse_state;
423 struct cmd_parse_scope *scope, *scope1;
424 int retval;
425
426 ps->commands = NULL((void *)0);
427 TAILQ_INIT(&ps->stack)do { (&ps->stack)->tqh_first = ((void *)0); (&ps
->stack)->tqh_last = &(&ps->stack)->tqh_first
; } while (0)
;
428
429 retval = yyparse();
430 TAILQ_FOREACH_SAFE(scope, &ps->stack, entry, scope1)for ((scope) = ((&ps->stack)->tqh_first); (scope) !=
((void *)0) && ((scope1) = ((scope)->entry.tqe_next
), 1); (scope) = (scope1))
{
431 TAILQ_REMOVE(&ps->stack, scope, entry)do { if (((scope)->entry.tqe_next) != ((void *)0)) (scope)
->entry.tqe_next->entry.tqe_prev = (scope)->entry.tqe_prev
; else (&ps->stack)->tqh_last = (scope)->entry.tqe_prev
; *(scope)->entry.tqe_prev = (scope)->entry.tqe_next; ;
; } while (0)
;
432 free(scope);
433 }
434 if (retval != 0) {
435 *cause = ps->error;
436 return (NULL((void *)0));
437 }
438
439 if (ps->commands == NULL((void *)0))
440 return (cmd_parse_new_commands());
441 return (ps->commands);
442}
443
444static struct cmd_parse_commands *
445cmd_parse_do_file(FILE *f, struct cmd_parse_input *pi, char **cause)
446{
447 struct cmd_parse_state *ps = &parse_state;
448
449 memset(ps, 0, sizeof *ps);
450 ps->input = pi;
451 ps->f = f;
452 return (cmd_parse_run_parser(cause));
453}
454
455static struct cmd_parse_commands *
456cmd_parse_do_buffer(const char *buf, size_t len, struct cmd_parse_input *pi,
457 char **cause)
458{
459 struct cmd_parse_state *ps = &parse_state;
460
461 memset(ps, 0, sizeof *ps);
462 ps->input = pi;
463 ps->buf = buf;
464 ps->len = len;
465 return (cmd_parse_run_parser(cause));
466}
467
468static void
469cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix)
470{
471 struct cmd_parse_command *cmd;
472 struct cmd_parse_argument *arg;
473 u_int i, j;
474 char *s;
475
476 i = 0;
477 TAILQ_FOREACH(cmd, cmds, entry)for((cmd) = ((cmds)->tqh_first); (cmd) != ((void *)0); (cmd
) = ((cmd)->entry.tqe_next))
{
478 j = 0;
479 TAILQ_FOREACH(arg, &cmd->arguments, entry)for((arg) = ((&cmd->arguments)->tqh_first); (arg) !=
((void *)0); (arg) = ((arg)->entry.tqe_next))
{
480 switch (arg->type) {
481 case CMD_PARSE_STRING:
482 log_debug("%s %u:%u: %s", prefix, i, j,
483 arg->string);
484 break;
485 case CMD_PARSE_COMMANDS:
486 xasprintf(&s, "%s %u:%u", prefix, i, j);
487 cmd_parse_log_commands(arg->commands, s);
488 free(s);
489 break;
490 case CMD_PARSE_PARSED_COMMANDS:
491 s = cmd_list_print(arg->cmdlist, 0);
492 log_debug("%s %u:%u: %s", prefix, i, j, s);
493 free(s);
494 break;
495 }
496 j++;
497 }
498 i++;
499 }
500}
501
502static int
503cmd_parse_expand_alias(struct cmd_parse_command *cmd,
504 struct cmd_parse_input *pi, struct cmd_parse_result *pr)
505{
506 struct cmd_parse_argument *arg, *arg1, *first;
507 struct cmd_parse_commands *cmds;
508 struct cmd_parse_command *last;
509 char *alias, *name, *cause;
510
511 if (pi->flags & CMD_PARSE_NOALIAS0x4)
512 return (0);
513 memset(pr, 0, sizeof *pr);
514
515 first = TAILQ_FIRST(&cmd->arguments)((&cmd->arguments)->tqh_first);
516 if (first == NULL((void *)0) || first->type != CMD_PARSE_STRING) {
517 pr->status = CMD_PARSE_SUCCESS;
518 pr->cmdlist = cmd_list_new();
519 return (1);
520 }
521 name = first->string;
522
523 alias = cmd_get_alias(name);
524 if (alias == NULL((void *)0))
525 return (0);
526 log_debug("%s: %u alias %s = %s", __func__, pi->line, name, alias);
527
528 cmds = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause);
529 free(alias);
530 if (cmds == NULL((void *)0)) {
531 pr->status = CMD_PARSE_ERROR;
532 pr->error = cause;
533 return (1);
534 }
535
536 last = TAILQ_LAST(cmds, cmd_parse_commands)(*(((struct cmd_parse_commands *)((cmds)->tqh_last))->tqh_last
))
;
537 if (last == NULL((void *)0)) {
538 pr->status = CMD_PARSE_SUCCESS;
539 pr->cmdlist = cmd_list_new();
540 return (1);
541 }
542
543 TAILQ_REMOVE(&cmd->arguments, first, entry)do { if (((first)->entry.tqe_next) != ((void *)0)) (first)
->entry.tqe_next->entry.tqe_prev = (first)->entry.tqe_prev
; else (&cmd->arguments)->tqh_last = (first)->entry
.tqe_prev; *(first)->entry.tqe_prev = (first)->entry.tqe_next
; ; ; } while (0)
;
544 cmd_parse_free_argument(first);
545
546 TAILQ_FOREACH_SAFE(arg, &cmd->arguments, entry, arg1)for ((arg) = ((&cmd->arguments)->tqh_first); (arg) !=
((void *)0) && ((arg1) = ((arg)->entry.tqe_next),
1); (arg) = (arg1))
{
547 TAILQ_REMOVE(&cmd->arguments, arg, entry)do { if (((arg)->entry.tqe_next) != ((void *)0)) (arg)->
entry.tqe_next->entry.tqe_prev = (arg)->entry.tqe_prev;
else (&cmd->arguments)->tqh_last = (arg)->entry
.tqe_prev; *(arg)->entry.tqe_prev = (arg)->entry.tqe_next
; ; ; } while (0)
;
548 TAILQ_INSERT_TAIL(&last->arguments, arg, entry)do { (arg)->entry.tqe_next = ((void *)0); (arg)->entry.
tqe_prev = (&last->arguments)->tqh_last; *(&last
->arguments)->tqh_last = (arg); (&last->arguments
)->tqh_last = &(arg)->entry.tqe_next; } while (0)
;
549 }
550 cmd_parse_log_commands(cmds, __func__);
551
552 pi->flags |= CMD_PARSE_NOALIAS0x4;
553 cmd_parse_build_commands(cmds, pi, pr);
554 pi->flags &= ~CMD_PARSE_NOALIAS0x4;
555 return (1);
556}
557
558static void
559cmd_parse_build_command(struct cmd_parse_command *cmd,
560 struct cmd_parse_input *pi, struct cmd_parse_result *pr)
561{
562 struct cmd_parse_argument *arg;
563 struct cmd *add;
564 char *cause;
565 struct args_value *values = NULL((void *)0);
566 u_int count = 0, idx;
567
568 memset(pr, 0, sizeof *pr);
569
570 if (cmd_parse_expand_alias(cmd, pi, pr))
571 return;
572
573 TAILQ_FOREACH(arg, &cmd->arguments, entry)for((arg) = ((&cmd->arguments)->tqh_first); (arg) !=
((void *)0); (arg) = ((arg)->entry.tqe_next))
{
574 values = xrecallocarray(values, count, count + 1,
575 sizeof *values);
576 switch (arg->type) {
577 case CMD_PARSE_STRING:
578 values[count].type = ARGS_STRING;
579 values[count].string = xstrdup(arg->string);
580 break;
581 case CMD_PARSE_COMMANDS:
582 cmd_parse_build_commands(arg->commands, pi, pr);
583 if (pr->status != CMD_PARSE_SUCCESS)
584 goto out;
585 values[count].type = ARGS_COMMANDS;
586 values[count].cmdlist = pr->cmdlist;
587 break;
588 case CMD_PARSE_PARSED_COMMANDS:
589 values[count].type = ARGS_COMMANDS;
590 values[count].cmdlist = arg->cmdlist;
591 values[count].cmdlist->references++;
592 break;
593 }
594 count++;
595 }
596
597 add = cmd_parse(values, count, pi->file, pi->line, &cause);
598 if (add == NULL((void *)0)) {
599 pr->status = CMD_PARSE_ERROR;
600 pr->error = cmd_parse_get_error(pi->file, pi->line, cause);
601 free(cause);
602 goto out;
603 }
604 pr->status = CMD_PARSE_SUCCESS;
605 pr->cmdlist = cmd_list_new();
606 cmd_list_append(pr->cmdlist, add);
607
608out:
609 for (idx = 0; idx < count; idx++)
610 args_free_value(&values[idx]);
611 free(values);
612}
613
614static void
615cmd_parse_build_commands(struct cmd_parse_commands *cmds,
616 struct cmd_parse_input *pi, struct cmd_parse_result *pr)
617{
618 struct cmd_parse_command *cmd;
619 u_int line = UINT_MAX(2147483647 *2U +1U);
620 struct cmd_list *current = NULL((void *)0), *result;
621 char *s;
622
623 memset(pr, 0, sizeof *pr);
624
625 /* Check for an empty list. */
626 if (TAILQ_EMPTY(cmds)(((cmds)->tqh_first) == ((void *)0))) {
627 pr->status = CMD_PARSE_SUCCESS;
628 pr->cmdlist = cmd_list_new();
629 return;
630 }
631 cmd_parse_log_commands(cmds, __func__);
632
633 /*
634 * Parse each command into a command list. Create a new command list
635 * for each line (unless the flag is set) so they get a new group (so
636 * the queue knows which ones to remove if a command fails when
637 * executed).
638 */
639 result = cmd_list_new();
640 TAILQ_FOREACH(cmd, cmds, entry)for((cmd) = ((cmds)->tqh_first); (cmd) != ((void *)0); (cmd
) = ((cmd)->entry.tqe_next))
{
641 if (((~pi->flags & CMD_PARSE_ONEGROUP0x10) && cmd->line != line)) {
642 if (current != NULL((void *)0)) {
643 cmd_parse_print_commands(pi, current);
644 cmd_list_move(result, current);
645 cmd_list_free(current);
646 }
647 current = cmd_list_new();
648 }
649 if (current == NULL((void *)0))
650 current = cmd_list_new();
651 line = pi->line = cmd->line;
652
653 cmd_parse_build_command(cmd, pi, pr);
654 if (pr->status != CMD_PARSE_SUCCESS) {
655 cmd_list_free(result);
656 cmd_list_free(current);
657 return;
658 }
659 cmd_list_append_all(current, pr->cmdlist);
660 cmd_list_free(pr->cmdlist);
661 }
662 if (current != NULL((void *)0)) {
663 cmd_parse_print_commands(pi, current);
664 cmd_list_move(result, current);
665 cmd_list_free(current);
666 }
667
668 s = cmd_list_print(result, 0);
669 log_debug("%s: %s", __func__, s);
670 free(s);
671
672 pr->status = CMD_PARSE_SUCCESS;
673 pr->cmdlist = result;
674}
675
676struct cmd_parse_result *
677cmd_parse_from_file(FILE *f, struct cmd_parse_input *pi)
678{
679 static struct cmd_parse_result pr;
680 struct cmd_parse_input input;
681 struct cmd_parse_commands *cmds;
682 char *cause;
683
684 if (pi == NULL((void *)0)) {
685 memset(&input, 0, sizeof input);
686 pi = &input;
687 }
688 memset(&pr, 0, sizeof pr);
689
690 cmds = cmd_parse_do_file(f, pi, &cause);
691 if (cmds == NULL((void *)0)) {
692 pr.status = CMD_PARSE_ERROR;
693 pr.error = cause;
694 return (&pr);
695 }
696 cmd_parse_build_commands(cmds, pi, &pr);
697 cmd_parse_free_commands(cmds);
698 return (&pr);
699
700}
701
702struct cmd_parse_result *
703cmd_parse_from_string(const char *s, struct cmd_parse_input *pi)
704{
705 struct cmd_parse_input input;
706
707 if (pi == NULL((void *)0)) {
708 memset(&input, 0, sizeof input);
709 pi = &input;
710 }
711
712 /*
713 * When parsing a string, put commands in one group even if there are
714 * multiple lines. This means { a \n b } is identical to "a ; b" when
715 * given as an argument to another command.
716 */
717 pi->flags |= CMD_PARSE_ONEGROUP0x10;
718 return (cmd_parse_from_buffer(s, strlen(s), pi));
719}
720
721enum cmd_parse_status
722cmd_parse_and_insert(const char *s, struct cmd_parse_input *pi,
723 struct cmdq_item *after, struct cmdq_state *state, char **error)
724{
725 struct cmd_parse_result *pr;
726 struct cmdq_item *item;
727
728 pr = cmd_parse_from_string(s, pi);
729 switch (pr->status) {
730 case CMD_PARSE_ERROR:
731 if (error != NULL((void *)0))
732 *error = pr->error;
733 else
734 free(pr->error);
735 break;
736 case CMD_PARSE_SUCCESS:
737 item = cmdq_get_command(pr->cmdlist, state);
738 cmdq_insert_after(after, item);
739 cmd_list_free(pr->cmdlist);
740 break;
741 }
742 return (pr->status);
743}
744
745enum cmd_parse_status
746cmd_parse_and_append(const char *s, struct cmd_parse_input *pi,
747 struct client *c, struct cmdq_state *state, char **error)
748{
749 struct cmd_parse_result *pr;
750 struct cmdq_item *item;
751
752 pr = cmd_parse_from_string(s, pi);
753 switch (pr->status) {
754 case CMD_PARSE_ERROR:
755 if (error != NULL((void *)0))
756 *error = pr->error;
757 else
758 free(pr->error);
759 break;
760 case CMD_PARSE_SUCCESS:
761 item = cmdq_get_command(pr->cmdlist, state);
762 cmdq_append(c, item);
763 cmd_list_free(pr->cmdlist);
764 break;
765 }
766 return (pr->status);
767}
768
769struct cmd_parse_result *
770cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi)
771{
772 static struct cmd_parse_result pr;
773 struct cmd_parse_input input;
774 struct cmd_parse_commands *cmds;
775 char *cause;
776
777 if (pi == NULL((void *)0)) {
778 memset(&input, 0, sizeof input);
779 pi = &input;
780 }
781 memset(&pr, 0, sizeof pr);
782
783 if (len == 0) {
784 pr.status = CMD_PARSE_SUCCESS;
785 pr.cmdlist = cmd_list_new();
786 return (&pr);
787 }
788
789 cmds = cmd_parse_do_buffer(buf, len, pi, &cause);
790 if (cmds == NULL((void *)0)) {
791 pr.status = CMD_PARSE_ERROR;
792 pr.error = cause;
793 return (&pr);
794 }
795 cmd_parse_build_commands(cmds, pi, &pr);
796 cmd_parse_free_commands(cmds);
797 return (&pr);
798}
799
800struct cmd_parse_result *
801cmd_parse_from_arguments(struct args_value *values, u_int count,
802 struct cmd_parse_input *pi)
803{
804 static struct cmd_parse_result pr;
805 struct cmd_parse_input input;
806 struct cmd_parse_commands *cmds;
807 struct cmd_parse_command *cmd;
808 struct cmd_parse_argument *arg;
809 u_int i;
810 char *copy;
811 size_t size;
812 int end;
813
814 /*
815 * The commands are already split up into arguments, so just separate
816 * into a set of commands by ';'.
817 */
818
819 if (pi == NULL((void *)0)) {
820 memset(&input, 0, sizeof input);
821 pi = &input;
822 }
823 memset(&pr, 0, sizeof pr);
824
825 cmds = cmd_parse_new_commands();
826
827 cmd = xcalloc(1, sizeof *cmd);
828 cmd->line = pi->line;
829 TAILQ_INIT(&cmd->arguments)do { (&cmd->arguments)->tqh_first = ((void *)0); (&
cmd->arguments)->tqh_last = &(&cmd->arguments
)->tqh_first; } while (0)
;
830
831 for (i = 0; i < count; i++) {
832 end = 0;
833 if (values[i].type == ARGS_STRING) {
834 copy = xstrdup(values[i].string);
835 size = strlen(copy);
836 if (size != 0 && copy[size - 1] == ';') {
837 copy[--size] = '\0';
838 if (size > 0 && copy[size - 1] == '\\')
839 copy[size - 1] = ';';
840 else
841 end = 1;
842 }
843 if (!end || size != 0) {
844 arg = xcalloc(1, sizeof *arg);
845 arg->type = CMD_PARSE_STRING;
846 arg->string = copy;
847 TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry)do { (arg)->entry.tqe_next = ((void *)0); (arg)->entry.
tqe_prev = (&cmd->arguments)->tqh_last; *(&cmd->
arguments)->tqh_last = (arg); (&cmd->arguments)->
tqh_last = &(arg)->entry.tqe_next; } while (0)
;
848 }
849 } else if (values[i].type == ARGS_COMMANDS) {
850 arg = xcalloc(1, sizeof *arg);
851 arg->type = CMD_PARSE_PARSED_COMMANDS;
852 arg->cmdlist = values[i].cmdlist;
853 arg->cmdlist->references++;
854 TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry)do { (arg)->entry.tqe_next = ((void *)0); (arg)->entry.
tqe_prev = (&cmd->arguments)->tqh_last; *(&cmd->
arguments)->tqh_last = (arg); (&cmd->arguments)->
tqh_last = &(arg)->entry.tqe_next; } while (0)
;
855 } else
856 fatalx("unknown argument type");
857 if (end) {
858 TAILQ_INSERT_TAIL(cmds, cmd, entry)do { (cmd)->entry.tqe_next = ((void *)0); (cmd)->entry.
tqe_prev = (cmds)->tqh_last; *(cmds)->tqh_last = (cmd);
(cmds)->tqh_last = &(cmd)->entry.tqe_next; } while
(0)
;
859 cmd = xcalloc(1, sizeof *cmd);
860 cmd->line = pi->line;
861 TAILQ_INIT(&cmd->arguments)do { (&cmd->arguments)->tqh_first = ((void *)0); (&
cmd->arguments)->tqh_last = &(&cmd->arguments
)->tqh_first; } while (0)
;
862 }
863 }
864 if (!TAILQ_EMPTY(&cmd->arguments)(((&cmd->arguments)->tqh_first) == ((void *)0)))
865 TAILQ_INSERT_TAIL(cmds, cmd, entry)do { (cmd)->entry.tqe_next = ((void *)0); (cmd)->entry.
tqe_prev = (cmds)->tqh_last; *(cmds)->tqh_last = (cmd);
(cmds)->tqh_last = &(cmd)->entry.tqe_next; } while
(0)
;
866 else
867 free(cmd);
868
869 cmd_parse_build_commands(cmds, pi, &pr);
870 cmd_parse_free_commands(cmds);
871 return (&pr);
872}
873
874static int printflike(1, 2)__attribute__ ((format (printf, 1, 2)))
875yyerror(const char *fmt, ...)
876{
877 struct cmd_parse_state *ps = &parse_state;
878 struct cmd_parse_input *pi = ps->input;
879 va_list ap;
880 char *error;
881
882 if (ps->error != NULL((void *)0))
883 return (0);
884
885 va_start(ap, fmt)__builtin_va_start(ap, fmt);
886 xvasprintf(&error, fmt, ap);
887 va_end(ap)__builtin_va_end(ap);
888
889 ps->error = cmd_parse_get_error(pi->file, pi->line, error);
890 free(error);
891 return (0);
892}
893
894static int
895yylex_is_var(char ch, int first)
896{
897 if (ch == '=')
898 return (0);
899 if (first && isdigit((u_char)ch))
900 return (0);
901 return (isalnum((u_char)ch) || ch == '_');
902}
903
904static void
905yylex_append(char **buf, size_t *len, const char *add, size_t addlen)
906{
907 if (addlen > SIZE_MAX0xffffffffffffffffUL - 1 || *len > SIZE_MAX0xffffffffffffffffUL - 1 - addlen)
908 fatalx("buffer is too big");
909 *buf = xrealloc(*buf, (*len) + 1 + addlen);
910 memcpy((*buf) + *len, add, addlen);
911 (*len) += addlen;
912}
913
914static void
915yylex_append1(char **buf, size_t *len, char add)
916{
917 yylex_append(buf, len, &add, 1);
918}
919
920static int
921yylex_getc1(void)
922{
923 struct cmd_parse_state *ps = &parse_state;
924 int ch;
925
926 if (ps->f != NULL((void *)0))
927 ch = getc(ps->f)(!__isthreaded ? (--(ps->f)->_r < 0 ? __srget(ps->
f) : (int)(*(ps->f)->_p++)) : (getc)(ps->f))
;
928 else {
929 if (ps->off == ps->len)
930 ch = EOF(-1);
931 else
932 ch = ps->buf[ps->off++];
933 }
934 return (ch);
935}
936
937static void
938yylex_ungetc(int ch)
939{
940 struct cmd_parse_state *ps = &parse_state;
941
942 if (ps->f != NULL((void *)0))
943 ungetc(ch, ps->f);
944 else if (ps->off > 0 && ch != EOF(-1))
945 ps->off--;
946}
947
948static int
949yylex_getc(void)
950{
951 struct cmd_parse_state *ps = &parse_state;
952 int ch;
953
954 if (ps->escapes != 0) {
955 ps->escapes--;
956 return ('\\');
957 }
958 for (;;) {
959 ch = yylex_getc1();
960 if (ch == '\\') {
961 ps->escapes++;
962 continue;
963 }
964 if (ch == '\n' && (ps->escapes % 2) == 1) {
965 ps->input->line++;
966 ps->escapes--;
967 continue;
968 }
969
970 if (ps->escapes != 0) {
971 yylex_ungetc(ch);
972 ps->escapes--;
973 return ('\\');
974 }
975 return (ch);
976 }
977}
978
979static char *
980yylex_get_word(int ch)
981{
982 char *buf;
983 size_t len;
984
985 len = 0;
986 buf = xmalloc(1);
987
988 do
989 yylex_append1(&buf, &len, ch);
990 while ((ch = yylex_getc()) != EOF(-1) && strchr(" \t\n", ch) == NULL((void *)0));
991 yylex_ungetc(ch);
992
993 buf[len] = '\0';
994 log_debug("%s: %s", __func__, buf);
995 return (buf);
996}
997
998static int
999yylex(void)
1000{
1001 struct cmd_parse_state *ps = &parse_state;
1002 char *token, *cp;
1003 int ch, next, condition;
1004
1005 if (ps->eol)
1006 ps->input->line++;
1007 ps->eol = 0;
1008
1009 condition = ps->condition;
1010 ps->condition = 0;
1011
1012 for (;;) {
1013 ch = yylex_getc();
1014
1015 if (ch == EOF(-1)) {
1016 /*
1017 * Ensure every file or string is terminated by a
1018 * newline. This keeps the parser simpler and avoids
1019 * having to add a newline to each string.
1020 */
1021 if (ps->eof)
1022 break;
1023 ps->eof = 1;
1024 return ('\n');
1025 }
1026
1027 if (ch == ' ' || ch == '\t') {
1028 /*
1029 * Ignore whitespace.
1030 */
1031 continue;
1032 }
1033
1034 if (ch == '\n') {
1035 /*
1036 * End of line. Update the line number.
1037 */
1038 ps->eol = 1;
1039 return ('\n');
1040 }
1041
1042 if (ch == ';' || ch == '{' || ch == '}') {
1043 /*
1044 * A semicolon or { or } is itself.
1045 */
1046 return (ch);
1047 }
1048
1049 if (ch == '#') {
1050 /*
1051 * #{ after a condition opens a format; anything else
1052 * is a comment, ignore up to the end of the line.
1053 */
1054 next = yylex_getc();
1055 if (condition && next == '{') {
1056 yylval.token = yylex_format();
1057 if (yylval.token == NULL((void *)0))
1058 return (ERROR257);
1059 return (FORMAT263);
1060 }
1061 while (next != '\n' && next != EOF(-1))
1062 next = yylex_getc();
1063 if (next == '\n') {
1064 ps->input->line++;
1065 return ('\n');
1066 }
1067 continue;
1068 }
1069
1070 if (ch == '%') {
1071 /*
1072 * % is a condition unless it is all % or all numbers,
1073 * then it is a token.
1074 */
1075 yylval.token = yylex_get_word('%');
1076 for (cp = yylval.token; *cp != '\0'; cp++) {
1077 if (*cp != '%' && !isdigit((u_char)*cp))
1078 break;
1079 }
1080 if (*cp == '\0')
1081 return (TOKEN264);
1082 ps->condition = 1;
1083 if (strcmp(yylval.token, "%hidden") == 0) {
1084 free(yylval.token);
1085 return (HIDDEN258);
1086 }
1087 if (strcmp(yylval.token, "%if") == 0) {
1088 free(yylval.token);
1089 return (IF259);
1090 }
1091 if (strcmp(yylval.token, "%else") == 0) {
1092 free(yylval.token);
1093 return (ELSE260);
1094 }
1095 if (strcmp(yylval.token, "%elif") == 0) {
1096 free(yylval.token);
1097 return (ELIF261);
1098 }
1099 if (strcmp(yylval.token, "%endif") == 0) {
1100 free(yylval.token);
1101 return (ENDIF262);
1102 }
1103 free(yylval.token);
1104 return (ERROR257);
1105 }
1106
1107 /*
1108 * Otherwise this is a token.
1109 */
1110 token = yylex_token(ch);
1111 if (token == NULL((void *)0))
1112 return (ERROR257);
1113 yylval.token = token;
1114
1115 if (strchr(token, '=') != NULL((void *)0) && yylex_is_var(*token, 1)) {
1116 for (cp = token + 1; *cp != '='; cp++) {
1117 if (!yylex_is_var(*cp, 0))
1118 break;
1119 }
1120 if (*cp == '=')
1121 return (EQUALS265);
1122 }
1123 return (TOKEN264);
1124 }
1125 return (0);
1126}
1127
1128static char *
1129yylex_format(void)
1130{
1131 char *buf;
1132 size_t len;
1133 int ch, brackets = 1;
1134
1135 len = 0;
1136 buf = xmalloc(1);
1137
1138 yylex_append(&buf, &len, "#{", 2);
1139 for (;;) {
1140 if ((ch = yylex_getc()) == EOF(-1) || ch == '\n')
1141 goto error;
1142 if (ch == '#') {
1143 if ((ch = yylex_getc()) == EOF(-1) || ch == '\n')
1144 goto error;
1145 if (ch == '{')
1146 brackets++;
1147 yylex_append1(&buf, &len, '#');
1148 } else if (ch == '}') {
1149 if (brackets != 0 && --brackets == 0) {
1150 yylex_append1(&buf, &len, ch);
1151 break;
1152 }
1153 }
1154 yylex_append1(&buf, &len, ch);
1155 }
1156 if (brackets != 0)
1157 goto error;
1158
1159 buf[len] = '\0';
1160 log_debug("%s: %s", __func__, buf);
1161 return (buf);
1162
1163error:
1164 free(buf);
1165 return (NULL((void *)0));
1166}
1167
1168static int
1169yylex_token_escape(char **buf, size_t *len)
1170{
1171 int ch, type, o2, o3, mlen;
1172 u_int size, i, tmp;
1173 char s[9], m[MB_LEN_MAX4];
1174
1175 ch = yylex_getc();
1176
1177 if (ch >= '4' && ch <= '7') {
1178 yyerror("invalid octal escape");
1179 return (0);
1180 }
1181 if (ch >= '0' && ch <= '3') {
1182 o2 = yylex_getc();
1183 if (o2 >= '0' && o2 <= '7') {
1184 o3 = yylex_getc();
1185 if (o3 >= '0' && o3 <= '7') {
1186 ch = 64 * (ch - '0') +
1187 8 * (o2 - '0') +
1188 (o3 - '0');
1189 yylex_append1(buf, len, ch);
1190 return (1);
1191 }
1192 }
1193 yyerror("invalid octal escape");
1194 return (0);
1195 }
1196
1197 switch (ch) {
1198 case EOF(-1):
1199 return (0);
1200 case 'a':
1201 ch = '\a';
1202 break;
1203 case 'b':
1204 ch = '\b';
1205 break;
1206 case 'e':
1207 ch = '\033';
1208 break;
1209 case 'f':
1210 ch = '\f';
1211 break;
1212 case 's':
1213 ch = ' ';
1214 break;
1215 case 'v':
1216 ch = '\v';
1217 break;
1218 case 'r':
1219 ch = '\r';
1220 break;
1221 case 'n':
1222 ch = '\n';
1223 break;
1224 case 't':
1225 ch = '\t';
1226 break;
1227 case 'u':
1228 type = 'u';
1229 size = 4;
1230 goto unicode;
1231 case 'U':
1232 type = 'U';
1233 size = 8;
1234 goto unicode;
1235 }
1236
1237 yylex_append1(buf, len, ch);
1238 return (1);
1239
1240unicode:
1241 for (i = 0; i < size; i++) {
1242 ch = yylex_getc();
1243 if (ch == EOF(-1) || ch == '\n')
1244 return (0);
1245 if (!isxdigit((u_char)ch)) {
1246 yyerror("invalid \\%c argument", type);
1247 return (0);
1248 }
1249 s[i] = ch;
1250 }
1251 s[i] = '\0';
1252
1253 if ((size == 4 && sscanf(s, "%4x", &tmp) != 1) ||
1254 (size == 8 && sscanf(s, "%8x", &tmp) != 1)) {
1255 yyerror("invalid \\%c argument", type);
1256 return (0);
1257 }
1258 mlen = wctomb(m, tmp);
1259 if (mlen <= 0 || mlen > (int)sizeof m) {
1260 yyerror("invalid \\%c argument", type);
1261 return (0);
1262 }
1263 yylex_append(buf, len, m, mlen);
1264 return (1);
1265}
1266
1267static int
1268yylex_token_variable(char **buf, size_t *len)
1269{
1270 struct environ_entry *envent;
1271 int ch, brackets = 0;
1272 char name[1024];
1273 size_t namelen = 0;
1274 const char *value;
1275
1276 ch = yylex_getc();
1277 if (ch == EOF(-1))
1278 return (0);
1279 if (ch == '{')
1280 brackets = 1;
1281 else {
1282 if (!yylex_is_var(ch, 1)) {
1283 yylex_append1(buf, len, '$');
1284 yylex_ungetc(ch);
1285 return (1);
1286 }
1287 name[namelen++] = ch;
1288 }
1289
1290 for (;;) {
1291 ch = yylex_getc();
1292 if (brackets && ch == '}')
1293 break;
1294 if (ch == EOF(-1) || !yylex_is_var(ch, 0)) {
1295 if (!brackets) {
1296 yylex_ungetc(ch);
1297 break;
1298 }
1299 yyerror("invalid environment variable");
1300 return (0);
1301 }
1302 if (namelen == (sizeof name) - 2) {
1303 yyerror("environment variable is too long");
1304 return (0);
1305 }
1306 name[namelen++] = ch;
1307 }
1308 name[namelen] = '\0';
1309
1310 envent = environ_find(global_environ, name);
1311 if (envent != NULL((void *)0) && envent->value != NULL((void *)0)) {
1312 value = envent->value;
1313 log_debug("%s: %s -> %s", __func__, name, value);
1314 yylex_append(buf, len, value, strlen(value));
1315 }
1316 return (1);
1317}
1318
1319static int
1320yylex_token_tilde(char **buf, size_t *len)
1321{
1322 struct environ_entry *envent;
1323 int ch;
1324 char name[1024];
1325 size_t namelen = 0;
1326 struct passwd *pw;
1327 const char *home = NULL((void *)0);
1328
1329 for (;;) {
1330 ch = yylex_getc();
1331 if (ch == EOF(-1) || strchr("/ \t\n\"'", ch) != NULL((void *)0)) {
1332 yylex_ungetc(ch);
1333 break;
1334 }
1335 if (namelen == (sizeof name) - 2) {
1336 yyerror("user name is too long");
1337 return (0);
1338 }
1339 name[namelen++] = ch;
1340 }
1341 name[namelen] = '\0';
1342
1343 if (*name == '\0') {
1344 envent = environ_find(global_environ, "HOME");
1345 if (envent != NULL((void *)0) && *envent->value != '\0')
1346 home = envent->value;
1347 else if ((pw = getpwuid(getuid())) != NULL((void *)0))
1348 home = pw->pw_dir;
1349 } else {
1350 if ((pw = getpwnam(name)) != NULL((void *)0))
1351 home = pw->pw_dir;
1352 }
1353 if (home == NULL((void *)0))
1354 return (0);
1355
1356 log_debug("%s: ~%s -> %s", __func__, name, home);
1357 yylex_append(buf, len, home, strlen(home));
1358 return (1);
1359}
1360
1361static char *
1362yylex_token(int ch)
1363{
1364 char *buf;
1365 size_t len;
1366 enum { START,
1367 NONE,
1368 DOUBLE_QUOTES,
1369 SINGLE_QUOTES } state = NONE, last = START;
1370
1371 len = 0;
1372 buf = xmalloc(1);
1373
1374 for (;;) {
1375 /* EOF or \n are always the end of the token. */
1376 if (ch == EOF(-1) || (state == NONE && ch == '\n'))
1377 break;
1378
1379 /* Whitespace or ; or } ends a token unless inside quotes. */
1380 if ((ch == ' ' || ch == '\t' || ch == ';' || ch == '}') &&
1381 state == NONE)
1382 break;
1383
1384 /*
1385 * Spaces and comments inside quotes after \n are removed but
1386 * the \n is left.
1387 */
1388 if (ch == '\n' && state != NONE) {
1389 yylex_append1(&buf, &len, '\n');
1390 while ((ch = yylex_getc()) == ' ' || ch == '\t')
1391 /* nothing */;
1392 if (ch != '#')
1393 continue;
1394 ch = yylex_getc();
1395 if (strchr(",#{}:", ch) != NULL((void *)0)) {
1396 yylex_ungetc(ch);
1397 ch = '#';
1398 } else {
1399 while ((ch = yylex_getc()) != '\n' && ch != EOF(-1))
1400 /* nothing */;
1401 }
1402 continue;
1403 }
1404
1405 /* \ ~ and $ are expanded except in single quotes. */
1406 if (ch == '\\' && state != SINGLE_QUOTES) {
1407 if (!yylex_token_escape(&buf, &len))
1408 goto error;
1409 goto skip;
1410 }
1411 if (ch == '~' && last != state && state != SINGLE_QUOTES) {
1412 if (!yylex_token_tilde(&buf, &len))
1413 goto error;
1414 goto skip;
1415 }
1416 if (ch == '$' && state != SINGLE_QUOTES) {
1417 if (!yylex_token_variable(&buf, &len))
1418 goto error;
1419 goto skip;
1420 }
1421 if (ch == '}' && state == NONE)
1422 goto error; /* unmatched (matched ones were handled) */
1423
1424 /* ' and " starts or end quotes (and is consumed). */
1425 if (ch == '\'') {
1426 if (state == NONE) {
1427 state = SINGLE_QUOTES;
1428 goto next;
1429 }
1430 if (state == SINGLE_QUOTES) {
1431 state = NONE;
1432 goto next;
1433 }
1434 }
1435 if (ch == '"') {
1436 if (state == NONE) {
1437 state = DOUBLE_QUOTES;
1438 goto next;
1439 }
1440 if (state == DOUBLE_QUOTES) {
1441 state = NONE;
1442 goto next;
1443 }
1444 }
1445
1446 /* Otherwise add the character to the buffer. */
1447 yylex_append1(&buf, &len, ch);
1448
1449 skip:
1450 last = state;
1451
1452 next:
1453 ch = yylex_getc();
1454 }
1455 yylex_ungetc(ch);
1456
1457 buf[len] = '\0';
1458 log_debug("%s: %s", __func__, buf);
1459 return (buf);
1460
1461error:
1462 free(buf);
1463 return (NULL((void *)0));
1464}
1465#line 1458 "cmd-parse.c"
1466/* allocate initial stack or double stack size, up to YYMAXDEPTH */
1467static int yygrowstack(void)
1468{
1469 unsigned int newsize;
1470 long sslen;
1471 short *newss;
1472 YYSTYPE *newvs;
1473
1474 if ((newsize = yystacksize) == 0)
9
Assuming the condition is false
10
Taking false branch
1475 newsize = YYINITSTACKSIZE200;
1476 else if (newsize >= YYMAXDEPTH10000)
11
Assuming 'newsize' is < YYMAXDEPTH
12
Taking false branch
1477 return -1;
1478 else if ((newsize *= 2) > YYMAXDEPTH10000)
13
Assuming the condition is false
14
Taking false branch
1479 newsize = YYMAXDEPTH10000;
1480 sslen = yyssp - yyss;
1481#ifdef SIZE_MAX0xffffffffffffffffUL
1482#define YY_SIZE_MAX0xffffffffffffffffUL SIZE_MAX0xffffffffffffffffUL
1483#else
1484#define YY_SIZE_MAX0xffffffffffffffffUL 0xffffffffU
1485#endif
1486 if (newsize && YY_SIZE_MAX0xffffffffffffffffUL / newsize < sizeof *newss)
15
Assuming 'newsize' is 0
1487 goto bail;
1488 newss = (short *)realloc(yyss, newsize * sizeof *newss);
16
Memory is released
1489 if (newss == NULL((void *)0))
17
Assuming 'newss' is equal to NULL
18
Taking true branch
1490 goto bail;
19
Control jumps to line 1504
1491 yyss = newss;
1492 yyssp = newss + sslen;
1493 if (newsize && YY_SIZE_MAX0xffffffffffffffffUL / newsize < sizeof *newvs)
1494 goto bail;
1495 newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs);
1496 if (newvs == NULL((void *)0))
1497 goto bail;
1498 yyvs = newvs;
1499 yyvsp = newvs + sslen;
1500 yystacksize = newsize;
1501 yysslim = yyss + newsize - 1;
1502 return 0;
1503bail:
1504 if (yyss)
20
Assuming 'yyss' is non-null
21
Taking true branch
1505 free(yyss);
22
Attempt to free released memory
1506 if (yyvs)
1507 free(yyvs);
1508 yyss = yyssp = NULL((void *)0);
1509 yyvs = yyvsp = NULL((void *)0);
1510 yystacksize = 0;
1511 return -1;
1512}
1513
1514#define YYABORTgoto yyabort goto yyabort
1515#define YYREJECTgoto yyabort goto yyabort
1516#define YYACCEPTgoto yyaccept goto yyaccept
1517#define YYERRORgoto yyerrlab goto yyerrlab
1518int
1519yyparse(void)
1520{
1521 int yym, yyn, yystate;
1522#if YYDEBUG0
1523 const char *yys;
1524
1525 if ((yys = getenv("YYDEBUG")))
1526 {
1527 yyn = *yys;
1528 if (yyn >= '0' && yyn <= '9')
1529 yydebug = yyn - '0';
1530 }
1531#endif /* YYDEBUG */
1532
1533 yynerrs = 0;
1534 yyerrflag = 0;
1535 yychar = (-1);
1536
1537 if (yyss == NULL((void *)0) && yygrowstack()) goto yyoverflow;
1
Assuming 'yyss' is not equal to NULL
1538 yyssp = yyss;
1539 yyvsp = yyvs;
1540 *yyssp = yystate = 0;
1541
1542yyloop:
1543 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
2
Taking false branch
1544 if (yychar
2.1
'yychar' is < 0
< 0)
3
Taking true branch
1545 {
1546 if ((yychar = yylex()) < 0) yychar = 0;
4
Taking false branch
1547#if YYDEBUG0
1548 if (yydebug)
1549 {
1550 yys = 0;
1551 if (yychar <= YYMAXTOKEN265) yys = yyname[yychar];
1552 if (!yys) yys = "illegal-symbol";
1553 printf("%sdebug: state %d, reading %d (%s)\n",
1554 YYPREFIX"yy", yystate, yychar, yys);
1555 }
1556#endif
1557 }
1558 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
5
Assuming 'yyn' is not equal to 0
6
Taking true branch
1559 yyn
5.1
'yyn' is <= YYTABLESIZE
<= YYTABLESIZE277 && yycheck[yyn] == yychar)
1560 {
1561#if YYDEBUG0
1562 if (yydebug)
1563 printf("%sdebug: state %d, shifting to state %d\n",
1564 YYPREFIX"yy", yystate, yytable[yyn]);
1565#endif
1566 if (yyssp >= yysslim && yygrowstack())
7
Assuming 'yyssp' is >= 'yysslim'
8
Calling 'yygrowstack'
1567 {
1568 goto yyoverflow;
1569 }
1570 *++yyssp = yystate = yytable[yyn];
1571 *++yyvsp = yylval;
1572 yychar = (-1);
1573 if (yyerrflag > 0) --yyerrflag;
1574 goto yyloop;
1575 }
1576 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1577 yyn <= YYTABLESIZE277 && yycheck[yyn] == yychar)
1578 {
1579 yyn = yytable[yyn];
1580 goto yyreduce;
1581 }
1582 if (yyerrflag) goto yyinrecovery;
1583#if defined(__GNUC__4)
1584 goto yynewerror;
1585#endif
1586yynewerror:
1587 yyerror("syntax error");
1588#if defined(__GNUC__4)
1589 goto yyerrlab;
1590#endif
1591yyerrlab:
1592 ++yynerrs;
1593yyinrecovery:
1594 if (yyerrflag < 3)
1595 {
1596 yyerrflag = 3;
1597 for (;;)
1598 {
1599 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE256) >= 0 &&
1600 yyn <= YYTABLESIZE277 && yycheck[yyn] == YYERRCODE256)
1601 {
1602#if YYDEBUG0
1603 if (yydebug)
1604 printf("%sdebug: state %d, error recovery shifting\
1605 to state %d\n", YYPREFIX"yy", *yyssp, yytable[yyn]);
1606#endif
1607 if (yyssp >= yysslim && yygrowstack())
1608 {
1609 goto yyoverflow;
1610 }
1611 *++yyssp = yystate = yytable[yyn];
1612 *++yyvsp = yylval;
1613 goto yyloop;
1614 }
1615 else
1616 {
1617#if YYDEBUG0
1618 if (yydebug)
1619 printf("%sdebug: error recovery discarding state %d\n",
1620 YYPREFIX"yy", *yyssp);
1621#endif
1622 if (yyssp <= yyss) goto yyabort;
1623 --yyssp;
1624 --yyvsp;
1625 }
1626 }
1627 }
1628 else
1629 {
1630 if (yychar == 0) goto yyabort;
1631#if YYDEBUG0
1632 if (yydebug)
1633 {
1634 yys = 0;
1635 if (yychar <= YYMAXTOKEN265) yys = yyname[yychar];
1636 if (!yys) yys = "illegal-symbol";
1637 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1638 YYPREFIX"yy", yystate, yychar, yys);
1639 }
1640#endif
1641 yychar = (-1);
1642 goto yyloop;
1643 }
1644yyreduce:
1645#if YYDEBUG0
1646 if (yydebug)
1647 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1648 YYPREFIX"yy", yystate, yyn, yyrule[yyn]);
1649#endif
1650 yym = yylen[yyn];
1651 if (yym)
1652 yyval = yyvsp[1-yym];
1653 else
1654 memset(&yyval, 0, sizeof yyval);
1655 switch (yyn)
1656 {
1657case 2:
1658#line 136 "/usr/src/usr.bin/tmux/cmd-parse.y"
1659{
1660 struct cmd_parse_state *ps = &parse_state;
1661
1662 ps->commands = yyvsp[0].commands;
1663 }
1664break;
1665case 3:
1666#line 143 "/usr/src/usr.bin/tmux/cmd-parse.y"
1667{
1668 yyval.commands = yyvsp[-1].commands;
1669 }
1670break;
1671case 4:
1672#line 147 "/usr/src/usr.bin/tmux/cmd-parse.y"
1673{
1674 yyval.commands = yyvsp[-2].commands;
1675 TAILQ_CONCAT(yyval.commands, yyvsp[-1].commands, entry)do { if (!(((yyvsp[-1].commands)->tqh_first) == ((void *)0
))) { *(yyval.commands)->tqh_last = (yyvsp[-1].commands)->
tqh_first; (yyvsp[-1].commands)->tqh_first->entry.tqe_prev
= (yyval.commands)->tqh_last; (yyval.commands)->tqh_last
= (yyvsp[-1].commands)->tqh_last; do { ((yyvsp[-1].commands
))->tqh_first = ((void *)0); ((yyvsp[-1].commands))->tqh_last
= &((yyvsp[-1].commands))->tqh_first; } while (0); } }
while (0)
;
1676 free(yyvsp[-1].commands);
1677 }
1678break;
1679case 5:
1680#line 154 "/usr/src/usr.bin/tmux/cmd-parse.y"
1681{
1682 yyval.commands = xmalloc (sizeof *yyval.commands);
1683 TAILQ_INIT(yyval.commands)do { (yyval.commands)->tqh_first = ((void *)0); (yyval.commands
)->tqh_last = &(yyval.commands)->tqh_first; } while
(0)
;
1684 }
1685break;
1686case 6:
1687#line 159 "/usr/src/usr.bin/tmux/cmd-parse.y"
1688{
1689 yyval.commands = xmalloc (sizeof *yyval.commands);
1690 TAILQ_INIT(yyval.commands)do { (yyval.commands)->tqh_first = ((void *)0); (yyval.commands
)->tqh_last = &(yyval.commands)->tqh_first; } while
(0)
;
1691 }
1692break;
1693case 7:
1694#line 164 "/usr/src/usr.bin/tmux/cmd-parse.y"
1695{
1696 struct cmd_parse_state *ps = &parse_state;
1697
1698 if (ps->scope == NULL((void *)0) || ps->scope->flag)
1699 yyval.commands = yyvsp[0].commands;
1700 else {
1701 yyval.commands = cmd_parse_new_commands();
1702 cmd_parse_free_commands(yyvsp[0].commands);
1703 }
1704 }
1705break;
1706case 8:
1707#line 175 "/usr/src/usr.bin/tmux/cmd-parse.y"
1708{
1709 struct cmd_parse_state *ps = &parse_state;
1710
1711 if (ps->scope == NULL((void *)0) || ps->scope->flag)
1712 yyval.commands = yyvsp[0].commands;
1713 else {
1714 yyval.commands = cmd_parse_new_commands();
1715 cmd_parse_free_commands(yyvsp[0].commands);
1716 }
1717 }
1718break;
1719case 9:
1720#line 187 "/usr/src/usr.bin/tmux/cmd-parse.y"
1721{
1722 yyval.token = yyvsp[0].token;
1723 }
1724break;
1725case 10:
1726#line 191 "/usr/src/usr.bin/tmux/cmd-parse.y"
1727{
1728 yyval.token = yyvsp[0].token;
1729 }
1730break;
1731case 11:
1732#line 196 "/usr/src/usr.bin/tmux/cmd-parse.y"
1733{
1734 struct cmd_parse_state *ps = &parse_state;
1735 struct cmd_parse_input *pi = ps->input;
1736 struct format_tree *ft;
1737 struct client *c = pi->c;
1738 struct cmd_find_state *fsp;
1739 struct cmd_find_state fs;
1740 int flags = FORMAT_NOJOBS0x4;
1741
1742 if (cmd_find_valid_state(&pi->fs))
1743 fsp = &pi->fs;
1744 else {
1745 cmd_find_from_client(&fs, c, 0);
1746 fsp = &fs;
1747 }
1748 ft = format_create(NULL((void *)0), pi->item, FORMAT_NONE0, flags);
1749 format_defaults(ft, c, fsp->s, fsp->wl, fsp->wp);
1750
1751 yyval.token = format_expand(ft, yyvsp[0].token);
1752 format_free(ft);
1753 free(yyvsp[0].token);
1754 }
1755break;
1756case 14:
1757#line 223 "/usr/src/usr.bin/tmux/cmd-parse.y"
1758{
1759 struct cmd_parse_state *ps = &parse_state;
1760 int flags = ps->input->flags;
1761
1762 if ((~flags & CMD_PARSE_PARSEONLY0x2) &&
1763 (ps->scope == NULL((void *)0) || ps->scope->flag))
1764 environ_put(global_environ, yyvsp[0].token, 0);
1765 free(yyvsp[0].token);
1766 }
1767break;
1768case 15:
1769#line 234 "/usr/src/usr.bin/tmux/cmd-parse.y"
1770{
1771 struct cmd_parse_state *ps = &parse_state;
1772 int flags = ps->input->flags;
1773
1774 if ((~flags & CMD_PARSE_PARSEONLY0x2) &&
1775 (ps->scope == NULL((void *)0) || ps->scope->flag))
1776 environ_put(global_environ, yyvsp[0].token, ENVIRON_HIDDEN0x1);
1777 free(yyvsp[0].token);
1778 }
1779break;
1780case 16:
1781#line 245 "/usr/src/usr.bin/tmux/cmd-parse.y"
1782{
1783 struct cmd_parse_state *ps = &parse_state;
1784 struct cmd_parse_scope *scope;
1785
1786 scope = xmalloc(sizeof *scope);
1787 yyval.flag = scope->flag = format_true(yyvsp[0].token);
1788 free(yyvsp[0].token);
1789
1790 if (ps->scope != NULL((void *)0))
1791 TAILQ_INSERT_HEAD(&ps->stack, ps->scope, entry)do { if (((ps->scope)->entry.tqe_next = (&ps->stack
)->tqh_first) != ((void *)0)) (&ps->stack)->tqh_first
->entry.tqe_prev = &(ps->scope)->entry.tqe_next;
else (&ps->stack)->tqh_last = &(ps->scope)->
entry.tqe_next; (&ps->stack)->tqh_first = (ps->scope
); (ps->scope)->entry.tqe_prev = &(&ps->stack
)->tqh_first; } while (0)
;
1792 ps->scope = scope;
1793 }
1794break;
1795case 17:
1796#line 259 "/usr/src/usr.bin/tmux/cmd-parse.y"
1797{
1798 struct cmd_parse_state *ps = &parse_state;
1799 struct cmd_parse_scope *scope;
1800
1801 scope = xmalloc(sizeof *scope);
1802 scope->flag = !ps->scope->flag;
1803
1804 free(ps->scope);
1805 ps->scope = scope;
1806 }
1807break;
1808case 18:
1809#line 271 "/usr/src/usr.bin/tmux/cmd-parse.y"
1810{
1811 struct cmd_parse_state *ps = &parse_state;
1812 struct cmd_parse_scope *scope;
1813
1814 scope = xmalloc(sizeof *scope);
1815 yyval.flag = scope->flag = format_true(yyvsp[0].token);
1816 free(yyvsp[0].token);
1817
1818 free(ps->scope);
1819 ps->scope = scope;
1820 }
1821break;
1822case 19:
1823#line 284 "/usr/src/usr.bin/tmux/cmd-parse.y"
1824{
1825 struct cmd_parse_state *ps = &parse_state;
1826
1827 free(ps->scope);
1828 ps->scope = TAILQ_FIRST(&ps->stack)((&ps->stack)->tqh_first);
1829 if (ps->scope != NULL((void *)0))
1830 TAILQ_REMOVE(&ps->stack, ps->scope, entry)do { if (((ps->scope)->entry.tqe_next) != ((void *)0)) (
ps->scope)->entry.tqe_next->entry.tqe_prev = (ps->
scope)->entry.tqe_prev; else (&ps->stack)->tqh_last
= (ps->scope)->entry.tqe_prev; *(ps->scope)->entry
.tqe_prev = (ps->scope)->entry.tqe_next; ; ; } while (0
)
;
1831 }
1832break;
1833case 20:
1834#line 294 "/usr/src/usr.bin/tmux/cmd-parse.y"
1835{
1836 if (yyvsp[-3].flag)
1837 yyval.commands = yyvsp[-1].commands;
1838 else {
1839 yyval.commands = cmd_parse_new_commands();
1840 cmd_parse_free_commands(yyvsp[-1].commands);
1841 }
1842 }
1843break;
1844case 21:
1845#line 303 "/usr/src/usr.bin/tmux/cmd-parse.y"
1846{
1847 if (yyvsp[-6].flag) {
1848 yyval.commands = yyvsp[-4].commands;
1849 cmd_parse_free_commands(yyvsp[-1].commands);
1850 } else {
1851 yyval.commands = yyvsp[-1].commands;
1852 cmd_parse_free_commands(yyvsp[-4].commands);
1853 }
1854 }
1855break;
1856case 22:
1857#line 313 "/usr/src/usr.bin/tmux/cmd-parse.y"
1858{
1859 if (yyvsp[-4].flag) {
1860 yyval.commands = yyvsp[-2].commands;
1861 cmd_parse_free_commands(yyvsp[-1].elif.commands);
1862 } else if (yyvsp[-1].elif.flag) {
1863 yyval.commands = yyvsp[-1].elif.commands;
1864 cmd_parse_free_commands(yyvsp[-2].commands);
1865 } else {
1866 yyval.commands = cmd_parse_new_commands();
1867 cmd_parse_free_commands(yyvsp[-2].commands);
1868 cmd_parse_free_commands(yyvsp[-1].elif.commands);
1869 }
1870 }
1871break;
1872case 23:
1873#line 327 "/usr/src/usr.bin/tmux/cmd-parse.y"
1874{
1875 if (yyvsp[-7].flag) {
1876 yyval.commands = yyvsp[-5].commands;
1877 cmd_parse_free_commands(yyvsp[-4].elif.commands);
1878 cmd_parse_free_commands(yyvsp[-1].commands);
1879 } else if (yyvsp[-4].elif.flag) {
1880 yyval.commands = yyvsp[-4].elif.commands;
1881 cmd_parse_free_commands(yyvsp[-5].commands);
1882 cmd_parse_free_commands(yyvsp[-1].commands);
1883 } else {
1884 yyval.commands = yyvsp[-1].commands;
1885 cmd_parse_free_commands(yyvsp[-5].commands);
1886 cmd_parse_free_commands(yyvsp[-4].elif.commands);
1887 }
1888 }
1889break;
1890case 24:
1891#line 344 "/usr/src/usr.bin/tmux/cmd-parse.y"
1892{
1893 if (yyvsp[-2].flag) {
1894 yyval.elif.flag = 1;
1895 yyval.elif.commands = yyvsp[0].commands;
1896 } else {
1897 yyval.elif.flag = 0;
1898 yyval.elif.commands = cmd_parse_new_commands();
1899 cmd_parse_free_commands(yyvsp[0].commands);
1900 }
1901 }
1902break;
1903case 25:
1904#line 355 "/usr/src/usr.bin/tmux/cmd-parse.y"
1905{
1906 if (yyvsp[-3].flag) {
1907 yyval.elif.flag = 1;
1908 yyval.elif.commands = yyvsp[-1].commands;
1909 cmd_parse_free_commands(yyvsp[0].elif.commands);
1910 } else if (yyvsp[0].elif.flag) {
1911 yyval.elif.flag = 1;
1912 yyval.elif.commands = yyvsp[0].elif.commands;
1913 cmd_parse_free_commands(yyvsp[-1].commands);
1914 } else {
1915 yyval.elif.flag = 0;
1916 yyval.elif.commands = cmd_parse_new_commands();
1917 cmd_parse_free_commands(yyvsp[-1].commands);
1918 cmd_parse_free_commands(yyvsp[0].elif.commands);
1919 }
1920 }
1921break;
1922case 26:
1923#line 373 "/usr/src/usr.bin/tmux/cmd-parse.y"
1924{
1925 struct cmd_parse_state *ps = &parse_state;
1926
1927 yyval.commands = cmd_parse_new_commands();
1928 if (!TAILQ_EMPTY(&yyvsp[0].command->arguments)(((&yyvsp[0].command->arguments)->tqh_first) == ((void
*)0))
&&
1929 (ps->scope == NULL((void *)0) || ps->scope->flag))
1930 TAILQ_INSERT_TAIL(yyval.commands, yyvsp[0].command, entry)do { (yyvsp[0].command)->entry.tqe_next = ((void *)0); (yyvsp
[0].command)->entry.tqe_prev = (yyval.commands)->tqh_last
; *(yyval.commands)->tqh_last = (yyvsp[0].command); (yyval
.commands)->tqh_last = &(yyvsp[0].command)->entry.tqe_next
; } while (0)
;
1931 else
1932 cmd_parse_free_command(yyvsp[0].command);
1933 }
1934break;
1935case 27:
1936#line 384 "/usr/src/usr.bin/tmux/cmd-parse.y"
1937{
1938 yyval.commands = yyvsp[-1].commands;
1939 }
1940break;
1941case 28:
1942#line 388 "/usr/src/usr.bin/tmux/cmd-parse.y"
1943{
1944 yyval.commands = yyvsp[-2].commands;
1945 TAILQ_CONCAT(yyval.commands, yyvsp[0].commands, entry)do { if (!(((yyvsp[0].commands)->tqh_first) == ((void *)0)
)) { *(yyval.commands)->tqh_last = (yyvsp[0].commands)->
tqh_first; (yyvsp[0].commands)->tqh_first->entry.tqe_prev
= (yyval.commands)->tqh_last; (yyval.commands)->tqh_last
= (yyvsp[0].commands)->tqh_last; do { ((yyvsp[0].commands
))->tqh_first = ((void *)0); ((yyvsp[0].commands))->tqh_last
= &((yyvsp[0].commands))->tqh_first; } while (0); } }
while (0)
;
1946 free(yyvsp[0].commands);
1947 }
1948break;
1949case 29:
1950#line 394 "/usr/src/usr.bin/tmux/cmd-parse.y"
1951{
1952 struct cmd_parse_state *ps = &parse_state;
1953
1954 if (!TAILQ_EMPTY(&yyvsp[0].command->arguments)(((&yyvsp[0].command->arguments)->tqh_first) == ((void
*)0))
&&
1955 (ps->scope == NULL((void *)0) || ps->scope->flag)) {
1956 yyval.commands = yyvsp[-2].commands;
1957 TAILQ_INSERT_TAIL(yyval.commands, yyvsp[0].command, entry)do { (yyvsp[0].command)->entry.tqe_next = ((void *)0); (yyvsp
[0].command)->entry.tqe_prev = (yyval.commands)->tqh_last
; *(yyval.commands)->tqh_last = (yyvsp[0].command); (yyval
.commands)->tqh_last = &(yyvsp[0].command)->entry.tqe_next
; } while (0)
;
1958 } else {
1959 yyval.commands = cmd_parse_new_commands();
1960 cmd_parse_free_commands(yyvsp[-2].commands);
1961 cmd_parse_free_command(yyvsp[0].command);
1962 }
1963 }
1964break;
1965case 30:
1966#line 408 "/usr/src/usr.bin/tmux/cmd-parse.y"
1967{
1968 yyval.commands = yyvsp[0].commands;
1969 }
1970break;
1971case 31:
1972#line 413 "/usr/src/usr.bin/tmux/cmd-parse.y"
1973{
1974 struct cmd_parse_state *ps = &parse_state;
1975
1976 yyval.command = xcalloc(1, sizeof *yyval.command);
1977 yyval.command->line = ps->input->line;
1978 TAILQ_INIT(&yyval.command->arguments)do { (&yyval.command->arguments)->tqh_first = ((void
*)0); (&yyval.command->arguments)->tqh_last = &
(&yyval.command->arguments)->tqh_first; } while (0)
;
1979 }
1980break;
1981case 32:
1982#line 421 "/usr/src/usr.bin/tmux/cmd-parse.y"
1983{
1984 struct cmd_parse_state *ps = &parse_state;
1985 struct cmd_parse_argument *arg;
1986
1987 yyval.command = xcalloc(1, sizeof *yyval.command);
1988 yyval.command->line = ps->input->line;
1989 TAILQ_INIT(&yyval.command->arguments)do { (&yyval.command->arguments)->tqh_first = ((void
*)0); (&yyval.command->arguments)->tqh_last = &
(&yyval.command->arguments)->tqh_first; } while (0)
;
1990
1991 arg = xcalloc(1, sizeof *arg);
1992 arg->type = CMD_PARSE_STRING;
1993 arg->string = yyvsp[0].token;
1994 TAILQ_INSERT_HEAD(&yyval.command->arguments, arg, entry)do { if (((arg)->entry.tqe_next = (&yyval.command->
arguments)->tqh_first) != ((void *)0)) (&yyval.command
->arguments)->tqh_first->entry.tqe_prev = &(arg)
->entry.tqe_next; else (&yyval.command->arguments)->
tqh_last = &(arg)->entry.tqe_next; (&yyval.command
->arguments)->tqh_first = (arg); (arg)->entry.tqe_prev
= &(&yyval.command->arguments)->tqh_first; } while
(0)
;
1995 }
1996break;
1997case 33:
1998#line 435 "/usr/src/usr.bin/tmux/cmd-parse.y"
1999{
2000 struct cmd_parse_state *ps = &parse_state;
2001 struct cmd_parse_argument *arg;
2002
2003 yyval.command = xcalloc(1, sizeof *yyval.command);
2004 yyval.command->line = ps->input->line;
2005 TAILQ_INIT(&yyval.command->arguments)do { (&yyval.command->arguments)->tqh_first = ((void
*)0); (&yyval.command->arguments)->tqh_last = &
(&yyval.command->arguments)->tqh_first; } while (0)
;
2006
2007 TAILQ_CONCAT(&yyval.command->arguments, yyvsp[0].arguments, entry)do { if (!(((yyvsp[0].arguments)->tqh_first) == ((void *)0
))) { *(&yyval.command->arguments)->tqh_last = (yyvsp
[0].arguments)->tqh_first; (yyvsp[0].arguments)->tqh_first
->entry.tqe_prev = (&yyval.command->arguments)->
tqh_last; (&yyval.command->arguments)->tqh_last = (
yyvsp[0].arguments)->tqh_last; do { ((yyvsp[0].arguments))
->tqh_first = ((void *)0); ((yyvsp[0].arguments))->tqh_last
= &((yyvsp[0].arguments))->tqh_first; } while (0); } }
while (0)
;
2008 free(yyvsp[0].arguments);
2009
2010 arg = xcalloc(1, sizeof *arg);
2011 arg->type = CMD_PARSE_STRING;
2012 arg->string = yyvsp[-1].token;
2013 TAILQ_INSERT_HEAD(&yyval.command->arguments, arg, entry)do { if (((arg)->entry.tqe_next = (&yyval.command->
arguments)->tqh_first) != ((void *)0)) (&yyval.command
->arguments)->tqh_first->entry.tqe_prev = &(arg)
->entry.tqe_next; else (&yyval.command->arguments)->
tqh_last = &(arg)->entry.tqe_next; (&yyval.command
->arguments)->tqh_first = (arg); (arg)->entry.tqe_prev
= &(&yyval.command->arguments)->tqh_first; } while
(0)
;
2014 }
2015break;
2016case 34:
2017#line 453 "/usr/src/usr.bin/tmux/cmd-parse.y"
2018{
2019 if (yyvsp[-2].flag)
2020 yyval.commands = yyvsp[-1].commands;
2021 else {
2022 yyval.commands = cmd_parse_new_commands();
2023 cmd_parse_free_commands(yyvsp[-1].commands);
2024 }
2025 }
2026break;
2027case 35:
2028#line 462 "/usr/src/usr.bin/tmux/cmd-parse.y"
2029{
2030 if (yyvsp[-4].flag) {
2031 yyval.commands = yyvsp[-3].commands;
2032 cmd_parse_free_commands(yyvsp[-1].commands);
2033 } else {
2034 yyval.commands = yyvsp[-1].commands;
2035 cmd_parse_free_commands(yyvsp[-3].commands);
2036 }
2037 }
2038break;
2039case 36:
2040#line 472 "/usr/src/usr.bin/tmux/cmd-parse.y"
2041{
2042 if (yyvsp[-3].flag) {
2043 yyval.commands = yyvsp[-2].commands;
2044 cmd_parse_free_commands(yyvsp[-1].elif.commands);
2045 } else if (yyvsp[-1].elif.flag) {
2046 yyval.commands = yyvsp[-1].elif.commands;
2047 cmd_parse_free_commands(yyvsp[-2].commands);
2048 } else {
2049 yyval.commands = cmd_parse_new_commands();
2050 cmd_parse_free_commands(yyvsp[-2].commands);
2051 cmd_parse_free_commands(yyvsp[-1].elif.commands);
2052 }
2053 }
2054break;
2055case 37:
2056#line 486 "/usr/src/usr.bin/tmux/cmd-parse.y"
2057{
2058 if (yyvsp[-5].flag) {
2059 yyval.commands = yyvsp[-4].commands;
2060 cmd_parse_free_commands(yyvsp[-3].elif.commands);
2061 cmd_parse_free_commands(yyvsp[-1].commands);
2062 } else if (yyvsp[-3].elif.flag) {
2063 yyval.commands = yyvsp[-3].elif.commands;
2064 cmd_parse_free_commands(yyvsp[-4].commands);
2065 cmd_parse_free_commands(yyvsp[-1].commands);
2066 } else {
2067 yyval.commands = yyvsp[-1].commands;
2068 cmd_parse_free_commands(yyvsp[-4].commands);
2069 cmd_parse_free_commands(yyvsp[-3].elif.commands);
2070 }
2071 }
2072break;
2073case 38:
2074#line 503 "/usr/src/usr.bin/tmux/cmd-parse.y"
2075{
2076 if (yyvsp[-1].flag) {
2077 yyval.elif.flag = 1;
2078 yyval.elif.commands = yyvsp[0].commands;
2079 } else {
2080 yyval.elif.flag = 0;
2081 yyval.elif.commands = cmd_parse_new_commands();
2082 cmd_parse_free_commands(yyvsp[0].commands);
2083 }
2084 }
2085break;
2086case 39:
2087#line 514 "/usr/src/usr.bin/tmux/cmd-parse.y"
2088{
2089 if (yyvsp[-2].flag) {
2090 yyval.elif.flag = 1;
2091 yyval.elif.commands = yyvsp[-1].commands;
2092 cmd_parse_free_commands(yyvsp[0].elif.commands);
2093 } else if (yyvsp[0].elif.flag) {
2094 yyval.elif.flag = 1;
2095 yyval.elif.commands = yyvsp[0].elif.commands;
2096 cmd_parse_free_commands(yyvsp[-1].commands);
2097 } else {
2098 yyval.elif.flag = 0;
2099 yyval.elif.commands = cmd_parse_new_commands();
2100 cmd_parse_free_commands(yyvsp[-1].commands);
2101 cmd_parse_free_commands(yyvsp[0].elif.commands);
2102 }
2103 }
2104break;
2105case 40:
2106#line 532 "/usr/src/usr.bin/tmux/cmd-parse.y"
2107{
2108 yyval.arguments = xcalloc(1, sizeof *yyval.arguments);
2109 TAILQ_INIT(yyval.arguments)do { (yyval.arguments)->tqh_first = ((void *)0); (yyval.arguments
)->tqh_last = &(yyval.arguments)->tqh_first; } while
(0)
;
2110
2111 TAILQ_INSERT_HEAD(yyval.arguments, yyvsp[0].argument, entry)do { if (((yyvsp[0].argument)->entry.tqe_next = (yyval.arguments
)->tqh_first) != ((void *)0)) (yyval.arguments)->tqh_first
->entry.tqe_prev = &(yyvsp[0].argument)->entry.tqe_next
; else (yyval.arguments)->tqh_last = &(yyvsp[0].argument
)->entry.tqe_next; (yyval.arguments)->tqh_first = (yyvsp
[0].argument); (yyvsp[0].argument)->entry.tqe_prev = &
(yyval.arguments)->tqh_first; } while (0)
;
2112 }
2113break;
2114case 41:
2115#line 539 "/usr/src/usr.bin/tmux/cmd-parse.y"
2116{
2117 TAILQ_INSERT_HEAD(yyvsp[0].arguments, yyvsp[-1].argument, entry)do { if (((yyvsp[-1].argument)->entry.tqe_next = (yyvsp[0]
.arguments)->tqh_first) != ((void *)0)) (yyvsp[0].arguments
)->tqh_first->entry.tqe_prev = &(yyvsp[-1].argument
)->entry.tqe_next; else (yyvsp[0].arguments)->tqh_last =
&(yyvsp[-1].argument)->entry.tqe_next; (yyvsp[0].arguments
)->tqh_first = (yyvsp[-1].argument); (yyvsp[-1].argument)->
entry.tqe_prev = &(yyvsp[0].arguments)->tqh_first; } while
(0)
;
2118 yyval.arguments = yyvsp[0].arguments;
2119 }
2120break;
2121case 42:
2122#line 545 "/usr/src/usr.bin/tmux/cmd-parse.y"
2123{
2124 yyval.argument = xcalloc(1, sizeof *yyval.argument);
2125 yyval.argument->type = CMD_PARSE_STRING;
2126 yyval.argument->string = yyvsp[0].token;
2127 }
2128break;
2129case 43:
2130#line 551 "/usr/src/usr.bin/tmux/cmd-parse.y"
2131{
2132 yyval.argument = xcalloc(1, sizeof *yyval.argument);
2133 yyval.argument->type = CMD_PARSE_STRING;
2134 yyval.argument->string = yyvsp[0].token;
2135 }
2136break;
2137case 44:
2138#line 557 "/usr/src/usr.bin/tmux/cmd-parse.y"
2139{
2140 yyval.argument = xcalloc(1, sizeof *yyval.argument);
2141 yyval.argument->type = CMD_PARSE_COMMANDS;
2142 yyval.argument->commands = yyvsp[0].commands;
2143 }
2144break;
2145case 45:
2146#line 564 "/usr/src/usr.bin/tmux/cmd-parse.y"
2147{
2148 yyval.commands = yyvsp[-1].commands;
2149 }
2150break;
2151case 46:
2152#line 568 "/usr/src/usr.bin/tmux/cmd-parse.y"
2153{
2154 yyval.commands = yyvsp[-2].commands;
2155 TAILQ_CONCAT(yyval.commands, yyvsp[-1].commands, entry)do { if (!(((yyvsp[-1].commands)->tqh_first) == ((void *)0
))) { *(yyval.commands)->tqh_last = (yyvsp[-1].commands)->
tqh_first; (yyvsp[-1].commands)->tqh_first->entry.tqe_prev
= (yyval.commands)->tqh_last; (yyval.commands)->tqh_last
= (yyvsp[-1].commands)->tqh_last; do { ((yyvsp[-1].commands
))->tqh_first = ((void *)0); ((yyvsp[-1].commands))->tqh_last
= &((yyvsp[-1].commands))->tqh_first; } while (0); } }
while (0)
;
2156 free(yyvsp[-1].commands);
2157 }
2158break;
2159#line 2152 "cmd-parse.c"
2160 }
2161 yyssp -= yym;
2162 yystate = *yyssp;
2163 yyvsp -= yym;
2164 yym = yylhs[yyn];
2165 if (yystate == 0 && yym == 0)
2166 {
2167#if YYDEBUG0
2168 if (yydebug)
2169 printf("%sdebug: after reduction, shifting from state 0 to\
2170 state %d\n", YYPREFIX"yy", YYFINAL4);
2171#endif
2172 yystate = YYFINAL4;
2173 *++yyssp = YYFINAL4;
2174 *++yyvsp = yyval;
2175 if (yychar < 0)
2176 {
2177 if ((yychar = yylex()) < 0) yychar = 0;
2178#if YYDEBUG0
2179 if (yydebug)
2180 {
2181 yys = 0;
2182 if (yychar <= YYMAXTOKEN265) yys = yyname[yychar];
2183 if (!yys) yys = "illegal-symbol";
2184 printf("%sdebug: state %d, reading %d (%s)\n",
2185 YYPREFIX"yy", YYFINAL4, yychar, yys);
2186 }
2187#endif
2188 }
2189 if (yychar == 0) goto yyaccept;
2190 goto yyloop;
2191 }
2192 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
2193 yyn <= YYTABLESIZE277 && yycheck[yyn] == yystate)
2194 yystate = yytable[yyn];
2195 else
2196 yystate = yydgoto[yym];
2197#if YYDEBUG0
2198 if (yydebug)
2199 printf("%sdebug: after reduction, shifting from state %d \
2200to state %d\n", YYPREFIX"yy", *yyssp, yystate);
2201#endif
2202 if (yyssp >= yysslim && yygrowstack())
2203 {
2204 goto yyoverflow;
2205 }
2206 *++yyssp = yystate;
2207 *++yyvsp = yyval;
2208 goto yyloop;
2209yyoverflow:
2210 yyerror("yacc stack overflow");
2211yyabort:
2212 if (yyss)
2213 free(yyss);
2214 if (yyvs)
2215 free(yyvs);
2216 yyss = yyssp = NULL((void *)0);
2217 yyvs = yyvsp = NULL((void *)0);
2218 yystacksize = 0;
2219 return (1);
2220yyaccept:
2221 if (yyss)
2222 free(yyss);
2223 if (yyvs)
2224 free(yyvs);
2225 yyss = yyssp = NULL((void *)0);
2226 yyvs = yyvsp = NULL((void *)0);
2227 yystacksize = 0;
2228 return (0);
2229}