tomwalters@0
|
1 /*
|
tomwalters@0
|
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
|
tomwalters@0
|
3 ===========================================================================
|
tomwalters@0
|
4
|
tomwalters@0
|
5 Permission to use, copy, modify, and distribute this software without fee
|
tomwalters@0
|
6 is hereby granted for research purposes, provided that this copyright
|
tomwalters@0
|
7 notice appears in all copies and in all supporting documentation, and that
|
tomwalters@0
|
8 the software is not redistributed for any fee (except for a nominal shipping
|
tomwalters@0
|
9 charge). Anyone wanting to incorporate all or part of this software in a
|
tomwalters@0
|
10 commercial product must obtain a license from the Medical Research Council.
|
tomwalters@0
|
11
|
tomwalters@0
|
12 The MRC makes no representations about the suitability of this
|
tomwalters@0
|
13 software for any purpose. It is provided "as is" without express or implied
|
tomwalters@0
|
14 warranty.
|
tomwalters@0
|
15
|
tomwalters@0
|
16 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
tomwalters@0
|
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
|
tomwalters@0
|
18 A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
|
tomwalters@0
|
19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
tomwalters@0
|
20 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
tomwalters@0
|
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
tomwalters@0
|
22 */
|
tomwalters@0
|
23
|
tomwalters@0
|
24 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
25
|
tomwalters@0
|
26 *
|
tomwalters@0
|
27 The Leanest Resource Manager in the West
|
tomwalters@0
|
28 -----------------------------------------
|
tomwalters@0
|
29
|
tomwalters@0
|
30
|
tomwalters@0
|
31 (*) is no more! The gallant <getopts.[ch]> has
|
tomwalters@0
|
32 given way to a new daring duo! Henceforth,
|
tomwalters@0
|
33 read "options" for "getopts". The new features
|
tomwalters@0
|
34 include classified options and user-supplied
|
tomwalters@0
|
35 "Help" information. See <options.c> for edit
|
tomwalters@0
|
36 history.
|
tomwalters@0
|
37
|
tomwalters@0
|
38 Copyright (c), 1989 The Medical Research Council of the United Kingdom.
|
tomwalters@0
|
39
|
tomwalters@0
|
40 Author : Paul Manson
|
tomwalters@0
|
41 Written : March 1st 1989 [See options.c for modifications history]
|
tomwalters@0
|
42
|
tomwalters@0
|
43 Options may be supplied as defaults (actually in the code), as command line
|
tomwalters@0
|
44 arguments, and in an option file. The default arguments may be overridden by
|
tomwalters@0
|
45 the option-file contents, which may be overridden in turn by command line
|
tomwalters@0
|
46 arguments. The syntax of a option file is as follows:
|
tomwalters@0
|
47
|
tomwalters@0
|
48 <option file> ::= { <option line> <linefeed> }
|
tomwalters@0
|
49
|
tomwalters@0
|
50 <option line> ::= <option specification> | <comment line> | <blank line>
|
tomwalters@0
|
51
|
tomwalters@0
|
52 <option specification> ::= <name> "=" <option value> [ <comment line> ]
|
tomwalters@0
|
53
|
tomwalters@0
|
54 <option value> ::= <contiguous character string> |
|
tomwalters@0
|
55 """ <any printable chars except """> """
|
tomwalters@0
|
56
|
tomwalters@0
|
57 <comment line> ::= "#" <absolutely anything>
|
tomwalters@0
|
58
|
tomwalters@0
|
59 where spaces are not considered significant except that the <value> ought to
|
tomwalters@0
|
60 be a quoted string if it contains spaces. On Unix, the OPTIONSPATH path in the
|
tomwalters@0
|
61 users' environment is used to search for a option file, but if this path is
|
tomwalters@0
|
62 absent, the current working directory will still be searched. On an IBM PC, the
|
tomwalters@0
|
63 the directory in which the application program was found is searched for the
|
tomwalters@0
|
64 option file. [In the future, this will be modified so that the current directory
|
tomwalters@0
|
65 is searched first].
|
tomwalters@0
|
66
|
tomwalters@0
|
67 Command line arguments may take any of the following forms;
|
tomwalters@0
|
68
|
tomwalters@0
|
69 1. -name
|
tomwalters@0
|
70
|
tomwalters@0
|
71 2. -name=value
|
tomwalters@0
|
72
|
tomwalters@0
|
73 3. name=value
|
tomwalters@0
|
74
|
tomwalters@0
|
75 where it should be noted that spaces ARE significant, and that the first of these
|
tomwalters@0
|
76 formats effects a set/toggle operation on the named option, by setting its
|
tomwalters@0
|
77 value to some system-defined default value (at present, this is "1").
|
tomwalters@0
|
78
|
tomwalters@0
|
79 If a user specifies -help on the command line then getopts uses the "help" option
|
tomwalters@0
|
80 (if there is one) to print a message detailing the options available to the
|
tomwalters@0
|
81 user. Specifying -update on the command line causes a new version of the currently
|
tomwalters@0
|
82 read option file to be written, incorporating any alterations which have been
|
tomwalters@0
|
83 effected by previous command line options.
|
tomwalters@0
|
84
|
tomwalters@0
|
85 Abbreviations are permitted for options, but it must be noted that only
|
tomwalters@0
|
86 unambiguous option specifications will have any effect (ambiguous specifications
|
tomwalters@0
|
87 are rejected with a warning message). If a option specification uses a name which
|
tomwalters@0
|
88 is an abbreviation for two options, but matches one of these options EXACTLY,
|
tomwalters@0
|
89 this is not considered to be ambiguous (the exact match being taken as the intended
|
tomwalters@0
|
90 one). Abbreviations are NOT permitted in option headers (see readopts and writeopts
|
tomwalters@0
|
91 below).
|
tomwalters@0
|
92
|
tomwalters@0
|
93 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
94
|
tomwalters@0
|
95 #include <stdio.h>
|
tomwalters@0
|
96
|
tomwalters@0
|
97 #define InputOption (1)
|
tomwalters@0
|
98 #define OutputOption (2)
|
tomwalters@0
|
99 #define InOutOption (0)
|
tomwalters@0
|
100 #define SilentOption (3)
|
tomwalters@0
|
101
|
tomwalters@0
|
102 typedef struct {
|
tomwalters@0
|
103 char *name ; /* The name of the option, */
|
tomwalters@0
|
104 char *defaultValue ; /* its default value, */
|
tomwalters@0
|
105 char **value ; /* The place where its current value is stored */
|
tomwalters@0
|
106 char *comment ; /* Something to print when the user types "-help" */
|
tomwalters@0
|
107 short classification; /* What form of option it is. */
|
tomwalters@0
|
108 } Option, *OptionPtr;
|
tomwalters@0
|
109
|
tomwalters@0
|
110 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
111
|
tomwalters@0
|
112 This structure may be used to build a database of option handles, as indicated
|
tomwalters@0
|
113 in the following sample program;
|
tomwalters@0
|
114
|
tomwalters@0
|
115 static char *samplerate, *inputfile;
|
tomwalters@0
|
116
|
tomwalters@0
|
117 static Option res[] = {
|
tomwalters@0
|
118 { "Sample Rate", "10000.0", &samplerate, "The Rate of Sampling", InOutOption },
|
tomwalters@0
|
119 { "Input File ", "input.data", &inputfile , "A File to Read From ", InOutOption }};
|
tomwalters@0
|
120
|
tomwalters@0
|
121 which declares two options, <samplerate> and <inputfile>, and gives them
|
tomwalters@0
|
122 default values. These defaults may later be overwritten by the function
|
tomwalters@0
|
123 getopts(), either from the option file or from the command line.
|
tomwalters@0
|
124
|
tomwalters@0
|
125 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
126
|
tomwalters@0
|
127
|
tomwalters@0
|
128 #define NumOptions(res) (sizeof(res) / ((sizeof(char *) + (sizeof(char **)))))
|
tomwalters@0
|
129
|
tomwalters@0
|
130 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
131
|
tomwalters@0
|
132 Provides a macro for determining how many options are present in a res[]
|
tomwalters@0
|
133 declaration such as that shown above. eg. NumOptions(res) == 2. This macro
|
tomwalters@0
|
134 should be used on calls to getopts, etc.
|
tomwalters@0
|
135
|
tomwalters@0
|
136 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
137
|
tomwalters@0
|
138
|
tomwalters@0
|
139 extern void getnopts(); /* (options, numOptions, &argc, &argv) */
|
tomwalters@0
|
140
|
tomwalters@0
|
141 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
142
|
tomwalters@0
|
143 This function should be called before an application program examines its arguments
|
tomwalters@0
|
144 (this is because it butchers them!). First of all, it reads the appropriate option
|
tomwalters@0
|
145 file and interprets the options specified therein (the name of the option file
|
tomwalters@0
|
146 is given by the name of the application, ie. argv[0]). After redefining the options
|
tomwalters@0
|
147 specified by the option file, it examines the arguments (given by argc and argv)
|
tomwalters@0
|
148 and scans them for additional options. Finally, it resets argc and argv for the
|
tomwalters@0
|
149 remainder of the program (if any) to deal with. NOTE THAT argc AND argv _MUST_ BE
|
tomwalters@0
|
150 PASSED AS POINTERS TO THIS ROUTINE!.
|
tomwalters@0
|
151
|
tomwalters@0
|
152 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
153
|
tomwalters@0
|
154
|
tomwalters@0
|
155 extern void getopts(); /* (options, &argc, &argv) */
|
tomwalters@0
|
156 extern void cmd_line_opts() ; /* (options, &argc, &argv) */
|
tomwalters@0
|
157
|
tomwalters@0
|
158 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
159
|
tomwalters@0
|
160 Some fussy people don't like to count their own option lists, so this routine
|
tomwalters@0
|
161 does the necessary dirty-work before passing the result(s) to getnopts(). You MUST
|
tomwalters@0
|
162 remember to null-terminate your options array; ie.
|
tomwalters@0
|
163
|
tomwalters@0
|
164 static char *samplerate, *inputfile;
|
tomwalters@0
|
165
|
tomwalters@0
|
166 static Option res[] = {
|
tomwalters@0
|
167 { "Sample Rate", "10000.0", &samplerate, "The Rate of Sampling", InOutOption },
|
tomwalters@0
|
168 { "Input File ", "input.data", &inputfile , "A File to Read From ", InOutOption },
|
tomwalters@0
|
169 NULL};
|
tomwalters@0
|
170
|
tomwalters@0
|
171 and upon your own head (or lesser, more sensitive, appendages) be it if you forget
|
tomwalters@0
|
172 to do this!
|
tomwalters@0
|
173
|
tomwalters@0
|
174 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
175
|
tomwalters@0
|
176
|
tomwalters@0
|
177 extern void readnopts(); /* (options, numOptions, filePointer) */
|
tomwalters@0
|
178 extern void readopts() ; /* (options, filePointer) */
|
tomwalters@0
|
179
|
tomwalters@0
|
180 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
181
|
tomwalters@0
|
182 Try to read a options header from the specified <file>, with reference to the
|
tomwalters@0
|
183 array of <options>. The header layout is specified below (see writenopts), and
|
tomwalters@0
|
184 the operation, if successful, will leave the filePointer set to the first byte
|
tomwalters@0
|
185 after the (padded) option header. Unsuccessful readnopts will cause en error
|
tomwalters@0
|
186 message and will terminate the program. If there does not appear to be a header
|
tomwalters@0
|
187 on the file at all, readnopts does nothing. The routine readopts counts the
|
tomwalters@0
|
188 options in <options> for you, and you MUST null-terminate your options
|
tomwalters@0
|
189 array if you use this routine.
|
tomwalters@0
|
190
|
tomwalters@0
|
191 WARNING: readopts and readnopts do NOT require that a option name found in a
|
tomwalters@0
|
192 header be an actual option of the calling program, and will IGNORE any such
|
tomwalters@0
|
193 option assignments.
|
tomwalters@0
|
194
|
tomwalters@0
|
195 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
196
|
tomwalters@0
|
197
|
tomwalters@0
|
198 extern void writenopts(); /* (options, numOptions, filePointer) */
|
tomwalters@0
|
199 extern void writeopts() ; /* (options, filePointer) */
|
tomwalters@0
|
200
|
tomwalters@0
|
201 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
202
|
tomwalters@0
|
203 Write the current option settings as specified by <options> into the
|
tomwalters@0
|
204 specified file. The options are written as an ASCII header, in the same form
|
tomwalters@0
|
205 as is required by getopts (and consequently, readopts). This header will begin
|
tomwalters@0
|
206 with some suitable comment (line beginning with a # character) to indicate that
|
tomwalters@0
|
207 it is in fact a option header. Following this comment will be information
|
tomwalters@0
|
208 concerning the size of the option file header. This information is used to tell
|
tomwalters@0
|
209 subsequent calls to readnopts the length of the option header; this header will
|
tomwalters@0
|
210 actually be padded to a block boundary to avoid disturbing the following data
|
tomwalters@0
|
211 unnecessarily. As might be expected, writeopts is a counting version of writenopts;
|
tomwalters@0
|
212 remember to NULL-terminate your option array if you use this routine.
|
tomwalters@0
|
213
|
tomwalters@0
|
214 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
215
|
tomwalters@0
|
216
|
tomwalters@0
|
217 extern FILE *fileopts(); /* (options, &argc, &argv ) */
|
tomwalters@0
|
218
|
tomwalters@0
|
219 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
220
|
tomwalters@0
|
221 A packaging function which performs getopts(options, &argc, &argv), then fopens
|
tomwalters@0
|
222 the next argument and does readopts on it. It returns a file handle to this file
|
tomwalters@0
|
223 with the header removed (ie. it points at the first byte of data).
|
tomwalters@0
|
224
|
tomwalters@0
|
225 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
226
|
tomwalters@0
|
227 extern FILE *optoutput(); /* (String) */
|
tomwalters@0
|
228
|
tomwalters@0
|
229 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
230
|
tomwalters@0
|
231 Simply open a file for output (depending on the value of String)... a NULL string
|
tomwalters@0
|
232 returns NULL, the default String (at present this is "1") sends to stdout, and
|
tomwalters@0
|
233 anything else is taken as being a path name for a file to create for writing.
|
tomwalters@0
|
234
|
tomwalters@0
|
235 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
236
|
tomwalters@0
|
237 extern void helpnopts(); /* (options, numOptions, program_name) */
|
tomwalters@0
|
238 extern void helpopts(); /* (options, program_name) */
|
tomwalters@0
|
239
|
tomwalters@0
|
240 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
241
|
tomwalters@0
|
242 Allows application programs to invoke the online help (ie. usage) information at
|
tomwalters@0
|
243 any point. The helpopts call counts the number of options for you, BUT ONLY IF
|
tomwalters@0
|
244 you remember to NULL-TERMINATE IT!
|
tomwalters@0
|
245
|
tomwalters@0
|
246 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
247
|
tomwalters@0
|
248 typedef void helpRoutine( /* (options, numOptions, program_name) */ );
|
tomwalters@0
|
249
|
tomwalters@0
|
250 extern helpRoutine *helpOptsHandler(); /* (helpRoutine) */
|
tomwalters@0
|
251
|
tomwalters@0
|
252 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
253
|
tomwalters@0
|
254 Allows an application program to install its very own helpHandler routine to
|
tomwalters@0
|
255 override the default help-message handler. The behaviour of such a routine is
|
tomwalters@0
|
256 implicitly trusted by <options>, so you should only install your own handler
|
tomwalters@0
|
257 when you are quite familiar with the Options structure format. This routine
|
tomwalters@0
|
258 returns the address of the previously installed handler (which is initially the
|
tomwalters@0
|
259 default handler) so that this may be reinstated at a later point.
|
tomwalters@0
|
260
|
tomwalters@0
|
261 ---------------------------------------------------------------------------------- */
|
tomwalters@0
|
262
|
tomwalters@0
|
263
|
tomwalters@0
|
264 #define isON(_STR) (!isOFF(_STR))
|
tomwalters@0
|
265
|
tomwalters@0
|
266 extern int isOFF();
|
tomwalters@0
|
267 /* char *optionStr; */
|
tomwalters@0
|
268
|
tomwalters@0
|
269 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
270
|
tomwalters@0
|
271 A convenience call which returns TRUE (1) if the optionStr is what options thinks
|
tomwalters@0
|
272 of as "ON", "YES", "TRUE", or "1".... This merely allows us to hide the actual
|
tomwalters@0
|
273 implementation of "ON" from the application programs.
|
tomwalters@0
|
274
|
tomwalters@0
|
275 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
276
|
tomwalters@0
|
277 extern int isNULL();
|
tomwalters@0
|
278 /* char *optionStr; */
|
tomwalters@0
|
279
|
tomwalters@0
|
280 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
281
|
tomwalters@0
|
282 A convenience call which returns TRUE (1) if the optionStr is what options thinks
|
tomwalters@0
|
283 of as "NULL", "NONE", nothing, zip, etc... This merely allows us to hide the actual
|
tomwalters@0
|
284 implementation of "NULL" from the application programs.
|
tomwalters@0
|
285
|
tomwalters@0
|
286 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
287
|
tomwalters@0
|
288 #define ON_OPTION "on"
|
tomwalters@0
|
289 #define OFF_OPTION "off"
|
tomwalters@0
|
290 #define NULL_OPTION "none"
|
tomwalters@0
|
291
|
tomwalters@0
|
292 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
293
|
tomwalters@0
|
294 NOTE: The above definitions allow the expression of constant option settings
|
tomwalters@0
|
295 via static option[] arrays... they do so at the risk of allowing some klutz
|
tomwalters@0
|
296 to alter them... the only solution to this problem (other than forcing
|
tomwalters@0
|
297 application programmers to read .h files) is to return copies of these
|
tomwalters@0
|
298 strings via procedure calls, and this precludes static initialisation.
|
tomwalters@0
|
299
|
tomwalters@0
|
300 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
301
|
tomwalters@0
|
302 extern int OptionStringsEqual();
|
tomwalters@0
|
303 /* char *str1, *str2; */
|
tomwalters@0
|
304
|
tomwalters@0
|
305 /* ---------------------------------------------------------------------------------
|
tomwalters@0
|
306
|
tomwalters@0
|
307 A routine to reduce the load on the application programmer by providing a simple
|
tomwalters@0
|
308 boolean check for string equality WITHOUT CASE SIGNIFICANCE. This allows applications
|
tomwalters@0
|
309 to leave case and typing problems within "options" reliably.
|
tomwalters@0
|
310
|
tomwalters@0
|
311 --------------------------------------------------------------------------------- */
|
tomwalters@0
|
312
|
tomwalters@0
|
313 extern char *versionstr;
|