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