Annotation of embedaddon/tmux/arguments.c, revision 1.1
1.1 ! misho 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
! 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: #include <unistd.h>
! 24:
! 25: #include "tmux.h"
! 26:
! 27: /*
! 28: * Manipulate command arguments.
! 29: */
! 30:
! 31: struct args_entry {
! 32: u_char flag;
! 33: char *value;
! 34: RB_ENTRY(args_entry) entry;
! 35: };
! 36:
! 37: static void args_set(struct args *, u_char, const char *);
! 38: static struct args_entry *args_find(struct args *, u_char);
! 39:
! 40: static int args_cmp(struct args_entry *, struct args_entry *);
! 41: RB_GENERATE_STATIC(args_tree, args_entry, entry, args_cmp);
! 42:
! 43: /* Arguments tree comparison function. */
! 44: static int
! 45: args_cmp(struct args_entry *a1, struct args_entry *a2)
! 46: {
! 47: return (a1->flag - a2->flag);
! 48: }
! 49:
! 50: /* Find a flag in the arguments tree. */
! 51: static struct args_entry *
! 52: args_find(struct args *args, u_char ch)
! 53: {
! 54: struct args_entry entry;
! 55:
! 56: entry.flag = ch;
! 57: return (RB_FIND(args_tree, &args->tree, &entry));
! 58: }
! 59:
! 60: /* Parse an argv and argc into a new argument set. */
! 61: struct args *
! 62: args_parse(const char *template, int argc, char **argv)
! 63: {
! 64: struct args *args;
! 65: int opt;
! 66:
! 67: args = xcalloc(1, sizeof *args);
! 68:
! 69: optreset = 1;
! 70: optind = 1;
! 71:
! 72: while ((opt = getopt(argc, argv, template)) != -1) {
! 73: if (opt < 0)
! 74: continue;
! 75: if (opt == '?' || strchr(template, opt) == NULL) {
! 76: args_free(args);
! 77: return (NULL);
! 78: }
! 79: args_set(args, opt, optarg);
! 80: }
! 81: argc -= optind;
! 82: argv += optind;
! 83:
! 84: args->argc = argc;
! 85: args->argv = cmd_copy_argv(argc, argv);
! 86:
! 87: return (args);
! 88: }
! 89:
! 90: /* Free an arguments set. */
! 91: void
! 92: args_free(struct args *args)
! 93: {
! 94: struct args_entry *entry;
! 95: struct args_entry *entry1;
! 96:
! 97: cmd_free_argv(args->argc, args->argv);
! 98:
! 99: RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
! 100: RB_REMOVE(args_tree, &args->tree, entry);
! 101: free(entry->value);
! 102: free(entry);
! 103: }
! 104:
! 105: free(args);
! 106: }
! 107:
! 108: /* Add to string. */
! 109: static void printflike(3, 4)
! 110: args_print_add(char **buf, size_t *len, const char *fmt, ...)
! 111: {
! 112: va_list ap;
! 113: char *s;
! 114: size_t slen;
! 115:
! 116: va_start(ap, fmt);
! 117: slen = xvasprintf(&s, fmt, ap);
! 118: va_end(ap);
! 119:
! 120: *len += slen;
! 121: *buf = xrealloc(*buf, *len);
! 122:
! 123: strlcat(*buf, s, *len);
! 124: free(s);
! 125: }
! 126:
! 127: /* Print a set of arguments. */
! 128: char *
! 129: args_print(struct args *args)
! 130: {
! 131: size_t len;
! 132: char *buf, *escaped;
! 133: int i, flags;
! 134: struct args_entry *entry;
! 135: static const char quoted[] = " #\"';$";
! 136:
! 137: len = 1;
! 138: buf = xcalloc(1, len);
! 139:
! 140: /* Process the flags first. */
! 141: RB_FOREACH(entry, args_tree, &args->tree) {
! 142: if (entry->value != NULL)
! 143: continue;
! 144:
! 145: if (*buf == '\0')
! 146: args_print_add(&buf, &len, "-");
! 147: args_print_add(&buf, &len, "%c", entry->flag);
! 148: }
! 149:
! 150: /* Then the flags with arguments. */
! 151: RB_FOREACH(entry, args_tree, &args->tree) {
! 152: if (entry->value == NULL)
! 153: continue;
! 154:
! 155: if (*buf != '\0')
! 156: args_print_add(&buf, &len, " -%c ", entry->flag);
! 157: else
! 158: args_print_add(&buf, &len, "-%c ", entry->flag);
! 159:
! 160: flags = VIS_OCTAL|VIS_TAB|VIS_NL;
! 161: if (entry->value[strcspn(entry->value, quoted)] != '\0')
! 162: flags |= VIS_DQ;
! 163: utf8_stravis(&escaped, entry->value, flags);
! 164: if (flags & VIS_DQ)
! 165: args_print_add(&buf, &len, "\"%s\"", escaped);
! 166: else
! 167: args_print_add(&buf, &len, "%s", escaped);
! 168: free(escaped);
! 169: }
! 170:
! 171: /* And finally the argument vector. */
! 172: for (i = 0; i < args->argc; i++) {
! 173: if (*buf != '\0')
! 174: args_print_add(&buf, &len, " ");
! 175:
! 176: flags = VIS_OCTAL|VIS_TAB|VIS_NL;
! 177: if (args->argv[i][strcspn(args->argv[i], quoted)] != '\0')
! 178: flags |= VIS_DQ;
! 179: utf8_stravis(&escaped, args->argv[i], flags);
! 180: if (flags & VIS_DQ)
! 181: args_print_add(&buf, &len, "\"%s\"", escaped);
! 182: else
! 183: args_print_add(&buf, &len, "%s", escaped);
! 184: free(escaped);
! 185: }
! 186:
! 187: return (buf);
! 188: }
! 189:
! 190: /* Return if an argument is present. */
! 191: int
! 192: args_has(struct args *args, u_char ch)
! 193: {
! 194: return (args_find(args, ch) == NULL ? 0 : 1);
! 195: }
! 196:
! 197: /* Set argument value in the arguments tree. */
! 198: static void
! 199: args_set(struct args *args, u_char ch, const char *value)
! 200: {
! 201: struct args_entry *entry;
! 202:
! 203: /* Replace existing argument. */
! 204: if ((entry = args_find(args, ch)) != NULL) {
! 205: free(entry->value);
! 206: entry->value = NULL;
! 207: } else {
! 208: entry = xcalloc(1, sizeof *entry);
! 209: entry->flag = ch;
! 210: RB_INSERT(args_tree, &args->tree, entry);
! 211: }
! 212:
! 213: if (value != NULL)
! 214: entry->value = xstrdup(value);
! 215: }
! 216:
! 217: /* Get argument value. Will be NULL if it isn't present. */
! 218: const char *
! 219: args_get(struct args *args, u_char ch)
! 220: {
! 221: struct args_entry *entry;
! 222:
! 223: if ((entry = args_find(args, ch)) == NULL)
! 224: return (NULL);
! 225: return (entry->value);
! 226: }
! 227:
! 228: /* Convert an argument value to a number. */
! 229: long long
! 230: args_strtonum(struct args *args, u_char ch, long long minval, long long maxval,
! 231: char **cause)
! 232: {
! 233: const char *errstr;
! 234: long long ll;
! 235: struct args_entry *entry;
! 236:
! 237: if ((entry = args_find(args, ch)) == NULL) {
! 238: *cause = xstrdup("missing");
! 239: return (0);
! 240: }
! 241:
! 242: ll = strtonum(entry->value, minval, maxval, &errstr);
! 243: if (errstr != NULL) {
! 244: *cause = xstrdup(errstr);
! 245: return (0);
! 246: }
! 247:
! 248: *cause = NULL;
! 249: return (ll);
! 250: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>