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();
63 _daContext
->argc
= argc
;
64 _daContext
->argv
= argv
;
65 _daContext
->programName
= argv
[0];
67 size
= (count
+ DEFAULT_OPTION_COUNT
) * sizeof(DAProgramOption
*);
68 _daContext
->options
= malloc(size
);
69 memset(_daContext
->options
, 0, size
);
71 _daContextAddDefaultOptions();
72 _daContextAddOptions(options
, count
);
74 for (i
= 1; i
< argc
; i
++) {
75 char *optStr
= argv
[i
];
77 /* Handle default options */
78 if (strcmp(argv
[i
], "-h") == 0 || strcmp(argv
[i
], "--help") == 0)
79 printHelp(programDescription
), exit(0);
81 if (strcmp(argv
[i
], "-v") == 0 || strcmp(argv
[i
], "--version") == 0)
82 puts(versionDescription
), exit(0);
84 if (strcmp(argv
[i
], "-w") == 0 || strcmp(argv
[i
], "--windowed") == 0) {
85 _daContext
->windowed
= 1;
90 /* options with a one-to-one mapping */
91 for (j
= 0; j
< count
; j
++) {
92 DAProgramOption
*option
= &options
[j
];
94 if ((option
->longForm
&& strcmp(option
->longForm
, optStr
) == 0)
95 || (option
->shortForm
&& strcmp(option
->shortForm
, optStr
) == 0)) {
98 i
= parseOption(option
, i
, argc
, argv
);
104 /* XXX: Parsing all options again... */
105 for (j
= 0; j
< count
; j
++) {
106 DAProgramOption
*option
= &options
[j
];
108 if (option
->shortForm
&& contains(option
->shortForm
, optStr
)) {
110 i
= parseOption(option
, i
, argc
, argv
);
115 printf("%s: unrecognized option '%s'\n", argv
[0], argv
[i
]);
116 printHelp(programDescription
), exit(1);
122 contains(char *needle
, char *haystack
)
126 assert(strlen(needle
) == 2);
130 pos
= strchr(haystack
, c
);
132 return (pos
!= NULL
);
136 parseOption(DAProgramOption
*option
, int i
, int argc
, char **argv
)
140 if (option
->type
== DONone
)
145 printf("%s: missing argument for option '%s'\n",
150 switch (option
->type
) {
152 *option
->value
.integer
= readIntOption(i
, argv
);
157 *option
->value
.integer
= readIntOption(i
, argv
);
159 if (*option
->value
.integer
< 0)
160 printf("%s: argument %s must be >= 0\n",
167 *option
->value
.string
= argv
[i
];
175 readIntOption(int index
, char **argv
)
179 if (sscanf(argv
[index
], "%i", &integer
) != 1)
180 DAError("error parsing argument for option %s\n", argv
[index
-1]),
189 return _daContext
->argc
;
195 return _daContext
->argv
;
201 return _daContext
->programName
;
212 struct DAContext
*context
= malloc(sizeof(struct DAContext
));
214 memset(context
, 0, sizeof(struct DAContext
));
222 if (_daContext
->optionCount
> 0) {
225 for (i
= 0; i
< _daContext
->optionCount
; i
++)
226 free(_daContext
->options
[i
]);
228 free(_daContext
->options
);
235 _daContextAddOption(DAProgramOption
*option
)
237 /* If the buffer is full, double its size */
238 if (sizeof(_daContext
->options
) == _daContext
->optionCount
* sizeof(DAProgramOption
)) {
239 DAProgramOption
**options
;
241 options
= (DAProgramOption
**)realloc(
242 (DAProgramOption
**)_daContext
->options
,
243 2 * sizeof(_daContext
->options
));
246 DAError("Out of memory");
248 _daContext
->options
= options
;
251 _daContext
->options
[_daContext
->optionCount
] = option
;
252 _daContext
->optionCount
++;
256 _daContextAddOptionData(char *shortForm
, char *longForm
,
257 char *description
, short type
)
259 DAProgramOption
*option
= malloc(sizeof(DAProgramOption
));
261 option
->shortForm
= shortForm
;
262 option
->longForm
= longForm
;
263 option
->description
= description
;
265 option
->used
= False
;
266 option
->value
.ptr
= NULL
;
268 _daContextAddOption(option
);
272 _daContextAddDefaultOptions(void)
274 _daContextAddOptionData("-h", "--help", "show this help text and exit", DONone
);
275 _daContextAddOptionData("-v", "--version", "show program version and exit", DONone
);
276 _daContextAddOptionData("-w", "--windowed", "run the application in windowed mode", DONone
);
280 _daContextAddOptions(DAProgramOption
*options
, int count
)
284 for (i
= 0; i
< count
; i
++)
285 _daContextAddOptionData(
286 options
[i
].shortForm
,
288 options
[i
].description
,
293 printHelp(char *description
)
296 DAProgramOption
**options
= _daContext
->options
;
297 int count
= _daContext
->optionCount
;
299 printf("Usage: %s [OPTIONS]\n", _daContext
->programName
);
303 for (i
= 0; i
< count
; i
++) {
307 if (options
[i
]->shortForm
&& options
[i
]->longForm
)
308 c
= printf(" %s, %s", options
[i
]->shortForm
, options
[i
]->longForm
);
309 else if (options
[i
]->shortForm
)
310 c
= printf(" %s", options
[i
]->shortForm
);
311 else if (options
[i
]->longForm
)
312 c
= printf(" %s", options
[i
]->longForm
);
316 if (options
[i
]->type
!= DONone
) {
317 switch (options
[i
]->type
) {
319 c
+= printf(" <integer>");
322 c
+= printf(" <string>");
325 c
+= printf(" <number>");
330 memset(blank
, ' ', 30);
334 printf("%s %s\n", blank
, options
[i
]->description
);