Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
6 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
6 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:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 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;
6 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;
6 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.h --- Command line argument parsing.
62
 *
63
 ** Author: Steve Folkes <smf@hermes.mod.uk>
64
 *
65
 **** Commentary:
66
 *
67
 ***=== INTRODUCTION =========================================================
68
 *
69
 * This file specifies the interface to a command line argument parsing
70
 * facility.  The facility has a standard behaviour, making it easier to have
71
 * a standard command line argument format.  The facility only parses command
72
 * line options, which it assumes precede the other arguments.  All options
73
 * must begin with an option character (either '+' or '-').  The facility
74
 * supports short (single character) options (should begin with '-' or '+')
75
 * and long (multiple character) options (should begin with '--' or '++').
76
 * Any arguments that begins with another character will terminate the parsing
77
 * without error (so that the program can deal with the remaining arguments).
78
 * In addition, the option '--' (or '++') will terminate the parse, so that a
79
 * user may specify non option arguments that begin with an option character.
80
 *
81
 * The parsing routines support a number of different option types, and deal
82
 * with shortest prefixes for non immediate options (an immediate option is
83
 * one where the data associated with it is part of the option string, and not
84
 * in a following word).
85
 *
86
 ***=== TYPES ================================================================
87
 *
88
 ** Type:	ArgTypeT
89
 ** Type:	ArgTypeP
90
 ** Repr:	enum {AT_SWITCH, AT_NEG_SWITCH, AT_PROC_SWITCH, AT_IMMEDIATE,
91
 *		      AT_EITHER, AT_FOLLOWING, AT_EMPTY, AT_FOLLOWING2}
92
 *
93
 * This is the type of the an option.  The constants have the following
94
 * meanings:
95
 *
96
 *	AT_SWITCH
97
 *
98
 * This is the type of a switch option.  The procedure value should be null.
99
 * The closure should be a pointer to a boolean.  If the option character is a
100
 * '-' then the boolean is set.  If the option character is '+' then the
101
 * boolean is reset.
102
 *
103
 *	AT_NEG_SWITCH
104
 *
105
 * This is the type of a negated switch option. The procedure value should be
106
 * null. The closure should be a pointer to a boolean.  If the option
107
 * character is a '-' then the boolean is reset.  If the option character is
108
 * '+' then the boolean is set.
109
 *
110
 *	AT_PROC_SWITCH
111
 *
112
 * This is the type of a switch option that needs some extra work to be
113
 * performed.  The procedure will be called with the option that was selected,
114
 * the error closure, the option closure, and a boolean (true if the option
115
 * character is '-', false otherwise).
116
 *
117
 *	AT_IMMEDIATE
118
 *
119
 * This is the type of an option with one immediate argument.  No shortest
120
 * prefix matching will be used for immediate arguments.  The procedure will
121
 * be called with the option that was selected, the error closure, the option
122
 * closure, and the argument to the option.  This type of argument should
123
 * appear at the end of the argument list that is passed to the
124
 * ``arg_parse_arguments'' function, as it may cause problems with shortest
125
 * prefix matching otherwise.
126
 *
127
 *	AT_EITHER
128
 *
129
 * This is the type of an option with one argument. If an immediate argument
130
 * exists, then that is used.  If no immediate argument exists, then the
131
 * following argument is used.  No shortest prefix matching will be used for
132
 * either arguments.  The procedure will be called with the option that was
133
 * selected, the error closure, the option closure, and the argument to the
134
 * option.  This type of argument should appear at the end of the argument
135
 * list that is passed to the ``arg_parse_arguments'' function, as it may
136
 * cause problems with shortest prefix matching otherwise.
137
 *
138
 *	AT_FOLLOWING
139
 *
140
 * This is the type of an option with one following argument.  The procedure
141
 * will be called with the option that was selected, the error closure, the
142
 * option closure, and the argument to the option.
143
 *
144
 *	AT_EMPTY
145
 *
146
 * This is the type of an option with no argument.  The procedure will be
147
 * called with the option that was selected, the error closure, and the option
148
 * closure.
149
 *
150
 *	AT_FOLLOWING2
151
 *
