1 /****************************************************************\
2 *                                                                *
3 *  Library for command line argument processing                  *
4 *                                                                *
5 *  Guy St.C. Slater..   mailto:guy@ebi.ac.uk                     *
6 *  Copyright (C) 2000-2009.  All Rights Reserved.                *
7 *                                                                *
8 *  This source code is distributed under the terms of the        *
9 *  GNU General Public License, version 3. See the file COPYING   *
10 *  or http://www.gnu.org/licenses/gpl.txt for details            *
11 *                                                                *
12 *  If you use this code, please keep this notice intact.         *
13 *                                                                *
14 \****************************************************************/
15 
16 #include "argument.h"
17 #include <stdio.h>  /* For fprintf() */
18 #include <stdlib.h> /* For exit() */
19 #include <string.h> /* For strlen() */
20 #include <ctype.h>  /* For isalnum() */
21 #include <unistd.h> /* For gethostname() */
22 
ArgumentOption_create(ArgumentSet * as,gchar symbol,gchar * option,gchar * type,gchar * desc,gchar * default_string,ArgumentHandler handler,gpointer handler_data)23 static ArgumentOption *ArgumentOption_create(ArgumentSet *as,
24                                              gchar symbol,
25                                              gchar *option,
26                                              gchar *type,
27                                              gchar *desc,
28                                              gchar *default_string,
29                                              ArgumentHandler handler,
30                                              gpointer handler_data){
31     register ArgumentOption *ao= g_new(ArgumentOption, 1);
32     ao->as = as;
33     ao->symbol = symbol;
34     ao->option = g_strdup(option);
35     ao->arg_value = NULL;
36     ao->desc = g_strdup(desc);
37     ao->type = g_strdup(type);
38     ao->default_string = g_strdup(default_string);
39     ao->handler = handler;
40     ao->handler_data = handler_data;
41     ao->env_var = NULL;
42     if(handler)
43         ao->arg_list = NULL;
44     else
45         ao->arg_list = g_ptr_array_new();
46     return ao;
47     }
48 
ArgumentOption_destroy(ArgumentOption * ao)49 static void ArgumentOption_destroy(ArgumentOption *ao){
50     g_free(ao->option);
51     g_free(ao->desc);
52     g_free(ao->type);
53     g_free(ao->default_string);
54     g_free(ao->env_var);
55     if(ao->arg_list)
56         g_ptr_array_free(ao->arg_list, TRUE);
57     g_free(ao);
58     return;
59     }
60 
ArgumentSet_destroy(ArgumentSet * as)61 static void ArgumentSet_destroy(ArgumentSet *as){
62     register gint i;
63     register ArgumentOption *ao;
64     for(i = 0; i < as->arg_option->len; i++){
65         ao = as->arg_option->pdata[i];
66         ArgumentOption_destroy(ao);
67         }
68     g_ptr_array_free(as->arg_option, TRUE);
69     g_free(as->desc);
70     g_free(as);
71     return;
72     }
73 
ArgumentOption_print_values(ArgumentOption * ao,gint use_long)74 static void ArgumentOption_print_values(ArgumentOption *ao,
75                                         gint use_long){
76     register gint i;
77     if(ao->arg_list){
78         if(ao->arg_list->len){
79             if((!ao->default_string)
80             || ((ao->arg_list->len == 1)
81                 && strcmp(ao->default_string,
82                           ao->arg_list->pdata[0]))){
83                 g_print("{%s", (gchar*)ao->arg_list->pdata[0]);
84                 for(i = 1; i < ao->arg_list->len; i++)
85                     g_print(":%s", (gchar*)ao->arg_list->pdata[i]);
86                 g_print("}");
87                 }
88         } else {
89             g_print(" <*** empty list ***>");
90             }
91     } else {
92         if(ao->arg_value){
93             if((!ao->default_string)
94             || strcmp(ao->default_string, ao->arg_value)){
95                 if(use_long)
96                     g_print("Using: ");
97                 g_print("<%s>", ao->arg_value);
98                 }
99         } else {
100             g_print(" <*** not set ***>");
101             }
102         }
103     return;
104     }
105 
ArgumentOption_is_set(ArgumentOption * ao)106 static gboolean ArgumentOption_is_set(ArgumentOption *ao){
107     if(ao->arg_list)
108         return ao->arg_list->len?TRUE:FALSE;
109     return ao->arg_value?TRUE:FALSE;
110     }
111 
ArgumentOption_add_value(ArgumentOption * ao,GPtrArray * error_queue,gchar * value)112 static void ArgumentOption_add_value(ArgumentOption *ao,
113                                GPtrArray *error_queue, gchar *value){
114     if(ao->arg_list){
115         g_ptr_array_add(ao->arg_list, value);
116     } else {
117         if(ao->arg_value)
118             g_ptr_array_add(error_queue,
119                 g_strdup_printf("Already set --%s to \"%s\"",
120                     ao->option, ao->arg_value));
121         else
122             ao->arg_value = value;
123         }
124     return;
125     }
126 
ArgumentOption_is_mandatory(ArgumentOption * ao)127 static gboolean ArgumentOption_is_mandatory(ArgumentOption *ao){
128     return ao->default_string?FALSE:TRUE;
129     }
130 
131 /**/
132 
ArgumentParse_boolean(gchar * arg_string)133 static gboolean ArgumentParse_boolean(gchar *arg_string){
134     register gint i;
135     gchar *true_string[6]  = {"Y", "T", "TRUE",  "YES", "ON", "1"},
136           *false_string[6] = {"N", "F", "FALSE", "NO",  "OFF", "0"};
137     for(i = 0; i < 6; i++){
138         if(!g_strcasecmp(arg_string, true_string[i]))
139             return TRUE;
140         if(!g_strcasecmp(arg_string, false_string[i]))
141             return FALSE;
142         }
143     g_error("Cannot parse boolean \"%s\"", arg_string);
144     return FALSE;
145     }
146 /* FIXME: change to work with error listing
147  */
148 
ArgumentHandler_short_help_func(gchar * arg_string,gpointer data)149 static gchar *ArgumentHandler_short_help_func(gchar *arg_string,
150                                               gpointer data){
151     register Argument *arg = (Argument*)data;
152     if(ArgumentParse_boolean(arg_string))
153         arg->show_short_help = TRUE;
154     return NULL;
155     }
156 
ArgumentHandler_long_help_func(gchar * arg_string,gpointer data)157 static gchar *ArgumentHandler_long_help_func(gchar *arg_string,
158                                              gpointer data){
159     register Argument *arg = (Argument*)data;
160     if(ArgumentParse_boolean(arg_string))
161         arg->show_long_help = TRUE;
162     return NULL;
163     }
164 
Argument_show_version(Argument * arg)165 static void Argument_show_version(Argument *arg){
166     register gchar *branch = "$Name:  $";
167     g_print("%s from %s version %s\n",
168             arg->name, PACKAGE, VERSION);
169     g_print("Using glib version %d.%d.%d\n",
170             GLIB_MAJOR_VERSION,
171             GLIB_MINOR_VERSION,
172             GLIB_MICRO_VERSION);
173     g_print("Built on %s\n", __DATE__);
174     if(strlen(branch) >= 10)
175         g_print("Branch: %.*s\n", (gint)(strlen(branch)-9), branch+7);
176     return;
177     }
178 
ArgumentHandler_version_func(gchar * arg_string,gpointer data)179 static gchar *ArgumentHandler_version_func(gchar *arg_string,
180                                            gpointer data){
181     register Argument *arg = (Argument*)data;
182     if(ArgumentParse_boolean(arg_string)){
183         Argument_show_version(arg);
184         exit(1);
185         }
186     return NULL;
187     }
188 
Argument_add_standard_options(Argument * arg)189 static void Argument_add_standard_options(Argument *arg){
190     register ArgumentSet *as = ArgumentSet_create("General Options");
191     ArgumentSet_add_option(as, 'h', "shorthelp", NULL,
192         "Display compact help text",
193         "FALSE", ArgumentHandler_short_help_func, arg);
194     ArgumentSet_add_option(as, '\0', "help", NULL,
195         "Displays verbose help text",
196         "FALSE", ArgumentHandler_long_help_func, arg);
197     ArgumentSet_add_option(as, 'v', "version", NULL,
198                            "Show version number for this program",
199                            "FALSE", ArgumentHandler_version_func, arg);
200     Argument_absorb_ArgumentSet(arg, as);
201     return;
202     }
203 
204 /**/
205 
206 typedef struct {
207     Argument_Cleanup_Func cleanup_func;
208                  gpointer user_data;
209 } Argument_Cleanup;
210 
Argument_add_cleanup(Argument * arg,Argument_Cleanup_Func cleanup_func,gpointer user_data)211 void Argument_add_cleanup(Argument *arg,
212                           Argument_Cleanup_Func cleanup_func,
213                           gpointer user_data){
214     register Argument_Cleanup *cleanup = g_new(Argument_Cleanup, 1);
215     cleanup->cleanup_func = cleanup_func;
216     cleanup->user_data = user_data;
217     g_ptr_array_add(arg->cleanup_list, cleanup);
218     return;
219     }
220 
Argument_cleanup(Argument * arg)221 static void Argument_cleanup(Argument *arg){
222     register Argument_Cleanup *cleanup;
223     register gint i;
224     for(i = 0; i < arg->cleanup_list->len; i++){
225         cleanup = arg->cleanup_list->pdata[i];
226         cleanup->cleanup_func(cleanup->user_data);
227         g_free(cleanup);
228         }
229     return;
230     }
231 
232 /**/
233 
Argument_strcmp_compare(gconstpointer a,gconstpointer b)234 static gint Argument_strcmp_compare(gconstpointer a, gconstpointer b){
235     return strcmp((gchar*)a, (gchar*)b);
236     }
237 
Argument_create(gint argc,gchar ** argv)238 static Argument *Argument_create(gint argc, gchar **argv){
239     register Argument *arg = g_new0(Argument, 1);
240     arg->arg_set = g_ptr_array_new();
241     arg->mandatory_set = g_ptr_array_new();
242     arg->cleanup_list = g_ptr_array_new();
243     arg->option_registry = g_tree_new(Argument_strcmp_compare);
244     arg->argc = argc;
245     arg->argv = argv;
246     Argument_add_standard_options(arg);
247     return arg;
248     }
249 
Argument_destroy(Argument * arg)250 static void Argument_destroy(Argument *arg){
251     register ArgumentSet *as;
252     register gint i;
253     for(i = 0; i < arg->arg_set->len; i++){
254         as = arg->arg_set->pdata[i];
255         ArgumentSet_destroy(as);
256         }
257     Argument_cleanup(arg);
258     g_ptr_array_free(arg->cleanup_list, TRUE);
259     g_ptr_array_free(arg->mandatory_set, TRUE);
260     g_ptr_array_free(arg->arg_set, TRUE);
261     g_tree_destroy(arg->option_registry);
262     g_free(arg->name);
263     g_free(arg->desc);
264     g_free(arg);
265     return;
266     }
267 
Argument_assertion_warning(void)268 static gboolean Argument_assertion_warning(void){
269     g_warning("Compiled with assertion checking - will run slowly");
270     return TRUE;
271     }
272 
Argument_error_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * message,gpointer user_data)273 static void Argument_error_handler(const gchar *log_domain,
274                                    GLogLevelFlags log_level,
275                                    const gchar *message,
276                                    gpointer user_data){
277     register Argument *arg = user_data;
278     register gchar
279         *stack_trace_str = (gchar*)g_getenv("EXONERATE_DEBUG_STACK_TRACE"),
280         *debug_str = (gchar*)g_getenv("EXONERATE_DEBUG");
281     fprintf(stderr, "** FATAL ERROR **: %s\n", message);
282     if(stack_trace_str
283     && ArgumentParse_boolean(stack_trace_str)){
284         fprintf(stderr, "Generating stack trace ...\n");
285         g_on_error_stack_trace(arg->name);
286         }
287     if(debug_str
288     && ArgumentParse_boolean(debug_str)){
289         fprintf(stderr, "Calling abort...\n");
290         abort();
291         }
292     fprintf(stderr, "exiting ...\n");
293     Argument_destroy(arg);
294     exit(1);
295     return;
296     }
297 /* This is probably not what one is supposed to do with glib,
298  * but it is to stop g_error() calling abort() and core dumping.
299  * Maybe switch to g_critical() after glib-2 migration.
300  */
301 
main(int argc,char ** argv)302 int main(int argc, char **argv){
303     register Argument *arg;
304     register gint retval;
305 #ifdef USE_PTHREADS
306     if(!g_thread_supported())
307         g_thread_init(NULL);
308 #endif /* USE_PTHREADS */
309     arg = Argument_create(argc, argv);
310     g_log_set_handler(NULL, G_LOG_LEVEL_ERROR|G_LOG_FLAG_FATAL,
311                       Argument_error_handler, arg);
312     g_assert(Argument_assertion_warning());
313     retval = Argument_main(arg);
314     Argument_destroy(arg);
315     return retval;
316     }
317 
Argument_usage(Argument * arg,gchar * synopsis)318 static void Argument_usage(Argument *arg, gchar *synopsis){
319     register ArgumentOption *ao;
320     register gint i;
321     Argument_show_version(arg);
322     g_print("\n%s: %s\n", arg->name, arg->desc);
323     if(synopsis){
324         g_print("%s\n", synopsis);
325     } else {
326         g_print("Synopsis:\n--------\n%s", arg->name);
327         for(i = 0; i < arg->mandatory_set->len; i++){
328             ao = arg->mandatory_set->pdata[i];
329             g_print(" <%s>", ao->type);
330             }
331         g_print("\n\n");
332         }
333     return;
334     }
335 
Argument_short_help(Argument * arg)336 static void Argument_short_help(Argument *arg){
337     register ArgumentSet *as;
338     register ArgumentOption *ao;
339     register gint i, j;
340     for(i = 0; i < arg->arg_set->len; i++){
341         as = arg->arg_set->pdata[i];
342         if(as->arg_option->len){
343             g_print("%s:\n", as->desc);
344             for(j = strlen(as->desc); j > 0; j--)
345                 g_print("-");
346             g_print("\n");
347             for(j = 0; j < as->arg_option->len; j++){
348                 ao = as->arg_option->pdata[j];
349                 if(ao->symbol)
350                     g_print("-%c ", ao->symbol);
351                 else
352                     g_print("   ");
353                 g_print("--%s", ao->option);
354                 if(ao->default_string)
355                     g_print(" [%s]", ao->default_string);
356                 else
357                     g_print(" [mandatory]");
358                 g_print(" ");
359                 ArgumentOption_print_values(ao, FALSE);
360                 g_print("\n");
361                 }
362             g_print("\n");
363             }
364         }
365     g_print("--\n");
366     return;
367     }
368 
Argument_long_help(Argument * arg)369 static void Argument_long_help(Argument *arg){
370     register ArgumentSet *as;
371     register ArgumentOption *ao;
372     register gint i, j;
373     register gchar *env_value;
374     for(i = 0; i < arg->arg_set->len; i++){
375         as = arg->arg_set->pdata[i];
376         if(as->arg_option->len){
377             g_print("%s:\n", as->desc);
378             for(j = strlen(as->desc); j > 0; j--)
379                 g_print("-");
380             g_print("\n\n");
381             for(j = 0; j < as->arg_option->len; j++){
382                 ao = as->arg_option->pdata[j];
383                 if(ao->symbol)
384                     g_print("-%c ", ao->symbol);
385                 g_print("--%s", ao->option);
386                 if(ao->type)
387                     g_print(" <%s>", ao->type);
388                 g_print("\n%s\n", ao->desc);
389                 g_print("Environment variable: $%s", ao->env_var);
390                 env_value = (gchar*)g_getenv(ao->env_var);
391                 if(env_value){
392                     g_print(" (Set to \"%s\")\n", env_value);
393                 } else {
394                     g_print(" (Not set)\n");
395                     }
396                 if(ao->default_string)
397                     g_print("Default: \"%s\"\n", ao->default_string);
398                 else
399                     g_print("*** This argument is mandatory ***\n");
400                 ArgumentOption_print_values(ao, TRUE);
401                 g_print("\n");
402                 }
403             }
404         }
405     g_print("--\n");
406     return;
407     }
408 
Argument_set_env_var_func(gpointer key,gpointer value,gpointer data)409 static gint Argument_set_env_var_func(gpointer key,
410                                       gpointer value,
411                                       gpointer data){
412     register ArgumentOption *ao = (ArgumentOption*)value;
413     register gchar *name = (gchar*)data;
414     register gint i;
415     ao->env_var = g_strdup_printf("%s_%s_%s",
416                   PACKAGE, name, ao->option);
417     for(i = strlen(ao->env_var)-1; i >= 0; i--)
418         if(isalnum(ao->env_var[i]))
419             ao->env_var[i] = toupper(ao->env_var[i]);
420         else
421             ao->env_var[i] = '_';
422     return FALSE;
423     }
424 
Argument_traverse_registry_func(gpointer key,gpointer value,gpointer data)425 static gint Argument_traverse_registry_func(gpointer key,
426                                             gpointer value,
427                                             gpointer data){
428     register ArgumentOption *ao = (ArgumentOption*)value;
429     register GPtrArray *error_queue = (GPtrArray*)data;
430     register gchar *err_msg, *env_var;
431     if(!ArgumentOption_is_set(ao)){
432         env_var = (gchar*)g_getenv(ao->env_var);
433         if(env_var)
434             ArgumentOption_add_value(ao, error_queue, env_var);
435         }
436     if(!ArgumentOption_is_set(ao)){
437         if(ArgumentOption_is_mandatory(ao)){
438             g_ptr_array_add(error_queue,
439                 g_strdup_printf(
440                     "No value set for mandatory argument --%s <%s>",
441                                             ao->option, ao->type));
442                 return FALSE;
443         } else {
444             ArgumentOption_add_value(ao, error_queue,
445                                      ao->default_string);
446             }
447         }
448     if(ao->handler){
449         err_msg = ao->handler(ao->arg_value, ao->handler_data);
450         if(err_msg)
451             g_ptr_array_add(error_queue, err_msg);
452     } else { /* List */
453         (*((GPtrArray**)ao->handler_data)) = ao->arg_list;
454         }
455     return FALSE;
456     }
457 
Argument_process_get_option(Argument * arg,gchar * string,GPtrArray * error_queue)458 static ArgumentOption *Argument_process_get_option(Argument *arg,
459                            gchar *string, GPtrArray *error_queue){
460     register ArgumentOption *ao = NULL;
461     register gint i;
462     if(string[0] == '-'){
463         if(string[1] == '-'){
464             ao = g_tree_lookup(arg->option_registry, string+2);
465             if(!ao)
466                 g_ptr_array_add(error_queue,
467                      g_strdup_printf("Unrecognised option \"%s\"",
468                                       string));
469         } else {
470             for(i = 1; string[i]; i++){
471                 ao = arg->symbol_registry[(guchar)string[i]];
472                 if(!ao)
473                     g_error("Unknown flag [%c] in argument [%s]",
474                             string[i], string);
475                 if(string[i+1]) /* If not last symbol */
476                     ArgumentOption_add_value(ao, error_queue, "TRUE");
477                 }
478             }
479         }
480     return ao;
481     }
482 
Argument_info(Argument * arg)483 void Argument_info(Argument *arg){
484     register gchar *cl = g_strjoinv(" ", arg->argv);
485     gchar hostname[1024];
486     g_print("Command line: [%s]\n", cl);
487     g_free(cl);
488     /**/
489     gethostname(hostname, 1024);
490     g_print("Hostname: [%s]\n", hostname);
491     return;
492     }
493 
Argument_process(Argument * arg,gchar * name,gchar * desc,gchar * synopsis)494 void Argument_process(Argument *arg, gchar *name, gchar *desc,
495                       gchar *synopsis){
496     register gint i;
497     register GPtrArray *unflagged_arg = g_ptr_array_new();
498     register ArgumentOption *ao;
499     register GPtrArray *error_queue = g_ptr_array_new();
500     arg->desc = desc?g_strdup(desc):g_strdup("");
501     arg->name = g_strdup(name);
502     g_tree_traverse(arg->option_registry, Argument_set_env_var_func,
503                     G_IN_ORDER, arg->name);
504     if(arg->mandatory_set->len && (arg->argc <= 1)){
505         Argument_usage(arg, synopsis);
506         exit(1);
507         }
508     for(i = 1; i < arg->argc; i++){
509         ao = Argument_process_get_option(arg, arg->argv[i],
510                                          error_queue);
511         if(ao){ /* -? */
512             if(ao->type){ /* Not boolean */
513                 if((i+1) == arg->argc){
514                     g_ptr_array_add(error_queue,
515                         g_strdup_printf("No argument supplied with %s",
516                             arg->argv[i]));
517                 } else {
518                     if(ao->handler){ /* Not list */
519                         ArgumentOption_add_value(ao, error_queue,
520                                                  arg->argv[++i]);
521                     } else { /* Is list */
522                         do {
523                             ArgumentOption_add_value(ao, error_queue,
524                                                      arg->argv[i+1]);
525                             i++;
526                         } while(((i+1) < arg->argc)
527                              && (arg->argv[i+1][0] != '-'));
528                         }
529                     }
530             } else { /* Is boolean */
531                 if((i+1) == arg->argc){
532                     ArgumentOption_add_value(ao, error_queue, "TRUE");
533                 } else {
534                     if(arg->argv[i+1][0] == '-'){
535                         ArgumentOption_add_value(ao, error_queue,
536                                                  "TRUE");
537                     } else {
538                         ArgumentOption_add_value(ao, error_queue,
539                                                  arg->argv[i+1]);
540                         i++;
541                         }
542                     }
543                 }
544         } else { /* unflagged argument */
545             g_ptr_array_add(unflagged_arg, arg->argv[i]);
546             }
547         }
548     if(arg->mandatory_set->len < unflagged_arg->len){
549         g_ptr_array_add(error_queue,
550           g_strdup_printf("Too many unflagged arguments"));
551     } else {
552         for(i = 0; i < unflagged_arg->len; i++){
553             ao = arg->mandatory_set->pdata[i];
554             ArgumentOption_add_value(ao, error_queue,
555                                      unflagged_arg->pdata[i]);
556             }
557         }
558     g_ptr_array_free(unflagged_arg, TRUE);
559     g_tree_traverse(arg->option_registry,
560                     Argument_traverse_registry_func,
561                     G_IN_ORDER, error_queue);
562     if((!(arg->show_short_help | arg->show_long_help)
563         && error_queue->len)){
564         Argument_usage(arg, synopsis);
565         g_print("--\n"
566                 "%d ERROR%s encountered in argument processing\n"
567                 "--\n",
568                 error_queue->len,
569                 (error_queue->len > 1)?"S were":" was");
570         for(i = 0; i < error_queue->len; i++){
571             g_print("[ %d ] : %s\n",
572                     i+1, (gchar*)error_queue->pdata[i]);
573             g_free(error_queue->pdata[i]);
574             }
575         g_print("--\n\n"
576                 "Use -h or --help for more information on usage\n"
577                 "\n");
578         exit(1);
579         }
580     if(arg->show_short_help){
581         Argument_usage(arg, synopsis);
582         Argument_short_help(arg);
583         exit(1);
584         }
585     if(arg->show_long_help){
586         Argument_usage(arg, synopsis);
587         Argument_long_help(arg);
588         exit(1);
589         }
590     g_ptr_array_free(error_queue, TRUE);
591     return;
592     }
593 /* FIXME: tidy */
594 
ArgumentSet_create(gchar * desc)595 ArgumentSet *ArgumentSet_create(gchar *desc){
596     register ArgumentSet *as = g_new(ArgumentSet, 1);
597     g_assert(desc);
598     as->desc = g_strdup(desc);
599     as->arg_option = g_ptr_array_new();
600     return as;
601     }
602 
Argument_absorb_ArgumentSet(Argument * arg,ArgumentSet * as)603 void Argument_absorb_ArgumentSet(Argument *arg, ArgumentSet *as){
604     register ArgumentOption *ao;
605     register gint i;
606     g_ptr_array_add(arg->arg_set, as);
607     for(i = 0; i < as->arg_option->len; i++){
608         ao = as->arg_option->pdata[i];
609         if(!ao->default_string)
610             g_ptr_array_add(arg->mandatory_set, ao);
611         if(ao->symbol){ /* Check option not already used */
612             g_assert(!arg->symbol_registry[(guchar)ao->symbol]);
613             arg->symbol_registry[(guchar)ao->symbol] = ao;
614             }
615         g_assert(!g_tree_lookup(arg->option_registry, ao));
616         g_tree_insert(arg->option_registry, ao->option, ao);
617         }
618     return;
619     }
620 
ArgumentSet_add_option(ArgumentSet * as,gchar symbol,gchar * option,gchar * type,gchar * desc,gchar * default_string,ArgumentHandler handler,gpointer handler_data)621 void ArgumentSet_add_option(ArgumentSet *as,
622                             gchar symbol,
623                             gchar *option,
624                             gchar *type,
625                             gchar *desc,
626                             gchar *default_string,
627                             ArgumentHandler handler,
628                             gpointer handler_data){
629     register ArgumentOption *ao = ArgumentOption_create(
630              as, symbol, option, type, desc,
631              default_string, handler, handler_data);
632     g_ptr_array_add(as->arg_option, ao);
633     return;
634     }
635 
Argument_parse_string(gchar * arg_string,gpointer data)636 gchar *Argument_parse_string(gchar *arg_string, gpointer data){
637     register gchar **dst_string = (gchar**)data;
638     if(!strcasecmp(arg_string, "NULL"))
639         (*dst_string) = NULL;
640     else
641         (*dst_string) = arg_string;
642     return NULL;
643     }
644 
Argument_parse_char(gchar * arg_string,gpointer data)645 gchar *Argument_parse_char(gchar *arg_string, gpointer data){
646     register gchar *dst_char = (gchar*)data;
647     if((!arg_string[0]) || (arg_string[1]))
648         return g_strdup_printf(
649                 "Expected single character argument not [%s]",
650                 arg_string);
651     (*dst_char) = arg_string[0];
652     return NULL;
653     }
654 
Argument_parse_int(gchar * arg_string,gpointer data)655 gchar *Argument_parse_int(gchar *arg_string, gpointer data){
656     register gint *dst_int = (gint*)data;
657     (*dst_int) = atoi(arg_string);
658     return NULL;
659     }
660 
Argument_parse_float(gchar * arg_string,gpointer data)661 gchar *Argument_parse_float(gchar *arg_string, gpointer data){
662     register gfloat *dst_float = (gfloat*)data;
663     (*dst_float) = atof(arg_string);
664     return NULL;
665     }
666 
Argument_parse_boolean(gchar * arg_string,gpointer data)667 gchar *Argument_parse_boolean(gchar *arg_string, gpointer data){
668     register gboolean *dst_boolean = (gboolean*)data;
669     (*dst_boolean) = ArgumentParse_boolean(arg_string);
670     return NULL;
671     }
672 
673 /**/
674 
675