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