152
 * This is the type of an option with two following arguments.  The procedure
153
 * will be called with the option that was selected, the error closure, the
154
 * option closure, and the arguments to the option.
155
 *
156
 *	AT_FOLLOWING3
157
 *
158
 * This is the type of an option with three following arguments.  The
159
 * procedure will be called with the option that was selected, the error
160
 * closure, the option closure, and the arguments to the option.
161
 *
162
 * Note that if a matched option is a short option, then the current position
163
 * is passed to the option handling procedure as the option name.  For long
164
 * options, the entire option string is passed.  If the handler is interested
165
 * in the option name, it should check the start of this string: if it is '-'
166
 * or '+' it should be a long option; otherwise it should be a short option.
167
 *
168
 ** Type:	ArgProcP
169
 ** Repr:	void (*) (CStringP, ArgUsageP, GenericP, ...)
170
 *
171
 * This is the type of a procedure to be called to parse a complex option.
172
 * Because of union initialisation problems, the latter arguments of this
173
 * function are untyped.
174
 *
175
 ** Type:	ArgListT
176
 ** Type:	ArgListP
177
 ** Repr:	<private>
178
 *
179
 * This is the type of an entry in an option list.  A vector of such entries
180
 * should be passed to the ``arg_parse_arguments'' function, with the last
181
 * entry being the ``ARG_PARSE_END_LIST'' macro.  Each entry has the following
182
 * fields: a name field (the name of the option without the leading '--' or
183
 * '++'), a short name field (a character), a type field (the type of the
184
 * option), a procedure field (the procedure to handle the option), a closure
185
 * field (a pointer to some arbritary data used by the procedure), and a
186
 * description field (the name of a named string that describes how the option
187
 * is used - see the file "error.h" for more information on named strings).
188
 * The description field should be surrounded by the ``UB'' and ``UE'' macros
189
 * for union initialisation.  The named strings used in the description fields
190
 * should themselves be interned before the ``arg_parse_arguments'' function
191
 * is called.  A typical argument list definition would be something like the
192
 * following:
193
 *
194
 *	static ArgListT arg_list [] = {
195
 *	    {
196
 *		"option name", 'o', AT_PROC_SWITCH, (ArgProcP) arg_proc,
197
 *		NIL (GenericP),
198
 *		UB "option description name" UE
199
 *	    }, ARG_PARSE_END_LIST
200
 *	};
201
 *
202
 * If an option has only a short form, then the name should be NIL (CStringP);
203
 * if it has only a long form, then the character should be '\0'.  It is
204
 * illegal for an option to have neither a long form or a short form.
205
 *
206
 ** Type:	ArgUsageT
207
 ** Type:	ArgUsageP
208
 ** Repr:	struct {CStringP usage; ArgListP arg_list;}
209
 *
210
 * This is the type of argument to be passed to ``write_arg_usage''.
211
 *
212
 ***=== FUNCTIONS ============================================================
213
 *
214
 ** Function:	void			arg_parse_intern_descriptions
6 7u83 215
 *			(ArgListP arg_list)
2 7u83 216
 ** Exceptions:	XX_dalloc_no_memory, XX_error_redefined_string
217
 *
218
 * This function should be called on all option lists that the program uses,
219
 * before they are passed to ``arg_parse_arguments''.  It replaces the
220
 * descrption name with the named string it represents.  It should only be
221
 * called once on each list.  The named strings used should be interned before
222
 * this function is called.
223
 *
6 7u83 224
 ** Function:	int arg_parse_arguments(ArgListP arg_list, EStringP usage,
225
 *					int argc, char **argv)
2 7u83 226
 ** Exceptions:	XX_dalloc_no_memory, XX_ostream_write_error
227
 *
228
 * This function does the argument parsing.  The arg_list argument should
229
 * specify the valid options for the program.  The usage estring should be a
230
 * named string, whose content is a summary of the program's usage.  The argc
231
 * and argv arguments should specify the actual arguments passed to the
232
 * program.  The parsing starts from the first argument, so the first element
233
 * of the program's argument list (the program name) should not be passed to
234
 * this function.  The function returns the number of elements of the list
235
 * that it parsed.
