Annotation of src/usr.bin/tmux/arguments.c, Revision 1.2
1.2 ! nicm 1: /* $OpenBSD: arguments.c,v 1.1 2011/01/04 00:42:46 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 <bitstring.h>
22: #include <stdlib.h>
23: #include <string.h>
24:
25: #include "tmux.h"
26:
27: /* Create an arguments set with no flags. */
28: struct args *
29: args_create(int argc, ...)
30: {
31: struct args *args;
32: va_list ap;
33: int i;
34:
35: args = xcalloc(1, sizeof *args);
36: if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
37: fatal("bit_alloc failed");
38:
39: args->argc = argc;
40: if (argc == 0)
41: args->argv = NULL;
42: else
43: args->argv = xcalloc(argc, sizeof **args->argv);
44:
45: va_start(ap, argc);
46: for (i = 0; i < argc; i++)
47: args->argv[i] = xstrdup(va_arg(ap, char *));
48: va_end(ap);
49:
50: return (args);
51: }
52:
53: /* Parse an argv and argc into a new argument set. */
54: struct args *
55: args_parse(const char *template, int argc, char **argv)
56: {
57: struct args *args;
58: char *ptr;
59: int opt;
60:
61: args = xcalloc(1, sizeof *args);
62: if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
63: fatal("bit_alloc failed");
64:
65: optreset = 1;
66: optind = 1;
67:
68: while ((opt = getopt(argc, argv, template)) != -1) {
69: if (opt < 0 || opt >= SCHAR_MAX)
70: continue;
71: if (opt == '?' || (ptr = strchr(template, opt)) == NULL) {
72: xfree(args->flags);
73: xfree(args);
74: return (NULL);
75: }
76:
77: bit_set(args->flags, opt);
78: if (ptr[1] == ':') {
79: if (args->values[opt] != NULL)
80: xfree(args->values[opt]);
81: args->values[opt] = xstrdup(optarg);
82: }
83: }
84: argc -= optind;
85: argv += optind;
86:
87: args->argc = argc;
88: args->argv = cmd_copy_argv(argc, argv);
89:
90: return (args);
91: }
92:
93: /* Free an arguments set. */
94: void
95: args_free(struct args *args)
96: {
97: u_int i;
98:
99: cmd_free_argv(args->argc, args->argv);
100:
101: for (i = 0; i < SCHAR_MAX; i++) {
102: if (args->values[i] != NULL)
103: xfree(args->values[i]);
104: }
105:
106: xfree(args->flags);
107: xfree(args);
108: }
109:
110: /* Print a set of arguments. */
111: size_t
112: args_print(struct args *args, char *buf, size_t len)
113: {
114: size_t off;
115: int i;
116: const char *quotes;
117:
118: /* There must be at least one byte at the start. */
119: if (len == 0)
120: return (0);
121: off = 0;
122:
123: /* Process the flags first. */
124: buf[off++] = '-';
125: for (i = 0; i < SCHAR_MAX; i++) {
126: if (!bit_test(args->flags, i) || args->values[i] != NULL)
127: continue;
128:
129: if (off == len - 1) {
130: buf[off] = '\0';
131: return (len);
132: }
133: buf[off++] = i;
134: buf[off] = '\0';
135: }
136: if (off == 1)
137: buf[--off] = '\0';
138:
139: /* Then the flags with arguments. */
140: for (i = 0; i < SCHAR_MAX; i++) {
141: if (!bit_test(args->flags, i) || args->values[i] == NULL)
142: continue;
143:
144: if (off >= len) {
145: /* snprintf will have zero terminated. */
146: return (len);
147: }
148:
149: if (strchr(args->values[i], ' ') != NULL)
150: quotes = "\"";
151: else
152: quotes = "";
153: off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
154: off != 0 ? " " : "", i, quotes, args->values[i], quotes);
155: }
156:
157: /* And finally the argument vector. */
158: for (i = 0; i < args->argc; i++) {
159: if (off >= len) {
160: /* snprintf will have zero terminated. */
161: return (len);
162: }
163:
164: if (strchr(args->argv[i], ' ') != NULL)
165: quotes = "\"";
166: else
167: quotes = "";
168: off += xsnprintf(buf + off, len - off, "%s%s%s%s",
169: off != 0 ? " " : "", quotes, args->argv[i], quotes);
170: }
171:
172: return (off);
173: }
174:
175: /* Return if an argument is present. */
176: int
177: args_has(struct args *args, u_char ch)
178: {
179: return (bit_test(args->flags, ch));
180: }
181:
182: /* Set argument value. */
183: void
184: args_set(struct args *args, u_char ch, const char *value)
185: {
1.2 ! nicm 186: if (args->values[ch] != NULL)
! 187: xfree(args->values[ch]);
! 188: if (value != NULL)
1.1 nicm 189: args->values[ch] = xstrdup(value);
1.2 ! nicm 190: else
! 191: args->values[ch] = NULL;
1.1 nicm 192: bit_set(args->flags, ch);
193: }
194:
195: /* Get argument value. Will be NULL if it isn't present. */
196: const char *
197: args_get(struct args *args, u_char ch)
198: {
199: return (args->values[ch]);
200: }
201:
202: /* Convert an argument value to a number. */
203: long long
204: args_strtonum(struct args *args,
205: u_char ch, long long minval, long long maxval, char **cause)
206: {
207: const char *errstr;
208: long long ll;
209:
210: if (!args_has(args, ch)) {
211: *cause = xstrdup("missing");
212: return (0);
213: }
214:
215: ll = strtonum(args->values[ch], minval, maxval, &errstr);
216: if (errstr != NULL) {
217: *cause = xstrdup(errstr);
218: return (0);
219: }
220:
221: *cause = NULL;
222: return (ll);
223: }