[BACK]Return to cmd-parse.y CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Diff for /src/usr.bin/tmux/cmd-parse.y between version 1.27 and 1.28

version 1.27, 2020/05/25 18:57:24 version 1.28, 2020/06/04 07:12:05
Line 43 
Line 43 
 };  };
   
 struct cmd_parse_command {  struct cmd_parse_command {
         char                             *name;  
         u_int                             line;          u_int                             line;
   
         int                               argc;          int                               argc;
Line 78 
Line 77 
 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 *);
   static char     *cmd_parse_commands_to_string(struct cmd_parse_commands *);
 static void      cmd_parse_print_commands(struct cmd_parse_input *, u_int,  static void      cmd_parse_print_commands(struct cmd_parse_input *, u_int,
                      struct cmd_list *);                       struct cmd_list *);
   
Line 111 
Line 111 
 %type <arguments> arguments  %type <arguments> arguments
 %type <flag> if_open if_elif  %type <flag> if_open if_elif
 %type <elif> elif elif1  %type <elif> elif elif1
 %type <commands> statements statement commands condition condition1  %type <commands> argument_statements statements statement
   %type <commands> commands condition condition1
 %type <command> command  %type <command> command
   
 %%  %%
Line 359 
Line 360 
                         struct cmd_parse_state  *ps = &parse_state;                          struct cmd_parse_state  *ps = &parse_state;
   
                         $$ = cmd_parse_new_commands();                          $$ = cmd_parse_new_commands();
                         if ($1->name != NULL &&                          if ($1->argc != 0 &&
                             (ps->scope == NULL || ps->scope->flag))                              (ps->scope == NULL || ps->scope->flag))
                                 TAILQ_INSERT_TAIL($$, $1, entry);                                  TAILQ_INSERT_TAIL($$, $1, entry);
                         else                          else
Line 379 
Line 380 
                 {                  {
                         struct cmd_parse_state  *ps = &parse_state;                          struct cmd_parse_state  *ps = &parse_state;
   
                         if ($3->name != NULL &&                          if ($3->argc != 0 &&
                             (ps->scope == NULL || ps->scope->flag)) {                              (ps->scope == NULL || ps->scope->flag)) {
                                 $$ = $1;                                  $$ = $1;
                                 TAILQ_INSERT_TAIL($$, $3, entry);                                  TAILQ_INSERT_TAIL($$, $3, entry);
Line 399 
Line 400 
                         struct cmd_parse_state  *ps = &parse_state;                          struct cmd_parse_state  *ps = &parse_state;
   
                         $$ = xcalloc(1, sizeof *$$);                          $$ = xcalloc(1, sizeof *$$);
                         $$->name = NULL;  
                         $$->line = ps->input->line;                          $$->line = ps->input->line;
                 }                  }
                 | optional_assignment TOKEN                  | optional_assignment TOKEN
Line 407 
Line 407 
                         struct cmd_parse_state  *ps = &parse_state;                          struct cmd_parse_state  *ps = &parse_state;
   
                         $$ = xcalloc(1, sizeof *$$);                          $$ = xcalloc(1, sizeof *$$);
                         $$->name = $2;  
                         $$->line = ps->input->line;                          $$->line = ps->input->line;
   
                           cmd_prepend_argv(&$$->argc, &$$->argv, $2);
   
                 }                  }
                 | optional_assignment TOKEN arguments                  | optional_assignment TOKEN arguments
                 {                  {
                         struct cmd_parse_state  *ps = &parse_state;                          struct cmd_parse_state  *ps = &parse_state;
   
                         $$ = xcalloc(1, sizeof *$$);                          $$ = xcalloc(1, sizeof *$$);
                         $$->name = $2;  
                         $$->line = ps->input->line;                          $$->line = ps->input->line;
   
                         $$->argc = $3.argc;                          $$->argc = $3.argc;
                         $$->argv = $3.argv;                          $$->argv = $3.argv;
                           cmd_prepend_argv(&$$->argc, &$$->argv, $2);
                 }                  }
   
 condition1      : if_open commands if_close  condition1      : if_open commands if_close
Line 524 
Line 525 
                 {                  {
                         $$ = $1;                          $$ = $1;
                 }                  }
                   | '{' argument_statements
                   {
                           $$ = cmd_parse_commands_to_string($2);
                           cmd_parse_free_commands($2);
                   }
   
   argument_statements     : statement '}'
                           {
                                   $$ = $1;
                           }
                           | statements '}'
                           {
                                   $$ = $1;
                           }
   
 %%  %%
   
 static char *  static char *
Line 558 
Line 573 
 static void  static void
 cmd_parse_free_command(struct cmd_parse_command *cmd)  cmd_parse_free_command(struct cmd_parse_command *cmd)
 {  {
         free(cmd->name);  
         cmd_free_argv(cmd->argc, cmd->argv);          cmd_free_argv(cmd->argc, cmd->argv);
         free(cmd);          free(cmd);
 }  }
Line 585 
Line 599 
         free(cmds);          free(cmds);
 }  }
   
   static char *
   cmd_parse_commands_to_string(struct cmd_parse_commands *cmds)
   {
           struct cmd_parse_command         *cmd;
           char                             *string = NULL, *s, *line;
   
           TAILQ_FOREACH(cmd, cmds, entry) {
                   line = cmd_stringify_argv(cmd->argc, cmd->argv);
                   if (string == NULL)
                           s = line;
                   else {
                           xasprintf(&s, "%s ; %s", s, line);
                           free(line);
                   }
   
                   free(string);
                   string = s;
           }
           if (string == NULL)
                   string = xstrdup("");
           log_debug("%s: %s", __func__, string);
           return (string);
   }
   
 static struct cmd_parse_commands *  static struct cmd_parse_commands *
 cmd_parse_run_parser(char **cause)  cmd_parse_run_parser(char **cause)
 {  {
Line 645 
Line 683 
         int                              i;          int                              i;
         struct cmd_list                 *cmdlist = NULL, *result;          struct cmd_list                 *cmdlist = NULL, *result;
         struct cmd                      *add;          struct cmd                      *add;
         char                            *alias, *cause, *s;          char                            *name, *alias, *cause, *s;
   
         /* Check for an empty list. */          /* Check for an empty list. */
         if (TAILQ_EMPTY(cmds)) {          if (TAILQ_EMPTY(cmds)) {
Line 661 
Line 699 
          * command list.           * command list.
          */           */
         TAILQ_FOREACH_SAFE(cmd, cmds, entry, next) {          TAILQ_FOREACH_SAFE(cmd, cmds, entry, next) {
                 alias = cmd_get_alias(cmd->name);                  name = cmd->argv[0];
   
                   alias = cmd_get_alias(name);
                 if (alias == NULL)                  if (alias == NULL)
                         continue;                          continue;
   
                 line = cmd->line;                  line = cmd->line;
                 log_debug("%s: %u %s = %s", __func__, line, cmd->name, alias);                  log_debug("%s: %u %s = %s", __func__, line, name, alias);
   
                 pi->line = line;                  pi->line = line;
                 cmds2 = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause);                  cmds2 = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause);
Line 683 
Line 723 
                         cmd_parse_free_command(cmd);                          cmd_parse_free_command(cmd);
                         continue;                          continue;
                 }                  }
                 for (i = 0; i < cmd->argc; i++)                  for (i = 1; i < cmd->argc; i++)
                         cmd_append_argv(&cmd2->argc, &cmd2->argv, cmd->argv[i]);                          cmd_append_argv(&cmd2->argc, &cmd2->argv, cmd->argv[i]);
   
                 after = cmd;                  after = cmd;
Line 707 
Line 747 
          */           */
         result = cmd_list_new();          result = cmd_list_new();
         TAILQ_FOREACH(cmd, cmds, entry) {          TAILQ_FOREACH(cmd, cmds, entry) {
                 log_debug("%s: %u %s", __func__, cmd->line, cmd->name);                  name = cmd->argv[0];
                   log_debug("%s: %u %s", __func__, cmd->line, name);
                 cmd_log_argv(cmd->argc, cmd->argv, __func__);                  cmd_log_argv(cmd->argc, cmd->argv, __func__);
   
                 if (cmdlist == NULL ||                  if (cmdlist == NULL ||
Line 721 
Line 762 
                 }                  }
                 line = cmd->line;                  line = cmd->line;
   
                 cmd_prepend_argv(&cmd->argc, &cmd->argv, cmd->name);  
                 add = cmd_parse(cmd->argc, cmd->argv, pi->file, line, &cause);                  add = cmd_parse(cmd->argc, cmd->argv, pi->file, line, &cause);
                 if (add == NULL) {                  if (add == NULL) {
                         cmd_list_free(result);                          cmd_list_free(result);
Line 921 
Line 961 
                             i);                              i);
   
                         cmd = xcalloc(1, sizeof *cmd);                          cmd = xcalloc(1, sizeof *cmd);
                         cmd->name = xstrdup(new_argv[0]);  
                         cmd->line = pi->line;                          cmd->line = pi->line;
   
                         cmd->argc = new_argc - 1;                          cmd->argc = new_argc;
                         cmd->argv = cmd_copy_argv(new_argc - 1, new_argv + 1);                          cmd->argv = cmd_copy_argv(new_argc, new_argv);
   
                         TAILQ_INSERT_TAIL(cmds, cmd, entry);                          TAILQ_INSERT_TAIL(cmds, cmd, entry);
                 }                  }
Line 941 
Line 980 
                             last);                              last);
   
                         cmd = xcalloc(1, sizeof *cmd);                          cmd = xcalloc(1, sizeof *cmd);
                         cmd->name = xstrdup(new_argv[0]);  
                         cmd->line = pi->line;                          cmd->line = pi->line;
   
                         cmd->argc = new_argc - 1;                          cmd->argc = new_argc;
                         cmd->argv = cmd_copy_argv(new_argc - 1, new_argv + 1);                          cmd->argv = cmd_copy_argv(new_argc, new_argv);
   
                         TAILQ_INSERT_TAIL(cmds, cmd, entry);                          TAILQ_INSERT_TAIL(cmds, cmd, entry);
                 }                  }
