[BACK]Return to cfg.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Diff for /src/usr.bin/tmux/cfg.c between version 1.70 and 1.71

version 1.70, 2019/05/20 13:23:32 version 1.71, 2019/05/23 11:13:30
Line 27 
Line 27 
   
 #include "tmux.h"  #include "tmux.h"
   
 /* Condition for %if, %elif, %else and %endif. */  
 struct cfg_cond {  
         size_t                  line;           /* line number of %if */  
         int                     met;            /* condition was met */  
         int                     skip;           /* skip later %elif/%else */  
         int                     saw_else;       /* saw a %else */  
   
         TAILQ_ENTRY(cfg_cond)   entry;  
 };  
 TAILQ_HEAD(cfg_conds, cfg_cond);  
   
 struct client            *cfg_client;  struct client            *cfg_client;
 static char              *cfg_file;  static char              *cfg_file;
 int                       cfg_finished;  int                       cfg_finished;
Line 86 
Line 75 
         struct client   *c;          struct client   *c;
   
         /*          /*
          * Configuration files are loaded without a client, so NULL is passed           * Configuration files are loaded without a client, so commands are run
          * into load_cfg() and commands run in the global queue with           * in the global queue with item->client NULL.
          * item->client NULL.  
          *           *
          * However, we must block the initial client (but just the initial           * However, we must block the initial client (but just the initial
          * client) so that its command runs after the configuration is loaded.           * client) so that its command runs after the configuration is loaded.
Line 103 
Line 91 
         }          }
   
         if (cfg_file == NULL)          if (cfg_file == NULL)
                 load_cfg(TMUX_CONF, NULL, NULL, CFG_QUIET, NULL);                  load_cfg(TMUX_CONF, NULL, NULL, CMD_PARSE_QUIET, NULL);
   
         if (cfg_file == NULL && (home = find_home()) != NULL) {          if (cfg_file == NULL && (home = find_home()) != NULL) {
                 xasprintf(&cfg_file, "%s/.tmux.conf", home);                  xasprintf(&cfg_file, "%s/.tmux.conf", home);
                 flags = CFG_QUIET;                  flags = CMD_PARSE_QUIET;
         }          }
         if (cfg_file != NULL)          if (cfg_file != NULL)
                 load_cfg(cfg_file, NULL, NULL, flags, NULL);                  load_cfg(cfg_file, NULL, NULL, flags, NULL);
Line 115 
Line 103 
         cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));          cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));
 }  }
   
 static int  
 cfg_check_cond(const char *path, size_t line, const char *p, int *skip,  
     struct client *c, struct cmd_find_state *fs)  
 {  
         struct format_tree      *ft;  
         char                    *s;  
         int                      result;  
   
         while (isspace((u_char)*p))  
                 p++;  
         if (p[0] == '\0') {  
                 cfg_add_cause("%s:%zu: invalid condition", path, line);  
                 *skip = 1;  
                 return (0);  
         }  
   
         ft = format_create(NULL, NULL, FORMAT_NONE, FORMAT_NOJOBS);  
         if (fs != NULL)  
                 format_defaults(ft, c, fs->s, fs->wl, fs->wp);  
         else  
                 format_defaults(ft, c, NULL, NULL, NULL);  
         s = format_expand(ft, p);  
         result = format_true(s);  
         free(s);  
         format_free(ft);  
   
         *skip = result;  
         return (result);  
 }  
   
 static void  
 cfg_handle_if(const char *path, size_t line, struct cfg_conds *conds,  
     const char *p, struct client *c, struct cmd_find_state *fs)  
 {  
         struct cfg_cond *cond;  
         struct cfg_cond *parent = TAILQ_FIRST(conds);  
   
         /*  
          * Add a new condition. If a previous condition exists and isn't  
          * currently met, this new one also can't be met.  
          */  
         cond = xcalloc(1, sizeof *cond);  
         cond->line = line;  
         if (parent == NULL || parent->met)  
                 cond->met = cfg_check_cond(path, line, p, &cond->skip, c, fs);  
         else  
                 cond->skip = 1;  
         cond->saw_else = 0;  
         TAILQ_INSERT_HEAD(conds, cond, entry);  
 }  
   
 static void  
 cfg_handle_elif(const char *path, size_t line, struct cfg_conds *conds,  
     const char *p, struct client *c, struct cmd_find_state *fs)  
 {  
         struct cfg_cond *cond = TAILQ_FIRST(conds);  
   
         /*  
          * If a previous condition exists and wasn't met, check this  
          * one instead and change the state.  
          */  
         if (cond == NULL || cond->saw_else)  
                 cfg_add_cause("%s:%zu: unexpected %%elif", path, line);  
         else if (!cond->skip)  
                 cond->met = cfg_check_cond(path, line, p, &cond->skip, c, fs);  
         else  
                 cond->met = 0;  
 }  
   
 static void  
 cfg_handle_else(const char *path, size_t line, struct cfg_conds *conds)  
 {  
         struct cfg_cond *cond = TAILQ_FIRST(conds);  
   
         /*  
          * If a previous condition exists and wasn't met and wasn't already  
          * %else, use this one instead.  
          */  
         if (cond == NULL || cond->saw_else) {  
                 cfg_add_cause("%s:%zu: unexpected %%else", path, line);  
                 return;  
         }  
         cond->saw_else = 1;  
         cond->met = !cond->skip;  
         cond->skip = 1;  
 }  
   
 static void  
 cfg_handle_endif(const char *path, size_t line, struct cfg_conds *conds)  
 {  
         struct cfg_cond *cond = TAILQ_FIRST(conds);  
   
         /*  
          * Remove previous condition if one exists.  
          */  
         if (cond == NULL) {  
                 cfg_add_cause("%s:%zu: unexpected %%endif", path, line);  
                 return;  
         }  
         TAILQ_REMOVE(conds, cond, entry);  
         free(cond);  
 }  
   
 static void  
 cfg_handle_directive(const char *p, const char *path, size_t line,  
     struct cfg_conds *conds, struct client *c, struct cmd_find_state *fs)  
 {  
         int     n = 0;  
   
         while (p[n] != '\0' && !isspace((u_char)p[n]))  
                 n++;  
         if (strncmp(p, "%if", n) == 0)  
                 cfg_handle_if(path, line, conds, p + n, c, fs);  
         else if (strncmp(p, "%elif", n) == 0)  
                 cfg_handle_elif(path, line, conds, p + n, c, fs);  
         else if (strcmp(p, "%else") == 0)  
                 cfg_handle_else(path, line, conds);  
         else if (strcmp(p, "%endif") == 0)  
                 cfg_handle_endif(path, line, conds);  
         else  
                 cfg_add_cause("%s:%zu: invalid directive: %s", path, line, p);  
 }  
   
 int  int
 load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,  load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
     struct cmdq_item **new_item)      struct cmdq_item **new_item)
 {  {
         FILE                    *f;          FILE                    *f;
         const char               delim[3] = { '\\', '\\', '\0' };          struct cmd_parse_input   pi;
         u_int                    found = 0;          struct cmd_parse_result *pr;
         size_t                   line = 0;  
         char                    *buf, *cause1, *p, *q;  
         struct cmd_list         *cmdlist;  
         struct cmdq_item        *new_item0;          struct cmdq_item        *new_item0;
         struct cfg_cond         *cond, *cond1;  
         struct cfg_conds         conds;  
         struct cmd_find_state   *fs = NULL;  
         struct client           *fc = NULL;  
   
         if (item != NULL) {          if (new_item != NULL)
                 fs = &item->target;                  *new_item = NULL;
                 fc = cmd_find_client(item, NULL, 1);  
         }  
   
         TAILQ_INIT(&conds);  
   
         log_debug("loading %s", path);          log_debug("loading %s", path);
         if ((f = fopen(path, "rb")) == NULL) {          if ((f = fopen(path, "rb")) == NULL) {
                 if (errno == ENOENT && (flags & CFG_QUIET))                  if (errno == ENOENT && (flags & CMD_PARSE_QUIET))
                         return (0);                          return (0);
                 cfg_add_cause("%s: %s", path, strerror(errno));                  cfg_add_cause("%s: %s", path, strerror(errno));
                 return (-1);                  return (-1);
         }          }
   
         while ((buf = fparseln(f, NULL, &line, delim, 0)) != NULL) {          memset(&pi, 0, sizeof pi);
                 log_debug("%s: %s", path, buf);          pi.flags = flags;
           pi.file = path;
   
                 p = buf;          pr = cmd_parse_from_file(f, &pi);
                 while (isspace((u_char)*p))  
                         p++;  
                 if (*p == '\0') {  
                         free(buf);  
                         continue;  
                 }  
                 q = p + strlen(p) - 1;  
                 while (q != p && isspace((u_char)*q))  
                         *q-- = '\0';  
   
                 if (*p == '%') {  
                         cfg_handle_directive(p, path, line, &conds, fc, fs);  
                         continue;  
                 }  
                 cond = TAILQ_FIRST(&conds);  
                 if (cond != NULL && !cond->met)  
                         continue;  
   
                 cmdlist = cmd_string_parse(p, path, line, &cause1);  
                 if (cmdlist == NULL) {  
                         free(buf);  
                         if (cause1 == NULL)  
                                 continue;  
                         cfg_add_cause("%s:%zu: %s", path, line, cause1);  
                         free(cause1);  
                         continue;  
                 }  
                 free(buf);  
   
                 new_item0 = cmdq_get_command(cmdlist, NULL, NULL, 0);  
                 if (item != NULL) {  
                         cmdq_insert_after(item, new_item0);  
                         item = new_item0;  
                 } else  
                         cmdq_append(c, new_item0);  
                 cmd_list_free(cmdlist);  
   
                 found++;  
         }  
         fclose(f);          fclose(f);
           if (pr->status == CMD_PARSE_EMPTY)
         TAILQ_FOREACH_REVERSE_SAFE(cond, &conds, cfg_conds, entry, cond1) {                  return (0);
                 cfg_add_cause("%s:%zu: unterminated %%if", path, cond->line);          if (pr->status == CMD_PARSE_ERROR) {
                 TAILQ_REMOVE(&conds, cond, entry);                  cfg_add_cause("%s", pr->error);
                 free(cond);                  free(pr->error);
                   return (-1);
         }          }
           if (flags & CMD_PARSE_PARSEONLY) {
                   cmd_list_free(pr->cmdlist);
                   return (0);
           }
   
           new_item0 = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
           if (item != NULL)
                   cmdq_insert_after(item, new_item0);
           else
                   cmdq_append(c, new_item0);
           cmd_list_free(pr->cmdlist);
   
         if (new_item != NULL)          if (new_item != NULL)
                 *new_item = item;                  *new_item = new_item0;
         return (found);          return (0);
 }  }
   
 void  void

Legend:
Removed from v.1.70  
changed lines
  Added in v.1.71