[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.16

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