5 #include <lttv/option.h>
7 /* Extensible array of popt command line options. Modules add options as
8 they are loaded and initialized. */
10 typedef struct _lttv_option
{
11 lttv_option_hook hook
;
15 static GArray
*lttv_options_command
;
17 static GArray
*lttv_options_command_popt
;
19 // unneeded static lttv_key *key ;
21 static int command_argc
;
23 static char **command_argv
;
25 /* Lists of hooks to be called at different places */
28 *hooks_options_before
,
31 static gboolean init_done
= FALSE
;
33 void lttv_options_command_parse(void *hook_data
, void *call_data
);
36 void lttv_option_init(int argc
, char **argv
) {
38 lttv_hooks
*hooks_init_after
;
41 else init_done
= TRUE
;
46 hooks_options_before
= lttv_hooks_new();
47 hooks_options_after
= lttv_hooks_new();
49 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
50 "hooks/options/before", hooks_options_before
);
52 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
53 "hooks/options/after", hooks_options_after
);
55 lttv_options_command_popt
= g_array_new(0,0,sizeof(struct poptOption
));
56 lttv_options_command
= g_array_new(0,0,sizeof(lttv_option
));
58 hooks_init_after
= lttv_attributes_get_pointer_pathname(lttv_global_attributes(),
60 lttv_hooks_add(hooks_init_after
, lttv_options_command_parse
, NULL
);
64 void lttv_option_destroy() {
66 struct poptOption
*poption
;
70 for(i
=0; i
< lttv_options_command_popt
->len
; i
++) {
71 poption
= &g_array_index (lttv_options_command_popt
, struct poptOption
, i
);
73 g_free((gpointer
)poption
->longName
);
74 g_free((gpointer
)poption
->descrip
);
75 g_free((gpointer
)poption
->argDescrip
);
77 g_array_free(lttv_options_command_popt
,TRUE
) ;
78 g_array_free(lttv_options_command
,TRUE
) ;
80 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
81 "hooks/options/before", NULL
);
83 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
84 "hooks/options/after", NULL
);
86 lttv_hooks_destroy(hooks_options_before
);
87 lttv_hooks_destroy(hooks_options_after
);
92 static int poptToLTT
[] = {
93 POPT_ARG_NONE
, POPT_ARG_STRING
, POPT_ARG_INT
, POPT_ARG_LONG
97 void lttv_option_add(const char *long_name
, const char char_name
,
98 const char *description
, const char *argDescription
,
99 const lttv_option_type t
, void *p
,
100 const lttv_option_hook h
, void *hook_data
)
102 struct poptOption poption
;
106 poption
.longName
= (char *)g_strdup(long_name
);
107 poption
.shortName
= char_name
;
108 poption
.descrip
= (char *)g_strdup(description
);
109 poption
.argDescrip
= (char *)g_strdup(argDescription
);
110 poption
.argInfo
= poptToLTT
[t
];
112 poption
.val
= lttv_options_command
->len
+ 1;
115 option
.hook_data
= hook_data
;
117 g_array_append_val(lttv_options_command_popt
,poption
);
118 g_array_append_val(lttv_options_command
,option
);
122 static struct poptOption endOption
= { NULL
, '\0', 0, NULL
, 0};
124 /* As we may load modules in the hooks called for argument processing,
125 * we have to recreate the argument context each time the
126 * lttv_options_command_popt is modified. This way we will be able to
127 * parse arguments defined by the modules
130 void lttv_options_command_parse(void *hook_data
, void *call_data
)
137 lttv_hooks_call(hooks_options_before
,NULL
);
138 /* Always add then remove the null option around the get context */
139 g_array_append_val(lttv_options_command_popt
, endOption
);
140 /* Compiler warning caused by const char ** for command_argv in header */
141 /* Nothing we can do about it. Header should not put it const. */
142 c
= poptGetContext("lttv", command_argc
, (const char**)command_argv
,
143 (struct poptOption
*)(lttv_options_command_popt
->data
),0);
145 /* We remove the null option here to be able to add options correctly */
146 g_array_remove_index(lttv_options_command_popt
,
147 lttv_options_command_popt
->len
- 1);
149 /* There is no last good offset */
152 /* Parse options while not end of options event */
153 while((rc
= poptGetNextOpt(c
)) != -1) {
155 if(rc
== POPT_ERROR_BADOPT
) {
156 /* We need to redo the context with information added by modules */
157 g_array_append_val(lttv_options_command_popt
, endOption
);
159 c
= poptGetContext("lttv", command_argc
, (const char**)command_argv
,
160 (struct poptOption
*)lttv_options_command_popt
->data
,0);
161 g_array_remove_index(lttv_options_command_popt
,
162 lttv_options_command_popt
->len
);
164 /* Cut out the already parsed elements */
166 while(poptGetNextOpt(c
) != lastrc
) { } ;
168 /* Get the same option once again */
169 g_assert(rc
= poptGetNextOpt(c
) != -1) ;
170 if(rc
== POPT_ERROR_BADOPT
) {
171 /* If here again we have a parsing error with all context info ok,
172 * then there is a problem in the arguments themself, give up */
173 g_critical("option %s: %s", poptBadOption(c
,0), poptStrerror(rc
));
178 /* Remember this offset as the last good option value */
181 /* Execute the hook registered with this option */
182 option
= ((lttv_option
*)lttv_options_command
->data
) + rc
- 1;
183 if(option
->hook
!= NULL
) option
->hook(option
->hook_data
);
189 lttv_hooks_call(hooks_options_after
,NULL
);