]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
2 | * parseargs.h | |
3 | * | |
4 | * Command line argument parser. | |
5 | * | |
6 | * Copyright 1996-2003 Glyph & Cog, LLC | |
7 | */ | |
8 | ||
9 | #include <stdio.h> | |
10 | #include <stddef.h> | |
11 | #include <string.h> | |
12 | #include <stdlib.h> | |
13 | #include <ctype.h> | |
14 | #include "parseargs.h" | |
15 | ||
16 | static ArgDesc *findArg(ArgDesc *args, char *arg); | |
17 | static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]); | |
18 | ||
19 | GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) { | |
20 | ArgDesc *arg; | |
21 | int i, j; | |
22 | GBool ok; | |
23 | ||
24 | ok = gTrue; | |
25 | i = 1; | |
26 | while (i < *argc) { | |
27 | if (!strcmp(argv[i], "--")) { | |
28 | --*argc; | |
29 | for (j = i; j < *argc; ++j) | |
30 | argv[j] = argv[j+1]; | |
31 | break; | |
32 | } else if ((arg = findArg(args, argv[i]))) { | |
33 | if (!grabArg(arg, i, argc, argv)) | |
34 | ok = gFalse; | |
35 | } else { | |
36 | ++i; | |
37 | } | |
38 | } | |
39 | return ok; | |
40 | } | |
41 | ||
42 | void printUsage(char *program, char *otherArgs, ArgDesc *args) { | |
43 | ArgDesc *arg; | |
44 | char *typ; | |
45 | int w, w1; | |
46 | ||
47 | w = 0; | |
48 | for (arg = args; arg->arg; ++arg) { | |
49 | if ((w1 = strlen(arg->arg)) > w) | |
50 | w = w1; | |
51 | } | |
52 | ||
53 | fprintf(stderr, "Usage: %s [options]", program); | |
54 | if (otherArgs) | |
55 | fprintf(stderr, " %s", otherArgs); | |
56 | fprintf(stderr, "\n"); | |
57 | ||
58 | for (arg = args; arg->arg; ++arg) { | |
59 | fprintf(stderr, " %s", arg->arg); | |
60 | w1 = 9 + w - strlen(arg->arg); | |
61 | switch (arg->kind) { | |
62 | case argInt: | |
63 | case argIntDummy: | |
64 | typ = " <int>"; | |
65 | break; | |
66 | case argFP: | |
67 | case argFPDummy: | |
68 | typ = " <fp>"; | |
69 | break; | |
70 | case argString: | |
71 | case argStringDummy: | |
72 | typ = " <string>"; | |
73 | break; | |
74 | case argFlag: | |
75 | case argFlagDummy: | |
76 | default: | |
77 | typ = ""; | |
78 | break; | |
79 | } | |
80 | fprintf(stderr, "%-*s", w1, typ); | |
81 | if (arg->usage) | |
82 | fprintf(stderr, ": %s", arg->usage); | |
83 | fprintf(stderr, "\n"); | |
84 | } | |
85 | } | |
86 | ||
87 | static ArgDesc *findArg(ArgDesc *args, char *arg) { | |
88 | ArgDesc *p; | |
89 | ||
90 | for (p = args; p->arg; ++p) { | |
91 | if (p->kind < argFlagDummy && !strcmp(p->arg, arg)) | |
92 | return p; | |
93 | } | |
94 | return NULL; | |
95 | } | |
96 | ||
97 | static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]) { | |
98 | int n; | |
99 | int j; | |
100 | GBool ok; | |
101 | ||
102 | ok = gTrue; | |
103 | n = 0; | |
104 | switch (arg->kind) { | |
105 | case argFlag: | |
106 | *(GBool *)arg->val = gTrue; | |
107 | n = 1; | |
108 | break; | |
109 | case argInt: | |
110 | if (i + 1 < *argc && isInt(argv[i+1])) { | |
111 | *(int *)arg->val = atoi(argv[i+1]); | |
112 | n = 2; | |
113 | } else { | |
114 | ok = gFalse; | |
115 | n = 1; | |
116 | } | |
117 | break; | |
118 | case argFP: | |
119 | if (i + 1 < *argc && isFP(argv[i+1])) { | |
120 | *(double *)arg->val = atof(argv[i+1]); | |
121 | n = 2; | |
122 | } else { | |
123 | ok = gFalse; | |
124 | n = 1; | |
125 | } | |
126 | break; | |
127 | case argString: | |
128 | if (i + 1 < *argc) { | |
129 | strncpy((char *)arg->val, argv[i+1], arg->size - 1); | |
130 | ((char *)arg->val)[arg->size - 1] = '\0'; | |
131 | n = 2; | |
132 | } else { | |
133 | ok = gFalse; | |
134 | n = 1; | |
135 | } | |
136 | break; | |
137 | default: | |
138 | fprintf(stderr, "Internal error in arg table\n"); | |
139 | n = 1; | |
140 | break; | |
141 | } | |
142 | if (n > 0) { | |
143 | *argc -= n; | |
144 | for (j = i; j < *argc; ++j) | |
145 | argv[j] = argv[j+n]; | |
146 | } | |
147 | return ok; | |
148 | } | |
149 | ||
150 | GBool isInt(char *s) { | |
151 | if (*s == '-' || *s == '+') | |
152 | ++s; | |
153 | while (isdigit(*s & 0xff)) | |
154 | ++s; | |
155 | if (*s) | |
156 | return gFalse; | |
157 | return gTrue; | |
158 | } | |
159 | ||
160 | GBool isFP(char *s) { | |
161 | int n; | |
162 | ||
163 | if (*s == '-' || *s == '+') | |
164 | ++s; | |
165 | n = 0; | |
166 | while (isdigit(*s & 0xff)) { | |
167 | ++s; | |
168 | ++n; | |
169 | } | |
170 | if (*s == '.') | |
171 | ++s; | |
172 | while (isdigit(*s & 0xff)) { | |
173 | ++s; | |
174 | ++n; | |
175 | } | |
176 | if (n > 0 && (*s == 'e' || *s == 'E')) { | |
177 | ++s; | |
178 | if (*s == '-' || *s == '+') | |
179 | ++s; | |
180 | n = 0; | |
181 | if (!isdigit(*s & 0xff)) | |
182 | return gFalse; | |
183 | do { | |
184 | ++s; | |
185 | } while (isdigit(*s & 0xff)); | |
186 | } | |
187 | if (*s) | |
188 | return gFalse; | |
189 | return gTrue; | |
190 | } |