OB.DAAC Logo
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 
22 struct parser;
23 typedef struct parser parser;
24 struct parser_chain;
25 typedef struct parser_chain parser_chain;
26 
27 struct parser {
30  unsigned args_parsed;
32  unsigned parent_index;
33  void *input, **child_inputs;
34  void *hook;
35 };
36 
37 struct parser_chain {
41  void **child_inputs;
44  void *storage;
45 };
46 
47 typedef struct parser_counts {
50 
51 
52 static argpar_option argpar_help_options[] = {
53  {"help", '?', 0, 0, "Give this help list", -1},
54  {0}
55 };
56 static int argpar_help_parser(int key, char *argv, argpar_state *state) {
57  switch (key){
58  case '?': {
59  if (!strcmp(argv, "json")){
61  } else if (!strcmp(argv, "params")){
62  if (!(state->flags & ARGPAR_STORE_PARAMS)){
63  fprintf(argpar_ostream ? argpar_ostream : stderr, "help=params is not enabled for this program.\n");
64  return ARGPAR_ERR_UNKNOWN;
65  }
66  return 0;
67  } else {
69  }
70  if (!(state->flags & ARGPAR_NO_EXIT)){
71  exit(0);
72  } else {
73  return ARGPAR_ERR_ABORT;
74  }
75  break;
76  }}
77  return 0;
78 }
79 static argpar argpar_help_argpar = {argpar_help_options, &argpar_help_parser};
80 
81 
82 
83 static argpar_option argpar_version_options[] = {
84  {"version", 'v', 0, 0, "Print program version", -1},
85  {0}
86 };
87 static int argpar_version_parser(int key, char *argv, argpar_state *state) {
88  switch (key){
89  case 'v': {
91  (*argpar_program_version_hook)(argpar_ostream, state);
92  } else if (argpar_program_version != NULL){
94  }
95  if (!(state->flags & ARGPAR_NO_EXIT)){
96  exit(0);
97  } else {
98  return ARGPAR_ERR_ABORT;
99  }
100  break;
101  }}
102  return 0;
103 }
104 static argpar argpar_version_argpar = {argpar_version_options, &argpar_version_parser};
105 
106 int compare_strings(const void* a, const void* b) {
107  return strcmp (*(const char **) a, *(const char **) b);
108 }
109 static shash *all_known_params, *all_known_params_location;
110 static argpar_option argpar_params_options[] = {
111  {"help", '?', 0, 0, "Print all params given to program", -1},
112  {0}
113 };
114 static int argpar_params_parser(int key, char *argv, argpar_state *state) {
115  switch (key){
116  case ARGPAR_KEY_INIT: {
117  all_known_params = shash_create(0);
118  all_known_params_location = shash_create(0);
119  break;
120  }
121  case ARGPAR_KEY_FINI: {
122  shash_rewind(all_known_params);
123  const char *value = NULL, *location_value = NULL;
124  FILE *output_stream = argpar_ostream ? argpar_ostream : stderr;
125 
126 #if SORT_PARAM_KEYS
127  const char *key = NULL;
128  while (!shash_next(all_known_params, &key, &value)){
129  location_value = shash_get(all_known_params_location, key);
130  fprintf(output_stream, "%s = %s (%s)\n", key, value, location_value);
131  }
132 #else
133  const char *all_keys[shash_size(all_known_params)];
134  size_t key_i = 0;
135  while (!shash_next(all_known_params, &all_keys[key_i++], NULL));
136  --key_i;
137  qsort(all_keys, key_i, sizeof(const char*), compare_strings);
138  for (size_t i=0;i<key_i;i++){
139  value = shash_get(all_known_params, all_keys[i]);
140  location_value = shash_get(all_known_params_location, all_keys[i]);
141  fprintf(output_stream, "%s = %s (%s)\n", all_keys[i], value, location_value);
142  }
143 #endif
144 
145  shash_destroy(all_known_params);
146  shash_destroy(all_known_params_location);
147  if (!(state->flags & ARGPAR_NO_EXIT)){
148  exit(0);
149  } else {
150  return ARGPAR_ERR_ABORT;
151  }
152  break;
153  }
154  case ARGPAR_KEY_UNKNOWN:
155  shash_set(all_known_params, state->arg_name, argv);
156  if (state->parfile == NULL){
157  shash_set(all_known_params_location, state->arg_name, "<command line>");
158  } else {
159  shash_set(all_known_params_location, state->arg_name, state->parfile);
160  }
161  break;
162  }
163  return 0;
164 }
165 static argpar argpar_params_argpar = {argpar_params_options, &argpar_params_parser};
166 
167 
168 
169 static long strtol_strict(const char *s) {
170  char *endptr;
171  errno = 0;
172  long ret = strtol(s, &endptr, 0);
173  if (!errno && *endptr != '\0') {
174  errno = EINVAL;
175  }
176  return ret;
177 }
178 
179 static double strtod_strict(const char *s) {
180  char *endptr;
181  errno = 0;
182  double ret = strtod(s, &endptr);
183  if (!errno && *endptr != '\0') {
184  errno = EINVAL;
185  }
186  return ret;
187 }
188 static void count_argpars(argpar *argpar, parser_counts *counts) {
189  if (argpar->options || argpar->parser) {
190  counts->parsers++;
191  }
193  if (children) {
194  while (children->argpar) {
195  count_argpars((children++)->argpar, counts);
196  counts->child_inputs++;
197  }
198  }
199 }
200 
201 static void add_parser(parser_chain *parser_chain, argpar *argpar, parser *parent, unsigned parent_index) {
203  p->parser = argpar->parser;
204  p->argpar = argpar;
205  p->args_parsed = 0;
206  p->parent = parent;
207  p->parent_index = parent_index;
208  p->input = NULL;
209  p->hook = NULL;
210 
212  if (children) {
213  p->child_inputs = parser_chain->last_child_input;
214  unsigned child_count = 0;
215  while (children[child_count].argpar) {
216  child_count++;
217  }
218  parser_chain->last_child_input += child_count;
219 
221  unsigned child_index = 0;
222  while (children->argpar) {
223  add_parser(parser_chain, (children++)->argpar, p, child_index++);
224  }
225  }
226 }
227 static int call_parser(parser *p, argpar_state *state, int key, char *arg) {
228  if (p->parser) {
229  int err;
230  state->hook = p->hook;
231  state->input = p->input;
232  state->child_inputs = p->child_inputs;
233  state->arg_num = p->args_parsed;
234  err = (*p->parser)(key, arg, state);
235  p->hook = state->hook;
236  return err;
237  } else {
238  return ARGPAR_ERR_UNKNOWN;
239  }
240 }
241 
242 static int parser_chain_init(parser_chain *parser_chain, argpar *argpar, unsigned argc, char **argv, unsigned flags, void *input) {
243  parser_counts counts = { 0, 0 };
244 
245  if (argpar) {
246  count_argpars(argpar, &counts);
247  }
248 
250  counts.parsers++;
251  }
252  if (!(flags & ARGPAR_NO_HELP)){
253  counts.parsers++;
254  }
255 
256  size_t parser_size = (counts.parsers + 1) * sizeof(parser);
257  size_t input_size = counts.child_inputs * sizeof(void*);
258  parser_chain->storage = malloc(parser_size + input_size);
259  if (!parser_chain->storage) {
260  return ENOMEM;
261  }
265  parser_chain->child_inputs = parser_chain->storage + parser_size;
267 
268  memset(parser_chain->child_inputs, 0, input_size);
269  memset(&parser_chain->state, 0, sizeof(argpar_state));
270 
272  parser_chain->state.argc = argc;
273  parser_chain->state.argv = argv;
275 // parser_chain->state.err_stream = stderr;
276 // parser_chain->state.out_stream = stdout;
277  parser_chain->state.next = 0;
278 // parser_chain->state.pstate = parser;
279 
280  add_parser(parser_chain, argpar, NULL, 0);
281 
283  add_parser(parser_chain, &argpar_version_argpar, NULL, 0);
284  }
285  if (!(flags & ARGPAR_NO_HELP)){
286  add_parser(parser_chain, &argpar_help_argpar, NULL, 0);
287 
288  if (flags & ARGPAR_STORE_PARAMS){
289  add_parser(parser_chain, &argpar_params_argpar, NULL, 0);
290  }
291  }
292 
295  }
296  int err = 0;
297  parser *p;
298  for (p = parser_chain->parsers; p < parser_chain->last_parser && (!err || err == ARGPAR_ERR_UNKNOWN); p++) {
299  if (p->parent != NULL) {
300  p->input = p->parent->child_inputs[p->parent_index];
301  }
302  if (!p->parser && p->argpar->children && p->argpar->children->argpar) {
303  // without a parser, every child gets the parent's input
304 // p->child_inputs[0] = p->input;
305  const argpar_child *children = p->argpar->children;
306  unsigned child_index = 0;
307  while (children++->argpar) {
308  p->child_inputs[child_index++] = p->input;
309  }
310  }
311  err = call_parser(p, &parser_chain->state, ARGPAR_KEY_INIT, 0);
312  }
313  if (err == ARGPAR_ERR_UNKNOWN) {
314  err = 0;
315  }
316 
317  if (err) {
318  return err;
319  }
320 
321  return 0;
322 }
323 static int parser_chain_finalize(parser_chain *p_chain, int err, unsigned *end_index) {
324  struct parser *parser;
325 
326  if (!err) {
327  if (p_chain->state.next == p_chain->state.argc) {
328  for (parser = p_chain->parsers; parser < p_chain->last_parser && (!err || err == ARGPAR_ERR_UNKNOWN); parser++) {
329  if (parser->args_parsed == 0) {
330  err = call_parser(parser, &p_chain->state, ARGPAR_KEY_NO_ARGS, 0);
331  }
332  }
333  for (parser = p_chain->last_parser - 1; parser >= p_chain->parsers && (!err || err == ARGPAR_ERR_UNKNOWN); parser--) {
334  err = call_parser(parser, &p_chain->state, ARGPAR_KEY_END, 0);
335  }
336 
337  if (err == ARGPAR_ERR_UNKNOWN) {
338  err = 0;
339  }
340  if (end_index) {
341  *end_index = p_chain->state.next;
342  }
343  } else if (end_index) {
344  *end_index = p_chain->state.next;
345  } else {
346 // if (!(p_chain->state.flags & ARGP_NO_ERRS) && p_chain->state.err_stream){
347 // fprintf(p_chain->state.err_stream, dgettext(p_chain->argp->argp_domain, "%s: Too many arguments\n"), p_chain->state.name);
348 // }
349  fprintf(stderr, "%s: Too many arguments\n", p_chain->state.name);
351  }
352  }
353 
354  if (err) {
355  if (err == ARGPAR_ERR_USAGE) {
356 // __argp_state_help(&p_chain->state, p_chain->state.err_stream, ARGP_HELP_STD_ERR);
357  argpar_usage(&p_chain->state);
358  }
359 
360  for (parser = p_chain->parsers; parser < p_chain->last_parser; parser++) {
361  call_parser(parser, &p_chain->state, ARGPAR_KEY_ERROR, 0);
362  }
363  } else {
364  for (parser = p_chain->last_parser - 1; parser >= p_chain->parsers && (!err || err == ARGPAR_ERR_UNKNOWN); parser--) {
365  err = call_parser(parser, &p_chain->state, ARGPAR_KEY_SUCCESS, 0);
366  }
367  if (err == ARGPAR_ERR_UNKNOWN) {
368  err = 0;
369  }
370  }
371 
372  for (parser = p_chain->last_parser - 1; parser >= p_chain->parsers; parser--) {
373  call_parser(parser, &p_chain->state, ARGPAR_KEY_FINI, 0);
374  }
375 
376  free(p_chain->storage);
377 
378  return err;
379 }
380 
381 static void initialize_unknown_state(argpar_state *state, char *key, char *value){
382  state->arg_name = key;
383  state->arg_alias = NULL;
384  state->arg_value = value;
385 
386  state->argv_as_int = 0;
387  state->argv_as_int_err = 1;
388  state->argv_as_dbl = 0;
389  state->argv_as_dbl_err = 1;
390 }
391 
392 static int parse_option(parser_chain *parser_chain, char *key, char *value) {
393  parser *parser;
394 
395  int return_value = 0;
396 
398  for (parser = parser_chain->parsers; parser < parser_chain->last_parser; parser++) {
399  if (parser->argpar == &argpar_params_argpar){
401  initialize_unknown_state(&s, key, value);
402  call_parser(parser, &s, ARGPAR_KEY_UNKNOWN, value);
403  break;
404  }
405  }
406  }
407 
408  for (parser = parser_chain->parsers; parser < parser_chain->last_parser; parser++) {
409  const argpar_option *o = parser->argpar->options;
410  bool is_parent = (parser->argpar == parser_chain->root_argpar);
411 
412  size_t i = 0;
413 
414  const argpar_option *base_option = NULL;
415 
416  while (o[i].name || o[i].doc) {
417  if (o[i].name && !((o[i].flags & OPTION_PARENT) && !is_parent) && !((o[i].flags & OPTION_CHILD) && is_parent) && !strcmp(o[i].name, key)) {
419 
420  if (!(o[i].flags & OPTION_ALIAS)){
421  base_option = &o[i];
422  }
423 
424  s.arg_name = base_option->name;
425  s.arg_alias = key;
426  s.arg_value = value;
427 
428  if (base_option->flags & OPTION_INT) {
429  s.argv_as_int = strtol_strict(value);
430  s.argv_as_int_err = errno;
431  } else {
432  s.argv_as_int = 0;
433  s.argv_as_int_err = 1;
434  }
435  if (base_option->flags & OPTION_DBL) {
436  s.argv_as_dbl = strtod_strict(value);
437  s.argv_as_dbl_err = errno;
438  } else {
439  s.argv_as_dbl = 0;
440  s.argv_as_dbl_err = 1;
441  }
442  return_value = call_parser(parser, &s, base_option->key, value);
443  if (return_value || !(parser_chain->state.flags & ARGPAR_ACCEPT_ANY)){
444  return return_value;
445  }
446  }
447  if (!(o[i].flags & (OPTION_DOC | OPTION_ALIAS))){
448  base_option = &o[i];
449  }
450  ++i;
451  }
454  initialize_unknown_state(&s, key, value);
455  int ret = call_parser(parser, &s, ARGPAR_KEY_UNKNOWN, value);
456  if (ret){
457  return ret;
458  }
459  }
460  }
462  return return_value;
463  }
464  return ARGPAR_ERR_UNKNOWN;
465 }
466 
467 static int parse_arg(parser_chain *parser_chain, char *arg) {
468  parser *parser;
469  int err = ARGPAR_ERR_UNKNOWN;
470 
472  if (s.flags & ARGPAR_CAST_ARGS) {
473  s.argv_as_int = strtol_strict(arg);
474  s.argv_as_int_err = errno;
475  s.argv_as_dbl = strtod_strict(arg);
476  s.argv_as_dbl_err = errno;
477  } else {
478  s.argv_as_int = 0;
479  s.argv_as_int_err = 1;
480  s.argv_as_dbl = 0;
481  s.argv_as_dbl_err = 1;
482  }
483 
485  err = call_parser(parser, &s, ARGPAR_KEY_ARG, arg);
486  }
487  s.next++;
488  return err;
489 }
490 
491 static int parse_file(parser_chain *p_chain, const char *path, const char *cwd) {
492  argpar *p = NULL;
493 
494  parser *parser;
495  for (parser = p_chain->parsers; parser < p_chain->last_parser && !p; parser++) {
496  p = parser->argpar;
497  }
498  if (!p) {
499  return ARGPAR_ERR_PARFILE;
500  }
501  if (p->parfile_buffer_count >= MAX_PARFILES) {
502  return ARGPAR_LIMIT_REACHED;
503  }
504 
505  FILE *file_h = NULL;
506  char *this_path, *this_cwd;
507  this_path = this_cwd = NULL;
508 
509  const char *parfile_was = p_chain->state.parfile;
510 
511  if (cwd != NULL && *path != '/') {
512  this_path = malloc((strlen(cwd) + strlen(path) + 2) * sizeof(char));
513  if (this_path == NULL) {
514  return ENOMEM;
515  }
516  strcpy(this_path, cwd);
517  strcat(this_path, "/");
518  strcat(this_path, path);
519  p_chain->state.parfile = this_path;
520  file_h = fopen(this_path, "rb");
521  } else {
522  p_chain->state.parfile = path;
523  file_h = fopen(path, "rb");
524  }
525  if (file_h == NULL) {
526  if (this_path != NULL) {
527  free(this_path);
528  }
529  return ARGPAR_ERR_PARFILE;
530  }
531 
532  fseek(file_h, 0, SEEK_END);
533  long file_size = ftell(file_h);
534  fseek(file_h, 0, SEEK_SET);
535  unsigned long this_buffer_index = p->parfile_buffer_count++;
536  if (p->parfile_buffer == NULL) {
537  p->parfile_buffer = calloc(MAX_PARFILES, sizeof(char*));
538  if (p->parfile_buffer == NULL) {
539  if (this_path != NULL) {
540  free(this_path);
541  }
542  return ENOMEM;
543  }
544  }
545  size_t ufile_size = (size_t) file_size;
546  p->parfile_buffer[this_buffer_index] = malloc((ufile_size + 1) * sizeof(char));
547  if (p->parfile_buffer[this_buffer_index] == NULL) {
548  if (this_path != NULL) {
549  free(this_path);
550  }
551  return ENOMEM;
552  }
553  size_t fread_count = fread(p->parfile_buffer[this_buffer_index], sizeof(char), ufile_size + 1, file_h);
554  if (fread_count != ufile_size || !feof(file_h)) {
555  if (this_path != NULL) {
556  free(this_path);
557  }
558  fclose(file_h);
559  return ARGPAR_ERR_PARFILE;
560  }
561  fclose(file_h);
562 
563  char *buffer = p->parfile_buffer[this_buffer_index];
564  char *buffer_end = &p->parfile_buffer[this_buffer_index][file_size];
565  *buffer_end = '\0';
566  char *v, *k;
567  int err = 0;
568  do {
569  char *k_end = NULL;
570  if (p_chain->state.flags & ARGPAR_NO_KEYARGS) {
571  k = NULL;
572  v = NULL;
573 
574  char *find_buffer = buffer;
575  while (find_buffer != buffer_end) {
576  if (*find_buffer == '=') {
577  k = strsep(&buffer, "=");
578  v = strsep(&buffer, "\n");
579  } else if (*find_buffer == '\n') {
580  k = strsep(&buffer, "\n");
581  k_end = k + strlen(k);
582  v = "1";
583  } else {
584  find_buffer++;
585  }
586  }
587  if (k == NULL){
588  k = buffer;
589  k_end = buffer_end;
590  v = "1";
591  }
592  } else {
593  k = strsep(&buffer, "=");
594  v = strsep(&buffer, "\n");
595  }
596  if (k == NULL || v == NULL) {
597  break;
598  }
599  while (isspace(*k) || *k == '"' || *k == '\''){
600  k++;
601  }
602  if (k_end == NULL){
603  k_end = v - 2;
604  }
605  while (isspace(*k_end) || *k_end == '"' || *k_end == '\'') {
606  *k_end = '\0';
607  k_end--;
608  }
609 
610  while (isspace(*v) || *v == '"' || *v == '\''){
611  v++;
612  }
613  char *v_end = v + strlen(v) - 1;
614  while (isspace(*v_end) || *v_end == '"' || *v_end == '\'') {
615  *v_end = '\0';
616  v_end--;
617  }
618  if (*k == '#') {
619  continue;
620  } else if (strlen(k)) {
621  if (strcmp(k, PARFILE_STR)) {
622  err = parse_option(p_chain, k, v);
623  if (err == ARGPAR_ERR_UNKNOWN) {
624  fprintf(argpar_ostream ? argpar_ostream : stderr, "Unknown option: %s\n\n", k);
625  }
626  } else {
627  if (this_cwd == NULL) {
628  if (this_path == NULL) {
629  this_path = strdup(path);
630  if (this_path == NULL) {
631  return ENOMEM;
632  }
633  }
634  this_cwd = dirname(this_path);
635  }
636  err = parse_file(p_chain, v, this_cwd);
637  }
638  }
639  } while (buffer != buffer_end && !err);
640 
641  p_chain->state.parfile = parfile_was;
642 
643  if (this_path) {
644  free(this_path);
645  }
646  return err;
647 }
648 
650  if (p && p != &argpar_help_argpar && p != &argpar_version_argpar) {
651  if (p->parfile_buffer){
652  unsigned i;
653  for (i = 0; i < p->parfile_buffer_count; i++) {
654  free(p->parfile_buffer[i]);
655  }
656  free(p->parfile_buffer);
657  p->parfile_buffer = NULL;
658  p->parfile_buffer_count = 0;
659  }
660 
661  // in case parsers manually loaded parfiles
662  const argpar_child *children = p->children;
663  if (children) {
664  while (children->argpar) {
666  }
667  }
668  }
669 
670  return 0;
671 }
672 
673 // stolen directly from argp
674 static char *nondestructive_basename(char *name) {
675  char *short_name = strrchr(name, '/');
676  return short_name ? short_name + 1 : name;
677 }
678 
679 int argpar_parse_args(argpar *p, unsigned argc, char *argv[], unsigned flags, unsigned *end_index, void *input) {
680  if (!(flags & ARGPAR_NO_HELP) && (argc < 1 || argv == NULL)) {
681  argpar_help(p, argpar_ostream ? argpar_ostream : stderr, flags, (argv == NULL ? "cmd" : nondestructive_basename(argv[0])));
682  return ARGPAR_ERR_USAGE;
683  } else {
684  parser_chain p_chain;
685  if (p->parfile_buffer == NULL) {
686  p->parfile_buffer_count = 0;
687  }
688  int err = parser_chain_init(&p_chain, p, argc, argv, flags, input);
689  if (!err) {
690  for (p_chain.state.next = 1; p_chain.state.next < argc && !err; p_chain.state.next++) {
691  if (p_chain.state.quoted && p_chain.state.next < p_chain.state.quoted) {
692  p_chain.state.quoted = 0;
693  }
694  if (p_chain.state.quoted) {
695  err = parse_arg(&p_chain, argv[p_chain.state.next]);
696  p_chain.state.arg_num++;
697  } else if (strcmp(argv[p_chain.state.next], "--") == 0) {
698  p_chain.state.quoted = p_chain.state.next + 1;
699  } else if (strchr(argv[p_chain.state.next], '=') != NULL) {
700  char *v = (char*) argv[p_chain.state.next];
701  char *k = strsep(&v, "=");
702  while (isspace(*k))
703  k++;
704  if (strcmp(k, PARFILE_STR)) {
705  err = parse_option(&p_chain, k, v);
706  if (err == ARGPAR_ERR_UNKNOWN) {
707  fprintf(argpar_ostream ? argpar_ostream : stderr, "Unknown option: %s\n\n", k);
708  }
709  } else if (!(flags & ARGPAR_SKIP_PARFILES)) {
710  err = parse_file(&p_chain, v, NULL);
711  }
712  } else if (flags & ARGPAR_NO_KEYARGS) {
713  char *k = (char*) argv[p_chain.state.next];
714  char *v = "1";
715  err = parse_option(&p_chain, k, v);
716  if (err == ARGPAR_ERR_UNKNOWN) {
717  fprintf(argpar_ostream ? argpar_ostream : stderr, "Unknown option: %s\n\n", k);
718  }
719  } else {
720  err = parse_arg(&p_chain, argv[p_chain.state.next]);
721  p_chain.state.arg_num++;
722  }
723  }
724  err = parser_chain_finalize(&p_chain, err, end_index);
725  }
726  return err;
727  }
728 }
729 
730 int argpar_parse_file(argpar *p, const char *path, unsigned flags, void *input) {
731  parser_chain p_chain;
732  int err = parser_chain_init(&p_chain, p, 0, NULL, flags, input);
733  if (!err) {
734  err = parse_file(&p_chain, path, NULL);
735  err = parser_chain_finalize(&p_chain, err, NULL);
736  }
737  return err;
738 }
739 
740 const char *argpar_version() {
741  return "argpar " ARGPAR_IMPLEMENTATION_STR ", API " ARGPAR_API_VERSION_STR;
742 }
743 
744 char **argpar_split_str(char *str, const char *delim) {
745  size_t ret_size_max = 8;
746  size_t ret_size = 0;
747  char **ret = malloc(sizeof(char*) * ret_size_max);
748  char **iter = ret;
749  while ((*iter = strsep(&str, delim)) != NULL) {
750  ret_size++;
751  iter++;
752  if (ret_size == ret_size_max) {
753  ret_size_max *= 2;
754  char **new_ret = realloc(ret, sizeof(char*) * ret_size_max);
755  if (new_ret == NULL) {
756  fprintf(argpar_ostream ? argpar_ostream : stderr, "Failed to reallocate array of size %lu\n", ret_size_max);
757  free(ret);
758  return NULL;
759  } else {
760  ret = new_ret;
761  iter = &ret[ret_size];
762  }
763  }
764  }
765  ret[ret_size] = NULL;
766  return ret;
767 }
768 
769 char **argpar_split_trim(char *str, const char *delim) {
770  char **ret = argpar_split_str(str, delim);
771  size_t i = 0;
772  for (; ret[i] != NULL; i++) {
773  while (isspace(*ret[i])) {
774  ret[i]++;
775  }
776  char *end = ret[i] + strlen(ret[i]) - 1;
777  while (end > ret[i] && isspace(*end)) {
778  end--;
779  }
780  *(end + 1) = '\0';
781  }
782  return ret;
783 }
784 
785 int *argpar_split_int(char *str, const char *delim) {
786  char **list = argpar_split_trim(str, delim);
787  size_t s = 0;
788  while (list[s] != NULL) {
789  s++;
790  }
791  int *ret = malloc(sizeof(int) * (s + 1));
792  ret[s] = NULL_INT;
793  for (size_t i = 0; i < s; i++) {
794  if (list[i][0]) {
795  ret[i] = strtol_strict(list[i]);
796  if (errno) {
797  free(ret);
798  free(list);
799  return NULL;
800  }
801  } else {
802  ret[i] = EMPTY_INT;
803  }
804  }
805  free(list);
806  return ret;
807 }
808 
809 double *argpar_split_dbl(char *str, const char *delim) {
810  char **list = argpar_split_trim(str, delim);
811  size_t s = 0;
812  while (list[s] != NULL) {
813  s++;
814  }
815  double *ret = malloc(sizeof(double) * (s + 1));
816  ret[s] = NAN;
817  for (size_t i = 0; i < s; i++) {
818  if (list[i][0]) {
819  ret[i] = strtod_strict(list[i]);
820  if (errno) {
821  free(ret);
822  free(list);
823  return NULL;
824  }
825  } else {
826  ret[i] = INFINITY;
827  }
828  }
829  free(list);
830  return ret;
831 }
832 
#define PARFILE_STR
Used to override the par file trigger.
Definition: argpar.h:54
size_t parsers
Definition: argpar.c:48
int32 value
Definition: Granule.c:1235
Master structure containing options, document strings, child parsers, and text filters....
Definition: argpar.h:398
#define EMPTY_INT
Definition: argpar.h:550
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:360
void * hook
Definition: argpar.c:34
Definition: argpar.c:27
#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:282
const argpar_option * options
Array of option structures, terminated by an empty entry (IE: {0}).
Definition: argpar.h:400
list(APPEND LIBS ${PGSTK_LIBRARIES}) add_executable(atteph_info_modis atteph_info_modis.c) target_link_libraries(atteph_info_modis $
Definition: CMakeLists.txt:7
unsigned int flags
Flags passed to parser functions to modify the behavior.
Definition: argpar.h:209
void * input
Definition: argpar.c:33
unsigned next
The index in ARGV of the next arg that to be parsed. May be modified.
Definition: argpar.h:206
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:769
parser * parsers
Definition: argpar.c:39
parser * last_parser
Definition: argpar.c:40
#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:403
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:785
#define ARGPAR_ERR_USAGE
Returned from the parser callback to signal argpar to stop parsing, print a usage summary,...
Definition: argpar.h:338
void * storage
Definition: argpar.c:44
char * name
The name used when printing messages. This is initialized to ARGV[0], or PROGRAM_INVOCATION_NAME if t...
Definition: argpar.h:233
void ** child_inputs
Definition: argpar.c:41
char ** argv
Pointer to arguments passed to argpar_parse_args.
Definition: argpar.h:203
#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:271
void * last_child_input
Definition: argpar.c:42
#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:295
uint8 * counts
Definition: l1_czcs_hdf.c:30
argpar_state state
Definition: argpar.c:43
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:377
#define ARGPAR_KEY_INIT
Passed as the key to each parser callback function before any parsing occurs. For most cases,...
Definition: argpar.h:287
const char * argpar_version()
Returns the source code version and the implemented API version.
Definition: argpar.c:740
#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
FILE * argpar_ostream
Definition: argpar.c:15
void ** child_inputs
Definition: argpar.c:33
instr * input
argpar_parser parser
Definition: argpar.c:28
int argpar_parse_file(argpar *p, const char *path, unsigned flags, void *input)
Parse a key=value store file.
Definition: argpar.c:730
#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:299
#define ARGPAR_NO_KEYARGS
Passed to the argpar_parse_ functions, this tells the parser to accept options without equal signs,...
Definition: argpar.h:125
#define ARGPAR_ERR_UNKNOWN
What to return for unrecognized keys within an argpar_parser function.
Definition: argpar.h:341
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:31
int flags
Modify the behavior of the argument by OR'ing one or more OPTION_ macros.
Definition: argpar.h:100
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:649
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:303
size_t child_inputs
Definition: argpar.c:48
#define ARGPAR_ERR_ABORT
Returned from the parser callback to signal argpar to stop parsing and return to the caller.
Definition: argpar.h:334
#define ARGPAR_KEY_FINI
Passed as the key to each parser callback function at the very end of the process....
Definition: argpar.h:291
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:32
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:20
#define isspace(c)
unsigned argc
Total number of arguments being parsed by a call of argpar_parse_args.
Definition: argpar.h:201
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:679
data_t b[NROOTS+1]
Definition: decode_rs.h:77
int compare_strings(const void *a, const void *b)
Definition: argpar.c:106
#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
const char * str
Definition: l1c_msi.cpp:35
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:809
#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:212
#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:196
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:345
const argpar_child * children
Array of argpar_child structures containing parsers to nest within this one. All options and argument...
Definition: argpar.h:413
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:215
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:744
#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:229
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:30
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:38
struct argpar * argpar
Underlying argpar struct.
Definition: argpar.h:379
#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:307
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:349
#define OPTION_PARENT
This option only applies if this parser is the top-most parser. Useful for return value documentation...
Definition: argpar.h:164
const char * argpar_program_version
Used as the program version string. If set, a version=1 option is automatically added....
Definition: argpar.c:19
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:29
float p[MODELMAX]
Definition: atrem_corl1.h:131
struct argpar * argpar
Pointer to the parent argpar object.
Definition: argpar.h:198
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:546