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

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