Mercurial > hg > index.cgi
annotate lwlib/lw_cmdline.c @ 6:1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
author | lost@l-w.ca |
---|---|
date | Sat, 22 Jan 2011 09:31:43 -0700 |
parents | 0e01d1343c02 |
children | fdc11ef4115b |
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> | |
25 | |
26 #include "lw_alloc.h" | |
27 | |
28 #define ___lw_cmdline_c_seen___ | |
29 #include "lw_cmdline.h" | |
30 | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
31 #define DOCCOL 30 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
32 #define LLEN 78 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
33 |
4 | 34 static struct lw_cmdline_options builtin[3] = |
35 { | |
36 { "help", '?', 0, 0, "give this help list" }, | |
37 { "usage", 0, 0, 0, "give a short usage message" }, | |
38 { "version", 'V', 0, 0, "print program version" } | |
39 }; | |
40 | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
41 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
|
42 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
43 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
|
44 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
|
45 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
|
46 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
47 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
|
48 } |
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 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
|
51 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
52 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
|
53 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
|
54 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
|
55 |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
56 if ((*o1) -> key < ((*o2) -> key)) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
57 return -1; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
58 if ((*o1) -> key > ((*o2) -> key)) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
59 return 1; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
60 return 0; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
61 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
62 |
4 | 63 static void lw_cmdline_usage(struct lw_cmdline_parser *parser, char *name) |
64 { | |
65 struct lw_cmdline_options **slist, **llist; | |
66 int nopt; | |
67 int i; | |
68 int t; | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
69 int col; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
70 |
4 | 71 for (nopt = 0; parser -> options[nopt].name; nopt++) |
72 /* do nothing */ ; | |
73 | |
74 slist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3)); | |
75 llist = lw_alloc(sizeof(struct lw_cmdline_options *) * (nopt + 3)); | |
76 | |
77 for (i = 0; i < nopt; i++) | |
78 { | |
79 slist[i] = &(parser -> options[i]); | |
80 llist[i] = &(parser -> options[i]); | |
81 } | |
82 | |
83 /* 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
|
84 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
|
85 qsort(llist, nopt, sizeof(struct lw_cmdline_options *), cmpr); |
4 | 86 |
87 /* now append the automatic options */ | |
88 slist[nopt] = &(builtin[0]); | |
89 slist[nopt + 1] = &(builtin[1]); | |
90 slist[nopt + 2] = &(builtin[2]); | |
91 | |
92 llist[nopt] = &(builtin[0]); | |
93 llist[nopt + 1] = &(builtin[1]); | |
94 llist[nopt + 2] = &(builtin[2]); | |
95 | |
96 /* now show the usage message */ | |
97 printf("Usage: %s", name); | |
98 | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
99 col = 7 + strlen(name); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
100 |
4 | 101 /* print short options that take no args */ |
102 t = 0; | |
103 for (i = 0; i < nopt + 3; i++) | |
104 { | |
105 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f) | |
106 { | |
107 if (slist[i]->arg == NULL) | |
108 { | |
109 if (!t) | |
110 { | |
111 printf(" [-"); | |
112 t = 1; | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
113 col += 3; |
4 | 114 } |
115 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
|
116 col++; |
4 | 117 } |
118 } | |
119 } | |
120 if (t) | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
121 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
122 col++; |
4 | 123 printf("]"); |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
124 } |
4 | 125 |
126 /* print short options that take args */ | |
127 for (i = 0; i < nopt + 3; i++) | |
128 { | |
129 if (slist[i]->key > 0x20 && slist[i]->key < 0x7f && slist[i] -> arg) | |
130 { | |
131 if (slist[i]->flags & lw_cmdline_opt_optional) | |
132 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
133 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
|
134 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
135 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
136 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
137 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
138 } |
4 | 139 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
|
140 col += t; |
4 | 141 } |
142 else | |
143 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
144 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
|
145 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
146 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
147 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
148 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
149 } |
4 | 150 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
|
151 col += t; |
4 | 152 } |
153 } | |
154 } | |
155 | |
156 /* print long options */ | |
157 for (i = 0; i < nopt + 3; i++) | |
158 { | |
159 if (llist[i]->arg) | |
160 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
161 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
|
162 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
|
163 t += 2; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
164 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
165 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
166 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
167 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
168 } |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
169 printf(" [--%s%s=%s%s]", |
4 | 170 llist[i] -> name, |
171 (llist[i] -> flags & lw_cmdline_opt_optional) ? "[" : "", | |
172 llist[i] -> arg, | |
173 (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
|
174 col += t; |
4 | 175 } |
176 else | |
177 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
178 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
|
179 if (col + t > LLEN) |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
180 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
181 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
182 col = 7; |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
183 } |
4 | 184 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
|
185 col += t; |
4 | 186 } |
187 } | |
188 | |
189 /* print "non option" text */ | |
190 if (parser -> args_doc) | |
191 { | |
6
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
192 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
|
193 { |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
194 printf("\n "); |
1e5e8ec406fb
Various output cleanups for --help and --usage in lw_cmdline
lost@l-w.ca
parents:
5
diff
changeset
|
195 } |
4 | 196 printf(" %s", parser -> args_doc); |
197 } | |
198 printf("\n"); | |
199 | |
200 /* clean up scratch lists */ | |
201 lw_free(slist); | |
202 lw_free(llist); | |
203 } | |
204 | |
5 | 205 static void lw_cmdline_help(struct lw_cmdline_parser *parser, char *name) |
4 | 206 { |
5 | 207 struct lw_cmdline_options **llist; |
208 int nopt; | |
209 int i; | |
210 int t; | |
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); | |
420 tstr[j - 1] = 0; | |
421 if (argv[i][j] == '=') | |
422 j++; | |
423 cch = j; | |
424 | |
425 for (j = 0; parser -> options[j].name; j++) | |
426 { | |
427 if (strcmp(parser -> options[j].name, tstr) == 0) | |
428 break; | |
429 } | |
430 lw_free(tstr); | |
431 tstr = argv[i] + cch; | |
432 cch = 0; | |
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 } |