MACSio  0.9
Multi-purpose, Application-Centric, Scalable I/O Proxy App
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
macsio_clargs.c
Go to the documentation of this file.
1 /*
2 Copyright (c) 2015, Lawrence Livermore National Security, LLC.
3 Produced at the Lawrence Livermore National Laboratory.
4 Written by Mark C. Miller
5 
6 LLNL-CODE-676051. All rights reserved.
7 
8 This file is part of MACSio
9 
10 Please also read the LICENSE file at the top of the source code directory or
11 folder hierarchy.
12 
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License (as published by the Free Software
15 Foundation) version 2, dated June 1991.
16 
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the terms and conditions of the GNU General
20 Public License for more details.
21 
22 You should have received a copy of the GNU General Public License along with
23 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
24 Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26 
27 #include <ctype.h>
28 #include <errno.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #ifdef HAVE_MPI
36 #include <mpi.h>
37 #endif
38 
39 #include <json-c/json.h>
40 
41 #include <macsio_clargs.h>
42 #include <macsio_log.h>
43 #include <macsio_utils.h>
44 
45 /* Flags for parameters */
46 #define PARAM_ASSIGNED 0x01
47 
48 typedef struct _knownArgInfo {
49  char *helpStr;
50  char *fmtStr;
51  char *defStr;
52  char *argName;
54  int paramCount;
55  char *paramTypes;
56  void **paramPtrs;
57  char *paramFlags;
59  struct _knownArgInfo *next;
61 
62 static double GetSizeFromModifierChar(char c)
63 {
64  if (!strncasecmp(MACSIO_UTILS_UnitsPrefixSystem, "decimal",
66  {
67  switch (c)
68  {
69  case 'k': case 'K': return 1000.0;
70  case 'm': case 'M': return 1000.0*1000.0;
71  case 'g': case 'G': return 1000.0*1000.0*1000.0;
72  case 't': case 'T': return 1000.0*1000.0*1000.0*1000.0;
73  case 'p': case 'P': return 1000.0*1000.0*1000.0*1000.0*1000.0;
74  }
75  }
76  else
77  {
78  switch (c)
79  {
80  case 'k': case 'K': return 1024.0;
81  case 'm': case 'M': return 1024.0*1024.0;
82  case 'g': case 'G': return 1024.0*1024.0*1024.0;
83  case 't': case 'T': return 1024.0*1024.0*1024.0*1024.0;
84  case 'p': case 'P': return 1024.0*1024.0*1024.0*1024.0*1024.0;
85  }
86  }
87 
88  return 1;
89 }
90 
91 /* Handles adding one or more params for a single key. If the key doesn't
92  exist, its a normal object add. If it does exist and is not already an
93  array object, delete it and make it into an array object. Otherwise
94  add the new param to the existing array object. */
95 static void
96 add_param_to_json_retobj(json_object *retobj, char const *key, json_object *addobj)
97 {
98  json_object *existing_member = 0;
99 
100  if (json_object_object_get_ex(retobj, key, &existing_member))
101  {
102  if (json_object_is_type(existing_member, json_type_array))
103  {
104  json_object_array_add(existing_member, addobj);
105  }
106  else
107  {
108  json_object *addarray = json_object_new_array();
109  json_object_array_add(addarray, existing_member);
110  json_object_array_add(addarray, addobj);
111  json_object_get(existing_member);
112  json_object_object_add(retobj, key, addarray); /* replaces */
113  }
114  }
115  else
116  {
117  json_object_object_add(retobj, key, addobj);
118  }
119 }
120 
121 /*---------------------------------------------------------------------------------------------------------------------------------
122  * Audience: Private
123  * Chapter: Example and Test Utilities
124  * Purpose: Parse and assign command-line arguments
125  *
126  * Description: This routine is designed to do parsing of simple command-line arguments and assign values associated with
127  * them to caller-supplied scalar variables. It is used in the following manner.
128  *
129  * MACSIO_ProccessCommandLine(argc, argv,
130  * "-multifile",
131  * "if specified, use a file-per-timestep",
132  * &doMultifile,
133  * "-numCycles %d",
134  * "specify the number of cycles to run",
135  * &numCycles,
136  * "-dims %d %f %d %f",
137  * "specify size (logical and geometric) of mesh",
138  * &Ni, &Xi, &Nj, &Xj
139  * MACSIO_CLARGS_END_OF_ARGS);
140  *
141  * After the argc,argv arguments, the remaining arguments come in groups of 3. The first of the three is a
142  * argument format specifier much like a printf statement. It indicates the type of each parameter to the
143  * argument and the number of parameters. Presently, it understands only %d, %f and %s types. the second
144  * of the three is a help line for the argument. Note, you can make this string as long as the C-compiler
145  * will permit. You *need*not* embed any '\n' charcters as the print routine will do that for you.
146  *
147  * Command line arguments for which only existence of the argument is tested assume a caller-supplied return
148  * value of int and will be assigned `1' if the argument exists and `0' otherwise.
149  *
150  * Do not name any argument with a substring `help' as that is reserved for obtaining help. Also, do not
151  * name any argument with the string `end_of_args' as that is used to indicate the end of the list of
152  * arguments passed to the function.
153  *
154  * If any argument on the command line has the substring `help', help will be printed by processor 0 and then
155  * this function calls MPI_Finalize() (in parallel) and exit().
156  *
157  * Parallel: This function must be called collectively in MPI_COMM_WORLD. Parallel and serial behavior is identical except in
158  * the
159  *
160  * Return: MACSIO_CLARGS_OK, MACSIO_CLARGS_ERROR or MACSIO_CLARGS_HELP
161  *
162  * Programmer: Mark Miller, LLNL, Thu Dec 19, 2001
163  *---------------------------------------------------------------------------------------------------------------------------------
164  */
165 int
167  void **retobj, /* returned object (for cases that need it) */
168  MACSIO_CLARGS_ArgvFlags_t flags, /* flag to indicate what to do if encounter an unknown argument (FATAL|WARN) */
169  int argi, /* first arg index to start processing at */
170  int argc, /* argc from main */
171  char **argv, /* argv from main */
172  ... /* a comma-separated list of 1) argument name and format specifier, 2) help-line for argument,
173  3) caller-supplied scalar variables to set */
174 )
175 {
176  char *argvStr = NULL;
177  int i, rank = 0;
178  int helpWasRequested = 0;
179  int invalidArgTypeFound = 0;
180  int firstArg;
181  int terminalWidth = 120 - 10;
182  int haveSeenSeparatorArg = 0;
183  MACSIO_KnownArgInfo_t *knownArgs;
184  va_list ap;
185  json_object *ret_json_obj = 0;
186  int depth;
187  int isgroup = 0;
188 
189 #ifdef HAVE_MPI
190  { int result;
191  if ((MPI_Initialized(&result) != MPI_SUCCESS) || !result)
192  {
195  ("MPI is not initialized"));
196  return MACSIO_CLARGS_ERROR;
197  }
198  }
199  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
200 #endif
201 
202  /* quick check for a help request */
203  if (rank == 0)
204  {
205  for (i = 0; i < argc; i++)
206  {
207  if (strstr(argv[i], "help") != NULL)
208  {
209  char *s;
210  helpWasRequested = 1;
211  if ((s=getenv("COLUMNS")) && isdigit(*s))
212  terminalWidth = (int)strtol(s, NULL, 0) - 10;
213  break;
214  }
215  }
216  }
217 
218 #ifdef HAVE_MPI
219 #warning DO JUST ONE BCAST HERE
220  MPI_Bcast(&helpWasRequested, 1, MPI_INT, 0, MPI_COMM_WORLD);
221 #endif
222 
223  /* everyone builds the command line parameter list */
224  va_start(ap, argv);
225 
226  knownArgs = NULL;
227  firstArg = 1;
228  depth = 1;
229  while (1)
230  {
231  int n, paramCount, argNameLength;
232  char *fmtStr, *defStr, *helpStr, *p, *paramTypes, *paramFlags;
233  void **paramPtrs;
234  MACSIO_KnownArgInfo_t *newArg, *oldArg;
235  int isgroup_begin, isgroup_end;
236 
237  /* get this arg's format specifier string */
238  fmtStr = va_arg(ap, char *);
239 
240  /* check to see if we're done */
241  if (!strncmp(fmtStr, MACSIO_CLARGS_END_OF_ARGS, strlen(MACSIO_CLARGS_END_OF_ARGS)))
242  break;
243 
244  /* check to see if this is a grouping item */
245  isgroup_begin = isgroup_end = 0;
246  if (!strncmp(fmtStr, MACSIO_CLARGS_GRP_BEG, strlen(MACSIO_CLARGS_GRP_BEG)))
247  {
248  isgroup_begin = 1;
249  depth++;
250  }
251  else if (!strncmp(fmtStr, MACSIO_CLARGS_GRP_END, strlen(MACSIO_CLARGS_GRP_END)))
252  {
253  isgroup_end = 1;
254  depth--;
255  }
256 
257  /* get this arg's default string */
258  defStr = va_arg(ap, char *);
259 
260  /* get this arg's help string */
261  helpStr = va_arg(ap, char *);
262 
263  /* print this arg's help string from proc 0 if help was requested */
264  if (helpWasRequested && rank == 0)
265  {
266  static int first = 1;
267  char helpFmtStr[32];
268  FILE *outFILE = (isatty(2) ? stderr : stdout);
269  int has_embedded_newlines = strchr(helpStr, '\n') != 0;
270  int help_str_len = strlen(helpStr);
271 
272  if (first)
273  {
274  first = 0;
275  fprintf(outFILE, "Usage and Help for \"%s\"\n", argv[0]);
276  fprintf(outFILE, "Defaults, if any, in square brackets after argument definition\n");
277  }
278 
279  /* this arguments format string */
280  if (isgroup_begin)
281  fprintf(outFILE, "\n%*s%s\n", 2*(depth-1), " ", &fmtStr[strlen(MACSIO_CLARGS_GRP_BEG)]);
282  else if (isgroup_end)
283  fprintf(outFILE, "\n");
284  else
285  fprintf(outFILE, "%*s%s [%s]\n", 2*depth, " ", fmtStr, defStr?defStr:"");
286 
287  if (has_embedded_newlines || help_str_len < terminalWidth)
288  {
289  p = helpStr;
290  while (p)
291  {
292  char *pnext = strchr(p, '\n');
293  int len = pnext ? pnext - p : strlen(p);
294  fprintf(outFILE, "%*s%*.*s\n", 2*(depth+1), " ", len, len, p);
295  p = pnext ? pnext+1 : 0;
296  }
297  }
298  else
299  {
300  /* this arguments help-line format string */
301  sprintf(helpFmtStr, "%%*s%%-%d.%ds", terminalWidth, terminalWidth);
302 
303  /* this arguments help string */
304  p = helpStr;
305  n = (int)strlen(helpStr);
306  i = 0;
307  while (i < n)
308  {
309  fprintf(outFILE, helpFmtStr, 2*(depth+1), " ", p);
310  p += terminalWidth;
311  i += terminalWidth;
312  if ((i < n) && (*p != ' '))
313  fprintf(outFILE, "-\n");
314  else
315  fprintf(outFILE, "\n");
316  }
317  }
318  }
319 
320  /* count number of parameters for this argument */
321  paramCount = 0;
322  n = (int)strlen(fmtStr);
323  argNameLength = 0;
324  for (i = 0; i < n; i++)
325  {
326  if (fmtStr[i] == '%' && fmtStr[i+1] != '%')
327  {
328  paramCount++;
329  if (argNameLength == 0)
330  argNameLength = i-1;
331  }
332  }
333 
334  if (paramCount)
335  {
336  int k;
337 
338  /* allocate a string for the conversion characters */
339  paramTypes = (char *) malloc((unsigned int)paramCount+1);
340 
341  /* allocate a string for the pointers to caller's arguments to set */
342  paramPtrs = (void **) calloc(paramCount, sizeof(void*));
343 
344  /* allocate flags for params */
345  paramFlags = (char*) calloc(paramCount+1, sizeof(char));
346 
347  /* ok, make a second pass through the string and setup argument pointers and conversion characters */
348  k = 0;
349  for (i = 0; i < n; i++)
350  {
351  if (fmtStr[i] == '%' && fmtStr[i+1] != '%')
352  {
353  paramTypes[k] = fmtStr[i+1];
354  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
355  {
356  switch (paramTypes[k])
357  {
358  case 'd': paramPtrs[k] = va_arg(ap, int *); break;
359  case 's': paramPtrs[k] = va_arg(ap, char **); break;
360  case 'f': paramPtrs[k] = va_arg(ap, double *); break;
361  case 'n': paramPtrs[k] = va_arg(ap, int *); break;
362  default: invalidArgTypeFound = k+1; break;
363  }
364  }
365  k++;
366  }
367  }
368  }
369  else
370  {
371  /* in this case, we assume we just have a boolean (int) value */
372  argNameLength = n;
373  paramTypes = NULL;
374  paramPtrs = (void **) malloc(sizeof(void*));
375  paramFlags = (char*) malloc(sizeof(char));
376  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
377  paramPtrs[0] = va_arg(ap, int *);
378  }
379 
380  /* ok, we're done with this parameter, so plug it into the paramInfo array */
381  newArg = (MACSIO_KnownArgInfo_t *) calloc(1, sizeof(MACSIO_KnownArgInfo_t));
382  newArg->helpStr = helpStr;
383  newArg->fmtStr = fmtStr;
384  newArg->defStr = defStr;
385  if (fmtStr[0] == '-')
386  {
387  if (fmtStr[1] == '-')
388  newArg->argName = strndup(&fmtStr[2], argNameLength-2);
389  else
390  newArg->argName = strndup(&fmtStr[1], argNameLength-1);
391  }
392  else
393  {
394  newArg->argName = strndup(&fmtStr[0], argNameLength-0);
395  }
396  newArg->argNameLength = argNameLength;
397  newArg->paramCount = paramCount;
398  newArg->paramTypes = paramTypes;
399  newArg->paramPtrs = paramPtrs;
400  newArg->paramFlags = paramFlags;
401  newArg->next = NULL;
402  if (firstArg)
403  {
404  firstArg = 0;
405  knownArgs = newArg;
406  oldArg = newArg;
407  }
408  else
409  oldArg->next = newArg;
410  oldArg = newArg;
411  }
412  va_end(ap);
413 
414 #ifdef HAVE_MPI
415  MPI_Bcast(&invalidArgTypeFound, 1, MPI_INT, 0, MPI_COMM_WORLD);
416 #endif
417  if (invalidArgTypeFound)
418  {
419  if (rank == 0)
422  ("invalid argument type encountered at position %d",invalidArgTypeFound));
423 #warning FIX WARN FAILURE BEHAVIOR HERE
424  return MACSIO_CLARGS_ERROR;
425  }
426 
427  /* exit if help was requested */
428  if (helpWasRequested)
429  return MACSIO_CLARGS_HELP;
430 
431  /* ok, now broadcast the whole argc, argv data */
432 #ifdef HAVE_MPI
433  {
434  int argvLen;
435  char *p;
436 
437  /* processor zero computes size of linearized argv and builds it */
438  if (rank == 0)
439  {
440 #warning MAKE THIS A CLARG
441  if (getenv("MACSIO_CLARGS_IGNORE_UNKNOWN_ARGS"))
443 
444  /* compute size of argv */
445  argvLen = 0;
446  for (i = 0; i < argc; i++)
447  argvLen += (strlen(argv[i])) + 1;
448 
449  /* allocate an array of chars to broadcast */
450  argvStr = (char *) malloc((unsigned int)argvLen);
451 
452  /* now, fill argvStr */
453  p = argvStr;
454  for (i = 0; i < argc; i++)
455  {
456  strcpy(p, argv[i]);
457  p += (strlen(argv[i]) + 1);
458  *(p-1) = '\0';
459  }
460  }
461 
462  /* now broadcast the linearized argv */
463  MPI_Bcast(&flags, 1, MPI_INT, 0, MPI_COMM_WORLD);
464  MPI_Bcast(&argc, 1, MPI_INT, 0, MPI_COMM_WORLD);
465  MPI_Bcast(&argvLen, 1, MPI_INT, 0, MPI_COMM_WORLD);
466  if (rank != 0)
467  argvStr = (char *) malloc((unsigned int)argvLen);
468  MPI_Bcast(argvStr, argvLen, MPI_CHAR, 0, MPI_COMM_WORLD);
469 
470  /* Issue: We're relying upon embedded nulls in argvStr */
471  /* now, put it back into the argv form */
472  if (rank != 0)
473  {
474  argv = (char **) malloc(argc * sizeof(char*));
475  p = argvStr;
476  for (i = 0; i < argc; i++)
477  {
478  argv[i] = p;
479  p += (strlen(p) + 1);
480  }
481  }
482  }
483 #endif
484 
485  /* And now, finally, we can process the arguments and assign them */
486  if (flags.route_mode == MACSIO_CLARGS_TOJSON)
487  ret_json_obj = json_object_new_object();
488  i = argi;
489  while (i < argc && !haveSeenSeparatorArg)
490  {
491  int foundArg;
493  char argName[64] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
494  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
495  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
496  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
497 
498  /* search known arguments for this command line argument */
499  p = knownArgs;
500  foundArg = 0;
501  while (p && !foundArg)
502  {
503  if (!strncmp(argv[i], p->fmtStr, (unsigned int)(p->argNameLength) ))
504  {
505  strncpy(argName, argv[i], (unsigned int)(p->argNameLength));
506  foundArg = 1;
507  }
508  else
509  p = p->next;
510  }
511  if (foundArg)
512  {
513  int j;
514 
515  /* assign command-line arguments to caller supplied parameters */
516  if (p->paramCount)
517  {
518  for (j = 0; j < p->paramCount; j++)
519  {
520  if (i == argc - 1)
521  MACSIO_LOG_MSGL(MACSIO_LOG_StdErr, Die, ("too few arguments for command-line options"));
522  switch (p->paramTypes[j])
523  {
524  case 'd':
525  {
526  int n = strlen(argv[++i])-1;
527  int tmpInt;
528  double tmpDbl, ndbl;
529  ndbl = GetSizeFromModifierChar(argv[i][n]);
530  tmpInt = strtol(argv[i], (char **)NULL, 10);
531  tmpDbl = tmpInt * ndbl;
532  if ((int)tmpDbl != tmpDbl)
533  {
536  ("integer overflow (%.0f) for arg \"%s\"",tmpDbl,argv[i-1]));
537  }
538  else
539  {
540  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
541  {
542  int *pInt = (int *) (p->paramPtrs[j]);
543  *pInt = (int) tmpDbl;
544  }
545  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
546  add_param_to_json_retobj(ret_json_obj, &argName[2], json_object_new_int((int)tmpDbl));
547  p->paramFlags[j] |= PARAM_ASSIGNED;
548  }
549  break;
550  }
551  case 's':
552  {
553  i++;
554  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
555  {
556  char **pChar = (char **) (p->paramPtrs[j]);
557  if (*pChar == NULL)
558  *pChar = (char*) malloc(strlen(argv[i])+1);
559  strcpy(*pChar, argv[i]);
560  }
561  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
562  add_param_to_json_retobj(ret_json_obj, &argName[2], json_object_new_string(argv[i]));
563  p->paramFlags[j] |= PARAM_ASSIGNED;
564  break;
565  }
566  case 'f':
567  {
568  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
569  {
570  double *pDouble = (double *) (p->paramPtrs[j]);
571  *pDouble = atof(argv[++i]);
572  }
573  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
574  add_param_to_json_retobj(ret_json_obj, &argName[2], json_object_new_double(atof(argv[++i])));
575  p->paramFlags[j] |= PARAM_ASSIGNED;
576  break;
577  }
578  case 'n': /* special case to return arg index */
579  {
580  haveSeenSeparatorArg = 1;
581  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
582  {
583  int *pInt = (int *) (p->paramPtrs[j]);
584  *pInt = i++;
585  }
586  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
587  add_param_to_json_retobj(ret_json_obj, "argi", json_object_new_int(i++));
588  p->paramFlags[j] |= PARAM_ASSIGNED;
589  break;
590  }
591  }
592  }
593  }
594  else
595  {
596  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
597  {
598  int *pInt = (int *) (p->paramPtrs[0]);
599  *pInt = 1;
600  p->paramFlags[0] |= PARAM_ASSIGNED;
601  }
602  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
603  {
604  add_param_to_json_retobj(ret_json_obj, &argName[2], json_object_new_boolean((json_bool)1));
605  p->paramFlags[0] |= PARAM_ASSIGNED;
606  }
607  }
608  }
609  else
610  {
611  char *p = strrchr(argv[0], '/');
612  FILE *outFILE = (isatty(2) ? stderr : stdout);
613  p = p ? p+1 : argv[0];
614  if (rank == 0)
617  ("%s: unknown argument %s. Type %s --help for help",p,argv[i],p));
618  return MACSIO_CLARGS_ERROR;
619  }
620 
621  /* move to next argument */
622  i++;
623  }
624 
625  /* free argvStr */
626  if (argvStr)
627  free(argvStr);
628 
629  /* free the argv pointers we created, locally */
630  if (rank != 0 && argv)
631  free(argv);
632 
633  /* find any args for which defaults are specified but a value
634  wasn't assigned from arc/argv and assign the default value(s). */
636  {
637  MACSIO_KnownArgInfo_t *pka = knownArgs;
638  while (pka)
639  {
640  if (pka->defStr)
641  {
642  if (pka->paramCount)
643  {
644  int j;
645  char *defStr, *defStrOrig;
646  defStr = defStrOrig = strdup(pka->defStr);
647  for (j = 0; j < pka->paramCount; j++)
648  {
649  char *defParam = strsep(&defStr, " ");
650 
651  if (pka->paramFlags[j] & PARAM_ASSIGNED) continue;
652 
654  ("Default value of \"%s\" assigned for param %d of arg \"%s\"",defParam,j,pka->argName));
655 
656  switch (pka->paramTypes[j])
657  {
658  case 'd':
659  {
660  int n = strlen(defParam)-1;
661  int tmpInt;
662  double tmpDbl, ndbl;
663  ndbl = GetSizeFromModifierChar(defParam[n]);
664  tmpInt = strtol(defParam, (char **)NULL, 10);
665  tmpDbl = tmpInt * ndbl;
666  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
667  {
668  int *pInt = (int *) (pka->paramPtrs[j]);
669  *pInt = (int) tmpDbl;
670  }
671  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
672  add_param_to_json_retobj(ret_json_obj, pka->argName, json_object_new_int((int)tmpDbl));
673  break;
674  }
675  case 's':
676  {
677  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
678  {
679  char **pChar = (char **) (pka->paramPtrs[j]);
680  if (*pChar == NULL)
681  *pChar = (char*) malloc(strlen(defParam)+1);
682  strcpy(*pChar, defParam);
683  }
684  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
685  {
686  add_param_to_json_retobj(ret_json_obj, pka->argName, json_object_new_string(defParam));
687  }
688  break;
689  }
690  case 'f':
691  {
692  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
693  {
694  double *pDouble = (double *) (pka->paramPtrs[j]);
695  *pDouble = atof(defParam);
696  }
697  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
698  add_param_to_json_retobj(ret_json_obj, pka->argName, json_object_new_double(atof(defParam)));
699  break;
700  }
701  }
702  }
703  free(defStrOrig);
704  }
705  else /* boolean arg case */
706  {
707  if (!(pka->paramFlags[0] & PARAM_ASSIGNED))
708  {
709  if (flags.route_mode == MACSIO_CLARGS_TOMEM)
710  {
711  int *pInt = (int *) (pka->paramPtrs[0]);
712  *pInt = 0;
713  }
714  else if (flags.route_mode == MACSIO_CLARGS_TOJSON)
716  }
717  }
718  }
719  pka = pka->next;
720  }
721  }
722 
723  /* free the known args stuff */
724  while (knownArgs)
725  {
726  MACSIO_KnownArgInfo_t *next = knownArgs->next;
727  if (knownArgs->paramTypes)
728  free(knownArgs->paramTypes);
729  if (knownArgs->paramPtrs)
730  free(knownArgs->paramPtrs);
731  if (knownArgs->paramFlags);
732  free(knownArgs->paramFlags);
733  if (knownArgs->argName)
734  free(knownArgs->argName);
735  free(knownArgs);
736  knownArgs = next;
737  }
738 
739  if (flags.route_mode == MACSIO_CLARGS_TOJSON)
740  *retobj = ret_json_obj;
741 
742  errno = 0;
743  return MACSIO_CLARGS_OK;
744 }
#define MACSIO_LOG_MSGL(LOG, SEV, MSG)
Convenience macro for logging a message to any specific log.
Definition: macsio_log.h:163
static double GetSizeFromModifierChar(char c)
Definition: macsio_clargs.c:62
struct json_object * json_object_new_string(const char *s)
Definition: json_object.c:727
MACSIO_LOG_LogHandle_t * MACSIO_LOG_StdErr
Log handle for MACSIO's stderr output.
Definition: macsio_log.c:46
#define MACSIO_CLARGS_WARN
Definition: macsio_clargs.h:35
char * paramTypes
Definition: macsio_clargs.c:55
struct json_object * json_object_new_object(void)
Definition: json_object.c:369
int json_object_is_type(struct json_object *obj, enum json_type type)
Definition: json_object.c:204
#define MACSIO_CLARGS_ASSIGN_ON
Definition: macsio_clargs.h:44
json_bool json_object_object_get_ex(struct json_object *obj, const char *key, struct json_object **value)
Definition: json_object.c:422
int MACSIO_CLARGS_ProcessCmdline(void **retobj, MACSIO_CLARGS_ArgvFlags_t flags, int argi, int argc, char **argv,...)
struct _knownArgInfo * next
Definition: macsio_clargs.c:59
#define MACSIO_CLARGS_OK
Definition: macsio_clargs.h:47
#define MACSIO_CLARGS_GRP_BEG
Definition: macsio_clargs.h:49
#define MACSIO_CLARGS_ERROR
Definition: macsio_clargs.h:36
int json_bool
Definition: json_object.h:80
struct _knownArgInfo MACSIO_KnownArgInfo_t
struct json_object * json_object_new_int(int32_t i)
Definition: json_object.c:495
int json_object_array_add(struct json_object *obj, struct json_object *val)
Definition: json_object.c:859
struct json_object * json_object_new_array(void)
Definition: json_object.c:828
struct json_object * json_object_new_boolean(json_bool b)
Definition: json_object.c:458
#define MACSIO_CLARGS_END_OF_ARGS
Definition: macsio_clargs.h:53
static void add_param_to_json_retobj(json_object *retobj, char const *key, json_object *addobj)
Definition: macsio_clargs.c:96
struct json_object * json_object_new_double(double d)
Definition: json_object.c:622
#define PARAM_ASSIGNED
Definition: macsio_clargs.c:46
#define MACSIO_CLARGS_HELP
Definition: macsio_clargs.h:46
#define MACSIO_CLARGS_TOMEM
Definition: macsio_clargs.h:39
char MACSIO_UTILS_UnitsPrefixSystem[32]
Definition: macsio_utils.c:34
struct json_object * json_object_get(struct json_object *obj)
Definition: json_object.c:147
#define MACSIO_CLARGS_TOJSON
Definition: macsio_clargs.h:40
void ** paramPtrs
Definition: macsio_clargs.c:56
char * paramFlags
Definition: macsio_clargs.c:57
#define MACSIO_CLARGS_GRP_END
Definition: macsio_clargs.h:50
#define MACSIO_LOG_MSGLV(LOG, VSEV, MSG)
Convenience macro for logging a message with variable severity to any specific log.
Definition: macsio_log.h:172
void json_object_object_add(struct json_object *obj, const char *key, struct json_object *val)
Definition: json_object.c:391