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