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  case('u'):{
93  pos += printf("=%lu", *(uint64_t*) o->variable);
94  break;
95  }
96  }
97  }
98  if (o->arg == OPTION_FLAG && (*(int*)o->variable) != 0){
99  pos += printf(" (%d)", (*(int*)o->variable));
100  }
101 
102  return pos;
103 }
104 
105 static void print_help_section(option_help * args, option_value_type type, char * name){
106  int first;
107  first = 1;
108  option_help * o;
109  for(o = args; o->shortVar != 0 || o->longVar != 0 || o->help != NULL ; o++){
110 
111  if (o->arg == type){
112  if( o->shortVar == 0 && o->longVar == 0 && o->help != NULL){
113  printf("%s\n", o->help);
114  continue;
115  }
116  if (first){
117  printf("\n%s\n", name);
118  first = 0;
119  }
120  printf(" ");
121  int pos = 0;
122  if(o->shortVar != 0 && o->longVar != 0){
123  pos += printf("-%c, --%s", o->shortVar, o->longVar);
124  }else if(o->shortVar != 0){
125  pos += printf("-%c", o->shortVar);
126  }else if(o->longVar != 0){
127  pos += printf("--%s", o->longVar);
128  }
129 
130  pos += print_value(o);
131  if(o->help != NULL){
132  for(int i = 0 ; i < (30 - pos); i++){
133  printf(" ");
134  }
135  printf("%s", o->help);
136  }
137  printf("\n");
138  }
139  }
140 }
141 
143  print_help_section(args, OPTION_REQUIRED_ARGUMENT, "Required arguments");
144  print_help_section(args, OPTION_FLAG, "Flags");
145  print_help_section(args, OPTION_OPTIONAL_ARGUMENT, "Optional arguments");
146 }
147 
148 
150  int pos = 0;
152  assert(o->variable != NULL);
153 
154  switch(o->type){
155  case('F'):{
156  pos += printf("=%.14f ", *(double*) o->variable);
157  break;
158  }
159  case('f'):{
160  pos += printf("=%.6f ", (double) *(float*) o->variable);
161  break;
162  }
163  case('d'):{
164  pos += printf("=%d ", *(int*) o->variable);
165  break;
166  }
167  case('H'):{
168  pos += printf("=HIDDEN");
169  break;
170  }
171  case('s'):{
172  if ( *(char**) o->variable != NULL && ((char**) o->variable)[0][0] != 0 ){
173  pos += printf("=%s", *(char**) o->variable);
174  }else{
175  pos += printf("=");
176  }
177  break;
178  }
179  case('c'):{
180  pos += printf("=%c", *(char*) o->variable);
181  break;
182  }
183  case('l'):{
184  pos += printf("=%lld", *(long long*) o->variable);
185  break;
186  }
187  case('u'):{
188  pos += printf("=%lu", *(uint64_t*) o->variable);
189  break;
190  }
191  }
192  }else{
193  //printf(" ");
194  }
195 
196  return pos;
197 }
198 
199 
201  option_help * o;
202  for(o = args; o->shortVar != 0 || o->longVar != 0 ; o++){
203  if (o->arg == type){
204  int pos = 0;
205  if (o->arg == OPTION_FLAG && (*(int*)o->variable) == 0){
206  continue;
207  }
208  printf("\t");
209 
210  if(o->shortVar != 0 && o->longVar != 0){
211  pos += printf("%s", o->longVar);
212  }else if(o->shortVar != 0){
213  pos += printf("%c", o->shortVar);
214  }else if(o->longVar != 0){
215  pos += printf("%s", o->longVar);
216  }
217 
218  pos += print_option_value(o);
219  printf("\n");
220  }
221  }
222 }
223 
224 
229 }
230 
231 static void option_parse_token(char ** argv, int * flag_parsed_next, int * requiredArgsSeen, options_all_t * opt_all, int * error, int * print_help){
232  char * txt = argv[0];
233  char * arg = strstr(txt, "=");
234 
235  int replaced_equal = 0;
236  int i = 0;
237  if(arg != NULL){
238  arg[0] = 0;
239  arg++;
240  replaced_equal = 1;
241  }
242  *flag_parsed_next = 0;
243 
244  for(int m = 0; m < opt_all->module_count; m++ ){
245  option_help * args = opt_all->modules[m].options;
246  if(args == NULL) continue;
247  // try to find matching option help
248  for(option_help * o = args; o->shortVar != 0 || o->longVar != 0 || o->help != NULL ; o++ ){
249  if( o->shortVar == 0 && o->longVar == 0 ){
250  // section
251  continue;
252  }
253  if ( (txt[0] == '-' && o->shortVar == txt[1]) || (strlen(txt) > 2 && txt[0] == '-' && txt[1] == '-' && o->longVar != NULL && strcmp(txt + 2, o->longVar) == 0)){
254  // now process the option.
255  switch(o->arg){
256  case (OPTION_FLAG):{
257  assert(o->type == 'd');
258  if(arg != NULL){
259  int val = atoi(arg);
260  (*(int*) o->variable) = (val < 0) ? 0 : val;
261  }else{
262  (*(int*) o->variable)++;
263  }
264  break;
265  }
267  case (OPTION_REQUIRED_ARGUMENT):{
268  // check if next is an argument
269  if(arg == NULL){
270  if(o->shortVar == txt[1] && txt[2] != 0){
271  arg = & txt[2];
272  }else{
273  // simply take the next value as argument
274  i++;
275  arg = argv[1];
276  *flag_parsed_next = 1;
277  }
278  }
279 
280  if(arg == NULL){
281  const char str[] = {o->shortVar, 0};
282  printf("Error, argument missing for option %s\n", (o->longVar != NULL) ? o->longVar : str);
283  exit(1);
284  }
285 
286  switch(o->type){
287  case('p'):{
288  // call the function in the variable
289  void(*fp)() = o->variable;
290  fp(arg);
291  break;
292  }
293  case('F'):{
294  *(double*) o->variable = atof(arg);
295  break;
296  }
297  case('f'):{
298  *(float*) o->variable = atof(arg);
299  break;
300  }
301  case('d'):{
302  int64_t val = string_to_bytes(arg);
303  if (val > INT_MAX || val < INT_MIN){
304  printf("WARNING: parsing the number %s to integer, this produced an overflow!\n", arg);
305  }
306  *(int*) o->variable = val;
307  break;
308  }
309  case('H'):
310  case('s'):{
311  (*(char **) o->variable) = strdup(arg);
312  break;
313  }
314  case('c'):{
315  (*(char *)o->variable) = arg[0];
316  if(strlen(arg) > 1){
317  printf("Error, ignoring remainder of string for option %c (%s).\n", o->shortVar, o->longVar);
318  }
319  break;
320  }
321  case('l'):{
322  *(long long*) o->variable = string_to_bytes(arg);
323  break;
324  }
325  case('u'):{
326  *(uint64_t*) o->variable = string_to_bytes(arg);
327  break;
328  }
329  default:
330  printf("ERROR: Unknown option type %c\n", o->type);
331  }
332  }
333  }
334  if(replaced_equal){
335  arg[-1] = '=';
336  }
337 
338  if(o->arg == OPTION_REQUIRED_ARGUMENT){
339  (*requiredArgsSeen)++;
340  }
341 
342  return;
343  }
344  }
345  }
346 
347  if(strcmp(txt, "-h") == 0 || strcmp(txt, "--help") == 0){
348  *print_help = 1;
349  }else{
350  *error = 1;
351  }
352 }
353 
354 int option_parse_str(char*val, options_all_t * opt_all){
355  int flag_parsed_next;
356  int error = 0;
357  int requiredArgsSeen = 0;
358  int print_help = 0;
359  char * argv[2] = {val, NULL};
360  option_parse_token(argv, & flag_parsed_next, & requiredArgsSeen, opt_all, & error, & print_help);
361  return error;
362 }
363 
364 int option_parse_key_value(char * key, char *val, options_all_t * opt_all){
365  int flag_parsed_next;
366  int error = 0;
367  int requiredArgsSeen = 0;
368  int print_help = 0;
369  char value[1024];
370  sprintf(value, "%s=%s", key, val);
371  char * argv[2] = {value, NULL};
372  option_parse_token(argv, & flag_parsed_next, & requiredArgsSeen, opt_all, & error, & print_help);
373  return error;
374 }
375 
376 int option_parse(int argc, char ** argv, options_all_t * opt_all){
377  int error = 0;
378  int requiredArgsSeen = 0;
379  int requiredArgsNeeded = 0;
380  int i;
381  int printhelp = 0;
382 
383  for(int m = 0; m < opt_all->module_count; m++ ){
384  option_help * args = opt_all->modules[m].options;
385  if(args == NULL) continue;
386  for(option_help * o = args; o->shortVar != 0 || o->longVar != 0 ; o++ ){
387  if(o->arg == OPTION_REQUIRED_ARGUMENT){
388  requiredArgsNeeded++;
389  }
390  }
391  }
392 
393  for(i=1; i < argc; i++){
394  int flag_parsed_next;
395  option_parse_token(& argv[i], & flag_parsed_next, & requiredArgsSeen, opt_all, & error, & printhelp);
396  if (flag_parsed_next){
397  i++;
398  }
399  if(error){
400  printf("Error invalid argument: %s\n", argv[i]);
401  }
402  }
403 
404  if( requiredArgsSeen != requiredArgsNeeded ){
405  printf("Error: Missing some required arguments\n\n");
406  printhelp = 1;
407  }
408 
409  if(error != 0){
410  printf("Invalid options\n");
411  printhelp = 1;
412  }
413 
414  if(printhelp == 1){
415  printf("Synopsis %s\n", argv[0]);
416  for(int m = 0; m < opt_all->module_count; m++ ){
417  option_help * args = opt_all->modules[m].options;
418  if(args == NULL) continue;
419  char * prefix = opt_all->modules[m].prefix;
420  if(prefix != NULL){
421  printf("\n\nModule %s\n", prefix);
422  }
423  option_print_help(args);
424  }
425  exit(0);
426  }
427 
428  return i;
429 }
option_module * modules
Definition: option.h:34
static int size
Definition: mdtest.c:91
int option_parse(int argc, char **argv, options_all_t *opt_all)
Definition: option.c:376
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:142
char * longVar
Definition: option.h:18
static void print_current_option_section(option_help *args, option_value_type type)
Definition: option.c:200
static void option_parse_token(char **argv, int *flag_parsed_next, int *requiredArgsSeen, options_all_t *opt_all, int *error, int *print_help)
Definition: option.c:231
char shortVar
Definition: option.h:17
void option_print_current(option_help *args)
Definition: option.c:225
static int print_option_value(option_help *o)
Definition: option.c:149
int option_parse_key_value(char *key, char *val, options_all_t *opt_all)
Definition: option.c:364
option_value_type arg
Definition: option.h:21
int option_parse_str(char *val, options_all_t *opt_all)
Definition: option.c:354
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:105
char * prefix
Definition: option.h:27
int module_count
Definition: option.h:33
char type
Definition: option.h:22
static struct cephfs_options o
Definition: aiori-CEPHFS.c:48
#define NULL
Definition: iordef.h:79