"Fossies" - the Fresh Open Source Software Archive 
Member "parsearg.c" (9 May 1995, 14271 Bytes) of package /linux/misc/old/cpost.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "parsearg.c" see the
Fossies "Dox" file reference documentation.
1 /*------------------------------------------------------------------*/
2 /* parsearg : parse parameters and options in an argv list */
3 /* see parsearg.h for a description */
4 /*------------------------------------------------------------------*/
5 /* 03-13-90 originally by Patrick J. Mueller */
6 /* 01-09-91 version 2.0 by Patrick J. Mueller */
7 /* 04-29-91 version 3.0 by Patrick J. Mueller */
8 /*------------------------------------------------------------------*/
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13 #include <string.h>
14 #include <ctype.h>
15
16 /*------------------------------------------------------------------*/
17 /* typedefs */
18 /*------------------------------------------------------------------*/
19 typedef enum
20 {
21 Boolean_Switch,
22 Variable_Switch
23 } Item_Type;
24
25 typedef struct Cmdline_Item
26 {
27 Item_Type type;
28 int position;
29 char sw_char;
30 void *variable;
31 struct Cmdline_Item *next;
32 } Cmdline_Item;
33
34 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
35 /*------------------------------------------------------------------*/
36 /* L O C A L F U N C T I O N S */
37 /*------------------------------------------------------------------*/
38 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
39
40 /*------------------------------------------------------------------*/
41 /* Search the Cmdline_Item list for a particular switch. Look for */
42 /* the option with a particular switch character (Boolean and */
43 /* Variable are treated as the same) */
44 /*------------------------------------------------------------------*/
45
46 static Cmdline_Item *get_item(
47 Cmdline_Item *head,
48 char sw_char,
49 int case_sense
50 )
51
52 {
53 Cmdline_Item *next;
54
55 /*---------------------------------------------------------------*/
56 /* traverse the linked list ... */
57 /*---------------------------------------------------------------*/
58 next = head;
59 while (next != NULL)
60 {
61 /*------------------------------------------------------------*/
62 /* for case sensitive switches, just compare chars */
63 /*------------------------------------------------------------*/
64 if (case_sense)
65 {
66 if (next->sw_char == sw_char)
67 return(next);
68 }
69
70 /*------------------------------------------------------------*/
71 /* otherwise, toupper the chars and compare */
72 /*------------------------------------------------------------*/
73 else
74 {
75 if (toupper(sw_char) == toupper(next->sw_char))
76 return(next);
77 }
78
79 /*------------------------------------------------------------*/
80 /* no matches so traverse to next item */
81 /*------------------------------------------------------------*/
82 next = next->next;
83 }
84
85 /*---------------------------------------------------------------*/
86 /* no matches at all! */
87 /*---------------------------------------------------------------*/
88 return(NULL);
89 }
90
91 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
92 /*------------------------------------------------------------------*/
93 /* M A I N F U N C T I O N */
94 /*------------------------------------------------------------------*/
95 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
96
97 /*------------------------------------------------------------------*/
98 /* the main function */
99 /*------------------------------------------------------------------*/
100 void parsearg(
101 int *argc,
102 char **argv,
103 int case_sense,
104 char *env_var,
105 char *delimiters,
106 char *format_string,
107 ...
108 )
109
110 {
111 char *tok;
112 Cmdline_Item *item_head;
113 Cmdline_Item *item_tail;
114 Cmdline_Item *item;
115 va_list arg_marker;
116 int i;
117 int parms;
118 int *ptr_int;
119 char **ptr_ptr_char;
120 char sw_char;
121 char *env_value;
122 int envc;
123 char *envv;
124 char *temp;
125
126 /*---------------------------------------------------------------*/
127 /* sanity checks */
128 /*---------------------------------------------------------------*/
129 if ((NULL == format_string) ||
130 (NULL == argv) ||
131 (0 == *argc))
132 return;
133
134 /*---------------------------------------------------------------*/
135 /* make a copy of the format string since we will be strtok()ing */
136 /* through it */
137 /*---------------------------------------------------------------*/
138 temp = malloc(1+strlen(format_string));
139 if (NULL == temp)
140 {
141 puts("Error allocating memory in parsearg()");
142 return;
143 }
144
145 strcpy(temp,format_string);
146 format_string = temp;
147
148 /*---------------------------------------------------------------*/
149 /* get environment variable value */
150 /*---------------------------------------------------------------*/
151 env_value = NULL;
152
153 if (NULL != env_var)
154 if ('\0' != *env_var)
155 {
156
157 /*---------------------------------------------------------*/
158 /* get value and copy if we found something */
159 /*---------------------------------------------------------*/
160 env_value = getenv(env_var);
161
162 if (NULL != env_value)
163 {
164 temp = malloc(1+strlen(env_value));
165 if (NULL == temp)
166 {
167 puts("Error allocating memory in parsearg()");
168 return;
169 }
170
171 strcpy(temp,env_value);
172 env_value = temp;
173 }
174 }
175
176 /*---------------------------------------------------------------*/
177 /* build option list */
178 /*---------------------------------------------------------------*/
179 item_head = item_tail = NULL;
180 va_start(arg_marker,format_string);
181
182 /*---------------------------------------------------------------*/
183 /* parse the format_string with strtok */
184 /*---------------------------------------------------------------*/
185 tok = strtok(format_string," ");
186
187 while (NULL != tok)
188 {
189 /*------------------------------------------------------------*/
190 /* allocate area for a new Item */
191 /*------------------------------------------------------------*/
192 item = (Cmdline_Item *) malloc(sizeof(Cmdline_Item));
193 if (NULL == item)
194 {
195 puts("Error allocating memory in parsearg()");
196 return;
197 }
198
199 /*------------------------------------------------------------*/
200 /* start assigning values to it */
201 /*------------------------------------------------------------*/
202 item->next = NULL;
203 item->sw_char = *tok++;
204
205 /*---------------------------------------------------------*/
206 /* is it a boolean switch? */
207 /*---------------------------------------------------------*/
208 if ('\0' == *tok)
209 item->type = Boolean_Switch;
210
211 /*---------------------------------------------------------*/
212 /* must be a variable switch */
213 /*---------------------------------------------------------*/
214 else
215 item->type = Variable_Switch;
216
217 /*------------------------------------------------------------*/
218 /* now get the variable pointer */
219 /*------------------------------------------------------------*/
220 item->variable = va_arg(arg_marker,void *);
221
222 /*------------------------------------------------------------*/
223 /* initialize boolean switches to 0 */
224 /*------------------------------------------------------------*/
225 if (Boolean_Switch == item->type)
226 {
227 ptr_int = item->variable;
228 *ptr_int = 0;
229 }
230
231 /*------------------------------------------------------------*/
232 /* and variable switches to NULL */
233 /*------------------------------------------------------------*/
234 else
235 {
236 ptr_ptr_char = item->variable;
237 *ptr_ptr_char = NULL;
238 }
239
240 /*------------------------------------------------------------*/
241 /* now insert into list (at end) */
242 /*------------------------------------------------------------*/
243 if (NULL == item_head)
244 item_head = item_tail = item;
245
246 else
247 {
248 item_tail->next = item;
249 item_tail = item;
250 }
251
252 /*------------------------------------------------------------*/
253 /* get next item in format_string */
254 /*------------------------------------------------------------*/
255 tok = strtok(NULL," ");
256 }
257
258 /*---------------------------------------------------------------*/
259 /* now we've set up the format_string. time to step through the */
260 /* args to set the switches on and off and to scanf through */
261 /* variable switches and parameters */
262 /*---------------------------------------------------------------*/
263
264 /*---------------------------------------------------------------*/
265 /* assign argc to parms and initialize argc to 0 */
266 /*---------------------------------------------------------------*/
267 parms = *argc;
268 *argc = 0;
269
270 /*---------------------------------------------------------------*/
271 /* We want to check the environment variables first. Try to get */
272 /* the first item with strtok (if we had anything to begin with. */
273 /* If we have anything, set envv to the value and set env to 1. */
274 /*---------------------------------------------------------------*/
275 envc = 0;
276 envv = NULL;
277
278 if (NULL != env_value)
279 {
280 envv = strtok(env_value," ");
281 if (NULL != envv)
282 envc = 1;
283 }
284
285 /*---------------------------------------------------------------*/
286 /* now loop through the environment variables and arguments */
287 /* setting the appropriate value in the CmdLine_Item list. */
288 /*---------------------------------------------------------------*/
289 for (i = 0; i < envc + parms; i++)
290 {
291 if (NULL != envv)
292 tok = envv;
293
294 else
295 tok = argv[i-envc];
296
297 /*------------------------------------------------------------*/
298 /* if it's a parameter, assign it to next argv pointer */
299 /*------------------------------------------------------------*/
300 if (('\0' == *tok) || (NULL == strchr(delimiters,*tok)))
301 {
302
303 /*---------------------------------------------------------*/
304 /* we don't want to handle environment values though */
305 /*---------------------------------------------------------*/
306 if (NULL == envv)
307 {
308 argv[*argc] = tok;
309 (*argc)++;
310 }
311 }
312
313 /*------------------------------------------------------------*/
314 /* otherwise it's a switch */
315 /*------------------------------------------------------------*/
316 else
317 {
318 tok++;
319
320 parse_switches:
321 sw_char = *tok++;
322
323 /*---------------------------------------------------------*/
324 /* is it a switch? */
325 /*---------------------------------------------------------*/
326 item = get_item(item_head,sw_char,case_sense);
327
328 if (NULL != item)
329 {
330 /*------------------------------------------------------*/
331 /* it's a switch, but is it variable or boolean? */
332 /*------------------------------------------------------*/
333 if (Variable_Switch == item->type)
334 {
335 ptr_ptr_char = item->variable;
336 *ptr_ptr_char = tok;
337 }
338
339 else
340 {
341 ptr_int = item->variable;
342 *ptr_int = 1;
343
344 /*---------------------------------------------------*/
345 /* handle multiple switches concatenated */
346 /*---------------------------------------------------*/
347 if ('\0' != *tok)
348 goto parse_switches;
349 }
350 }
351
352 }
353
354 /*------------------------------------------------------------*/
355 /* now get the next environment value if we need to */
356 /*------------------------------------------------------------*/
357 if (NULL != envv)
358 {
359 envv = strtok(NULL," ");
360 if (NULL != envv)
361 envc++;
362 }
363
364 }
365
366 /*---------------------------------------------------------------*/
367 /* now release all the memory we used */
368 /*---------------------------------------------------------------*/
369 item = item_head;
370 while (NULL != item)
371 {
372 item_head = item->next;
373 free(item);
374 item = item_head;
375 }
376
377 free(format_string);
378
379 /*---------------------------------------------------------------*/
380 /* don't release this memory as we may have set pointers into it */
381 /* I guess if we wanted to be >real< tricky we could somehow */
382 /* return pointers into the original string ... nah!!! */
383 /*---------------------------------------------------------------*/
384 #if defined(SHOOT_YOURSELF_IN_THE_FOOT)
385 if (NULL != env_value)
386 free(env_value);
387 #endif
388
389 return;
390 }
391