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