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

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