Line 1123 
Line 1161 
                         return ('\n');                          return ('\n');
                 }                  }
   
                 if (ch == ';') {                  if (ch == ';' || ch == '{' || ch == '}') {
                         /*                          /*
                          * A semicolon is itself.                           * A semicolon or { or } is itself.
                          */                           */
                         return (';');                          return (ch);
                 }                  }
   
                 if (ch == '#') {                  if (ch == '#') {
Line 1442 
Line 1480 
         return (1);          return (1);
 }  }
   
 static int  
 yylex_token_brace(char **buf, size_t *len)  
 {  
         struct cmd_parse_state  *ps = &parse_state;  
         int                      ch, lines = 0, nesting = 1, escape = 0;  
         int                      quote = '\0', token = 0;  
   
         /*  
          * Extract a string up to the matching unquoted '}', including newlines  
          * and handling nested braces.  
          *  
          * To detect the final and intermediate braces which affect the nesting  
          * depth, we scan the input as if it was a tmux config file, and ignore  
          * braces which would be considered quoted, escaped, or in a comment.  
          *  
          * We update the token state after every character because '#' begins a  
          * comment only when it begins a token. For simplicity, we treat an  
          * unquoted directive format as comment.  
          *  
          * The result is verbatim copy of the input excluding the final brace.  
          */  
   
         for (ch = yylex_getc1(); ch != EOF; ch = yylex_getc1()) {  
                 yylex_append1(buf, len, ch);  
                 if (ch == '\n')  
                         lines++;  
   
                 /*  
                  * If the previous character was a backslash (escape is set),  
                  * escape anything if unquoted or in double quotes, otherwise  
                  * escape only '\n' and '\\'.  
                  */  
                 if (escape &&  
                     (quote == '\0' ||  
                     quote == '"' ||  
                     ch == '\n' ||  
                     ch == '\\')) {  
                         escape = 0;  
                         if (ch != '\n')  
                                 token = 1;  
                         continue;  
                 }  
   
                 /*  
                  * The character is not escaped. If it is a backslash, set the  
                  * escape flag.  
                  */  
                 if (ch == '\\') {  
                         escape = 1;  
                         continue;  
                 }  
                 escape = 0;  
   
                 /* A newline always resets to unquoted. */  
                 if (ch == '\n') {  
                         quote = token = 0;  
                         continue;  
                 }  
   
                 if (quote) {  
                         /*  
                          * Inside quotes or comment. Check if this is the  
                          * closing quote.  
                          */  
                         if (ch == quote && quote != '#')  
                                 quote = 0;  
                         token = 1;  /* token continues regardless */  
                 } else {  
                         /* Not inside quotes or comment. */  
                         switch (ch) {  
                         case '"':  
                         case '\'':  
                         case '#':  
                                 /* Beginning of quote or maybe comment. */  
                                 if (ch != '#' || !token)  
                                         quote = ch;  
                                 token = 1;  
                                 break;  
                         case ' ':  
                         case '\t':  
                         case ';':  
                                 /* Delimiter - token resets. */  
                                 token = 0;  
                                 break;  
                         case '{':  
                                 nesting++;  
                                 token = 0; /* new commands set - token resets */  
                                 break;  
                         case '}':  
                                 nesting--;  
                                 token = 1;  /* same as after quotes */  
                                 if (nesting == 0) {  
                                         (*len)--; /* remove closing } */  
                                         ps->input->line += lines;  
                                         return (1);  
                                 }  
                                 break;  
                         default:  
                                 token = 1;  
                                 break;  
                         }  
                 }  
         }  
   
         /*  
          * Update line count after error as reporting the opening line is more  
          * useful than EOF.  
          */  
         yyerror("unterminated brace string");  
         ps->input->line += lines;  
         return (0);  
 }  
   
 static char *  static char *
 yylex_token(int ch)  yylex_token(int ch)
 {  {
Line 1580 
Line 1505 
                 }                  }
   
                 /* Whitespace or ; ends a token unless inside quotes. */                  /* Whitespace or ; ends a token unless inside quotes. */
                 if ((ch == ' ' || ch == '\t' || ch == ';') && state == NONE)                  if ((ch == ' ' || ch == '\t' || ch == ';' || ch == '}') &&
                       state == NONE)
                         break;                          break;
   
                 /*                  /*
Line 1598 
Line 1524 
                 }                  }
                 if (ch == '$' && state != SINGLE_QUOTES) {                  if (ch == '$' && state != SINGLE_QUOTES) {
                         if (!yylex_token_variable(&buf, &len))                          if (!yylex_token_variable(&buf, &len))
                                 goto error;  
                         goto skip;  
                 }  
                 if (ch == '{' && state == NONE) {  
                         if (!yylex_token_brace(&buf, &len))  
                                 goto error;                                  goto error;
                         goto skip;                          goto skip;
                 }                  }

Legend:
Removed from v.1.27  
changed lines
  Added in v.1.28