tweak for include emulation recreation
[lttv.git] / ltt / branches / poly / lttv / option.c
CommitLineData
eccb5352 1
c71d80de 2#include "lttv.h"
3#include "option.h"
4#include "hook.h"
eccb5352 5#include <popt.h>
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
15extern lttv_attributes *attributes_global;
16
17static GArray *lttv_options_command;
18
19static GArray *lttv_options_command_popt;
20
21// unneeded static lttv_key *key ;
22
23static int command_argc;
24
25static char **command_argv;
26
27/* Lists of hooks to be called at different places */
28
29static lttv_hooks
30 *hooks_options_before,
31 *hooks_options_after;
32
33static gboolean init_done = FALSE;
34
35void lttv_options_command_parse(void *hook_data, void *call_data);
36
37
38void lttv_option_init(int argc, char **argv) {
39
40 lttv_hooks *hooks_init_after;
41
42 if(init_done) return;
43 else init_done = TRUE;
44
45 command_argc = argc;
46 command_argv = argv;
47
48 hooks_options_before = lttv_hooks_new();
49 hooks_options_after = lttv_hooks_new();
50
51 lttv_attributes_set_pointer_pathname(attributes_global,
52 "hooks/options/before", hooks_options_before);
53
54 lttv_attributes_set_pointer_pathname(attributes_global,
55 "hooks/options/after", hooks_options_after);
56
57 lttv_options_command_popt = g_array_new(0,0,sizeof(struct poptOption));
58 lttv_options_command = g_array_new(0,0,sizeof(lttv_option));
59
60 hooks_init_after = lttv_attributes_get_pointer_pathname(attributes_global,
61 "hooks/init/after");
62 lttv_hooks_add(hooks_init_after, lttv_options_command_parse, NULL);
63
64}
65
66void lttv_option_destroy() {
67
68 g_array_free(lttv_options_command_popt,TRUE) ;
69 g_array_free(lttv_options_command,TRUE) ;
70
71 lttv_attributes_set_pointer_pathname(attributes_global,
72 "hooks/options/before", NULL);
73
74 lttv_attributes_set_pointer_pathname(attributes_global,
75 "hooks/options/after", NULL);
76
77 lttv_hooks_destroy(hooks_options_before);
78 lttv_hooks_destroy(hooks_options_after);
79
80}
81
82
83static int poptToLTT[] = {
84 POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG
85};
86
87
88void lttv_option_add(char *long_name, char char_name, char *description,
89 char *argDescription, lttv_option_type t, void *p,
90 lttv_option_hook h, void *hook_data)
91{
92 struct poptOption poption;
93
94 lttv_option option;
95
96 poption.longName = long_name;
97 poption.shortName = char_name;
98 poption.descrip = description;
99 poption.argDescrip = argDescription;
100 poption.argInfo = poptToLTT[t];
101 poption.arg = p;
102 poption.val = lttv_options_command->len + 1;
103
104 option.hook = h;
105 option.hook_data = hook_data;
106
107 g_array_append_val(lttv_options_command_popt,poption);
108 g_array_append_val(lttv_options_command,option);
109}
110
111
112static struct poptOption endOption = { NULL, '\0', 0, NULL, 0};
113
114/* As we may load modules in the hooks called for argument processing,
115 * we have to recreate the argument context each time the
116 * lttv_options_command_popt is modified. This way we will be able to
117 * parse arguments defined by the modules
118 */
119
120void lttv_options_command_parse(void *hook_data, void *call_data)
121{
122 int rc;
123 int lastrc;
124 poptContext c;
125 lttv_option *option;
126
127 lttv_hooks_call(hooks_options_before,NULL);
128 /* Always add then remove the null option around the get context */
129 g_array_append_val(lttv_options_command_popt, endOption);
130 /* Compiler warning caused by const char ** for command_argv in header */
131 /* Nothing we can do about it. Header should not put it const. */
132 c = poptGetContext("lttv", command_argc, (const char**)command_argv,
133 (struct poptOption *)(lttv_options_command_popt->data),0);
134
135 /* We remove the null option here to be able to add options correctly */
136 g_array_remove_index(lttv_options_command_popt,
137 lttv_options_command_popt->len - 1);
138
139 /* There is no last good offset */
140 lastrc = -1;
141
142 /* Parse options while not end of options event */
143 while((rc = poptGetNextOpt(c)) != -1) {
144
145 if(rc == POPT_ERROR_BADOPT) {
146 /* We need to redo the context with information added by modules */
147 g_array_append_val(lttv_options_command_popt, endOption);
148 poptFreeContext(c);
149 c = poptGetContext("lttv", command_argc, (const char**)command_argv,
150 (struct poptOption *)lttv_options_command_popt->data,0);
151 g_array_remove_index(lttv_options_command_popt,
152 lttv_options_command_popt->len);
153
154 /* Cut out the already parsed elements */
155 if(lastrc != -1)
156 while(poptGetNextOpt(c) != lastrc) { } ;
157
158 /* Get the same option once again */
159 g_assert(rc = poptGetNextOpt(c) != -1) ;
160 if(rc == POPT_ERROR_BADOPT) {
161 /* If here again we have a parsing error with all context info ok,
162 * then there is a problem in the arguments themself, give up */
163 g_critical("option %s: %s", poptBadOption(c,0), poptStrerror(rc));
164 break ;
165 }
166 }
167
168 /* Remember this offset as the last good option value */
169 lastrc = rc;
170
171 /* Execute the hook registered with this option */
172 option = ((lttv_option *)lttv_options_command->data) + rc - 1;
173 if(option->hook != NULL) option->hook(option->hook_data);
174
175 }
176
177 poptFreeContext(c);
178
179 lttv_hooks_call(hooks_options_after,NULL);
180
181}
182
This page took 0.029154 seconds and 4 git commands to generate.