Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**** arg-parse.c --- Command line argument parsing.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 **** Commentary:
36
 *
37
 * This file implements the command line argument parsing routines specified
38
 * in "arg-parse.h".  See that file for more details.
39
 *
40
 **** Change Log:
41
 * $Log: arg-parse.c,v $
42
 * Revision 1.1.1.1  1998/01/17  15:57:43  release
43
 * First version to be checked into rolling release.
44
 *
45
 * Revision 1.3  1994/12/12  11:44:26  smf
46
 * Performing changes for 'CR94_178.sid+tld-update' - bringing in line with
47
 * OSSG C Coding Standards.
48
 *
49
 * Revision 1.2  1994/08/22  09:36:39  smf
50
 * Fixed bug DR114:ids-too-long.
51
 *
52
 * Revision 1.1.1.1  1994/07/25  16:05:47  smf
53
 * Initial import of library shared files.
54
 *
55
**/
56
 
57
/****************************************************************************/
58
 
59
#include "arg-parse.h"
60
#include "gen-errors.h"
61
 
62
/*--------------------------------------------------------------------------*/
63
 
64
void
65
arg_parse_intern_descriptions PROTO_N ((arg_list))
66
			      PROTO_T (ArgListP arg_list)
67
{
68
    while ((arg_list->name != NIL (CStringP)) ||
69
	   (arg_list->short_name != '\0')) {
70
	EStringP estring = error_lookup_string (arg_list->u.name);
71
 
72
	ASSERT (estring != NIL (EStringP));
73
	arg_list->u.message = estring;
74
	arg_list ++;
75
    }
76
}
77
 
78
int
79
arg_parse_arguments PROTO_N ((arg_list, usage, argc, argv))
80
		    PROTO_T (ArgListP arg_list X
81
			     EStringP usage X
82
			     int      argc X
83
			     char   **argv)
