Annotation of src/usr.bin/tmux/arguments.c, Revision 1.1
1.1 ! nicm 1: /* $OpenBSD: cmd.c,v 1.48 2010/12/30 23:16:18 nicm Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2010 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 <bitstring.h>
! 22: #include <stdlib.h>
! 23: #include <string.h>
! 24:
! 25: #include "tmux.h"
! 26:
! 27: /* Create an arguments set with no flags. */
! 28: struct args *
! 29: args_create(int argc, ...)
! 30: {
! 31: struct args *args;
! 32: va_list ap;
! 33: int i;
! 34:
! 35: args = xcalloc(1, sizeof *args);
! 36: if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
! 37: fatal("bit_alloc failed");
! 38:
! 39: args->argc = argc;
! 40: if (argc == 0)
! 41: args->argv = NULL;
! 42: else
! 43: args->argv = xcalloc(argc, sizeof **args->argv);
! 44:
! 45: va_start(ap, argc);
! 46: for (i = 0; i < argc; i++)
! 47: args->argv[i] = xstrdup(va_arg(ap, char *));
! 48: va_end(ap);
! 49:
! 50: return (args);
! 51: }
! 52:
! 53: /* Parse an argv and argc into a new argument set. */
! 54: struct args *
! 55: args_parse(const char *template, int argc, char **argv)
! 56: {
! 57: struct args *args;
! 58: char *ptr;
! 59: int opt;
! 60:
! 61: args = xcalloc(1, sizeof *args);
! 62: if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
! 63: fatal("bit_alloc failed");
! 64:
! 65: optreset = 1;
! 66: optind = 1;
! 67:
! 68: while ((opt = getopt(argc, argv, template)) != -1) {
! 69: if (opt < 0 || opt >= SCHAR_MAX)
! 70: continue;
! 71: if (opt == '?' || (ptr = strchr(template, opt)) == NULL) {
! 72: xfree(args->flags);
! 73: xfree(args);
! 74: return (NULL);
! 75: }
! 76:
! 77: bit_set(args->flags, opt);
! 78: if (ptr[1] == ':') {
! 79: if (args->values[opt] != NULL)
! 80: xfree(args->values[opt]);
! 81: args->values[opt] = xstrdup(optarg);
! 82: }
! 83: }
! 84: argc -= optind;
! 85: argv += optind;
! 86:
! 87: args->argc = argc;
! 88: args->argv = cmd_copy_argv(argc, argv);
! 89:
! 90: return (args);
! 91: }
! 92:
! 93: /* Free an arguments set. */
! 94: void
! 95: args_free(struct args *args)
! 96: {
! 97: u_int i;
! 98:
! 99: cmd_free_argv(args->argc, args->argv);
! 100:
! 101: for (i = 0; i < SCHAR_MAX; i++) {
! 102: if (args->values[i] != NULL)
! 103: xfree(args->values[i]);
! 104: }
! 105:
! 106: xfree(args->flags);
! 107: xfree(args);
! 108: }
! 109:
! 110: /* Print a set of arguments. */
! 111: size_t
! 112: args_print(struct args *args, char *buf, size_t len)
! 113: {
! 114: size_t off;
! 115: int i;
! 116: const char *quotes;
! 117:
! 118: /* There must be at least one byte at the start. */
! 119: if (len == 0)
! 120: return (0);
! 121: off = 0;
! 122:
! 123: /* Process the flags first. */
! 124: buf[off++] = '-';
! 125: for (i = 0; i < SCHAR_MAX; i++) {
! 126: if (!bit_test(args->flags, i) || args->values[i] != NULL)
! 127: continue;
! 128:
! 129: if (off == len - 1) {
! 130: buf[off] = '\0';
! 131: return (len);
! 132: }
! 133: buf[off++] = i;
! 134: buf[off] = '\0';
! 135: }
! 136: if (off == 1)
! 137: buf[--off] = '\0';
! 138:
! 139: /* Then the flags with arguments. */
! 140: for (i = 0; i < SCHAR_MAX; i++) {
! 141: if (!bit_test(args->flags, i) || args->values[i] == NULL)
! 142: continue;
! 143:
! 144: if (off >= len) {
! 145: /* snprintf will have zero terminated. */
! 146: return (len);
! 147: }
! 148:
! 149: if (strchr(args->values[i], ' ') != NULL)
! 150: quotes = "\"";
! 151: else
! 152: quotes = "";
! 153: off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
! 154: off != 0 ? " " : "", i, quotes, args->values[i], quotes);
! 155: }
! 156:
! 157: /* And finally the argument vector. */
! 158: for (i = 0; i < args->argc; i++) {
! 159: if (off >= len) {
! 160: /* snprintf will have zero terminated. */
! 161: return (len);
! 162: }
! 163:
! 164: if (strchr(args->argv[i], ' ') != NULL)
! 165: quotes = "\"";
! 166: else
! 167: quotes = "";
! 168: off += xsnprintf(buf + off, len - off, "%s%s%s%s",
! 169: off != 0 ? " " : "", quotes, args->argv[i], quotes);
! 170: }
! 171:
! 172: return (off);
! 173: }
! 174:
! 175: /* Return if an argument is present. */
! 176: int
! 177: args_has(struct args *args, u_char ch)
! 178: {
! 179: return (bit_test(args->flags, ch));
! 180: }
! 181:
! 182: /* Set argument value. */
! 183: void
! 184: args_set(struct args *args, u_char ch, const char *value)
! 185: {
! 186: if (value != NULL) {
! 187: if (args->values[ch] != NULL)
! 188: xfree(args->values[ch]);
! 189: args->values[ch] = xstrdup(value);
! 190: }
! 191: bit_set(args->flags, ch);
! 192: }
! 193:
! 194: /* Get argument value. Will be NULL if it isn't present. */
! 195: const char *
! 196: args_get(struct args *args, u_char ch)
! 197: {
! 198: return (args->values[ch]);
! 199: }
! 200:
! 201: /* Convert an argument value to a number. */
! 202: long long
! 203: args_strtonum(struct args *args,
! 204: u_char ch, long long minval, long long maxval, char **cause)
! 205: {
! 206: const char *errstr;
! 207: long long ll;
! 208:
! 209: if (!args_has(args, ch)) {
! 210: *cause = xstrdup("missing");
! 211: return (0);
! 212: }
! 213:
! 214: ll = strtonum(args->values[ch], minval, maxval, &errstr);
! 215: if (errstr != NULL) {
! 216: *cause = xstrdup(errstr);
! 217: return (0);
! 218: }
! 219:
! 220: *cause = NULL;
! 221: return (ll);
! 222: }