NASA Logo
Ocean Color Science Software

ocssw V2022
argpar.c
Go to the documentation of this file.
1 // implemented version numbers
2 #define ARGPAR_IMPLEMENTATION 2001001
3 #define ARGPAR_IMPLEMENTATION_STR "2.1.1"
4 #define ARGPAR_API_VERSION 2001000
5 #define ARGPAR_API_VERSION_STR "2.1.0"
6 #include "argpar.h"
7 
8 #include "shash.h"
9 
10 #include <ctype.h>
11 #include <errno.h>
12 #include <libgen.h>
13 #include <limits.h>
14 #include <stdbool.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
21 const char *argpar_program_name;
22 
25 
28 
29 struct parser;
30 typedef struct parser parser;
31 struct parser_chain;
32 typedef struct parser_chain parser_chain;
33 
34 struct parser {
37  unsigned args_parsed;
39  unsigned parent_index;
40  void *input, **child_inputs;
41  void *hook;
42 };
43 
44 struct parser_chain {
48  void **child_inputs;
51  void *storage;
52 };
53 
54 typedef struct parser_counts {
57 
58 
59 static argpar_option argpar_help_options[] = {
60  {"help", '?', 0, 0, "Give this help list", -1},
61  {0}
62 };
63 static int argpar_help_parser(int key, char *argv, argpar_state *state) {
64  switch (key){
65  case '?': {
66  if (!strcmp(argv, "json")){
68  } else if (!strcmp(argv, "params")){
69  if (!(state->flags & ARGPAR_STORE_PARAMS)){
70  fprintf(argpar_ostream ? argpar_ostream : stderr, "help=params is not enabled for this program.\n");
71  return ARGPAR_ERR_UNKNOWN;
72  }
73  return 0;
74  } else {
76  }
77  if (!(state->flags & ARGPAR_NO_EXIT)){
78  exit(0);
79  } else {
80  return ARGPAR_ERR_ABORT;
81  }
82  break;
83  }}
84  return 0;
85 }
86 static argpar argpar_help_argpar = {argpar_help_options, &argpar_help_parser};
87 
88 
89 
90 static argpar_option argpar_version_options[] = {
91  {"version", 'v', 0, 0, "Print program version", -1},
92  {0}
93 };
94 static int argpar_version_parser(int key, char *argv, argpar_state *state) {
95  switch (key){
96  case 'v': {
98  (*argpar_program_version_hook)(argpar_ostream, state);
99  } else if (argpar_program_version != NULL){
101  }
102  if (!(state->flags & ARGPAR_NO_EXIT)){
103  exit(0);
104  } else {
105  return ARGPAR_ERR_ABORT;
106  }
107  break;
108  }}
109  return 0;
110 }
111 static argpar argpar_version_argpar = {argpar_version_options, &argpar_version_parser};
112 
113 int compare_strings(const void* a, const void* b) {
114  return strcmp (*(const char **) a, *(const char **) b);
115 }
116 static shash *all_known_params, *all_known_params_location;
117 static argpar_option argpar_params_options[] = {
118  {"help", '?', 0, 0, "Print all params given to program", -1},
119  {0}
120 };
121 static int argpar_params_parser(int key, char *argv, argpar_state *state) {
122  switch (key){
123  case ARGPAR_KEY_INIT: {
124  all_known_params = shash_create(0);
125  all_known_params_location = shash_create(0);
126  break;
127  }
128  case ARGPAR_KEY_FINI: {
129  shash_rewind(all_known_params);
130  const char *value = NULL, *location_value = NULL;
131  FILE *output_stream = argpar_ostream ? argpar_ostream : stderr;
132 
133 #if SORT_PARAM_KEYS
134  const char *key = NULL;
135  while (!shash_next(all_known_params, &key, &value)){
136  location_value = shash_get(all_known_params_location, key);
137  fprintf(output_stream, "%s = %s (%s)\n", key, value, location_value);
138  }
139 #else
140  const char *all_keys[shash_size(all_known_params)];
141  size_t key_i = 0;
142  while (!shash_next(all_known_params, &all_keys[key_i++], NULL));
143  --key_i;
144  qsort(all_keys, key_i, sizeof(const char*), compare_strings);
145  for (size_t i=0;i<key_i;i++){
146  value = shash_get(all_known_params, all_keys[i]);
147  location_value = shash_get(all_known_params_location, all_keys[i]);
148  fprintf(output_stream, "%s = %s (%s)\n", all_keys[i], value, location_value);
149  }
150 #endif
151 
152  shash_destroy(all_known_params);
153  shash_destroy(all_known_params_location);
154  if (!(state->flags & ARGPAR_NO_EXIT)){
155  exit(0);
156  } else {
157  return ARGPAR_ERR_ABORT;
158  }
159  break;
160  }
161  case ARGPAR_KEY_UNKNOWN:
162  shash_set(all_known_params, state->arg_name, argv);
163  if (state->parfile == NULL){
164  shash_set(all_known_params_location, state->arg_name, "<command line>");
165  } else {
166  shash_set(all_known_params_location, state->arg_name, state->parfile);
167  }
168  break;
169  }
170  return 0;
171 }
172 static argpar argpar_params_argpar = {argpar_params_options, &argpar_params_parser};
173 
174 
175 
176 static long strtol_strict(const char *s) {
177  char *endptr;
178  errno = 0;
179  long ret = strtol(s, &endptr, 0);
180  if (!errno && *endptr != '\0') {
181  errno = EINVAL;
182  }
183  return ret;
184 }
185 
186 static double strtod_strict(const char *s) {
187  char *endptr;
188  errno = 0;
189  double ret = strtod(s, &endptr);
190  if (!errno && *endptr != '\0') {
191  errno = EINVAL;
192  }
193  return ret;
194 }
195 static void count_argpars(argpar *argpar, parser_counts *counts) {
196  if (argpar->options || argpar->parser) {
197  counts->parsers++;
198  }
200  if (children) {
201  while (children->argpar) {
202  count_argpars((children++)->argpar, counts);
203  counts->child_inputs++;
204  }
205  }
206 }
207 
208 static void add_parser(parser_chain *parser_chain, argpar *argpar, parser *parent, unsigned parent_index) {
210  p->parser = argpar->parser;
211  p->argpar = argpar;
212  p->args_parsed = 0;
213  p->parent = parent;
214  p->parent_index = parent_index;
215  p->input = NULL;
216  p->hook = NULL;
217 
219  if (children) {
220  p->child_inputs = parser_chain->last_child_input;
221  unsigned child_count = 0;
222  while (children[child_count].argpar) {
223  child_count++;
224  }
225  parser_chain->last_child_input += child_count;
226 
228  unsigned child_index = 0;
229  while (children->argpar) {
230  add_parser(parser_chain, (children++)->argpar, p, child_index++);
231  }
232  }
233 }
234 static int call_parser(parser *p, argpar_state *state, int key, char *arg) {
235  if (p->parser) {
236  int err;
237  state->hook = p->hook;
238  state->input = p->input;
239  state->child_inputs = p->child_inputs;
240  state->arg_num = p->args_parsed;
241  err = (*p->parser)(key, arg, state);
242  p->hook = state->hook;
243  return err;
244  } else {
245  return ARGPAR_ERR_UNKNOWN;
246  }
247 }
248 
249 static int parser_chain_init(parser_chain *parser_chain, argpar *argpar, unsigned argc, char **argv, unsigned flags, void *input) {
250  parser_counts counts = { 0, 0 };
251 
252  if (argpar) {
253  count_argpars(argpar, &counts);
254  }
255 
257  counts.parsers++;
258  }
259  if (!(flags & ARGPAR_NO_HELP)){
260  counts.parsers++;
261  }
262 
263  size_t parser_size = (counts.parsers + 1) * sizeof(parser);
264  size_t input_size = counts.child_inputs * sizeof(void*);
265  parser_chain->storage = malloc(parser_size + input_size);
266  if (!parser_chain->storage) {
267  return ENOMEM;
268  }
272  parser_chain->child_inputs = parser_chain->storage + parser_size;
274 
275  memset(parser_chain->child_inputs, 0, input_size);
276  memset(&parser_chain->state, 0, sizeof(argpar_state));
277 
280  parser_chain->state.argv = argv;
282 // parser_chain->state.err_stream = stderr;
283 // parser_chain->state.out_stream = stdout;
284  parser_chain->state.next = 0;
285 // parser_chain->state.pstate = parser;
286 
287  add_parser(parser_chain, argpar, NULL, 0);
288 
290  add_parser(parser_chain, &argpar_version_argpar, NULL, 0);
291  }
292  if (!(flags & ARGPAR_NO_HELP)){
293  add_parser(parser_chain, &argpar_help_argpar, NULL, 0);
294 
295  if (flags & ARGPAR_STORE_PARAMS){
296  add_parser(parser_chain, &argpar_params_argpar, NULL, 0);
297  }
298  }
299 
302  }
303  int err = 0;
304  parser *p;
305  for (p = parser_chain->parsers; p < parser_chain->last_parser && (!err || err == ARGPAR_ERR_UNKNOWN); p++) {
306  if (p->parent != NULL) {
307  p->input = p->parent->child_inputs[p->parent_index];
308  }
309  if (!p->parser && p->argpar->children && p->argpar->children->argpar) {
310  // without a parser, every child gets the parent's input
311 // p->child_inputs[0] = p->input;
312  const argpar_child *children = p->argpar->children;
313  unsigned child_index = 0;
314  while (children++->argpar) {
315  p->child_inputs[child_index++] = p->input;
316  }
317  }
318  err = call_parser(p, &parser_chain->state, ARGPAR_KEY_INIT, 0);
319  }
320  if (err == ARGPAR_ERR_UNKNOWN) {
321  err = 0;
322  }
323 
324  if (err) {
325  return err;
326  }
327 
328  return 0;
329 }
330 static int parser_chain_finalize(parser_chain *p_chain, int err, unsigned *end_index) {
331  struct parser *parser;
332 
333  if (!err) {
334  if (p_chain->state.next == p_chain->state.argc) {
335  for (parser = p_chain->parsers; parser < p_chain->last_parser && (!err || err == ARGPAR_ERR_UNKNOWN); parser++) {
336  if (parser->args_parsed == 0) {
337  err = call_parser(parser, &p_chain->state, ARGPAR_KEY_NO_ARGS, 0);
338  }
339  }
340  for (parser = p_chain->last_parser - 1; parser >= p_chain->parsers && (!err || err == ARGPAR_ERR_UNKNOWN); parser--) {
341  err = call_parser(parser, &p_chain->state, ARGPAR_KEY_END, 0);
342  }
343 
344  if (err == ARGPAR_ERR_UNKNOWN) {
345  err = 0;
346  }
347  if (end_index) {
348  *end_index = p_chain->state.next;
349  }
350  } else if (end_index) {
351  *end_index = p_chain->state.next;
352  } else {
353 // if (!(p_chain->state.flags & ARGP_NO_ERRS) && p_chain->state.err_stream){
354 // fprintf(p_chain->state.err_stream, dgettext(p_chain->argp->argp_domain, "%s: Too many arguments\n"), p_chain->state.name);
355 // }
356  fprintf(stderr, "%s: Too many arguments\n", p_chain->state.name);
358  }
359  }
360 
361  if (err) {
362  if (err == ARGPAR_ERR_USAGE) {
363 // __argp_state_help(&p_chain->state, p_chain->state.err_stream, ARGP_HELP_STD_ERR);
364  argpar_usage(&p_chain->state);
365  }
366 
367  for (parser = p_chain->parsers; parser < p_chain->last_parser; parser++) {
368  call_parser(parser, &p_chain->state, ARGPAR_KEY_ERROR, 0);
369  }
370  } else {
371  for (parser = p_chain->last_parser - 1; parser >= p_chain->parsers && (!err || err == ARGPAR_ERR_UNKNOWN); parser--) {
372  err = call_parser(parser, &p_chain->state, ARGPAR_KEY_SUCCESS, 0);
373  }
374  if (err == ARGPAR_ERR_UNKNOWN) {
375  err = 0;
376  }
377  }
378 
379  for (parser = p_chain->last_parser - 1; parser >= p_chain->parsers; parser--) {
380  call_parser(parser, &p_chain->state, ARGPAR_KEY_FINI, 0);
381  }
382 
383  free(p_chain->storage);
384 
385  return err;
386 }
387 
388 static void initialize_unknown_state(argpar_state *state, char *key, char *value){
389  state->arg_name = key;
390  state->arg_alias = NULL;
391  state->arg_value = value;
392 
393  state->argv_as_int = 0;
394  state->argv_as_int_err = 1;
395  state->argv_as_dbl = 0;
396  state->argv_as_dbl_err = 1;
397 }
398 
399 static int parse_option(parser_chain *parser_chain, char *key, char *value) {
400  parser *parser;
401 
402  int return_value = 0;
403 
405  for (parser = parser_chain->parsers; parser < parser_chain->last_parser; parser++) {
406  if (parser->argpar == &argpar_params_argpar){
408  initialize_unknown_state(&s, key, value);
409  call_parser(parser, &s, ARGPAR_KEY_UNKNOWN, value);
410  break;
411  }
412  }
413  }
414 
415  for (parser = parser_chain->parsers; parser < parser_chain->last_parser; parser++) {
416  const argpar_option *o = parser->argpar->options;
417  bool is_parent = (parser->argpar == parser_chain->root_argpar);
418 
419  size_t i = 0;
420 
421  const argpar_option *base_option = NULL;
422 
423  while (o[i].name || o[i].doc) {
424  if (o[i].name && !((o[i].flags & OPTION_PARENT) && !is_parent) && !((o[i].flags & OPTION_CHILD) && is_parent) && !strcmp(o[i].name, key)) {
426 
427  if (!(o[i].flags & OPTION_ALIAS)){
428  base_option = &o[i];
429  }
430 
431  s.arg_name = base_option->name;
432  s.arg_alias = key;
433  s.arg_value = value;
434 
435  if (base_option->flags & OPTION_INT) {
436  s.argv_as_int = strtol_strict(value);
437  s.argv_as_int_err = errno;
438  } else {
439  s.argv_as_int = 0;
440  s.argv_as_int_err = 1;
441  }
442  if (base_option->flags & OPTION_DBL) {
443  s.argv_as_dbl = strtod_strict(value);
444  s.argv_as_dbl_err = errno;
445  } else {
446  s.argv_as_dbl = 0;
447  s.argv_as_dbl_err = 1;
448  }
449  return_value = call_parser(parser, &s, base_option->key, value);
450  if (return_value || !(parser_chain->state.flags & ARGPAR_ACCEPT_ANY)){
451  return return_value;
452  }
453  }
454  if (!(o[i].flags & (OPTION_DOC | OPTION_ALIAS))){
455  base_option = &o[i];
456  }
457  ++i;
458  }
461  initialize_unknown_state(&s, key, value);
462  int ret = call_parser(parser, &s, ARGPAR_KEY_UNKNOWN, value);
463  if (ret){
464  return ret;
465  }
466  }
467  }
469  return return_value;
470  }
471  return ARGPAR_ERR_UNKNOWN;
472 }
473 
474 static int parse_arg(parser_chain *parser_chain, char *arg) {
475  parser *parser;
476  int err = ARGPAR_ERR_UNKNOWN;
477 
479  if (s.flags & ARGPAR_CAST_ARGS) {
480  s.argv_as_int = strtol_strict(arg);
481  s.argv_as_int_err = errno;
482  s.argv_as_dbl = strtod_strict(arg);
483  s.argv_as_dbl_err = errno;
484  } else {
485  s.argv_as_int = 0;
486  s.argv_as_int_err = 1;
487  s.argv_as_dbl = 0;
488  s.argv_as_dbl_err = 1;
489  }
490 
492  err = call_parser(parser, &s, ARGPAR_KEY_ARG, arg);
493  }
494  s.next++;
495  return err;
496 }
497 
498 static int parse_file(parser_chain *p_chain, const char *path, const char *cwd) {
499  argpar *p = NULL;
500 
501  parser *parser;
502  for (parser = p_chain->parsers; parser < p_chain->last_parser && !p; parser++) {
503  p = parser->argpar;
504  }
505  if (!p) {
506  return ARGPAR_ERR_PARFILE;
507  }
508  if (p->parfile_buffer_count >= MAX_PARFILES) {
509  return ARGPAR_LIMIT_REACHED;
510  }
511 
512  FILE *file_h = NULL;
513  char *this_path, *this_cwd;
514  this_path = this_cwd = NULL;
515 
516  const char *parfile_was = p_chain->state.parfile;
517 
518  if (cwd != NULL && *path != '/') {
519  this_path = malloc((strlen(cwd) + strlen(path) + 2) * sizeof(char));
520  if (this_path == NULL) {
521  return ENOMEM;
522  }
523  strcpy(this_path, cwd);
524  strcat(this_path, "/");
525  strcat(this_path, path);
526  p_chain->state.parfile = this_path;
527  file_h = fopen(this_path, "rb");
528  } else {
529  p_chain->state.parfile = path;
530  file_h = fopen(path, "rb");
531  }
532  if (file_h == NULL) {
533  if (this_path != NULL) {
534  free(this_path);
535  }
536  return ARGPAR_ERR_PARFILE;
537  }
538 
539  fseek(file_h, 0, SEEK_END);
540  long file_size = ftell(file_h);
541  fseek(file_h, 0, SEEK_SET);
542  unsigned long this_buffer_index = p->parfile_buffer_count++;
543  if (p->parfile_buffer == NULL) {
544  p->parfile_buffer = calloc(MAX_PARFILES, sizeof(char*));
545  if (p->parfile_buffer == NULL) {
546  if (this_path != NULL) {
547  free(this_path);
548  }
549  return ENOMEM;
550  }
551  }
552  size_t ufile_size = (size_t) file_size;
553  p->parfile_buffer[this_buffer_index] = malloc((ufile_size + 1) * sizeof(char));
554  if (p->parfile_buffer[this_buffer_index] == NULL) {
555  if (this_path != NULL) {
556  free(this_path);
557  }
558  return ENOMEM;
559  }
560  size_t fread_count = fread(p->parfile_buffer[this_buffer_index], sizeof(char), ufile_size + 1, file_h);
561  if (fread_count != ufile_size || !feof(file_h)) {
562  if (this_path != NULL) {
563  free(this_path);
564  }
565  fclose(file_h);
566  return ARGPAR_ERR_PARFILE;
567  }
568  fclose(file_h);
569 
570  char *buffer = p->parfile_buffer[this_buffer_index];
571  char *buffer_end = &p->parfile_buffer[this_buffer_index][file_size];
572  *buffer_end = '\0';
573  char *v, *k;
574  int err = 0;
575  do {
576  char *k_end = NULL;
577  if (p_chain->state.flags & ARGPAR_NO_KEYARGS) {
578  k = NULL;
579  v = NULL;
580 
581  char *find_buffer = buffer;
582  while (find_buffer != buffer_end) {
583  if (*find_buffer == '=') {
584  k = strsep(&buffer, "=");
585  v = strsep(&buffer, "\n");
586  } else if (*find_buffer == '\n') {
587  k = strsep(&buffer, "\n");
588  k_end = k + strlen(k);
589  v = "1";
590  } else {
591  find_buffer++;
592  }
593  }
594  if (k == NULL){
595  k = buffer;
596  k_end = buffer_end;
597  v = "1";
598  }
599  } else {
600  k = strsep(&buffer, "=");
601  v = strsep(&buffer, "\n");
602  }
603  if (k == NULL || v == NULL) {
604  break;
605  }
606  while (isspace(*k) || *k == '"' || *k == '\''){
607  k++;
608  }
609  if (k_end == NULL){
610  k_end = v - 2;
611  }
612  while (isspace(*k_end) || *k_end == '"' || *k_end == '\'') {
613  *k_end = '\0';
614  k_end--;
615  }
616 
617  while (isspace(*v) || *v == '"' || *v == '\''){
618  v++;
619  }
620  char *v_end = v + strlen(v) - 1;
621  while (isspace(*v_end) || *v_end == '"' || *v_end == '\'') {
622  *v_end = '\0';
623  v_end--;
624  }
625  if (*k == '#') {
626  continue;
627  } else if (strlen(k)) {
628  if (strcmp(k, PARFILE_STR)) {
629  err = parse_option(p_chain, k, v);
630  if (err == ARGPAR_ERR_UNKNOWN) {
631  fprintf(argpar_ostream ? argpar_ostream : stderr, "Unknown option: %s\n\n", k);
632  }
633  } else {
634  if (this_cwd == NULL) {
635  if (this_path == NULL) {
636  this_path = strdup(path);
637  if (this_path == NULL) {
638  return ENOMEM;
639  }
640  }
641  this_cwd = dirname(this_path);
642  }
643  err = parse_file(p_chain, v, this_cwd);
644  }
645  }
646  } while (buffer != buffer_end && !err);
647 
648  p_chain->state.parfile = parfile_was;
649 
650  if (this_path) {
651  free(this_path);
652  }
653  return err;
654 }
655 
657  if (p && p != &argpar_help_argpar && p != &argpar_version_argpar) {
658  if (p->parfile_buffer){
659  unsigned i;
660  for (i = 0; i < p->parfile_buffer_count; i++) {
661  free(p->parfile_buffer[i]);
662  }
663  free(p->parfile_buffer);
664  p->parfile_buffer = NULL;
665  p->parfile_buffer_count = 0;
666  }
667 
668  // in case parsers manually loaded parfiles
669  const argpar_child *children = p->children;
670  if (children) {
671  while (children->argpar) {
673  }
674  }
675  }
676 
677  return 0;
678 }
679 
680 // stolen directly from argp
681 static char *nondestructive_basename(char *name) {
682  char *short_name = strrchr(name, '/');
683  return short_name ? short_name + 1 : name;
684 }
685 
686 int argpar_parse_args(argpar *p, unsigned argc, char *argv[], unsigned flags, unsigned *end_index, void *input) {
687  if (!(flags & ARGPAR_NO_HELP) && (argc < 1 || argv == NULL)) {
688  argpar_help(p, argpar_ostream ? argpar_ostream : stderr, flags, (argv == NULL ? "cmd" : nondestructive_basename(argv[0])));
689  return ARGPAR_ERR_USAGE;
690  } else {
691  parser_chain p_chain;
692  if (p->parfile_buffer == NULL) {
693  p->parfile_buffer_count = 0;
694  }
695  int err = parser_chain_init(&p_chain, p, argc, argv, flags, input);
696  if (!err) {
697  for (p_chain.state.next = 1; p_chain.state.next < argc && !err; p_chain.state.next++) {
698  if (p_chain.state.quoted && p_chain.state.next < p_chain.state.quoted) {
699  p_chain.state.quoted = 0;
700  }
701  if (p_chain.state.quoted) {
702  err = parse_arg(&p_chain, argv[p_chain.state.next]);
703  p_chain.state.arg_num++;
704  } else if (strcmp(argv[p_chain.state.next], "--") == 0) {
705  p_chain.state.quoted = p_chain.state.next + 1;
706  } else if (strchr(argv[p_chain.state.next], '=') != NULL) {
707  char *v = (char*) argv[p_chain.state.next];
708  char *k = strsep(&v, "=");
709  while (isspace(*k))
710  k++;
711  if (strcmp(k, PARFILE_STR)) {
712  err = parse_option(&p_chain, k, v);
713  if (err == ARGPAR_ERR_UNKNOWN) {
714  fprintf(argpar_ostream ? argpar_ostream : stderr, "Unknown option: %s\n\n", k);
715  }
716  } else if (!(flags & ARGPAR_SKIP_PARFILES)) {
717  err = parse_file(&p_chain, v, NULL);
718  }
719  } else if (flags & ARGPAR_NO_KEYARGS) {
720  char *k = (char*) argv[p_chain.state.next];
721  char *v = "1";
722  err = parse_option(&p_chain, k, v);
723  if (err == ARGPAR_ERR_UNKNOWN) {
724  fprintf(argpar_ostream ? argpar_ostream : stderr, "Unknown option: %s\n\n", k);
725  }
726  } else {
727  err = parse_arg(&p_chain, argv[p_chain.state.next]);
728  p_chain.state.arg_num++;
729  }
730  }
731  err = parser_chain_finalize(&p_chain, err, end_index);
732  }
733  return err;
734  }
735 }
736 
737 int argpar_parse_file(argpar *p, const char *path, unsigned flags, void *input) {
738  parser_chain p_chain;
739  int err = parser_chain_init(&p_chain, p, 0, NULL, flags, input);
740  if (!err) {
741  err = parse_file(&p_chain, path, NULL);
742  err = parser_chain_finalize(&p_chain, err, NULL);
743  }
744  return err;
745 }
746 
747 const char *argpar_version() {
748  return "argpar " ARGPAR_IMPLEMENTATION_STR ", API " ARGPAR_API_VERSION_STR;
749 }
750 
751 char **argpar_split_str(char *str, const char *delim) {
752  size_t ret_size_max = 8;
753  size_t ret_size = 0;
754  char **ret = malloc(sizeof(char*) * ret_size_max);
755  char **iter = ret;
756  while ((*iter = strsep(&str, delim)) != NULL) {
757  ret_size++;
758  iter++;
759  if (ret_size == ret_size_max) {
760  ret_size_max *= 2;
761  char **new_ret = realloc(ret, sizeof(char*) * ret_size_max);
762  if (new_ret == NULL) {
763  fprintf(argpar_ostream ? argpar_ostream : stderr, "Failed to reallocate array of size %lu\n", ret_size_max);
764  free(ret);
765  return NULL;
766  } else {
767  ret = new_ret;
768  iter = &ret[ret_size];
769  }
770  }
771  }
772  ret[ret_size] = NULL;
773  return ret;
774 }
775 
776 char **argpar_split_trim(char *str, const char *delim) {
777  char **ret = argpar_split_str(str, delim);
778  size_t i = 0;
779  for (; ret[i] != NULL; i++) {
780  while (isspace(*ret[i])) {
781  ret[i]++;
782  }
783  char *end = ret[i] + strlen(ret[i]) - 1;
784  while (end > ret[i] && isspace(*end)) {
785  end--;
786  }
787  *(end + 1) = '\0';
788  }
789  return ret;
790 }
791 
792 int *argpar_split_int(char *str, const char *delim) {
793  char **list = argpar_split_trim(str, delim);
794  size_t s = 0;
795  while (list[s] != NULL) {
796  s++;
797  }
798  int *ret = malloc(sizeof(int) * (s + 1));
799  ret[s] = NULL_INT;
800  for (size_t i = 0; i < s; i++) {
801  if (list[i][0]) {
802  ret[i] = strtol_strict(list[i]);
803  if (errno) {
804  free(ret);
805  free(list);
806  return NULL;
807  }
808  } else {
809  ret[i] = EMPTY_INT;
810  }
811  }
812  free(list);
813  return ret;
814 }
815 
816 double *argpar_split_dbl(char *str, const char *delim) {
817  char **list = argpar_split_trim(str, delim);
818  size_t s = 0;
819  while (list[s] != NULL) {
820  s++;
821  }
822  double *ret = malloc(sizeof(double) * (s + 1));
823  ret[s] = NAN;
824  for (size_t i = 0; i < s; i++) {
825  if (list[i][0]) {
826  ret[i] = strtod_strict(list[i]);
827  if (errno) {
828  free(ret);
829  free(list);
830  return NULL;
831  }
832  } else {
833  ret[i] = INFINITY;
834  }
835  }
836  free(list);
837  return ret;
838 }
839 
#define PARFILE_STR
Used to override the par file trigger.
Definition: argpar.h:54
size_t parsers
Definition: argpar.c:55
int32 value
Definition: Granule.c:1235
Master structure containing options, document strings, child parsers, and text filters....
Definition: argpar.h:391
#define EMPTY_INT
Definition: argpar.h:543
int(* argpar_parser)(int key, char *argv, argpar_state *state)
Pointer to a callback function to call for each argument and option parsed.
Definition: argpar.h:353
void * hook
Definition: argpar.c:41
Definition: argpar.c:34
#define ARGPAR_KEY_END
Passed as the key to the parser callback function when there are no more arguments left to parse.
Definition: argpar.h:275
const argpar_option * options
Array of option structures, terminated by an empty entry (IE: {0}).
Definition: argpar.h:393
unsigned int flags
Flags passed to parser functions to modify the behavior.
Definition: argpar.h:202
void * input
Definition: argpar.c:40
unsigned next
The index in ARGV of the next arg that to be parsed. May be modified.
Definition: argpar.h:199
char ** argpar_split_trim(char *str, const char *delim)
Splits a string on a delimiter, returning a NULL-terminated list of strings, trimming left and right ...
Definition: argpar.c:776
parser * parsers
Definition: argpar.c:46
parser * last_parser
Definition: argpar.c:47
#define NULL
Definition: decode_rs.h:63
#define OPTION_INT
Cast this option as a long. The value and any error will be reflected in the argpar_state struct duri...
Definition: argpar.h:160
argpar_parser parser
Parser function handed all options and arguments, as well as various ARGPAR_KEY_ keys for events such...
Definition: argpar.h:396
argpar_child children[]
Definition: argpar.c:424
int * argpar_split_int(char *str, const char *delim)
Splits a string on a delimiter, returning a NULL_INT-terminated list of ints.
Definition: argpar.c:792
#define ARGPAR_ERR_USAGE
Returned from the parser callback to signal argpar to stop parsing, print a usage summary,...
Definition: argpar.h:331
void * storage
Definition: argpar.c:51
char * name
The name used when printing messages. This is initialized to ARGV[0], or PROGRAM_INVOCATION_NAME if t...
Definition: argpar.h:226
void ** child_inputs
Definition: argpar.c:48
char ** argv
Pointer to arguments passed to argpar_parse_args.
Definition: argpar.h:196
#define ARGPAR_KEY_ARG
This is not an option at all, but rather a command line argument. If a parser receiving this key retu...
Definition: argpar.h:264
void * last_child_input
Definition: argpar.c:49
#define ARGPAR_KEY_SUCCESS
Passed as the key to each parser callback function when parsing has finished and no errors were retur...
Definition: argpar.h:288
uint8 * counts
Definition: l1_czcs_hdf.c:30
argpar_state state
Definition: argpar.c:50
shash * shash_create(uint32_t options)
Initialize a shash object.
Definition: shash.c:105
int shash_set(shash *h, const char *key, const char *value)
Add or overwrite a pointer, associating it with the given key.
Definition: shash.c:224
Implementation-specific, generic type to store the shash object.
Definition: shash.c:40
Child parser for nesting argpars.
Definition: argpar.h:370
#define ARGPAR_KEY_INIT
Passed as the key to each parser callback function before any parsing occurs. For most cases,...
Definition: argpar.h:280
const char * argpar_version()
Returns the source code version and the implemented API version.
Definition: argpar.c:747
#define ARGPAR_CAST_ARGS
Passed to the argpar_parse_ functions, this tells the parser to cast all key arguments to long and do...
Definition: argpar.h:116
void ** child_inputs
Definition: argpar.c:40
instr * input
argpar_parser parser
Definition: argpar.c:35
int argpar_parse_file(argpar *p, const char *path, unsigned flags, void *input)
Parse a key=value store file.
Definition: argpar.c:737
#define ARGPAR_KEY_ERROR
Passed as the key to each parser callback function when parsing has finished and an error was returne...
Definition: argpar.h:292
#define ARGPAR_NO_KEYARGS
Passed to the argpar_parse_ functions, this tells the parser to accept options without equal signs,...
Definition: argpar.h:125
const char * argpar_program_name
How to display the program name. If not given, it will be derived during a call to argpar_parse_args.
Definition: argpar.c:21
#define ARGPAR_ERR_UNKNOWN
What to return for unrecognized keys within an argpar_parser function.
Definition: argpar.h:334
int argpar_help(argpar *argpar, FILE *stream, unsigned flags, char *name)
Print the default usage summary with all available sections.
Definition: argpar-help.c:512
int state(double tjdTDB, JPLIntUtilType *util, double posvel[13][6], double *pnut)
#define ARGPAR_NO_EXIT
Passed to the argpar_parse_ functions, this tells argpar not to call exit after printing help/usage,...
Definition: argpar.h:132
#define MAX_PARFILES
Maximum amount of parfiles to be able to load into one object.
Definition: argpar.h:49
parser * parent
Definition: argpar.c:38
int flags
Modify the behavior of the argument by OR'ing one or more OPTION_ macros.
Definition: argpar.h:100
list(APPEND LIBS ${NETCDF_LIBRARIES}) find_package(GSL REQUIRED) include_directories($
Definition: CMakeLists.txt:8
const char * shash_get(shash *h, const char *key)
Find a pointer associated with the given string.
Definition: shash.c:205
string path
Definition: color_dtdb.py:221
int argpar_clean(argpar *p)
Free any space consumed by argpar for parfiles.
Definition: argpar.c:656
char * strdup(const char *)
#define ARGPAR_KEY_NO_ARGS
Passed as the key to each parser callback function when parsing has finished and no key arguments wer...
Definition: argpar.h:296
FILE * argpar_ostream
Where to print errors and usage summaries to, defaults to STDERR.
Definition: argpar.c:24
size_t child_inputs
Definition: argpar.c:55
#define ARGPAR_ERR_ABORT
Returned from the parser callback to signal argpar to stop parsing and return to the caller.
Definition: argpar.h:327
#define ARGPAR_KEY_FINI
Passed as the key to each parser callback function at the very end of the process....
Definition: argpar.h:284
int shash_next(shash *h, const char **key, const char **value)
Retrieves the next key-value pair in the shash. The order in which the pointers are returned shall be...
Definition: shash.c:283
#define ARGPAR_SKIP_PARFILES
Passed to argpar_parse_args, this tells the parser to ignore parfile= arguments, useful for overwriti...
Definition: argpar.h:120
int argpar_usage(argpar_state *state)
Print usage summary, called within a argpar_parser.
Definition: argpar-help.c:506
int shash_size(shash *h)
Retrieves the number of key-value pairs in the hash object.
Definition: shash.c:320
int errno
unsigned parent_index
Definition: argpar.c:39
int shash_rewind(shash *h)
Rewind iterator for traversing all the keys and values.
Definition: shash.c:277
void(* argpar_program_version_hook)(FILE *stream, argpar_state *state)
Called to print the version string. If set, a version=1 option is automatically added.
Definition: argpar.c:27
#define isspace(c)
unsigned argc
Total number of arguments being parsed by a call of argpar_parse_args.
Definition: argpar.h:194
int argpar_parse_args(argpar *p, unsigned argc, char *argv[], unsigned flags, unsigned *end_index, void *input)
Parse an array of key=value pairs and/or key arguments.
Definition: argpar.c:686
data_t b[NROOTS+1]
Definition: decode_rs.h:77
int compare_strings(const void *a, const void *b)
Definition: argpar.c:113
#define ARGPAR_STORE_PARAMS
Passed to the argpar_parse_ functions, this tells argpar to create a special parser that stores all p...
Definition: argpar.h:141
double * argpar_split_dbl(char *str, const char *delim)
Splits a string on a delimiter, returning a NAN-terminated list of doubles.
Definition: argpar.c:816
#define OPTION_ALIAS
Do not add an extra newline after this documentation string. Useful for lists and manual formatting.
Definition: argpar.h:175
flags
Definition: DDAlgorithm.h:22
unsigned arg_num
The number of key arguments processed so far.
Definition: argpar.h:205
#define OPTION_DOC
This option isn't actually an option, merely text for the usage summary.
Definition: argpar.h:152
int argpar_usage_json(argpar_state *state)
Print usage summary, called within a argpar_parser, in a format more suitable for automated parsing.
Definition: argpar-json.c:414
State variable to be filled before each call to the parser callback.
Definition: argpar.h:189
A simple dictionary library for storing strings.
#define ARGPAR_ERR_PARFILE
Returned from argpar_parse_args and argpar_parse_file when an error has occurred in reading a parfile...
Definition: argpar.h:338
const argpar_child * children
Array of argpar_child structures containing parsers to nest within this one. All options and argument...
Definition: argpar.h:406
Library for reading command-line arguments in the form of key=value.
#define OPTION_CHILD
This option only applies if this parser is not the top-most parser.
Definition: argpar.h:167
unsigned quoted
The index of the first argument after –, if found.
Definition: argpar.h:208
const char * name
The key to search for.
Definition: argpar.h:89
char ** argpar_split_str(char *str, const char *delim)
Splits a string on a delimiter, returning a NULL-terminated list of strings.
Definition: argpar.c:751
#define ARGPAR_API_VERSION_STR
Definition: argpar.c:5
const char * parfile
The name of the parfile being parsed, or NULL if the argument comes from the command line.
Definition: argpar.h:222
data_t s[NROOTS]
Definition: decode_rs.h:75
#define ARGPAR_NO_HELP
Passed to the argpar_parse_ functions, this tells argpar not to add the help option.
Definition: argpar.h:128
unsigned args_parsed
Definition: argpar.c:37
int shash_destroy(shash *h)
Destroy a shash object, free'ing the memory used.
Definition: shash.c:136
#define ARGPAR_ACCEPT_ANY
Passed to the argpar_parse_ functions, this tells argpar to call every parser with every option found...
Definition: argpar.h:136
argpar * root_argpar
Definition: argpar.c:45
struct argpar * argpar
Underlying argpar struct.
Definition: argpar.h:372
#define ARGPAR_IMPLEMENTATION_STR
Definition: argpar.c:3
#define ARGPAR_KEY_UNKNOWN
Passed as the key to each parser callback function when an unknown option has been found....
Definition: argpar.h:300
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
#define ARGPAR_LIMIT_REACHED
Returned from argpar_parse_args and argpar_parse_file when attempting to load more than the maximum a...
Definition: argpar.h:342
#define OPTION_PARENT
This option only applies if this parser is the top-most parser. Useful for return value documentation...
Definition: argpar.h:164
Definition: aerosol.c:136
const char * argpar_program_version
Used as the program version string. If set, a version=1 option is automatically added....
Definition: argpar.c:26
int k
Definition: decode_rs.h:73
Stores the configuration for a par argument.
Definition: argpar.h:87
#define OPTION_DBL
Cast this option as a double. The value and any error will be reflected in the argpar_state struct du...
Definition: argpar.h:156
argpar * argpar
Definition: argpar.c:36
float p[MODELMAX]
Definition: atrem_corl1.h:131
struct argpar * argpar
Pointer to the parent argpar object.
Definition: argpar.h:191
int key
The value to pass to the parser callback. Must be a positive and non-zero.
Definition: argpar.h:91
#define NULL_INT
Definition: argpar.h:539