Mercurial > hg > index.cgi
annotate lwlib/lw_cmdline.c @ 57:e2728091b75a
Added a \* macro parameter expansion to include all macro parameters
author | lost@l-w.ca |
---|---|
date | Wed, 06 Apr 2011 00:12:33 -0600 |
parents | 2077b755b8b4 |
children | 8b0be0fc42cf |
rev | line source |
---|---|
4 | 1 /* |
2 lw_cmdline.c | |
3 | |
4 Copyright © 2010 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
8
fdc11ef4115b
Switched lwlink to lw_cmdline from argp and also brought in lw_alloc and lw_string to replace util.c
lost@l-w.ca
parents:
6
diff
changeset
|
25 #include <ctype.h> |
4 | 26 |
27 #include "lw_alloc.h" | |
28 | |
29 #define ___lw_cmdline_c_seen___ | |
30 #include "lw_cmdline.h" | |
31 | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
32 #define DOCCOL 30 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
33 #define LLEN 78 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
34 |
4 | 35 static struct lw_cmdline_options builtin[3] = |
36 { | |
37 { "help", '?', 0, 0, "give this help list" }, | |
38 { "usage", 0, 0, 0, "give a short usage message" }, | |
39 { "version", 'V', 0, 0, "print program version" } | |
40 }; | |
41 | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
42 static int cmpr(const void *e1, const void *e2) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
43 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
44 struct lw_cmdline_options **o1, **o2; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
45 o1 = (struct lw_cmdline_options **)e1; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
46 o2 = (struct lw_cmdline_options **)e2; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
47 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
48 return strcmp((*o1) -> name, (*o2) -> name); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
49 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
50 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
51 static int cmpr2(const void *e1, const void *e2) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
52 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
53 struct lw_cmdline_options **o1, **o2; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
54 o1 = (struct lw_cmdline_options **)e1; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
55 o2 = (struct lw_cmdline_options **)e2; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
56 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
57 if ((*o1) -> key < ((*o2) -> key)) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
58 return -1; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
59 if ((*o1) -> key > ((*o2) -> key)) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
60 return 1; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
61 return 0; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
62 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
63 |
4 | 64 static void lw_cmdline_usage(struct lw_cmdline_parser *parser, char *name) |
65 { | |
66 struct lw_cmdline_options **slist, **llist; | |
67 int nopt; | |
68 int i; | |
69 int t; | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
70 int col; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
71 |
4 | 72 for (nopt = 0; parser -> options[nopt].name; nopt++) |
73 /* do nothing */ ; | |
74 | |
75 slist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3)); | |
76 llist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3)); | |
77 | |
78 for (i = 0; i < nopt; i++) | |
79 { | |
80 slist[i] = &(parser -> options[i]); | |
81 llist[i] = &(parser -> options[i]); | |
82 } | |
83 | |
84 /* now sort the two lists */ | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
85 qsort(slist, nopt, sizeof(struct lw_cmdline_options *), cmpr2); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
86 qsort(llist, nopt, sizeof(struct lw_cmdline_options *), cmpr); |
4 | 87 |
88 /* now append the automatic options */ | |
89 slist[nopt] = &(builtin[0]); | |
90 slist[nopt + 1] = &(builtin[1]); | |
91 slist[nopt + 2] = &(builtin[2]); | |
92 | |
93 llist[nopt] = &(builtin[0]); | |
94 llist[nopt + 1] = &(builtin[1]); | |
95 llist[nopt + 2] = &(builtin[2]); | |
96 | |
97 /* now show the usage message */ | |
98 printf("Usage: %s", name); | |
99 | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
100 col = 7 + strlen(name); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
101 |
4 | 102 /* print short options that take no args */ |
103 t = 0; | |
104 for (i = 0; i < nopt + 3; i++) | |
105 { | |
106 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f) | |
107 { | |
108 if (slist[i]->arg == NULL) | |
109 { | |
110 if (!t) | |
111 { | |
112 printf(" [-"); | |
113 t = 1; | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
114 col += 3; |
4 | 115 } |
116 printf("%c", slist[i]->key); | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
117 col++; |
4 | 118 } |
119 } | |
120 } | |
121 if (t) | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
122 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
123 col++; |
4 | 124 printf("]"); |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
125 } |
4 | 126 |
127 /* print short options that take args */ | |
128 for (i = 0; i < nopt + 3; i++) | |
129 { | |
130 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f && slist[i] -> arg) | |
131 { | |
132 if (slist[i]->flags & lw_cmdline_opt_optional) | |
133 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
134 t = 7 + strlen(slist[i] -> arg); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
135 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
136 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
137 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
138 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
139 } |
4 | 140 printf(" [-%c[%s]]", slist[i]->key, slist[i]->arg); |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
141 col += t; |
4 | 142 } |
143 else | |
144 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
145 t = 6 + strlen(slist[i] -> arg); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
146 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
147 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
148 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
149 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
150 } |
4 | 151 printf(" [-%c %s]", slist[i]->key, slist[i]->arg); |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
152 col += t; |
4 | 153 } |
154 } | |
155 } | |
156 | |
157 /* print long options */ | |
158 for (i = 0; i < nopt + 3; i++) | |
159 { | |
160 if (llist[i]->arg) | |
161 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
162 t = strlen(llist[i] -> name) + 6 + strlen(llist[i] -> arg); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
163 if (llist[i] -> flags & lw_cmdline_opt_optional) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
164 t += 2; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
165 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
166 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
167 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
168 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
169 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
170 printf(" [--%s%s=%s%s]", |
4 | 171 llist[i] -> name, |
172 (llist[i] -> flags & lw_cmdline_opt_optional) ? "[" : "", | |
173 llist[i] -> arg, | |
174 (llist[i] -> flags & lw_cmdline_opt_optional) ? "]" : ""); | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
175 col += t; |
4 | 176 } |
177 else | |
178 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
179 t = strlen(llist[i] -> name) + 5; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
180 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
181 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
182 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
183 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
184 } |
4 | 185 printf(" [--%s]", llist[i] -> name); |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
186 col += t; |
4 | 187 } |
188 } | |
189 | |
190 /* print "non option" text */ | |
191 if (parser -> args_doc) | |
192 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
193 if (col + strlen(parser -> args_doc) + 1 > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
194 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
195 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
196 } |
4 | 197 printf(" %s", parser -> args_doc); |
198 } | |
199 printf("\n"); | |
200 | |
201 /* clean up scratch lists */ | |
202 lw_free(slist); | |
203 lw_free(llist); | |
204 } | |
205 | |
5 | 206 static void lw_cmdline_help(struct lw_cmdline_parser *parser, char *name) |
4 | 207 { |
5 | 208 struct lw_cmdline_options **llist; |
209 int nopt; | |
210 int i; | |
211 char *tstr; | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
212 int col = 0; |
5 | 213 |
214 tstr = parser -> doc; | |
215 for (nopt = 0; parser -> options[nopt].name; nopt++) | |
216 /* do nothing */ ; | |
217 | |
218 llist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3)); | |
219 | |
220 for (i = 0; i < nopt; i++) | |
221 { | |
222 llist[i] = &(parser -> options[i]); | |
223 } | |
224 | |
225 /* now sort the list */ | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
226 qsort(llist, nopt, sizeof(struct lw_cmdline_options *), cmpr); |
5 | 227 |
228 /* now append the automatic options */ | |
229 llist[nopt] = &(builtin[0]); | |
230 llist[nopt + 1] = &(builtin[1]); | |
231 llist[nopt + 2] = &(builtin[2]); | |
232 | |
233 /* print brief usage */ | |
234 printf("Usage: %s [OPTION...] %s\n", name, parser -> args_doc ? parser -> args_doc : ""); | |
235 if (tstr) | |
236 { | |
237 while (*tstr && *tstr != '\v') | |
238 fputc(*tstr++, stdout); | |
239 if (*tstr) | |
240 tstr++; | |
241 } | |
242 fputc('\n', stdout); | |
243 fputc('\n', stdout); | |
244 | |
245 /* display options - do it the naïve way for now */ | |
246 for (i = 0; i < (nopt + 3); i++) | |
247 { | |
248 if (llist[i] -> key > 0x20 && llist[i] -> key < 0x7F) | |
249 { | |
250 printf(" -%c, ", llist[i] -> key); | |
251 } | |
252 else | |
253 { | |
254 printf(" "); | |
255 } | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
256 col = 8 + strlen(llist[i] -> name); |
5 | 257 |
258 printf("--%s", llist[i] -> name); | |
259 if (llist[i] -> arg) | |
260 { | |
261 if (llist[i] -> flags & lw_cmdline_opt_optional) | |
262 { | |
263 printf("[=%s]", llist[i] -> arg); | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
264 col += 3 + strlen(llist[i] -> arg); |
5 | 265 } |
266 else | |
267 { | |
268 printf("=%s", llist[i] -> arg); | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
269 col += 1 + strlen(llist[i] -> arg); |
5 | 270 } |
271 } | |
272 if (llist[i] -> doc) | |
273 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
274 char *s = llist[i] -> doc; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
275 char *s2; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
276 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
277 while (*s && isspace(*s)) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
278 s++; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
279 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
280 if (col > DOCCOL) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
281 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
282 fputc('\n', stdout); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
283 col = 0; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
284 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
285 while (*s) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
286 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
287 while (col < (DOCCOL - 1)) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
288 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
289 fputc(' ', stdout); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
290 col++; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
291 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
292 for (s2 = s; *s2 && !isspace(*s2); s2++) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
293 /* do nothing */ ; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
294 if ((col + (s2 - s) + 1) > LLEN && col >= DOCCOL) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
295 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
296 /* next line */ |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
297 fputc('\n', stdout); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
298 col = 0; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
299 continue; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
300 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
301 col++; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
302 fputc(' ', stdout); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
303 while (s != s2) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
304 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
305 fputc(*s, stdout); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
306 col++; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
307 s++; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
308 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
309 while (*s && isspace(*s)) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
310 s++; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
311 } |
5 | 312 } |
313 fputc('\n', stdout); | |
314 } | |
315 | |
316 printf("\nMandatory or optional arguments to long options are also mandatory or optional\nfor any corresponding short options.\n"); | |
317 | |
318 if (*tstr) | |
319 { | |
320 printf("\n%s\n", tstr); | |
321 } | |
322 | |
323 /* clean up scratch lists */ | |
324 lw_free(llist); | |
4 | 325 } |
326 | |
327 int lw_cmdline_parse(struct lw_cmdline_parser *parser, int argc, char **argv, unsigned flags, int *arg_index, void *input) | |
328 { | |
329 int i, j, r; | |
330 int firstarg; | |
331 int nextarg; | |
332 char *tstr; | |
333 int cch; | |
334 | |
335 /* first, permute the argv array so that all option arguments are at the start */ | |
336 for (i = 1, firstarg = 1; i < argc; i++) | |
337 { | |
338 if (argv[i][0] == '-' && argv[i][1]) | |
339 { | |
340 /* have an option arg */ | |
341 if (firstarg == i) | |
342 { | |
343 firstarg++; | |
344 continue; | |
345 } | |
346 tstr = argv[i]; | |
347 for (j = i; j > firstarg; j--) | |
348 { | |
349 argv[j] = argv[j - 1]; | |
350 } | |
351 argv[firstarg] = tstr; | |
352 firstarg++; | |
353 if (argv[firstarg - 1][1] == '-' && argv[firstarg - 1][2] == 0) | |
354 break; | |
355 } | |
356 } | |
357 | |
358 /* now start parsing options */ | |
359 nextarg = firstarg; | |
360 i = 1; | |
361 cch = 0; | |
362 while (i < firstarg) | |
363 { | |
364 if (cch > 0 && argv[i][cch] == 0) | |
365 { | |
366 i++; | |
367 cch = 0; | |
368 continue; | |
369 } | |
370 | |
371 if (cch > 0) | |
372 goto shortopt; | |
373 | |
374 /* skip the "--" option */ | |
375 if (argv[i][1] == '-' && argv[i][2] == 0) | |
376 break; | |
377 | |
378 if (argv[i][1] == '-') | |
379 { | |
380 goto longopt; | |
381 } | |
382 | |
383 cch = 1; | |
384 shortopt: | |
385 /* handle a short option here */ | |
386 | |
387 /* automatic options */ | |
388 if (argv[i][cch] == '?') | |
389 goto do_help; | |
390 if (argv[i][cch] == 'V') | |
391 goto do_version; | |
392 /* look up key */ | |
393 for (j = 0; parser -> options[j].name; j++) | |
394 if (parser -> options[j].key == argv[i][cch]) | |
395 break; | |
396 cch++; | |
397 tstr = argv[i] + cch; | |
398 if (!*tstr) | |
399 { | |
400 if (nextarg < argc) | |
401 tstr = argv[nextarg]; | |
402 else | |
403 tstr = NULL; | |
404 } | |
405 goto common; | |
406 | |
407 longopt: | |
408 if (strcmp(argv[i], "--help") == 0) | |
409 goto do_help; | |
410 if (strcmp(argv[i], "--usage") == 0) | |
411 goto do_usage; | |
412 if (strcmp(argv[i], "--version") == 0) | |
413 goto do_version; | |
414 /* look up name */ | |
415 | |
416 for (j = 2; argv[i][j] && argv[i][j] != '='; j++) | |
417 /* do nothing */ ; | |
418 tstr = lw_alloc(j - 1); | |
419 strncpy(tstr, argv[i] + 2, j - 2); | |
52 | 420 tstr[j - 2] = 0; |
4 | 421 if (argv[i][j] == '=') |
422 j++; | |
423 cch = j; | |
424 for (j = 0; parser -> options[j].name; j++) | |
425 { | |
426 if (strcmp(parser -> options[j].name, tstr) == 0) | |
427 break; | |
428 } | |
429 lw_free(tstr); | |
430 tstr = argv[i] + cch; | |
431 cch = 0; | |
37 | 432 i++; |
4 | 433 |
434 common: | |
435 /* j will be the offset into the option table when we get here */ | |
436 /* cch will be zero and tstr will point to the arg if it's a long option */ | |
437 /* cch will be > 0 and tstr points to the theoretical option, either within */ | |
438 /* this string or "nextarg" */ | |
439 if (parser -> options[j].name == NULL) | |
440 { | |
441 fprintf(stderr, "Unknown option. See %s --usage.\n", argv[0]); | |
442 exit(1); | |
443 } | |
444 if (parser -> options[j].arg) | |
445 { | |
446 if (tstr && cch && argv[i][cch] == 0) | |
447 nextarg++; | |
448 | |
449 if (!*tstr) | |
450 tstr = NULL; | |
451 | |
452 if (!tstr && (parser -> options[j].flags & lw_cmdline_opt_optional) == 0) | |
453 { | |
454 fprintf(stderr, "Option %s requires argument.\n", parser -> options[j].name); | |
455 } | |
456 } | |
457 r = (*(parser -> parser))(parser -> options[j].key, tstr, input); | |
458 if (r != 0) | |
459 return r; | |
460 } | |
461 /* handle non-option args */ | |
462 if (arg_index) | |
463 *arg_index = nextarg; | |
464 for (i = nextarg; i < argc; i++) | |
465 { | |
466 r = (*(parser -> parser))(lw_cmdline_key_arg, argv[i], input); | |
467 if (r != 0) | |
468 return r; | |
469 } | |
470 r = (*(parser -> parser))(lw_cmdline_key_end, NULL, input); | |
471 return r; | |
472 | |
473 do_help: | |
5 | 474 lw_cmdline_help(parser, argv[0]); |
4 | 475 exit(0); |
476 | |
477 do_version: | |
478 printf("%s\n", parser -> program_version); | |
479 exit(0); | |
480 | |
481 do_usage: | |
482 lw_cmdline_usage(parser, argv[0]); | |
483 exit(0); | |
484 } |