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

Annotation of src/usr.bin/tmux/arguments.c, Revision 1.14

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