IOR
option.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <limits.h>
7 
8 #include <option.h>
9 
10 /*
11 * Takes a string of the form 64, 8m, 128k, 4g, etc. and converts to bytes.
12 */
13 int64_t string_to_bytes(char *size_str)
14 {
15  int64_t size = 0;
16  char range;
17  int rc;
18 
19  rc = sscanf(size_str, " %lld %c ", (long long*) & size, &range);
20  if (rc == 2) {
21  switch ((int)range) {
22  case 'k':
23  case 'K':
24  size <<= 10;
25  break;
26  case 'm':
27  case 'M':
28  size <<= 20;
29  break;
30  case 'g':
31  case 'G':
32  size <<= 30;
33  break;
34  case 't':
35  case 'T':
36  size <<= 40;
37  break;
38  case 'p':
39  case 'P':
40  size <<= 50;
41  break;
42  }
43  } else if (rc == 0) {
44  size = -1;
45  }
46  return (size);
47 }
48 
49 /*
50  * Initial revision by JK
51  */
52 
53 static int print_value(option_help * o){
54  int pos = 0;
56  assert(o->variable != NULL);
57 
58  switch(o->type){
59  case('p'):{
60  pos += printf("=STRING");
61  break;
62  }
63  case('F'):{
64  pos += printf("=%.14f ", *(double*) o->variable);
65  break;
66  }
67  case('f'):{
68  pos += printf("=%.6f ", (double) *(float*) o->variable);
69  break;
70  }
71  case('d'):{
72  pos += printf("=%d ", *(int*) o->variable);
73  break;
74  }
75  case('H'):
76  case('s'):{
77  if ( *(char**) o->variable != NULL && ((char**) o->variable)[0][0] != 0 ){
78  pos += printf("=%s", *(char**) o->variable);
79  }else{
80  pos += printf("=STRING");
81  }
82  break;
83  }
84  case('c'):{
85  pos += printf("=%c", *(char*) o->variable);
86  break;
87  }
88  case('l'):{
89  pos += printf("=%lld", *(long long*) o->variable);
90  break;
91  }
92  }
93  }
94  if (o->arg == OPTION_FLAG && (*(int*)o->variable) != 0){
95  pos += printf(" (%d)", (*(int*)o->variable));
96  }
97 
98  return pos;
99 }
100 
101 static void print_help_section(option_help * args, option_value_type type, char * name){
102  int first;
103  first = 1;
104  option_help * o;
105  for(o = args; o->shortVar != 0 || o->longVar != 0 || o->help != NULL ; o++){
106 
107  if (o->arg == type){
108  if( o->shortVar == 0 && o->longVar == 0 && o->help != NULL){
109  printf("%s\n", o->help);
110  continue;
111  }
112  if (first){
113  printf("\n%s\n", name);
114  first = 0;
115  }
116  printf(" ");
117  int pos = 0;
118  if(o->shortVar != 0 && o->longVar != 0){
119  pos += printf("-%c, --%s", o->shortVar, o->longVar);
120  }else if(o->shortVar != 0){
121  pos += printf("-%c", o->shortVar);
122  }else if(o->longVar != 0){
123  pos += printf("--%s", o->longVar);
124  }
125 
126  pos += print_value(o);
127  if(o->help != NULL){
128  for(int i = 0 ; i < (30 - pos); i++){
129  printf(" ");
130  }
131  printf("%s", o->help);
132  }
133  printf("\n");
134  }
135  }
136 }
137 
139  print_help_section(args, OPTION_REQUIRED_ARGUMENT, "Required arguments");
140  print_help_section(args, OPTION_FLAG, "Flags");
141  print_help_section(args, OPTION_OPTIONAL_ARGUMENT, "Optional arguments");
142 }
143 
144 
146  int pos = 0;
148  assert(o->variable != NULL);
149 
150  switch(o->type){
151  case('F'):{
152  pos += printf("=%.14f ", *(double*) o->variable);
153  break;
154  }
155  case('f'):{
156  pos += printf("=%.6f ", (double) *(float*) o->variable);
157  break;
158  }
159  case('d'):{
160  pos += printf("=%d ", *(int*) o->variable);
161  break;
162  }
163  case('H'):{
164  pos += printf("=HIDDEN");
165  break;
166  }
167  case('s'):{
168  if ( *(char**) o->variable != NULL && ((char**) o->variable)[0][0] != 0 ){
169  pos += printf("=%s", *(char**) o->variable);
170  }else{
171  pos += printf("=");
172  }
173  break;
174  }
175  case('c'):{
176  pos += printf("=%c", *(char*) o->variable);
177  break;
178  }
179  case('l'):{
180  pos += printf("=%lld", *(long long*) o->variable);
181  break;
182  }
183  }
184  }else{
185  //printf(" ");
186  }
187 
188  return pos;
189 }
190 
191 
193  option_help * o;
194  for(o = args; o->shortVar != 0 || o->longVar != 0 ; o++){
195  if (o->arg == type){
196  int pos = 0;
197  if (o->arg == OPTION_FLAG && (*(int*)o->variable) == 0){
198  continue;
199  }
200  printf("\t");
201 
202  if(o->shortVar != 0 && o->longVar != 0){
203  pos += printf("%s", o->longVar);
204  }else if(o->shortVar != 0){
205  pos += printf("%c", o->shortVar);
206  }else if(o->longVar != 0){
207  pos += printf("%s", o->longVar);
208  }
209 
210  pos += print_option_value(o);
211  printf("\n");
212  }
213  }
214 }
215 
216 
221 }
222 
223 int option_parse(int argc, char ** argv, options_all * opt_all){
224  int error = 0;
225  int requiredArgsSeen = 0;
226  int requiredArgsNeeded = 0;
227  int i;
228  int printhelp = 0;
229 
230  for(int m = 0; m < opt_all->module_count; m++ ){
231  option_help * args = opt_all->modules[m].options;
232  if(args == NULL) continue;
233  for(option_help * o = args; o->shortVar != 0 || o->longVar != 0 ; o++ ){
234  if(o->arg == OPTION_REQUIRED_ARGUMENT){
235  requiredArgsNeeded++;
236  }
237  }
238  }
239 
240  for(i=1; i < argc; i++){
241  char * txt = argv[i];
242  int foundOption = 0;
243  char * arg = strstr(txt, "=");
244  int replaced_equal = 0;
245  if(arg != NULL){
246  arg[0] = 0;
247  arg++;
248  replaced_equal = 1;
249  }
250 
251  for(int m = 0; m < opt_all->module_count; m++ ){
252  option_help * args = opt_all->modules[m].options;
253  if(args == NULL) continue;
254  // try to find matching option help
255  for(option_help * o = args; o->shortVar != 0 || o->longVar != 0 || o->help != NULL ; o++ ){
256  if( o->shortVar == 0 && o->longVar == 0 ){
257  // section
258  continue;
259  }
260  if ( (txt[0] == '-' && o->shortVar == txt[1]) || (strlen(txt) > 2 && txt[0] == '-' && txt[1] == '-' && o->longVar != NULL && strcmp(txt + 2, o->longVar) == 0)){
261  foundOption = 1;
262 
263  // now process the option.
264  switch(o->arg){
265  case (OPTION_FLAG):{
266  assert(o->type == 'd');
267  (*(int*) o->variable)++;
268  break;
269  }
271  case (OPTION_REQUIRED_ARGUMENT):{
272  // check if next is an argument
273  if(arg == NULL){
274  if(o->shortVar == txt[1] && txt[2] != 0){
275  arg = & txt[2];
276  }else{
277  // simply take the next value as argument
278  i++;
279  arg = argv[i];
280  }
281  }
282 
283  if(arg == NULL){
284  const char str[] = {o->shortVar, 0};
285  printf("Error, argument missing for option %s\n", (o->longVar != NULL) ? o->longVar : str);
286  exit(1);
287  }
288 
289  switch(o->type){
290  case('p'):{
291  // call the function in the variable
292  void(*fp)() = o->variable;
293  fp(arg);
294  break;
295  }
296  case('F'):{
297  *(double*) o->variable = atof(arg);
298  break;
299  }
300  case('f'):{
301  *(float*) o->variable = atof(arg);
302  break;
303  }
304  case('d'):{
305  int64_t val = string_to_bytes(arg);
306  if (val > INT_MAX || val < INT_MIN){
307  printf("WARNING: parsing the number %s to integer, this produced an overflow!\n", arg);
308  }
309  *(int*) o->variable = val;
310  break;
311  }
312  case('H'):
313  case('s'):{
314  (*(char **) o->variable) = strdup(arg);
315  break;
316  }
317  case('c'):{
318  (*(char *)o->variable) = arg[0];
319  if(strlen(arg) > 1){
320  printf("Error, ignoring remainder of string for option %c (%s).\n", o->shortVar, o->longVar);
321  }
322  break;
323  }
324  case('l'):{
325  *(long long*) o->variable = string_to_bytes(arg);
326  break;
327  }
328  default:
329  printf("ERROR: Unknown option type %c\n", o->type);
330  }
331  }
332  }
333  if(replaced_equal){
334  arg[-1] = '=';
335  }
336 
337  if(o->arg == OPTION_REQUIRED_ARGUMENT){
338  requiredArgsSeen++;
339  }
340 
341  break;
342  }
343  }
344  }
345  if (! foundOption){
346  if(strcmp(txt, "-h") == 0 || strcmp(txt, "--help") == 0){
347  printhelp = 1;
348  }else{
349  printf("Error invalid argument: %s\n", txt);
350  error = 1;
351  }
352  }
353  }
354 
355  if( requiredArgsSeen != requiredArgsNeeded ){
356  printf("Error: Missing some required arguments\n\n");
357  printhelp = -1;
358  }
359 
360  if(error != 0){
361  printf("Invalid options\n");
362  printhelp = -1;
363  }
364 
365  if(printhelp == 1){
366  printf("Synopsis %s\n", argv[0]);
367  for(int m = 0; m < opt_all->module_count; m++ ){
368  option_help * args = opt_all->modules[m].options;
369  if(args == NULL) continue;
370  char * prefix = opt_all->modules[m].prefix;
371  if(prefix != NULL){
372  printf("\n\nModule %s\n", prefix);
373  }
374  option_print_help(args);
375  }
376  exit(0);
377  }
378 
379  return i;
380 }
static int size
Definition: mdtest.c:82
option_value_type
Definition: option.h:10
CURLcode rc
Definition: aiori-S3.c:121
void * variable
Definition: option.h:23
void option_print_help(option_help *args)
Definition: option.c:138
option_module * modules
Definition: option.h:33
int option_parse(int argc, char **argv, options_all *opt_all)
Definition: option.c:223
char * longVar
Definition: option.h:18
int module_count
Definition: option.h:32
static void print_current_option_section(option_help *args, option_value_type type)
Definition: option.c:192
char shortVar
Definition: option.h:17
void option_print_current(option_help *args)
Definition: option.c:217
static int print_option_value(option_help *o)
Definition: option.c:145
option_value_type arg
Definition: option.h:21
static int print_value(option_help *o)
Definition: option.c:53
int64_t string_to_bytes(char *size_str)
Definition: option.c:13
char * help
Definition: option.h:19
option_help * options
Definition: option.h:28
static void print_help_section(option_help *args, option_value_type type, char *name)
Definition: option.c:101
char * prefix
Definition: option.h:27
char type
Definition: option.h:22
static struct dummy_options o
Definition: aiori-DUMMY.c:25
#define NULL
Definition: iordef.h:79