1 /* Id */ 2 3 /* 4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include "tmux.h" 25 26 struct cmd_list * 27 cmd_list_parse(int argc, char **argv, const char* file, u_int line, 28 char **cause) 29 { 30 struct cmd_list *cmdlist; 31 struct cmd *cmd; 32 int i, lastsplit; 33 size_t arglen, new_argc; 34 char **copy_argv, **new_argv; 35 36 copy_argv = cmd_copy_argv(argc, argv); 37 38 cmdlist = xcalloc(1, sizeof *cmdlist); 39 cmdlist->references = 1; 40 TAILQ_INIT(&cmdlist->list); 41 42 lastsplit = 0; 43 for (i = 0; i < argc; i++) { 44 arglen = strlen(copy_argv[i]); 45 if (arglen == 0 || copy_argv[i][arglen - 1] != ';') 46 continue; 47 copy_argv[i][arglen - 1] = '\0'; 48 49 if (arglen > 1 && copy_argv[i][arglen - 2] == '\\') { 50 copy_argv[i][arglen - 2] = ';'; 51 continue; 52 } 53 54 new_argc = i - lastsplit; 55 new_argv = copy_argv + lastsplit; 56 if (arglen != 1) 57 new_argc++; 58 59 cmd = cmd_parse(new_argc, new_argv, file, line, cause); 60 if (cmd == NULL) 61 goto bad; 62 TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry); 63 64 lastsplit = i + 1; 65 } 66 67 if (lastsplit != argc) { 68 cmd = cmd_parse(argc - lastsplit, copy_argv + lastsplit, 69 file, line, cause); 70 if (cmd == NULL) 71 goto bad; 72 TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry); 73 } 74 75 cmd_free_argv(argc, copy_argv); 76 return (cmdlist); 77 78 bad: 79 cmd_list_free(cmdlist); 80 cmd_free_argv(argc, copy_argv); 81 return (NULL); 82 } 83 84 void 85 cmd_list_free(struct cmd_list *cmdlist) 86 { 87 struct cmd *cmd, *cmd1; 88 89 if (--cmdlist->references != 0) 90 return; 91 92 TAILQ_FOREACH_SAFE(cmd, &cmdlist->list, qentry, cmd1) { 93 TAILQ_REMOVE(&cmdlist->list, cmd, qentry); 94 args_free(cmd->args); 95 free(cmd->file); 96 free(cmd); 97 } 98 99 free(cmdlist); 100 } 101 102 size_t 103 cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len) 104 { 105 struct cmd *cmd; 106 size_t off; 107 108 off = 0; 109 TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { 110 if (off >= len) 111 break; 112 off += cmd_print(cmd, buf + off, len - off); 113 if (off >= len) 114 break; 115 if (TAILQ_NEXT(cmd, qentry) != NULL) 116 off += xsnprintf(buf + off, len - off, " ; "); 117 } 118 return (off); 119 } 120