2 * Copyright (c) 1999-2005 Alfredo K. Kojima, Alban G. Hertroys
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #define DEFAULT_OPTION_COUNT 3
31 extern struct DAContext
*_daContext
;
37 static void _daContextAddDefaultOptions(void);
38 static void _daContextAddOptions(DAProgramOption
*options
, int count
);
39 static void printHelp(char *description
);
41 int contains(char *needle
, char *haystack
);
42 int parseOption(DAProgramOption
*option
, int i
, int argc
, char **argv
);
43 int readIntOption(int index
, char **argv
);
53 DAProgramOption
*options
,
55 char *programDescription
,
56 char *versionDescription
)
61 _daContext
= DAContextInit(argc
, argv
);
63 size
= (count
+ DEFAULT_OPTION_COUNT
) * sizeof(DAProgramOption
*);
64 _daContext
->options
= malloc(size
);
65 memset(_daContext
->options
, 0, size
);
67 _daContextAddDefaultOptions();
68 _daContextAddOptions(options
, count
);
70 for (i
= 1; i
< argc
; i
++) {
71 char *optStr
= argv
[i
];
73 /* Handle default options */
74 if (strcmp(argv
[i
], "-h") == 0 || strcmp(argv
[i
], "--help") == 0)
75 printHelp(programDescription
), exit(0);
77 if (strcmp(argv
[i
], "-v") == 0 || strcmp(argv
[i
], "--version") == 0)
78 puts(versionDescription
), exit(0);
80 if (strcmp(argv
[i
], "-w") == 0 || strcmp(argv
[i
], "--windowed") == 0) {
81 _daContext
->windowed
= 1;
86 /* options with a one-to-one mapping */
87 for (j
= 0; j
< count
; j
++) {
88 DAProgramOption
*option
= &options
[j
];
90 if ((option
->longForm
&& strcmp(option
->longForm
, optStr
) == 0)
91 || (option
->shortForm
&& strcmp(option
->shortForm
, optStr
) == 0)) {
94 i
= parseOption(option
, i
, argc
, argv
);
100 /* XXX: Parsing all options again... */
101 for (j
= 0; j
< count
; j
++) {
102 DAProgramOption
*option
= &options
[j
];
104 if (option
->shortForm
&& contains(option
->shortForm
, optStr
)) {
106 i
= parseOption(option
, i
, argc
, argv
);
111 printf("%s: unrecognized option '%s'\n", argv
[0], argv
[i
]);
112 printHelp(programDescription
), exit(1);
118 contains(char *needle
, char *haystack
)
122 if (strlen(needle
) == 2 && needle
[0] == '-') {
123 pos
= strchr(haystack
, needle
[1]);
126 return (pos
!= NULL
);
130 parseOption(DAProgramOption
*option
, int i
, int argc
, char **argv
)
134 if (option
->type
== DONone
)
139 printf("%s: missing argument for option '%s'\n",
144 switch (option
->type
) {
146 *option
->value
.integer
= readIntOption(i
, argv
);
151 *option
->value
.integer
= readIntOption(i
, argv
);
153 if (*option
->value
.integer
< 0)
154 printf("%s: argument %s must be >= 0\n",
161 *option
->value
.string
= argv
[i
];
169 readIntOption(int index
, char **argv
)
173 if (sscanf(argv
[index
], "%i", &integer
) != 1)
174 DAError("error parsing argument for option %s\n", argv
[index
-1]),
183 return _daContext
->argc
;
189 return _daContext
->argv
;
195 return _daContext
->programName
;
204 DAContextInit(int argc
, char **argv
)
206 struct DAContext
*context
= malloc(sizeof(struct DAContext
));
208 memset(context
, 0, sizeof(struct DAContext
));
210 context
->argc
= argc
;
211 context
->argv
= argv
;
212 context
->programName
= argv
[0];
220 if (_daContext
->optionCount
> 0) {
223 for (i
= 0; i
< _daContext
->optionCount
; i
++)
224 free(_daContext
->options
[i
]);
226 free(_daContext
->options
);
233 _daContextAddOption(DAProgramOption
*option
)
235 /* If the buffer is full, double its size */
236 if (sizeof(_daContext
->options
) == _daContext
->optionCount
* sizeof(DAProgramOption
)) {
237 DAProgramOption
**options
;
239 options
= (DAProgramOption
**)realloc(
240 (DAProgramOption
**)_daContext
->options
,
241 2 * sizeof(_daContext
->options
));
244 DAError("Out of memory");
246 _daContext
->options
= options
;
249 _daContext
->options
[_daContext
->optionCount
] = option
;
250 _daContext
->optionCount
++;
254 _daContextAddOptionData(char *shortForm
, char *longForm
,
255 char *description
, short type
)
257 DAProgramOption
*option
= malloc(sizeof(DAProgramOption
));
259 option
->shortForm
= shortForm
;
260 option
->longForm
= longForm
;
261 option
->description
= description
;
263 option
->used
= False
;
264 option
->value
.ptr
= NULL
;
266 _daContextAddOption(option
);
270 _daContextAddDefaultOptions(void)
272 _daContextAddOptionData("-h", "--help", "show this help text and exit", DONone
);
273 _daContextAddOptionData("-v", "--version", "show program version and exit", DONone
);
274 _daContextAddOptionData("-w", "--windowed", "run the application in windowed mode", DONone
);
278 _daContextAddOptions(DAProgramOption
*options
, int count
)
282 for (i
= 0; i
< count
; i
++)
283 _daContextAddOptionData(
284 options
[i
].shortForm
,
286 options
[i
].description
,
291 printHelp(char *description
)
294 DAProgramOption
**options
= _daContext
->options
;
295 int count
= _daContext
->optionCount
;
297 printf("Usage: %s [OPTIONS]\n", _daContext
->programName
);
301 for (i
= 0; i
< count
; i
++) {
305 if (options
[i
]->shortForm
&& options
[i
]->longForm
)
306 c
= printf(" %s, %s", options
[i
]->shortForm
, options
[i
]->longForm
);
307 else if (options
[i
]->shortForm
)
308 c
= printf(" %s", options
[i
]->shortForm
);
309 else if (options
[i
]->longForm
)
310 c
= printf(" %s", options
[i
]->longForm
);
314 if (options
[i
]->type
!= DONone
) {
315 switch (options
[i
]->type
) {
317 c
+= printf(" <integer>");
320 c
+= printf(" <string>");
323 c
+= printf(" <number>");
328 memset(blank
, ' ', 30);
332 printf("%s %s\n", blank
, options
[i
]->description
);