3db185ea7371059679a867e213229600c301b77a
[platform/upstream/isl.git] / isl_arg.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "isl_arg.h"
15
16 static void set_default_choice(struct isl_arg *arg, void *opt)
17 {
18         *(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value;
19 }
20
21 static void set_default_bool(struct isl_arg *arg, void *opt)
22 {
23         *(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value;
24 }
25
26 static void set_default_child(struct isl_arg *arg, void *opt)
27 {
28         void *child = calloc(1, arg->u.child.size);
29
30         if (child)
31                 isl_arg_set_defaults(arg->u.child.child, child);
32
33         *(void **)(((char *)opt) + arg->offset) = child;
34 }
35
36 void isl_arg_set_defaults(struct isl_arg *arg, void *opt)
37 {
38         int i;
39
40         for (i = 0; arg[i].type != isl_arg_end; ++i) {
41                 switch (arg[i].type) {
42                 case isl_arg_choice:
43                         set_default_choice(&arg[i], opt);
44                         break;
45                 case isl_arg_bool:
46                         set_default_bool(&arg[i], opt);
47                         break;
48                 case isl_arg_child:
49                         set_default_child(&arg[i], opt);
50                         break;
51                 }
52         }
53 }
54
55 static void print_arg_help(struct isl_arg *decl, const char *prefix)
56 {
57         if (decl->short_name)
58                 printf("  -%c, --", decl->short_name);
59         else
60                 printf("      --");
61         if (prefix)
62                 printf("%s-", prefix);
63         printf("%s", decl->long_name);
64 }
65
66 static void print_choice_help(struct isl_arg *decl, const char *prefix)
67 {
68         int i;
69
70         print_arg_help(decl, prefix);
71         printf("=");
72
73         for (i = 0; decl->u.choice.choice[i].name; ++i) {
74                 if (i)
75                         printf("|");
76                 printf("%s", decl->u.choice.choice[i].name);
77         }
78
79         printf("\n");
80 }
81
82 static void print_bool_help(struct isl_arg *decl, const char *prefix)
83 {
84         print_arg_help(decl, prefix);
85         printf("\n");
86 }
87
88 static void print_help(struct isl_arg *arg, const char *prefix)
89 {
90         int i;
91
92         for (i = 0; arg[i].type != isl_arg_end; ++i) {
93                 switch (arg[i].type) {
94                 case isl_arg_choice:
95                         print_choice_help(&arg[i], prefix);
96                         break;
97                 case isl_arg_bool:
98                         print_bool_help(&arg[i], prefix);
99                         break;
100                 }
101         }
102
103         for (i = 0; arg[i].type != isl_arg_end; ++i) {
104                 if (arg[i].type != isl_arg_child)
105                         continue;
106
107                 printf("\n");
108                 print_help(arg[i].u.child.child, arg[i].long_name);
109         }
110 }
111
112 static void print_help_and_exit(struct isl_arg *arg, const char *prog)
113 {
114         const char *slash;
115
116         slash = strrchr(prog, '/');
117         if (slash)
118                 printf("Usage: %s [OPTION...]\n\n", slash + 1);
119
120         print_help(arg, NULL);
121
122         exit(0);
123 }
124
125 static int parse_choice_option(struct isl_arg *decl, const char *arg,
126         const char *prefix, void *opt)
127 {
128         int i;
129         const char *equal;
130         const char *name;
131
132         if (strncmp(arg, "--", 2))
133                 return 0;
134
135         name = arg + 2;
136         equal = strchr(name, '=');
137         if (!equal)
138                 return 0;
139
140         if (prefix) {
141                 size_t prefix_len = strlen(prefix);
142                 if (strncmp(name, prefix, prefix_len) == 0 &&
143                     name[prefix_len] == '-')
144                         name += prefix_len + 1;
145         }
146
147         if (strncmp(name, decl->long_name, equal - name))
148                 return 0;
149
150         for (i = 0; decl->u.choice.choice[i].name; ++i) {
151                 if (strcmp(equal + 1, decl->u.choice.choice[i].name))
152                         continue;
153
154                 *(unsigned *)(((char *)opt) + decl->offset) =
155                         decl->u.choice.choice[i].value;
156
157                 return 1;
158         }
159
160         return 0;
161 }
162
163 static int parse_bool_option(struct isl_arg *decl, const char *arg, void *opt)
164 {
165         int i;
166
167         if ((arg[0] == '-' && arg[1] == decl->short_name && arg[2] == '\0') ||
168             (strncmp(arg, "--", 2) == 0 &&
169              strcmp(arg + 2, decl->long_name) == 0)) {
170                 *(unsigned *)(((char *)opt) + decl->offset) = 1;
171
172                 return 1;
173         }
174
175         return 0;
176 }
177
178 static int parse_option(struct isl_arg *decl, const char *arg,
179         const char *prefix, void *opt);
180
181 static int parse_child_option(struct isl_arg *decl, const char *arg, void *opt)
182 {
183         return parse_option(decl->u.child.child, arg, decl->long_name,
184                                 *(void **)(((char *)opt) + decl->offset));
185 }
186
187 static int parse_option(struct isl_arg *decl, const char *arg,
188         const char *prefix, void *opt)
189 {
190         int i;
191
192         for (i = 0; decl[i].type != isl_arg_end; ++i) {
193                 switch (decl[i].type) {
194                 case isl_arg_choice:
195                         if (parse_choice_option(&decl[i], arg, prefix, opt))
196                                 return 1;
197                         break;
198                 case isl_arg_bool:
199                         if (parse_bool_option(&decl[i], arg, opt))
200                                 return 1;
201                         break;
202                 case isl_arg_child:
203                         if (parse_child_option(&decl[i], arg, opt))
204                                 return 1;
205                         break;
206                 }
207         }
208
209         return 0;
210 }
211
212 static int drop_argument(int argc, char **argv, int drop)
213 {
214         for (; drop < argc; ++drop)
215                 argv[drop] = argv[drop + 1];
216
217         return argc - 1;
218 }
219
220 int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt)
221 {
222         int skip = 0;
223         int i;
224
225         for (i = 1; i < argc; ++i) {
226                 if (strcmp(argv[i], "--help") == 0)
227                         print_help_and_exit(arg, argv[0]);
228         }
229
230         while (argc > 1 + skip) {
231                 if (parse_option(arg, argv[1 + skip], NULL, opt))
232                         argc = drop_argument(argc, argv, 1 + skip);
233                 else {
234                         fprintf(stderr, "unrecognized option: %s\n",
235                                         argv[1 + skip]);
236                         exit(-1);
237                 }
238         }
239
240         return argc;
241 }