remove files unneeded for lttv
[lttv.git] / lttv / lttv / lttv / option.c
CommitLineData
9c312311 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
4e4d11b3 19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
eccb5352 22
ffd54a90 23#include <popt.h>
24#include <glib.h>
08b1c66e 25#include <lttv/module.h>
fcdf0ec2 26#include <lttv/option.h>
eccb5352 27
dc877563 28typedef struct _LttvOption {
ffd54a90 29 char *long_name;
dc877563 30 char char_name;
ffd54a90 31 char *description;
32 char *arg_description;
dc877563 33 LttvOptionType t;
34 gpointer p;
ffd54a90 35 LttvOptionHook hook;
dc877563 36 gpointer hook_data;
d18abf7d 37
38 /* Keep the order of addition */
39 guint val;
dc877563 40} LttvOption;
eccb5352 41
dc877563 42GHashTable *options;
eccb5352 43
eccb5352 44
dc877563 45static void
46list_options(gpointer key, gpointer value, gpointer user_data)
47{
d18abf7d 48 GPtrArray *list = (GPtrArray *)user_data;
49 LttvOption *option = (LttvOption *)value;
50
51 if(list->len < option->val)
52 g_ptr_array_set_size(list, option->val);
53 list->pdata[option->val-1] = option;
dc877563 54}
eccb5352 55
eccb5352 56
dc877563 57static void
58free_option(LttvOption *option)
59{
60 g_free(option->long_name);
61 g_free(option->description);
62 g_free(option->arg_description);
63 g_free(option);
64}
eccb5352 65
eccb5352 66
dc877563 67void lttv_option_add(const char *long_name, const char char_name,
68 const char *description, const char *arg_description,
69 const LttvOptionType t, void *p,
70 const LttvOptionHook h, void *hook_data)
71{
72 LttvOption *option;
eccb5352 73
2a2fa4f0 74 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add option %s", long_name);
dc877563 75 if(g_hash_table_lookup(options, long_name) != NULL) {
76 g_warning("duplicate option");
77 return;
78 }
eccb5352 79
dc877563 80 option = g_new(LttvOption, 1);
81 option->long_name = g_strdup(long_name);
82 option->char_name = char_name;
83 option->description = g_strdup(description);
84 option->arg_description = g_strdup(arg_description);
85 option->t = t;
86 option->p = p;
ffd54a90 87 option->hook = h;
dc877563 88 option->hook_data = hook_data;
d18abf7d 89 option->val = g_hash_table_size(options) + 1;
dc877563 90 g_hash_table_insert(options, option->long_name, option);
91}
eccb5352 92
eccb5352 93
dc877563 94void
95lttv_option_remove(const char *long_name)
96{
97 LttvOption *option = g_hash_table_lookup(options, long_name);
eccb5352 98
2a2fa4f0 99 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Remove option %s", long_name);
dc877563 100 if(option == NULL) {
101 g_warning("trying to remove unknown option %s", long_name);
102 return;
103 }
104 g_hash_table_remove(options, long_name);
105 free_option(option);
eccb5352 106}
107
eccb5352 108
dc877563 109static int poptToLTT[] = {
110 POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG
111};
150ef81a 112
00e74b69 113static struct poptOption endOption = { NULL, '\0', 0, NULL, 0, NULL, NULL };
f68ad60d 114
eccb5352 115
dc877563 116static void
117build_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc,
ffd54a90 118 int argc, char **argv)
dc877563 119{
120 LttvOption *option;
eccb5352 121
dc877563 122 GPtrArray *list;
eccb5352 123
dc877563 124 struct poptOption *popts;
eccb5352 125
dc877563 126 poptContext c;
eccb5352 127
dc877563 128 guint i;
eccb5352 129
d18abf7d 130 list = g_ptr_array_sized_new(g_hash_table_size(options));
eccb5352 131
dc877563 132 g_hash_table_foreach(options, list_options, list);
eccb5352 133
dc877563 134 /* Build a popt options array from our list */
eccb5352 135
dc877563 136 popts = g_new(struct poptOption, list->len + 1);
eccb5352 137
d18abf7d 138 /* add the options in the reverse order, so last additions are parsed first */
dc877563 139 for(i = 0 ; i < list->len ; i++) {
00e74b69 140 guint reverse_i = list->len-1-i;
dc877563 141 option = (LttvOption *)list->pdata[i];
00e74b69 142 popts[reverse_i].longName = option->long_name;
143 popts[reverse_i].shortName = option->char_name;
144 popts[reverse_i].descrip = option->description;
145 popts[reverse_i].argDescrip = option->arg_description;
146 popts[reverse_i].argInfo = poptToLTT[option->t];
147 popts[reverse_i].arg = option->p;
148 popts[reverse_i].val = option->val;
dc877563 149 }
150
151 /* Terminate the array for popt and create the context */
eccb5352 152
dc877563 153 popts[list->len] = endOption;
154 c = poptGetContext(argv[0], argc, (const char**)argv, popts, 0);
eccb5352 155
dc877563 156 *plist = list;
157 *ppopts = popts;
158 *pc = c;
eccb5352 159}
160
161
dc877563 162static void
163destroy_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc)
164{
165 g_ptr_array_free(*plist, TRUE); *plist = NULL;
166 g_free(*ppopts); *ppopts = NULL;
ffd54a90 167 poptFreeContext(*pc);
dc877563 168}
eccb5352 169
eccb5352 170
dc877563 171void lttv_option_parse(int argc, char **argv)
eccb5352 172{
dc877563 173 GPtrArray *list;
174
175 LttvOption *option;
176
177 int i, rc, first_arg;
178
179 struct poptOption *popts;
180
eccb5352 181 poptContext c;
eccb5352 182
dc877563 183 i = 0;
eccb5352 184
dc877563 185 first_arg = 0;
eccb5352 186
d18abf7d 187 guint hash_size = 0;
188
dc877563 189 build_popts(&list, &popts, &c, argc, argv);
eccb5352 190
191 /* Parse options while not end of options event */
dc877563 192
eccb5352 193 while((rc = poptGetNextOpt(c)) != -1) {
dc877563 194
195 /* The option was recognized and the rc value returned is the argument
196 position in the array. Call the associated hook if present. */
197
198 if(rc > 0) {
199 option = (LttvOption *)(list->pdata[rc - 1]);
2a2fa4f0 200 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Option %s encountered",
201 option->long_name);
d18abf7d 202 hash_size = g_hash_table_size(options);
b445142a 203 if(option->hook != NULL) {
2a2fa4f0 204 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s hook called",
205 option->long_name);
b445142a 206 option->hook(option->hook_data);
207 }
dc877563 208 i++;
d18abf7d 209
210 /* If the size of the option hash changed, add new options
211 * right now. It resolves the conflict of multiple same short
212 * option use.
213 */
214 if(hash_size != g_hash_table_size(options)) {
215 destroy_popts(&list, &popts, &c);
216 build_popts(&list, &popts, &c, argc, argv);
217
218 /* Get back to the same argument */
219
220 first_arg = i;
221 for(i = 0; i < first_arg; i++) {
222 rc = poptGetNextOpt(c);
223 option = (LttvOption *)(list->pdata[rc - 1]);
224 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s rescanned, skipped",
225 option->long_name);
226 }
227 }
dc877563 228 }
229
230 else if(rc == POPT_ERROR_BADOPT && i != first_arg) {
2a2fa4f0 231 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
232 "Option %s not recognized, rescan options with new additions",
233 poptBadOption(c,0));
dc877563 234
235 /* Perhaps this option is newly added, restart parsing */
236
237 destroy_popts(&list, &popts, &c);
238 build_popts(&list, &popts, &c, argc, argv);
239
240 /* Get back to the same argument */
241
242 first_arg = i;
b445142a 243 for(i = 0; i < first_arg; i++) {
244 rc = poptGetNextOpt(c);
245 option = (LttvOption *)(list->pdata[rc - 1]);
2a2fa4f0 246 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s rescanned, skipped",
247 option->long_name);
b445142a 248 }
eccb5352 249 }
eccb5352 250
dc877563 251 else {
eccb5352 252
dc877563 253 /* The option has some error and it is not because this is a newly
254 added option not recognized. */
eccb5352 255
dc877563 256 g_error("option %s: %s", poptBadOption(c,0), poptStrerror(rc));
257 break;
258 }
259
260 }
261
262 destroy_popts(&list, &popts, &c);
eccb5352 263}
264
08b1c66e 265/* CHECK */
d888c9c8 266static void show_help(LttvOption *option)
267{
268 printf("--%s -%c argument: %s\n" , option->long_name,
269 option->char_name,
270 option->arg_description);
271 printf(" %s\n" , option->description);
272
273}
274
275void lttv_option_show_help(void)
276{
d888c9c8 277 GPtrArray *list = g_ptr_array_new();
278
00e74b69 279 guint i;
d888c9c8 280
281 g_hash_table_foreach(options, list_options, list);
282
283 printf("Built-in commands available:\n");
284 printf("\n");
285
286 for(i = 0 ; i < list->len ; i++) {
287 show_help((LttvOption *)list->pdata[i]);
288 }
289 g_ptr_array_free(list, TRUE);
d888c9c8 290}
b445142a 291
08b1c66e 292static void init()
293{
294 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init option.c");
295 options = g_hash_table_new(g_str_hash, g_str_equal);
296}
297
298
299static void destroy()
300{
08b1c66e 301 GPtrArray *list = g_ptr_array_new();
302
00e74b69 303 guint i;
08b1c66e 304
305 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy option.c");
306 g_hash_table_foreach(options, list_options, list);
307 g_hash_table_destroy(options);
308
309 for(i = 0 ; i < list->len ; i++) {
310 free_option((LttvOption *)list->pdata[i]);
311 }
312 g_ptr_array_free(list, TRUE);
313}
314
315LTTV_MODULE("option", "Command line options processing", \
316 "Functions to add, remove and parse command line options", \
317 init, destroy)
This page took 0.0871459999999999 seconds and 4 git commands to generate.