Annotation of embedaddon/tmux/arguments.c, revision 1.1.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>