84
{
85
    int       tmp_argc = argc;
86
    char    **tmp_argv = argv;
87
    ArgUsageT closure;
88
 
89
    closure.usage    = error_string_contents (usage);
90
    closure.arg_list = arg_list;
91
    while (tmp_argc) {
92
	CStringP option = (tmp_argv [0]);
93
	char     c      = (option [0]);
94
 
95
	if ((((c == '-') && (option [1] == '-')) ||
96
	     ((c == '+') && (option [1] == '+'))) && (option [2] == '\0')) {
97
	    return (argc - tmp_argc + 1);
98
	} else if (((c == '-') && (option [1] == '-')) ||
99
		   ((c == '+') && (option [1] == '+'))) {
100
	    ArgListP tmp_list  = arg_list;
101
	    ArgListP chosen    = NIL (ArgListP);
102
	    unsigned matches   = 0;
103
	    CStringP immediate = NIL (CStringP);
104
 
105
	    while ((tmp_list->name != NIL (CStringP)) ||
106
		   (tmp_list->short_name != '\0')) {
107
		CStringP opt = (tmp_list->name);
108
		CStringP arg = (&(option [2]));
109
 
110
		if (opt != NIL (CStringP)) {
111
		    char optch;
112
		    char argch;
113
 
114
		    do {
115
			optch = (*opt ++);
116
			argch = (*arg ++);
117
		    } while (optch && argch && (optch == argch));
118
		    if (optch == argch) {
119
			chosen    = tmp_list;
120
			matches   = 1;
121
			immediate = (arg - 1);
122
			break;
123
		    } else if ((optch == '\0') &&
124
			       (((tmp_list->type) == AT_IMMEDIATE) ||
125
				((tmp_list->type) == AT_EITHER))) {
126
			chosen    = tmp_list;
127
			matches   = 1;
128
			immediate = (arg - 1);
129
			break;
130
		    } else if (argch == '\0') {
131
			chosen = tmp_list;
132
			matches ++;
133
		    }
134
		}
135
		tmp_list ++;
136
	    }
137
	    if (matches == 0) {
138
		E_arg_parse_unknown_option (option, &closure);
139
		UNREACHED;
140
	    } else if (matches > 1) {
141
		E_arg_parse_ambiguous_option (option, &closure);
142
		UNREACHED;
143
	    } else {
144
		switch (chosen->type) EXHAUSTIVE {
145
		  case AT_SWITCH:
146
		    (*((BoolP) (chosen->closure))) = (c == '-');
147
		    break;
148
		  case AT_NEG_SWITCH:
149
		    (*((BoolP) (chosen->closure))) = (c == '+');
150
		    break;
151
		  case AT_PROC_SWITCH:
152
		    (*(chosen->proc)) (option, &closure, chosen->closure,
153
				       c == '-');
154
		    break;
155
		  case AT_IMMEDIATE:
156
		    if (immediate != NIL (CStringP)) {
157
			(*(chosen->proc)) (option, &closure, chosen->closure,
158
					   immediate);
159
		    } else {
160
			E_arg_parse_unknown_option (option, &closure);
161
			UNREACHED;
162
		    }
163
		    break;
164
		  case AT_EITHER:
165
		    if (immediate != NIL (CStringP)) {
166
			if (immediate [0] != '\0') {
167
			    (*(chosen->proc)) (option, &closure,
168
					       chosen->closure, immediate);
169
			} else if (tmp_argc > 1) {
170
			    tmp_argv ++;
171
			    tmp_argc --;
172
			    (*(chosen->proc)) (option, &closure,
173
					       chosen->closure, tmp_argv [0]);
174
			} else {
175
			    E_arg_parse_missing_argument (option, &closure);
176
			    UNREACHED;
177
			}
178
		    } else {
179
			E_arg_parse_unknown_option (option, &closure);
180
			UNREACHED;
181
		    }
182
		    break;
183
		  case AT_FOLLOWING:
184
		    if (tmp_argc > 1) {
185
			tmp_argv ++;
186
			tmp_argc --;
187
			(*(chosen->proc)) (option, &closure, chosen->closure,
188
					   tmp_argv [0]);
189
		    } else {
190
			E_arg_parse_missing_argument (option, &closure);
191
			UNREACHED;
192
		    }
193
		    break;
194
		  case AT_EMPTY:
195
		    (*(chosen->proc)) (option, &closure, chosen->closure);
196
		    break;
197
		  case AT_FOLLOWING2:
198
		    if (tmp_argc > 2) {
199
			tmp_argv += 2;
200
			tmp_argc -= 2;
201
			(*(chosen->proc)) (option, &closure, chosen->closure,
202
					   tmp_argv [-1], tmp_argv [0]);
203
		    } else {
204
			E_arg_parse_missing_argument (option, &closure);
205
			UNREACHED;
206
		    }
207
		    break;
208
		  case AT_FOLLOWING3:
209
		    if (tmp_argc > 3) {
210
			tmp_argv += 3;
211
			tmp_argc -= 3;
212
			(*(chosen->proc)) (option, &closure, chosen->closure,
213
					   tmp_argv [-2], tmp_argv [-1],
214
					   tmp_argv [0]);
215
		    } else {
216
			E_arg_parse_missing_argument (option, &closure);
217
			UNREACHED;
218
		    }
219
		    break;
220
		}
221
	    }
222
	} else if (((c == '-') && (option [1] == '+')) ||
223
		   ((c == '+') && (option [1] == '-')) ||
224
		   ((c == '-') && (option [1] == '\0')) ||
225
		   ((c == '+') && (option [1] == '\0'))) {
226
	    E_arg_parse_unknown_option (option, &closure);
227
	    UNREACHED;
228
	} else if ((c == '-') || (c == '+')) {
229
	    CStringP opt = &(option [1]);
230
 
231
	    while ((opt != NIL (CStringP)) && (*opt != '\0')) {
232
		ArgListP tmp_list = arg_list;
233
		ArgListP chosen   = NIL (ArgListP);
234
 
235
		while ((tmp_list->name != NIL (CStringP)) ||
236
		       (tmp_list->short_name != '\0')) {
237
		    if (tmp_list->short_name == *opt) {
238
			chosen = tmp_list;
239
			break;
240
		    }
241
		    tmp_list ++;
242
		}
243
		if (chosen) {
244
		    switch (chosen->type) EXHAUSTIVE {
245
		      case AT_SWITCH:
246
			(*((BoolP) (chosen->closure))) = (c == '-');
247
			break;
248
		      case AT_NEG_SWITCH:
249
			(*((BoolP) (chosen->closure))) = (c == '+');
250
			break;
251
		      case AT_PROC_SWITCH:
252
			(*(chosen->proc)) (opt, &closure, chosen->closure,
253
					   c == '-');
254
			break;
255
		      case AT_IMMEDIATE:
256
			(*(chosen->proc)) (opt, &closure, chosen->closure,
257
					   opt + 1);
258
			opt = NIL (CStringP);
259
			break;
260
		      case AT_EITHER:
261
			if (opt [1] != '\0') {
262
			    (*(chosen->proc)) (opt, &closure, chosen->closure,
263
					       opt + 1);
264
			} else if (tmp_argc > 1) {
265
			    tmp_argv ++;
266
			    tmp_argc --;
267
			    (*(chosen->proc)) (opt, &closure, chosen->closure,
268
					       tmp_argv [0]);
269
			} else {
270
			    E_arg_parse_missing_short_arg (option, opt,
271
							   &closure);
272
			    UNREACHED;
273
			}
274
			opt = NIL (CStringP);
275
			break;
276
		      case AT_FOLLOWING:
277
			if (tmp_argc > 1) {
278
			    tmp_argv ++;
279
			    tmp_argc --;
280
			    (*(chosen->proc)) (opt, &closure, chosen->closure,
281
					       tmp_argv [0]);
282
			} else {
283
			    E_arg_parse_missing_short_arg (option, opt,
284
							   &closure);
285
			    UNREACHED;
286
			}
287
			break;
288
		      case AT_EMPTY:
289
			(*(chosen->proc)) (opt, &closure, chosen->closure);
290
			break;
291
		      case AT_FOLLOWING2:
292
			if (tmp_argc > 2) {
293
			    tmp_argv += 2;
294
			    tmp_argc -= 2;
295
			    (*(chosen->proc)) (opt, &closure, chosen->closure,
296
					       tmp_argv [-1], tmp_argv [0]);
297
			} else {
298
			    E_arg_parse_missing_short_arg (option, opt,
299
							   &closure);
300
			    UNREACHED;
301
			}
302
			break;
303
		      case AT_FOLLOWING3:
304
			if (tmp_argc > 3) {
305
			    tmp_argv += 3;
306
			    tmp_argc -= 3;
307
			    (*(chosen->proc)) (opt, &closure, chosen->closure,
308
					       tmp_argv [-2], tmp_argv [-1],
309
					       tmp_argv [0]);
310
			} else {
311
			    E_arg_parse_missing_short_arg (option, opt,
312
							   &closure);
313
			    UNREACHED;
314
			}
315
			break;
316
		    }
317
		} else {
318
		    E_arg_parse_unknown_short_opt (option, opt, &closure);
319
		    UNREACHED;
320
		}
321
		if (opt) {
322
		    opt ++;
323
		}
324
	    }
325
	} else {
326
	    return (argc - tmp_argc);
327
	}
328
	tmp_argv ++;
329
	tmp_argc --;
330
    }
331
    return (argc);
332
}
333
 
334
void
335
write_arg_usage PROTO_N ((ostream, closure))
336
		PROTO_T (OStreamP  ostream X
337
			 ArgUsageP closure)
338
{
339
    CStringP usage    = (closure->usage);
340
    ArgListP arg_list = (closure->arg_list);
341
 
342
    write_cstring (ostream, usage);
343
    while ((arg_list->name != NIL (CStringP)) ||
344
	   (arg_list->short_name != '\0')) {
345
	CStringP desc = error_string_contents (arg_list->u.message);
346
 
347
	if (arg_list->name) {
348
	    write_newline (ostream);
349
	    write_cstring (ostream, "    {--|++}");
350
	    write_cstring (ostream, arg_list->name);
351
	    write_cstring (ostream, desc);
352
	}
353
	if (arg_list->short_name != '\0') {
354
	    write_newline (ostream);
355
	    write_cstring (ostream, "    {-|+}");
356
	    write_char (ostream, arg_list->short_name);
357
	    write_cstring (ostream, desc);
358
	}
359
	arg_list ++;
360
    }
361
}
362
 
363
/*
364
 * Local variables(smf):
365
 * eval: (include::add-path-entry "../os-interface" "../generated")
366
 * end:
367
**/