Copies from older experiments which should not have been checked in.
[lttv.git] / ltt / branches / poly / lttv / option.c
CommitLineData
1cab0928 1#include <popt.h>
eccb5352 2
3d218f2a 3#include <lttv/hook.h>
c71d80de 4#include "lttv.h"
5#include "option.h"
eccb5352 6
7/* Extensible array of popt command line options. Modules add options as
8 they are loaded and initialized. */
9
10typedef struct _lttv_option {
11 lttv_option_hook hook;
12 void *hook_data;
13} lttv_option;
14
eccb5352 15static GArray *lttv_options_command;
16
17static GArray *lttv_options_command_popt;
18
19// unneeded static lttv_key *key ;
20
21static int command_argc;
22
23static char **command_argv;
24
25/* Lists of hooks to be called at different places */
26
27static lttv_hooks
28 *hooks_options_before,
29 *hooks_options_after;
30
31static gboolean init_done = FALSE;
32
33void lttv_options_command_parse(void *hook_data, void *call_data);
34
35
36void lttv_option_init(int argc, char **argv) {
37
38 lttv_hooks *hooks_init_after;
39
40 if(init_done) return;
41 else init_done = TRUE;
42
43 command_argc = argc;
44 command_argv = argv;
45
46 hooks_options_before = lttv_hooks_new();
47 hooks_options_after = lttv_hooks_new();
48
1cab0928 49 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
eccb5352 50 "hooks/options/before", hooks_options_before);
51
1cab0928 52 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
eccb5352 53 "hooks/options/after", hooks_options_after);
54
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));
57
1cab0928 58 hooks_init_after = lttv_attributes_get_pointer_pathname(lttv_global_attributes(),
eccb5352 59 "hooks/init/after");
60 lttv_hooks_add(hooks_init_after, lttv_options_command_parse, NULL);
61
62}
63
64void lttv_option_destroy() {
65
f68ad60d 66 struct poptOption *poption;
150ef81a 67
68 int i;
f68ad60d 69
150ef81a 70 for(i=0; i < lttv_options_command_popt->len ; i++) {
f68ad60d 71 poption = &g_array_index (lttv_options_command_popt, struct poptOption, i);
72
150ef81a 73 g_free((gpointer)poption->longName);
74 g_free((gpointer)poption->descrip);
75 g_free((gpointer)poption->argDescrip);
f68ad60d 76 }
eccb5352 77 g_array_free(lttv_options_command_popt,TRUE) ;
78 g_array_free(lttv_options_command,TRUE) ;
79
1cab0928 80 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
eccb5352 81 "hooks/options/before", NULL);
82
1cab0928 83 lttv_attributes_set_pointer_pathname(lttv_global_attributes(),
eccb5352 84 "hooks/options/after", NULL);
85
86 lttv_hooks_destroy(hooks_options_before);
87 lttv_hooks_destroy(hooks_options_after);
88
89}
90
91
92static int poptToLTT[] = {
93 POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG
94};
95
96
f68ad60d 97void lttv_option_add(const char *long_name, const char char_name,
98 const char *description, const char *argDescription,
150ef81a 99 const lttv_option_type t, void *p,
f68ad60d 100 const lttv_option_hook h, void *hook_data)
eccb5352 101{
102 struct poptOption poption;
103
104 lttv_option option;
105
f68ad60d 106 poption.longName = (char *)g_strdup(long_name);
eccb5352 107 poption.shortName = char_name;
f68ad60d 108 poption.descrip = (char *)g_strdup(description);
109 poption.argDescrip = (char *)g_strdup(argDescription);
eccb5352 110 poption.argInfo = poptToLTT[t];
111 poption.arg = p;
112 poption.val = lttv_options_command->len + 1;
113
114 option.hook = h;
115 option.hook_data = hook_data;
116
117 g_array_append_val(lttv_options_command_popt,poption);
118 g_array_append_val(lttv_options_command,option);
119}
120
121
122static struct poptOption endOption = { NULL, '\0', 0, NULL, 0};
123
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
128 */
129
130void lttv_options_command_parse(void *hook_data, void *call_data)
131{
132 int rc;
133 int lastrc;
134 poptContext c;
135 lttv_option *option;
136
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);
144
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);
148
149 /* There is no last good offset */
150 lastrc = -1;
151
152 /* Parse options while not end of options event */
153 while((rc = poptGetNextOpt(c)) != -1) {
154
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);
158 poptFreeContext(c);
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);
163
164 /* Cut out the already parsed elements */
165 if(lastrc != -1)
166 while(poptGetNextOpt(c) != lastrc) { } ;
167
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));
174 break ;
175 }
176 }
177
178 /* Remember this offset as the last good option value */
179 lastrc = rc;
180
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);
184
185 }
186
187 poptFreeContext(c);
188
189 lttv_hooks_call(hooks_options_after,NULL);
190
191}
192
This page took 0.029263 seconds and 4 git commands to generate.