236
 *
6 7u83 237
 ** Function:	void write_arg_usage(OStreamP ostream, ArgUsageP closure)
2 7u83 238
 ** Exceptions:	XX_dalloc_no_memory, XX_ostream_write_error
239
 *
240
 * This function can be used to write out a usage message based upon the usage
241
 * information supplied.
242
 *
243
 ***=== MACROS ===============================================================
244
 *
245
 ** Macro:	ARG_PARSE_END_LIST
246
 ** Exceptions:
247
 *
248
 * This macro should be used to terminate an option list.
249
 *
250
 **** Change Log:
251
 * $Log: arg-parse.h,v $
252
 * Revision 1.1.1.1  1998/01/17  15:57:17  release
253
 * First version to be checked into rolling release.
254
 *
255
 * Revision 1.2  1994/12/12  11:44:28  smf
256
 * Performing changes for 'CR94_178.sid+tld-update' - bringing in line with
257
 * OSSG C Coding Standards.
258
 *
259
 * Revision 1.1.1.1  1994/07/25  16:05:47  smf
260
 * Initial import of library shared files.
261
 *
262
**/
263
 
264
/****************************************************************************/
265
 
266
#ifndef H_ARG_PARSE
267
#define H_ARG_PARSE
268
 
269
#include "os-interface.h"
270
#include "cstring.h"
271
#include "error.h"
272
#include "ostream.h"
273
 
274
/*--------------------------------------------------------------------------*/
275
 
276
#ifdef FS_NO_ENUM
277
typedef int ArgTypeT, *ArgTypeP;
278
#define AT_SWITCH	(0)
279
#define AT_NEG_SWITCH	(1)
280
#define AT_PROC_SWITCH	(2)
281
#define AT_IMMEDIATE	(3)
282
#define AT_EITHER	(4)
283
#define AT_FOLLOWING	(5)
284
#define AT_EMPTY	(6)
285
#define AT_FOLLOWING2	(7)
286
#define AT_FOLLOWING3	(8)
287
#else
288
typedef enum {
289
    AT_SWITCH,
290
    AT_NEG_SWITCH,
291
    AT_PROC_SWITCH,
292
    AT_IMMEDIATE,
293
    AT_EITHER,
294
    AT_FOLLOWING,
295
    AT_EMPTY,
296
    AT_FOLLOWING2,
297
    AT_FOLLOWING3
298
} ArgTypeT, *ArgTypeP;
299
#endif /* defined (FS_NO_ENUM) */
300
 
301
struct ArgListT;
302
typedef struct ArgUsageT {
303
    CStringP			usage;
304
    struct ArgListT	       *arg_list;
305
} ArgUsageT, *ArgUsageP;
306
 
6 7u83 307
typedef void(*ArgProcP)(CStringP, ArgUsageP, GenericP, ...);
2 7u83 308
 
309
typedef struct ArgListT {
310
    CStringP			name;
311
    char			short_name;
312
    ArgTypeT			type;
313
    ArgProcP			proc;
314
    GenericP			closure;
315
    UNION {
316
	CStringP		name;
317
	EStringP		message;
318
    } u;
319
} ArgListT, *ArgListP;
320
 
321
/*--------------------------------------------------------------------------*/
322
 
323
extern void			arg_parse_intern_descriptions
6 7u83 324
(ArgListP);
2 7u83 325
extern int			arg_parse_arguments
6 7u83 326
(ArgListP, EStringP, int, char **);
2 7u83 327
 
328
extern void			write_arg_usage
6 7u83 329
(OStreamP, ArgUsageP);
2 7u83 330
 
331
/*--------------------------------------------------------------------------*/
332
 
333
#define ARG_PARSE_END_LIST \
6 7u83 334
{NIL(CStringP), '\0',(ArgTypeT)0, NIL(ArgProcP), NIL(GenericP), \
335
 UB NIL(CStringP)UE}
2 7u83 336
 
337
#endif /* !defined (H_ARG_PARSE) */
338
 
339
/*
340
 * Local variables(smf):
341
 * eval: (include::add-path-entry "../os-interface" "../generated")
342
 * end:
343
**/