git-svn-id: http://ltt.polymtl.ca/svn@289 04897980-b3bd-0310-b5e0-8ef037075253
[lttv.git] / ltt / branches / poly / lttv / option.c
CommitLineData
eccb5352 1
ffd54a90 2#include <popt.h>
3#include <glib.h>
fcdf0ec2 4#include <lttv/option.h>
eccb5352 5
dc877563 6typedef struct _LttvOption {
ffd54a90 7 char *long_name;
dc877563 8 char char_name;
ffd54a90 9 char *description;
10 char *arg_description;
dc877563 11 LttvOptionType t;
12 gpointer p;
ffd54a90 13 LttvOptionHook hook;
dc877563 14 gpointer hook_data;
15} LttvOption;
eccb5352 16
dc877563 17GHashTable *options;
eccb5352 18
eccb5352 19
dc877563 20static void
21list_options(gpointer key, gpointer value, gpointer user_data)
22{
23 g_ptr_array_add((GPtrArray *)user_data, value);
24}
eccb5352 25
eccb5352 26
dc877563 27static void
28free_option(LttvOption *option)
29{
30 g_free(option->long_name);
31 g_free(option->description);
32 g_free(option->arg_description);
33 g_free(option);
34}
eccb5352 35
eccb5352 36
dc877563 37void lttv_option_init(int argc, char **argv)
38{
39 options = g_hash_table_new(g_str_hash, g_str_equal);
40}
eccb5352 41
eccb5352 42
dc877563 43void lttv_option_destroy()
44{
45 LttvOption option;
eccb5352 46
ffd54a90 47 GPtrArray *list = g_ptr_array_new();
eccb5352 48
dc877563 49 int i;
eccb5352 50
dc877563 51 g_hash_table_foreach(options, list_options, list);
52 g_hash_table_destroy(options);
eccb5352 53
dc877563 54 for(i = 0 ; i < list->len ; i++) {
55 free_option((LttvOption *)list->pdata[i]);
56 }
57 g_ptr_array_free(list, TRUE);
58}
eccb5352 59
eccb5352 60
dc877563 61void lttv_option_add(const char *long_name, const char char_name,
62 const char *description, const char *arg_description,
63 const LttvOptionType t, void *p,
64 const LttvOptionHook h, void *hook_data)
65{
66 LttvOption *option;
eccb5352 67
dc877563 68 if(g_hash_table_lookup(options, long_name) != NULL) {
69 g_warning("duplicate option");
70 return;
71 }
eccb5352 72
dc877563 73 option = g_new(LttvOption, 1);
74 option->long_name = g_strdup(long_name);
75 option->char_name = char_name;
76 option->description = g_strdup(description);
77 option->arg_description = g_strdup(arg_description);
78 option->t = t;
79 option->p = p;
ffd54a90 80 option->hook = h;
dc877563 81 option->hook_data = hook_data;
82 g_hash_table_insert(options, option->long_name, option);
83}
eccb5352 84
eccb5352 85
dc877563 86void
87lttv_option_remove(const char *long_name)
88{
89 LttvOption *option = g_hash_table_lookup(options, long_name);
eccb5352 90
dc877563 91 if(option == NULL) {
92 g_warning("trying to remove unknown option %s", long_name);
93 return;
94 }
95 g_hash_table_remove(options, long_name);
96 free_option(option);
eccb5352 97}
98
eccb5352 99
dc877563 100static int poptToLTT[] = {
101 POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG
102};
150ef81a 103
dc877563 104static struct poptOption endOption = { NULL, '\0', 0, NULL, 0};
f68ad60d 105
eccb5352 106
dc877563 107static void
108build_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc,
ffd54a90 109 int argc, char **argv)
dc877563 110{
111 LttvOption *option;
eccb5352 112
dc877563 113 GPtrArray *list;
eccb5352 114
dc877563 115 struct poptOption *popts;
eccb5352 116
dc877563 117 poptContext c;
eccb5352 118
dc877563 119 guint i;
eccb5352 120
dc877563 121 list = g_ptr_array_new();
eccb5352 122
dc877563 123 g_hash_table_foreach(options, list_options, list);
eccb5352 124
dc877563 125 /* Build a popt options array from our list */
eccb5352 126
dc877563 127 popts = g_new(struct poptOption, list->len + 1);
eccb5352 128
dc877563 129 for(i = 0 ; i < list->len ; i++) {
130 option = (LttvOption *)list->pdata[i];
131 popts[i].longName = option->long_name;
132 popts[i].shortName = option->char_name;
133 popts[i].descrip = option->description;
134 popts[i].argDescrip = option->arg_description;
135 popts[i].argInfo = poptToLTT[option->t];
136 popts[i].arg = option->p;
137 popts[i].val = i + 1;
138 }
139
140 /* Terminate the array for popt and create the context */
eccb5352 141
dc877563 142 popts[list->len] = endOption;
143 c = poptGetContext(argv[0], argc, (const char**)argv, popts, 0);
eccb5352 144
dc877563 145 *plist = list;
146 *ppopts = popts;
147 *pc = c;
eccb5352 148}
149
150
dc877563 151static void
152destroy_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc)
153{
154 g_ptr_array_free(*plist, TRUE); *plist = NULL;
155 g_free(*ppopts); *ppopts = NULL;
ffd54a90 156 poptFreeContext(*pc);
dc877563 157}
eccb5352 158
eccb5352 159
dc877563 160void lttv_option_parse(int argc, char **argv)
eccb5352 161{
dc877563 162 GPtrArray *list;
163
164 LttvOption *option;
165
166 int i, rc, first_arg;
167
168 struct poptOption *popts;
169
eccb5352 170 poptContext c;
eccb5352 171
dc877563 172 i = 0;
eccb5352 173
dc877563 174 first_arg = 0;
eccb5352 175
dc877563 176 build_popts(&list, &popts, &c, argc, argv);
eccb5352 177
178 /* Parse options while not end of options event */
dc877563 179
eccb5352 180 while((rc = poptGetNextOpt(c)) != -1) {
dc877563 181
182 /* The option was recognized and the rc value returned is the argument
183 position in the array. Call the associated hook if present. */
184
185 if(rc > 0) {
186 option = (LttvOption *)(list->pdata[rc - 1]);
187 if(option->hook != NULL) option->hook(option->hook_data);
188 i++;
189 }
190
191 else if(rc == POPT_ERROR_BADOPT && i != first_arg) {
192
193 /* Perhaps this option is newly added, restart parsing */
194
195 destroy_popts(&list, &popts, &c);
196 build_popts(&list, &popts, &c, argc, argv);
197
198 /* Get back to the same argument */
199
200 first_arg = i;
201 for(i = 0; i < first_arg; i++) poptGetNextOpt(c);
eccb5352 202 }
eccb5352 203
dc877563 204 else {
eccb5352 205
dc877563 206 /* The option has some error and it is not because this is a newly
207 added option not recognized. */
eccb5352 208
dc877563 209 g_error("option %s: %s", poptBadOption(c,0), poptStrerror(rc));
210 break;
211 }
212
213 }
214
215 destroy_popts(&list, &popts, &c);
eccb5352 216}
217
d888c9c8 218static void show_help(LttvOption *option)
219{
220 printf("--%s -%c argument: %s\n" , option->long_name,
221 option->char_name,
222 option->arg_description);
223 printf(" %s\n" , option->description);
224
225}
226
227void lttv_option_show_help(void)
228{
229 LttvOption option;
230
231 GPtrArray *list = g_ptr_array_new();
232
233 int i;
234
235 g_hash_table_foreach(options, list_options, list);
236
237 printf("Built-in commands available:\n");
238 printf("\n");
239
240 for(i = 0 ; i < list->len ; i++) {
241 show_help((LttvOption *)list->pdata[i]);
242 }
243 g_ptr_array_free(list, TRUE);
244
245
246}
This page took 0.036224 seconds and 4 git commands to generate.