diff options
author | pgen <p.gen.progs@gmail.com> | 2019-11-23 14:24:36 +0100 |
---|---|---|
committer | pgen <p.gen.progs@gmail.com> | 2019-11-23 14:24:36 +0100 |
commit | b741f94da993907fa4c17eba814b779cf47e1aa0 (patch) | |
tree | 4e518fe0009d8861ecdd864ea3ae3046c8a20382 /ctxopt.c | |
parent | 1eff407070f604abde21d329b75c61e9d597a609 (diff) |
Update ctxopt
Diffstat (limited to 'ctxopt.c')
-rw-r--r-- | ctxopt.c | 579 |
1 files changed, 329 insertions, 250 deletions
@@ -11,25 +11,27 @@ #include <string.h> #include "ctxopt.h" -errors ctxopterrno = CTXOPTNOERR; - /* *********************** */ /* Static global variables */ /* *********************** */ static void * contexts_bst; static void * options_bst; +state_t * cur_state; + /* Prototypes */ /* ****************** */ /* Messages interface */ /* ****************** */ -static void (**err_functions)(char *, char *, char *, char *, char *); +static void (**err_functions)(errors e, state_t * state); + +static void +fatal_internal(const char * format, ...); static void -fatal(errors e, char * opt_par, char * opt_params, char * opt_name, - char * ctx_par, char * ctx_name, const char * format, ...); +fatal(errors e, char * errmsg); static void error(const char * format, ...); @@ -147,7 +149,7 @@ rtrim(char * str, const char * trim_str, size_t min); static int strchrcount(char * str, char c); -int +static int strpref(char * s1, char * s2); static char * @@ -205,7 +207,7 @@ static void match_prefix_cb(const void * node, walk_order_e kind, int level); static int -has_unseen_mandatory_opt(ctx_inst_t * ctx_inst); +has_unseen_mandatory_opt(ctx_inst_t * ctx_inst, char ** missing); static int opt_parse(char * s, opt_t ** opt); @@ -228,32 +230,75 @@ evaluate_ctx_inst(ctx_inst_t * ctx_inst); /* ====================== */ /* Message implementation */ /* ====================== */ + static void -fatal(errors e, char * opt_par, char * opt_params, char * opt_name, - char * ctx_par, char * ctx_name, const char * format, ...) +fatal_internal(const char * format, ...) { va_list args; - ctxopterrno = e; + va_start(args, format); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + va_end(args); - if (e == CTXOPTINTERNAL) - fprintf(stderr, "ctxopt internal: "); + exit(EXIT_FAILURE); +} +static void +fatal(errors e, char * errmsg) +{ if (err_functions[e] != NULL) - err_functions[e](opt_par, opt_params, opt_name, ctx_par, ctx_name); + err_functions[e](e, cur_state); else { - va_start(args, format); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - } + switch (e) + { + case CTXOPTNOERR: + break; + case CTXOPTMISPAR: + if (cur_state->cur_opt_par_name != NULL) + fprintf(stderr, + "Mandatory parameter(s): %s are missing in the context " + "introduced by %s.", + errmsg, cur_state->ctx_par_name); + else + fprintf( + stderr, + "Mandatory parameter(s): %s are missing in the first context.", + errmsg); - if (ctx_name != NULL) - ctxopt_ctx_disp_usage(ctx_name, continue_after); + free(errmsg); + break; + case CTXOPTMISARG: + if (cur_state->pre_opt_par_name != NULL) + fprintf(stderr, "%s requires argument(s).", + cur_state->pre_opt_par_name); + else + fprintf(stderr, "%s requires argument(s).", + cur_state->cur_opt_par_name); + break; + case CTXOPTDUPOPT: + fprintf(stderr, + "The parameter(s) %s can only appear once in this context.", + cur_state->cur_opt_par_name); + break; + case CTXOPTUNKPAR: + fprintf(stderr, "Unknown parameter: %s", cur_state->cur_opt_par_name); + fprintf(stderr, errmsg); + break; + case CTXOPTINCOPT: + fprintf(stderr, "%s is incompatible with %s\n", + cur_state->cur_opt_par_name, errmsg); + break; + case CTXOPTERRSIZE: + break; + } + } - va_end(args); + if (cur_state->ctx_name != NULL) + ctxopt_ctx_disp_usage(cur_state->ctx_name, continue_after); - exit(EXIT_FAILURE); + exit(e); } static void @@ -285,9 +330,8 @@ xmalloc(size_t size) real_size = (size > 0) ? size : 1; allocated = malloc(real_size); if (allocated == NULL) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "Insufficient memory (attempt to malloc %lu bytes)\n", - (unsigned long int)size); + fatal_internal("Insufficient memory (attempt to malloc %lu bytes)\n", + (unsigned long int)size); return allocated; } @@ -304,9 +348,8 @@ xcalloc(size_t n, size_t size) size = (size > 0) ? size : 1; allocated = calloc(n, size); if (allocated == NULL) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "Insufficient memory (attempt to calloc %lu bytes)\n", - (unsigned long int)size); + fatal_internal("Insufficient memory (attempt to calloc %lu bytes)\n", + (unsigned long int)size); return allocated; } @@ -321,9 +364,8 @@ xrealloc(void * p, size_t size) allocated = realloc(p, size); if (allocated == NULL && size > 0) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "Insufficient memory (attempt to xrealloc %lu bytes)\n", - (unsigned long int)size); + fatal_internal("Insufficient memory (attempt to xrealloc %lu bytes)\n", + (unsigned long int)size); return allocated; } @@ -594,7 +636,7 @@ ll_find(ll_t * const list, void * const data, /* IN start_node : The node of the list which will be the first node to */ /* consider to create the array */ /* OUT: count : The number of elements of the resulting array. */ -/* OUT: array : The resulting array. */ +/* OUT: array : The resulting array or NULL if the list is empty. */ /* RC : : The number of elements of the resulting array. */ /* ==================================================================== */ static int @@ -608,9 +650,13 @@ ll_strarray(ll_t * list, ll_node_t * start_node, int * count, char *** array) node = start_node; if (list == NULL || node == NULL) + { + *array = NULL; + return 0; + } - *array = xmalloc((list->len + 1) * sizeof(char **)); + *array = xmalloc((list->len + 1) * sizeof(char *)); while (node != NULL) { (*array)[n++] = (char *)(node->data); @@ -620,7 +666,6 @@ ll_strarray(ll_t * list, ll_node_t * start_node, int * count, char *** array) } (*array)[*count] = NULL; - *array = xrealloc(*array, ((*count) + 1) * sizeof(char **)); return *count; } @@ -852,7 +897,7 @@ strchrcount(char * str, char c) /* =============================================== */ /* Is the string str2 a prefix of the string str1? */ /* =============================================== */ -int +static int strpref(char * str1, char * str2) { while (*str1 != '\0' && *str1 == *str2) @@ -864,56 +909,98 @@ strpref(char * str1, char * str2) return *str2 == '\0'; } -/*===================================================================== */ -/* Allocate memory and safely concatenate strings. Stolen from a public */ -/* domain implementation which can be found here: */ -/* http://openwall.info/wiki/people/solar/software/\ */ -/* public-domain-source-code */ -/* ==================================================================== */ +/* ====================================================================== */ +/* Strings concatenation with dynamic memory allocation */ +/* IN : a variable number of char * arguments with NULL terminating */ +/* the sequence. */ +/* */ +/* Returns a new allocated string containing the concatenation of all */ +/* the arguments. It is the caller's responsibility to free the resulting */ +/* string. */ +/* ====================================================================== */ static char * -concat(const char * s1, ...) +xstrcat(const char * str, ...) { - va_list args; - const char * s; - char * p, *result; - size_t l, m, n; + size_t l; + va_list args; + char * s; + char * result; + + l = 1 + strlen(str); + va_start(args, str); - m = n = strlen(s1); - va_start(args, s1); - while ((s = va_arg(args, char *))) + s = va_arg(args, char *); + + while (s) { - l = strlen(s); - if ((m += l) < l) - break; + l += strlen(s); + s = va_arg(args, char *); } + va_end(args); - if (s || m >= INT_MAX) - return NULL; - result = (char *)xmalloc(m + 1); + result = xmalloc(l); + result[0] = '\0'; - memcpy(p = result, s1, n); - p += n; - va_start(args, s1); - while ((s = va_arg(args, char *))) + strcat(result, str); + + va_start(args, str); + s = va_arg(args, char *); + + while (s) { - l = strlen(s); - if ((n += l) < l || n > m) - break; - memcpy(p, s, l); - p += l; + strcat(result, s); + s = va_arg(args, char *); } va_end(args); - if (s || m != n || p != result + n) - { - free(result); - return NULL; - } - *p = 0; return result; } +/* ======================================================================== */ +/* Strings concatenation with dynamic memory allocation */ +/* IN : a variable number of char * arguments with NULL terminating */ +/* the sequence. */ +/* The first one must have been dynamically allocated and is mandatory */ +/* */ +/* Returns a new allocated string containing the concatenation of all */ +/* the arguments. It is the caller's responsibility to free the resulting */ +/* string. */ +/* ======================================================================== */ +static char * +strappend(char * str, ...) +{ + size_t l; + va_list args; + char * s; + + l = 1 + strlen(str); + va_start(args, str); + + s = va_arg(args, char *); + + while (s) + { + l += strlen(s); + s = va_arg(args, char *); + } + + va_end(args); + + str = xrealloc(str, l); + + va_start(args, str); + s = va_arg(args, char *); + + while (s) + { + strcat(str, s); + s = va_arg(args, char *); + } + va_end(args); + + return str; +} /* ====================================================================== */ /* public domain strtok_r() by Charlie Gordon */ /* from comp.lang.c 9/14/2007 */ @@ -1055,18 +1142,19 @@ struct opt_s int opt_count_matter; /* 1 if we must restrict the count, else 0 */ int occurrences; /* Number of occurrences of the option in a context */ char opt_count_oper; /* <, = or > */ - int opt_count_mark; /* Value to be compared to with opt_count_oper */ - char * arg; /* text represent the argument in in description of * - | the option. */ - int optional_args; /* 1 of option is optional else 0 */ - int multiple_args; /* 1 is option can appear more than once in a * - | context instance */ + unsigned opt_count_mark; /* Value to be compared to with opt_count_oper */ + char * arg; /* text represent the argument in in description * + | of the option. */ + int optional_args; /* 1 of option is optional else 0 */ + int multiple_args; /* 1 is option can appear more than once in a | context * + | instance */ int opt_args_count_matter; /* 1 if we must restrict the count, else 0 */ char opt_args_count_oper; /* <, = or > */ - int opt_args_count_mark; /* Value to be compared to with opt_count_oper */ - int eval_first; /* 1 if this option must be evaluated before * - |the options without this mark */ + unsigned + opt_args_count_mark; /* Value to be compared to with opt_count_oper */ + int eval_first; /* 1 if this option must be evaluated before * + |the options without this mark */ ll_t * constraints_list; /* List of constraints checking functions * | pointers. */ @@ -1128,6 +1216,7 @@ struct constraint_s char ** args; }; +state_t * cur_state = NULL; static ll_t * cmdline_list; static ctx_t * main_ctx = NULL; static ctx_inst_t * first_ctx_inst = NULL; /* Pointer to the fist context * @@ -1224,7 +1313,7 @@ static ctx_t * locate_ctx(char * name) { bst_t * node; - ctx_t ctx; + ctx_t ctx = { 0 }; ctx.name = name; @@ -1238,7 +1327,7 @@ static opt_t * locate_opt(char * name) { bst_t * node; - opt_t opt; + opt_t opt = { 0 }; opt.name = name; @@ -1252,7 +1341,7 @@ static par_t * locate_par(char * name, ctx_t * ctx) { bst_t * node; - par_t par; + par_t par = { 0 }; void * bst = ctx->par_bst; par.name = name; @@ -1273,29 +1362,30 @@ print_options(ll_t * list, int * has_optional, int * has_ellipsis, char * line; char * option; - line = " "; + line = xstrdup(" "); + while (node != NULL) { - option = ""; + option = xstrdup(""); opt = node->data; if (opt->optional) { - option = concat(option, "[", NULL); + option = strappend(option, "[", NULL); *has_optional = 1; } if (opt->eval_first) { - option = concat(option, "*", NULL); + option = strappend(option, "*", NULL); *has_early_eval = 1; } - option = concat(option, opt->params, NULL); + option = strappend(option, opt->params, NULL); if (opt->next_ctx != NULL) { - option = concat(option, ">", opt->next_ctx, NULL); + option = strappend(option, ">", opt->next_ctx, NULL); *has_ctx_change = 1; } @@ -1308,28 +1398,29 @@ print_options(ll_t * list, int * has_optional, int * has_ellipsis, o[0] = opt->opt_count_oper; o[1] = '\0'; snprintf(m, 3, "%u", opt->opt_count_mark); - option = concat(option, "...", o, m, NULL); + option = strappend(option, "...", o, m, NULL); *has_rule = 1; } + else + option = strappend(option, "...", NULL); - option = concat(option, "...", NULL); *has_ellipsis = 1; } if (opt->args) { - if (strcmp(opt->arg, "#") == 0) *has_generic_arg = 1; - option = concat(option, " ", NULL); + option = strappend(option, " ", NULL); + if (opt->optional_args) { - option = concat(option, "[", opt->arg, NULL); + option = strappend(option, "[", opt->arg, NULL); *has_optional = 1; } else - option = concat(option, opt->arg, NULL); + option = strappend(option, opt->arg, NULL); if (opt->multiple_args) { @@ -1340,32 +1431,36 @@ print_options(ll_t * list, int * has_optional, int * has_ellipsis, o[0] = opt->opt_args_count_oper; o[1] = '\0'; snprintf(m, 3, "%u", opt->opt_args_count_mark); - option = concat(option, "...", o, m, NULL); + option = strappend(option, "...", o, m, NULL); *has_rule = 1; } else - option = concat(option, "...", NULL); + option = strappend(option, "...", NULL); + *has_ellipsis = 1; } if (opt->optional_args) - option = concat(option, "]", NULL); + option = strappend(option, "]", NULL); } if (opt->optional) - option = concat(option, "]", NULL); + option = strappend(option, "]", NULL); if (strlen(line) + 1 + strlen(option) < 80) - line = concat(line, option, " ", NULL); + line = strappend(line, option, " ", NULL); else { printf("%s\n", line); line[2] = '\0'; - line = concat(line, option, " ", NULL); + line = strappend(line, option, " ", NULL); } + free(option); node = node->next; } + printf("%s\n", line); + free(line); } @@ -1384,7 +1479,7 @@ bst_seen_opt_cb(const void * node, walk_order_e kind, int level) if ((!seen_opt->opt->optional) && seen_opt->seen == 0) { user_rc = 1; - user_string = concat(user_string, seen_opt->opt->params, " ", NULL); + user_string = strappend(user_string, seen_opt->opt->params, " ", NULL); } } } @@ -1432,7 +1527,6 @@ static void bst_match_par_cb(const void * node, walk_order_e kind, int level) { ctx_t * ctx = ((bst_t *)node)->key; - par_t * par; if (kind == postorder || kind == leaf) { @@ -1440,9 +1534,9 @@ bst_match_par_cb(const void * node, walk_order_e kind, int level) while (*str != '\0') { - if ((par = locate_par(str, ctx)) != NULL) + if (locate_par(str, ctx) != NULL) { - user_string2 = concat(user_string2, " ", ctx->name, NULL); + user_string2 = strappend(user_string2, " ", ctx->name, NULL); break; } str[strlen(str) - 1] = '\0'; @@ -1460,7 +1554,7 @@ match_prefix_cb(const void * node, walk_order_e kind, int level) if (strpref(par->name, (char *)user_object)) { user_rc++; - user_string = concat(user_string, par->name, " ", NULL); + user_string = strappend(user_string, par->name, " ", NULL); } } @@ -1587,22 +1681,10 @@ abbrev_expand(char * par_name, ctx_t * ctx) static void check_for_missing_mandatory_opt(ctx_inst_t * ctx_inst, char * opt_par) { - if (has_unseen_mandatory_opt(ctx_inst)) - { - if (ctx_inst->par_name != NULL) - { - fatal(CTXOPTMISPAR, opt_par, user_string, NULL, ctx_inst->par_name, - ctx_inst->ctx->name, - "Mandatory parameter(s): %s are missing in the context " - "introduced by %s.", - user_string, ctx_inst->par_name); - } - else - fatal(CTXOPTMISPAR, opt_par, user_string, NULL, ctx_inst->par_name, - ctx_inst->ctx->name, - "Mandatory parameter(s): %s are missing in the first context.", - user_string); - } + char * missing; + + if (has_unseen_mandatory_opt(ctx_inst, &missing)) + fatal(CTXOPTMISPAR, missing); } /* ====================================================== */ @@ -1610,7 +1692,7 @@ check_for_missing_mandatory_opt(ctx_inst_t * ctx_inst, char * opt_par) /* when quitting a context, else 0 */ /* ====================================================== */ static int -has_unseen_mandatory_opt(ctx_inst_t * ctx_inst) +has_unseen_mandatory_opt(ctx_inst_t * ctx_inst, char ** missing) { user_rc = 0; *user_string = '\0'; @@ -1618,6 +1700,8 @@ has_unseen_mandatory_opt(ctx_inst_t * ctx_inst) bst_walk(ctx_inst->seen_opt_bst, bst_seen_opt_cb); rtrim(user_string, " ", 0); + *missing = user_string; + return user_rc ? 1 : 0; } @@ -1640,23 +1724,23 @@ check_for_occurrences_issues(ctx_inst_t * ctx_inst) { case '=': if (opt->occurrences > 0 && opt->opt_count_mark != opt->occurrences) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s must appear exactly %u times in this context, seen %u.", - opt->params, opt->opt_count_mark, opt->occurrences); + fatal_internal( + "%s must appear exactly %u times in this context, seen %u.", + opt->params, opt->opt_count_mark, opt->occurrences); break; case '<': if (opt->occurrences > 0 && opt->opt_count_mark <= opt->occurrences) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s must appear less than %u times in this context, seen %u.", - opt->params, opt->opt_count_mark, opt->occurrences); + fatal_internal( + "%s must appear less than %u times in this context, seen %u.", + opt->params, opt->opt_count_mark, opt->occurrences); break; case '>': if (opt->occurrences > 0 && opt->opt_count_mark >= opt->occurrences) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s must appear more than %u times in this context, seen %u.", - opt->params, opt->opt_count_mark, opt->occurrences); + fatal_internal( + "%s must appear more than %u times in this context, seen %u.", + opt->params, opt->opt_count_mark, opt->occurrences); break; } @@ -1678,23 +1762,20 @@ check_for_occurrences_issues(ctx_inst_t * ctx_inst) { case '=': if (nb_values > 0 && opt->opt_args_count_mark != nb_values) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s must have exactly %u arguments, not %u.", opt->params, - opt->opt_args_count_mark, nb_values); + fatal_internal("%s must have exactly %u arguments, not %u.", + opt->params, opt->opt_args_count_mark, nb_values); break; case '<': if (nb_values > 0 && opt->opt_args_count_mark <= nb_values) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s must have less than %u arguments, not %u.", opt->params, - opt->opt_args_count_mark, nb_values); + fatal_internal("%s must have less than %u arguments, not %u.", + opt->params, opt->opt_args_count_mark, nb_values); break; case '>': if (nb_values > 0 && opt->opt_args_count_mark >= nb_values) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s must have more than %u arguments, not %u.", opt->params, - opt->opt_args_count_mark, nb_values); + fatal_internal("%s must have more than %u arguments, not %u.", + opt->params, opt->opt_args_count_mark, nb_values); break; } @@ -1813,21 +1894,24 @@ opt_parse(char * s, opt_t ** opt) s = p; if (*s == '<' || *s == '=' || *s == '>') { - unsigned count; + unsigned value; int offset; - n = sscanf(s + 1, "%u%n", &count, &offset); + n = sscanf(s + 1, "%u%n", &value, &offset); if (n == 1) { opt_count_matter = 1; opt_count_oper = *s; - opt_count_mark = count; + opt_count_mark = value; } s += offset + 1; } } else + { + free(opt_name); return -(s - s_orig - 1); + } } /* A blank separates the option name and the argument tag */ @@ -1854,22 +1938,25 @@ opt_parse(char * s, opt_t ** opt) if (*s == '<' || *s == '=' || *s == '>') { - unsigned count; + unsigned value; int offset; - n = sscanf(s + 1, "%u%n", &count, &offset); + n = sscanf(s + 1, "%u%n", &value, &offset); if (n == 1) { opt_args_count_matter = 1; opt_args_count_oper = *s; - opt_args_count_mark = count; + opt_args_count_mark = value; } s += offset + 1; } /* optional arg tag must end with a ] */ if (*s != ']') + { + free(opt_name); return -(s - s_orig - 1); + } s++; /* skip the ] */ } @@ -1886,15 +1973,15 @@ opt_parse(char * s, opt_t ** opt) if (*s == '<' || *s == '=' || *s == '>') { - unsigned count; + unsigned value; int offset; - n = sscanf(s + 1, "%u%n", &count, &offset); + n = sscanf(s + 1, "%u%n", &value, &offset); if (n == 1) { opt_args_count_matter = 1; opt_args_count_oper = *s; - opt_args_count_mark = count; + opt_args_count_mark = value; } s += offset + 1; } @@ -1938,8 +2025,7 @@ success: next_ctx = NULL; if (*opt_name == '>') - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s: option name is missing.", opt_name); + fatal_internal("%s: option name is missing.", opt_name); count = strchrcount(opt_name, '>'); if (count == 1) @@ -1949,8 +2035,7 @@ success: *tmp = '\0'; } else if (count > 1) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s: only one occurrence of '>' is allowed.", opt_name); + fatal_internal("%s: only one occurrence of '>' is allowed.", opt_name); *opt = xmalloc(sizeof(opt_t)); @@ -2084,6 +2169,8 @@ ctxopt_init(void) ctxopt_initialized = 1; + cur_state = xcalloc(sizeof(state_t), 0); + /* Initialize custom error function pointers to NULL */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ err_functions = xmalloc(CTXOPTERRSIZE * sizeof(void *)); @@ -2109,8 +2196,7 @@ opt_set_parms(char * opt_name, char * par_str) /* """"""""""""""""""""""""""""""""""" */ opt = locate_opt(opt_name); if (opt == NULL) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, "Unknown option %s", - opt_name); + fatal_internal("Unknown option %s", opt_name); /* For each context using this option */ /* """""""""""""""""""""""""""""""""" */ @@ -2125,8 +2211,7 @@ opt_set_parms(char * opt_name, char * par_str) ctx = locate_ctx(ctx_name); if (ctx == NULL) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, "Unknown context %s", - ctx_name); + fatal_internal("Unknown context %s", ctx_name); else { void * par_bst = ctx->par_bst; @@ -2134,8 +2219,7 @@ opt_set_parms(char * opt_name, char * par_str) tmp_par_str = xstrdup(par_str); par_name = xstrtok_r(tmp_par_str, " \t,", &end_tmp_par_str); if (par_name == NULL) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "Parameters are missing for option %s", opt_name); + fatal_internal("Parameters are missing for option %s", opt_name); /* For each parameter given in par_str, create an par_t object and */ /* insert it the in the parameters bst of the context. */ @@ -2175,13 +2259,14 @@ opt_set_parms(char * opt_name, char * par_str) return rc; } -/* ===================================================================== */ -/* Creation of a new context instance */ -/* IN ctx : a context pointer to allow this instance to access */ -/* the context fields */ -/* IN prev_ctx_inst : the context instance whose option leading to the */ -/* creation of this new context instance is part of */ -/* ===================================================================== */ +/* ==================================================================== */ +/* Creation of a new context instance */ +/* IN ctx : a context pointer to allow this instance to */ +/* access the context fields */ +/* IN prev_ctx_inst : the context instance whose option leading to the */ +/* creation of this new context instance is part of */ +/* OUT : The new conxtext (cannot be NULL) */ +/* ==================================================================== */ static ctx_inst_t * new_ctx_inst(ctx_t * ctx, ctx_inst_t * prev_ctx_inst) { @@ -2198,7 +2283,10 @@ new_ctx_inst(ctx_t * ctx, ctx_inst_t * prev_ctx_inst) /* This will serve during the evaluation of the option callbacks */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (prev_ctx_inst != NULL) + { gen_opt_inst = (opt_inst_t *)(prev_ctx_inst->opt_inst_list->tail->data); + cur_state->opt_name = gen_opt_inst->opt->name; + } else gen_opt_inst = NULL; @@ -2212,6 +2300,8 @@ new_ctx_inst(ctx_t * ctx, ctx_inst_t * prev_ctx_inst) ctx_inst->opt_inst_list = ll_new(); ctx_inst->seen_opt_bst = NULL; + cur_state->ctx_name = ctx->name; + ll_node_t * node; if (prev_ctx_inst == NULL) @@ -2286,12 +2376,11 @@ new_ctx_inst(ctx_t * ctx, ctx_inst_t * prev_ctx_inst) /* context as all options has have a seen_opt structure in */ /* seen_opt_bst */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s is not known in the context %s", opt->name, ctx->name); + fatal_internal("%s is not known in the context %s", opt->name, + ctx->name); } else - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s: unknown option.", opt_name); + fatal_internal("%s: unknown option.", opt_name); opt_name = strtok(NULL, " \t"); } @@ -2577,12 +2666,11 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, ll_node_t * node; if (!ctxopt_build_cmdline_list(nb_words, words)) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "The command line could not be parsed: missing { or } detected."); + fatal_internal( + "The command line could not be parsed: missing { or } detected."); if (main_ctx == NULL) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "At least one context must have been created."); + fatal_internal("At least one context must have been created."); /* Create the first ctx_inst record */ /* """""""""""""""""""""""""""""""" */ @@ -2616,6 +2704,9 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, { ctx_inst = ctx_inst->prev_ctx_inst; ctx = ctx_inst->ctx; + + cur_state->ctx_name = ctx->name; + cur_state->ctx_par_name = ctx_inst->par_name; } } else if (expect_par && *par_name == '-') @@ -2623,6 +2714,8 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, int pos = 0; char * prefix; + cur_state->cur_opt_par_name = par_name; + /* An expected parameter has been seen */ /* """"""""""""""""""""""""""""""""""" */ if ((par = locate_par(par_name, ctx)) == NULL) @@ -2664,7 +2757,7 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, /* following word must be a parameter or nothing */ /* hence prefix it with a dash. */ /* ''''''''''''''''''''''''''''''''''''''''''''' */ - word = concat("-", par_name + pos, NULL); + word = xstrcat("-", par_name + pos, NULL); /* Insert it after the current node in the list */ /* """""""""""""""""""""""""""""""""""""""""""" */ @@ -2679,23 +2772,27 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, if (ctx_inst->prev_ctx_inst == NULL) { - char * errmsg = "Unknown parameter: %s"; + char * errmsg = xstrdup(""); + ; *user_string = '\0'; *user_string2 = '\0'; - user_string = concat(user_string, par_name, NULL); + user_string = strappend(user_string, par_name, NULL); + bst_walk(contexts_bst, bst_match_par_cb); if (*user_string2 != '\0') - errmsg = concat(errmsg, - "\nIt appears to be defined in the context(s):", - user_string2, - "\n'smenu -h' or 'smenu -H' can be helpful here.", - NULL); - - fatal(CTXOPTUNKPAR, par_name, NULL, NULL, ctx_inst->par_name, - ctx_inst->ctx->name, errmsg, par_name); + { + errmsg = strappend( + errmsg, + "\nIt appears to be defined in the context(s):", user_string2, + "\n'smenu -h' or 'smenu -H' can be helpful here.", NULL); + } + + // fatal(CTXOPTUNKPAR, par_name, NULL, NULL, ctx_inst->par_name, + // ctx_inst->ctx->name, errmsg, par_name); + fatal(CTXOPTUNKPAR, errmsg); } else { @@ -2705,6 +2802,9 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, ctx_inst = ctx_inst->prev_ctx_inst; ctx = ctx_inst->ctx; + cur_state->ctx_name = ctx->name; + cur_state->ctx_par_name = ctx_inst->par_name; + cli_node = cli_node->prev; } } @@ -2765,10 +2865,7 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, bst_seen_opt = (seen_opt_t *)(bst_node->key); if (!opt->multiple && bst_seen_opt->seen == 1) - fatal(CTXOPTDUPOPT, par_name, opt->params, opt->name, - ctx_inst->par_name, ctx_inst->ctx->name, - "The parameter(s) %s can only appear once in this context.", - opt->params); + fatal(CTXOPTDUPOPT, NULL); /* Check if this option is compatible with the options already */ /* seen in this context instance. */ @@ -2799,10 +2896,7 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, { bst_seen_opt = (seen_opt_t *)(bst_node->key); if (bst_seen_opt->seen == 0) - fatal(CTXOPTINCTXOPTT, par_name, (char *)user_object, - bst_seen_opt->opt->name, ctx_inst->par_name, - ctx_inst->ctx->name, "%s is incompatible with %s\n", - par_name, (char *)user_object); + fatal(CTXOPTINCOPT, (char *)user_object); } } @@ -2822,12 +2916,13 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, ctx = locate_ctx(opt->next_ctx); if (ctx == NULL) - fatal(CTXOPTINTERNAL, NULL, NULL, NULL, NULL, NULL, - "%s: unknown context.", opt->next_ctx); + fatal_internal("%s: unknown context.", opt->next_ctx); opt_inst->next_ctx_inst = ctx_inst = new_ctx_inst(ctx, ctx_inst); ctx_inst->par_name = xstrdup(par_name); + cur_state->ctx_par_name = ctx_inst->par_name; + ll_append(ctx_inst_list, ctx_inst); } @@ -2889,8 +2984,7 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, prev_arg = (char *)(cli_node->prev->data); - fatal(CTXOPTMISARG, prev_arg, opt->params, opt->name, ctx_inst->par_name, - ctx_inst->ctx->name, "%s requires argument(s).", prev_arg); + fatal(CTXOPTMISARG, NULL); } else if (expect_par_or_arg) { @@ -2912,8 +3006,7 @@ ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, if (cmdline_list->len > 0 && *par_name == '-') { if (expect_arg && !opt->optional_args) - fatal(CTXOPTMISARG, par_name, opt->params, opt->name, ctx_inst->par_name, - ctx_inst->ctx->na |