void nn_parse_options (struct nn_commandline *cline, void *target, int argc, char **argv) { struct nn_parse_context ctx; int num_options; ctx.def = cline; ctx.options = cline->options; ctx.target = target; ctx.argc = argc; ctx.argv = argv; ctx.requires = cline->required_options; for (num_options = 0; ctx.options[num_options].longname; ++num_options); ctx.last_option_usage = calloc (sizeof (char *), num_options); if (!ctx.last_option_usage) nn_memory_error (&ctx); ctx.mask = 0; ctx.args_left = argc - 1; ctx.arg = argv; nn_parse_arg0 (&ctx); while (nn_get_arg (&ctx)) { nn_parse_arg (&ctx); } nn_check_requires (&ctx); free (ctx.last_option_usage); }
static void nn_append_string (struct nn_parse_context *ctx, struct nn_option *opt, char *str) { struct nn_string_list *lst; lst = (struct nn_string_list *)( ((char *)ctx->target) + opt->offset); if (lst->items) { lst->num += 1; lst->items = realloc (lst->items, sizeof (char *) * lst->num); } else { lst->items = malloc (sizeof (char *)); lst->num = 1; } if (!lst->items) { nn_memory_error (ctx); } lst->items[lst->num-1] = str; }
static void nn_process_option (struct nn_parse_context *ctx, int opt_index, char *argument) { struct nn_option *opt; struct nn_enum_item *items; char *endptr; struct nn_blob *blob; FILE *file; char *data; size_t data_len; size_t data_buf; size_t bytes_read; opt = &ctx->options[opt_index]; if (ctx->mask & opt->conflicts_mask) { nn_option_conflict (ctx, opt_index); } ctx->mask |= opt->mask_set; switch (opt->type) { case NN_OPT_HELP: nn_print_help (ctx, stdout); exit (0); return; case NN_OPT_INT: *(long *)(((char *)ctx->target) + opt->offset) = strtol (argument, &endptr, 0); if (endptr == argument || *endptr != 0) { nn_option_error ("requires integer argument", ctx, opt_index); } return; case NN_OPT_INCREMENT: *(int *)(((char *)ctx->target) + opt->offset) += 1; return; case NN_OPT_DECREMENT: *(int *)(((char *)ctx->target) + opt->offset) -= 1; return; case NN_OPT_ENUM: items = (struct nn_enum_item *)opt->pointer; for (; items->name; ++items) { if (!strcmp (items->name, argument)) { *(int *)(((char *)ctx->target) + opt->offset) = \ items->value; return; } } nn_invalid_enum_value (ctx, opt_index, argument); return; case NN_OPT_SET_ENUM: *(int *)(((char *)ctx->target) + opt->offset) = \ *(int *)(opt->pointer); return; case NN_OPT_STRING: *(char **)(((char *)ctx->target) + opt->offset) = argument; return; case NN_OPT_BLOB: blob = (struct nn_blob *)(((char *)ctx->target) + opt->offset); blob->data = argument; blob->length = strlen (argument); blob->need_free = 0; return; case NN_OPT_FLOAT: #if defined NN_HAVE_WINDOWS *(float *)(((char *)ctx->target) + opt->offset) = (float) atof (argument); #else *(float *)(((char *)ctx->target) + opt->offset) = strtof (argument, &endptr); if (endptr == argument || *endptr != 0) { nn_option_error ("requires float point argument", ctx, opt_index); } #endif return; case NN_OPT_LIST_APPEND: nn_append_string (ctx, opt, argument); return; case NN_OPT_LIST_APPEND_FMT: data_buf = strlen (argument) + strlen (opt->pointer); data = malloc (data_buf); #if defined NN_HAVE_WINDOWS data_len = _snprintf_s (data, data_buf, _TRUNCATE, opt->pointer, argument); #else data_len = snprintf (data, data_buf, opt->pointer, argument); #endif assert (data_len < data_buf); nn_append_string (ctx, opt, data); nn_append_string_to_free (ctx, opt, data); return; case NN_OPT_READ_FILE: if (!strcmp (argument, "-")) { file = stdin; } else { file = fopen (argument, "r"); if (!file) { fprintf (stderr, "Error opening file ``%s'': %s\n", argument, strerror (errno)); exit (2); } } data = malloc (4096); if (!data) nn_memory_error (ctx); data_len = 0; data_buf = 4096; for (;;) { bytes_read = fread (data + data_len, 1, data_buf - data_len, file); data_len += bytes_read; if (feof (file)) break; if (data_buf - data_len < 1024) { if (data_buf < (1 << 20)) { data_buf *= 2; /* grow twice until not too big */ } else { data_buf += 1 << 20; /* grow 1 Mb each time */ } data = realloc (data, data_buf); if (!data) nn_memory_error (ctx); } } if (data_len != data_buf) { data = realloc (data, data_len); assert (data); } if (ferror (file)) { #if defined _MSC_VER #pragma warning (push) #pragma warning (disable:4996) #endif fprintf (stderr, "Error reading file ``%s'': %s\n", argument, strerror (errno)); #if defined _MSC_VER #pragma warning (pop) #endif exit (2); } if (file != stdin) { fclose (file); } blob = (struct nn_blob *)(((char *)ctx->target) + opt->offset); blob->data = data; blob->length = data_len; blob->need_free = 1; return; } abort (); }