diff options
author | Konstantin Osipov <kostja@sun.com> | 2010-02-03 03:06:42 +0300 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2010-02-03 03:06:42 +0300 |
commit | 0ce6d93f858eb5b67f8988946274ab2b9f060de4 (patch) | |
tree | 8555c47c0ce18227ce535252d2c2966af26183d3 /mysys | |
parent | c2fe19883e624ddd0e37768f860fa0853848adb3 (diff) | |
parent | e698ae01128fde4f82d4595e67a72cfac09ca125 (diff) | |
download | mariadb-git-0ce6d93f858eb5b67f8988946274ab2b9f060de4.tar.gz |
Merge next-mr -> next-4284.
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/my_getopt.c | 325 | ||||
-rw-r--r-- | mysys/my_once.c | 5 | ||||
-rw-r--r-- | mysys/safemalloc.c | 2 | ||||
-rw-r--r-- | mysys/typelib.c | 226 |
4 files changed, 386 insertions, 172 deletions
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index f5854043459..6b81ff66c7f 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -22,30 +22,21 @@ #include <errno.h> #include <m_string.h> -typedef void (*init_func_p)(const struct my_option *option, uchar* *variable, +typedef void (*init_func_p)(const struct my_option *option, uchar **variable, longlong value); static void default_reporter(enum loglevel level, const char *format, ...); my_error_reporter my_getopt_error_reporter= &default_reporter; -static int findopt(char *optpat, uint length, - const struct my_option **opt_res, - char **ffname); -my_bool getopt_compare_strings(const char *s, - const char *t, - uint length); +static int findopt(char *, uint, const struct my_option **, char **); +my_bool getopt_compare_strings(const char *, const char *, uint); static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); -static ulonglong getopt_ull(char *arg, const struct my_option *optp, - int *err); +static ulonglong getopt_ull(char *, const struct my_option *, int *); static double getopt_double(char *arg, const struct my_option *optp, int *err); -static void init_variables(const struct my_option *options, - init_func_p init_one_value); -static void init_one_value(const struct my_option *option, uchar* *variable, - longlong value); -static void fini_one_value(const struct my_option *option, uchar* *variable, - longlong value); -static int setval(const struct my_option *opts, uchar* *value, char *argument, - my_bool set_maximum_value); +static void init_variables(const struct my_option *, init_func_p); +static void init_one_value(const struct my_option *, uchar **, longlong); +static void fini_one_value(const struct my_option *, uchar **, longlong); +static int setval(const struct my_option *, uchar **, char *, my_bool); static char *check_struct_option(char *cur_arg, char *key_name); /* @@ -60,6 +51,7 @@ enum enum_special_opt { OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE}; char *disabled_my_option= (char*) "0"; +char *enabled_my_option= (char*) "1"; /* This is a flag that can be set in client programs. 0 means that @@ -282,7 +274,7 @@ int handle_options(int *argc, char ***argv, my_getopt_error_reporter(ERROR_LEVEL, "%s: ambiguous option '--%s-%s' (--%s-%s)", my_progname, special_opt_prefix[i], - cur_arg, special_opt_prefix[i], + opt_str, special_opt_prefix[i], prev_found); return EXIT_AMBIGUOUS_OPTION; } @@ -294,11 +286,11 @@ int handle_options(int *argc, char ***argv, for example: --skip-option=0 -> option = TRUE */ optend= (optend && *optend == '0' && !(*(optend + 1))) ? - (char*) "1" : disabled_my_option; + enabled_my_option : disabled_my_option; break; case OPT_ENABLE: optend= (optend && *optend == '0' && !(*(optend + 1))) ? - disabled_my_option : (char*) "1"; + disabled_my_option : enabled_my_option; break; case OPT_MAXIMUM: set_maximum_value= 1; @@ -386,7 +378,7 @@ int handle_options(int *argc, char ***argv, } return EXIT_OPTION_DISABLED; } - if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG) + if (must_be_var && optp->arg_type == NO_ARG) { if (my_getopt_print_errors) my_getopt_error_reporter(ERROR_LEVEL, @@ -428,33 +420,19 @@ int handle_options(int *argc, char ***argv, else { my_getopt_error_reporter(WARNING_LEVEL, - "%s: ignoring option '--%s' due to \ -invalid value '%s'", + "%s: ignoring option '--%s' " + "due to invalid value '%s'", my_progname, optp->name, optend); continue; } if (get_one_option && get_one_option(optp->id, optp, - *((my_bool*) value) ? - (char*) "1" : disabled_my_option)) + *((my_bool*) value) ? + enabled_my_option : disabled_my_option)) return EXIT_ARGUMENT_INVALID; continue; } argument= optend; } - else if (optp->arg_type == OPT_ARG && - (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) || - (optp->var_type & GET_TYPE_MASK) == GET_ENUM)) - { - if (optend == disabled_my_option) - init_one_value(optp, value, 0); - else - { - if (!optend) /* No argument -> enable option */ - init_one_value(optp, value, 1); - else - argument= optend; - } - } else if (optp->arg_type == REQUIRED_ARG && !optend) { /* Check if there are more arguments after this one, @@ -481,9 +459,9 @@ invalid value '%s'", for (optend= cur_arg; *optend; optend++) { opt_found= 0; - for (optp= longopts; optp->id; optp++) + for (optp= longopts; optp->name; optp++) { - if (optp->id == (int) (uchar) *optend) + if (optp->id && optp->id == (int) (uchar) *optend) { /* Option recognized. Find next what to do with it */ opt_found= 1; @@ -539,12 +517,7 @@ invalid value '%s'", } if ((error= setval(optp, optp->value, argument, set_maximum_value))) - { - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Error while setting value '%s' to '%s'", - my_progname, argument, optp->name); return error; - } if (get_one_option && get_one_option(optp->id, optp, argument)) return EXIT_UNSPECIFIED_ERROR; break; @@ -563,12 +536,7 @@ invalid value '%s'", continue; } if ((error= setval(optp, value, argument, set_maximum_value))) - { - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Error while setting value '%s' to '%s'", - my_progname, argument, optp->name); return error; - } if (get_one_option && get_one_option(optp->id, optp, argument)) return EXIT_UNSPECIFIED_ERROR; @@ -637,79 +605,130 @@ static char *check_struct_option(char *cur_arg, char *key_name) Will set the option value to given value */ -static int setval(const struct my_option *opts, uchar* *value, char *argument, +static int setval(const struct my_option *opts, uchar **value, char *argument, my_bool set_maximum_value) { - int err= 0; + int err= 0, res= 0; - if (value && argument) - { - uchar* *result_pos= ((set_maximum_value) ? - opts->u_max_value : value); + if (!argument) + argument= enabled_my_option; - if (!result_pos) + if (value) + { + if (set_maximum_value && !(value= opts->u_max_value)) + { + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Maximum value of '%s' cannot be set", + my_progname, opts->name); return EXIT_NO_PTR_TO_VARIABLE; + } switch ((opts->var_type & GET_TYPE_MASK)) { case GET_BOOL: /* If argument differs from 0, enable option, else disable */ - *((my_bool*) result_pos)= (my_bool) atoi(argument) != 0; + *((my_bool*) value)= (my_bool) atoi(argument) != 0; break; case GET_INT: - *((int*) result_pos)= (int) getopt_ll(argument, opts, &err); + *((int*) value)= (int) getopt_ll(argument, opts, &err); break; case GET_UINT: - *((uint*) result_pos)= (uint) getopt_ull(argument, opts, &err); + *((uint*) value)= (uint) getopt_ull(argument, opts, &err); break; case GET_LONG: - *((long*) result_pos)= (long) getopt_ll(argument, opts, &err); + *((long*) value)= (long) getopt_ll(argument, opts, &err); break; case GET_ULONG: - *((long*) result_pos)= (long) getopt_ull(argument, opts, &err); + *((long*) value)= (long) getopt_ull(argument, opts, &err); break; case GET_LL: - *((longlong*) result_pos)= getopt_ll(argument, opts, &err); + *((longlong*) value)= getopt_ll(argument, opts, &err); break; case GET_ULL: - *((ulonglong*) result_pos)= getopt_ull(argument, opts, &err); + *((ulonglong*) value)= getopt_ull(argument, opts, &err); break; case GET_DOUBLE: - *((double*) result_pos)= getopt_double(argument, opts, &err); + *((double*) value)= getopt_double(argument, opts, &err); break; case GET_STR: - *((char**) result_pos)= argument; + if (argument == enabled_my_option) + break; /* string options don't use this default of "1" */ + *((char**) value)= argument; break; case GET_STR_ALLOC: - if ((*((char**) result_pos))) - my_free((*(char**) result_pos), MYF(MY_WME | MY_FAE)); - if (!(*((char**) result_pos)= my_strdup(argument, MYF(MY_WME)))) - return EXIT_OUT_OF_MEMORY; + if (argument == enabled_my_option) + break; /* string options don't use this default of "1" */ + if ((*((char**) value))) + my_free((*(char**) value), MYF(MY_WME | MY_FAE)); + if (!(*((char**) value)= my_strdup(argument, MYF(MY_WME)))) + { + res= EXIT_OUT_OF_MEMORY; + goto ret; + }; break; case GET_ENUM: - if (((*(int*)result_pos)= - find_type(argument, opts->typelib, 2) - 1) < 0) + if (((*(uint*)value)= + find_type(argument, opts->typelib, 2) - 1) == (uint)-1) { - /* - Accept an integer representation of the enumerated item. - */ + /* Accept an integer representation of the enumerated item */ char *endptr; - unsigned int arg= (unsigned int) strtol(argument, &endptr, 10); + uint arg= (uint) strtol(argument, &endptr, 10); if (*endptr || arg >= opts->typelib->count) - return EXIT_ARGUMENT_INVALID; - *(int*)result_pos= arg; + { + res= EXIT_ARGUMENT_INVALID; + goto ret; + }; + *(uint*)value= arg; } break; case GET_SET: - *((ulonglong*)result_pos)= find_typeset(argument, opts->typelib, &err); + *((ulonglong*)value)= find_typeset(argument, opts->typelib, &err); if (err) - return EXIT_ARGUMENT_INVALID; + { + /* Accept an integer representation of the set */ + char *endptr; + ulonglong arg= (ulonglong) strtol(argument, &endptr, 10); + if (*endptr || (arg >> 1) >= (1ULL << (opts->typelib->count-1))) + { + res= EXIT_ARGUMENT_INVALID; + goto ret; + }; + *(ulonglong*)value= arg; + err= 0; + } + break; + case GET_FLAGSET: + { + char *error; + uint error_len; + + *((ulonglong*)value)= + find_set_from_flags(opts->typelib, opts->typelib->count, + *(ulonglong *)value, opts->def_value, + argument, strlen(argument), + &error, &error_len); + if (error) + { + res= EXIT_ARGUMENT_INVALID; + goto ret; + }; + } break; - default: /* dummy default to avoid compiler warnings */ + case GET_NO_ARG: /* get_one_option has taken care of the value already */ + default: /* dummy default to avoid compiler warnings */ break; } if (err) - return EXIT_UNKNOWN_SUFFIX; + { + res= EXIT_UNKNOWN_SUFFIX; + goto ret; + }; } return 0; + +ret: + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Error while setting value '%s' to '%s'", + my_progname, argument, opts->name); + return res; } @@ -887,7 +906,7 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, break; } - num= ((num - optp->sub_size) / block_size); + num= (num / block_size); num= (longlong) (num * block_size); if (num < optp->min_value) @@ -898,7 +917,7 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, } if (fix) - *fix= adjusted; + *fix= old != num; else if (adjusted) my_getopt_error_reporter(WARNING_LEVEL, "option '%s': signed value %s adjusted to %s", @@ -970,7 +989,7 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, } if (fix) - *fix= adjusted; + *fix= old != num; else if (adjusted) my_getopt_error_reporter(WARNING_LEVEL, "option '%s': unsigned value %s adjusted to %s", @@ -979,6 +998,29 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, return num; } +double getopt_double_limit_value(double num, const struct my_option *optp, + my_bool *fix) +{ + my_bool adjusted= FALSE; + double old= num; + if (optp->max_value && num > (double) optp->max_value) + { + num= (double) optp->max_value; + adjusted= TRUE; + } + if (num < (double) optp->min_value) + { + num= (double) optp->min_value; + adjusted= TRUE; + } + if (fix) + *fix= adjusted; + else if (adjusted) + my_getopt_error_reporter(WARNING_LEVEL, + "option '%s': value %g adjusted to %g", + optp->name, old, num); + return num; +} /* Get double value withing ranges @@ -1000,15 +1042,12 @@ static double getopt_double(char *arg, const struct my_option *optp, int *err) num= my_strtod(arg, &end, &error); if (end[0] != 0 || error) { - fprintf(stderr, - "%s: ERROR: Invalid decimal value for option '%s'\n", - my_progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "Invalid decimal value for option '%s'\n", optp->name); *err= EXIT_ARGUMENT_INVALID; return 0.0; } - if (optp->max_value && num > (double) optp->max_value) - num= (double) optp->max_value; - return max(num, (double) optp->min_value); + return getopt_double_limit_value(num, optp, NULL); } /* @@ -1050,6 +1089,7 @@ static void init_one_value(const struct my_option *option, uchar* *variable, *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL); break; case GET_SET: + case GET_FLAGSET: *((ulonglong*) variable)= (ulonglong) value; break; case GET_DOUBLE: @@ -1125,7 +1165,7 @@ void my_cleanup_options(const struct my_option *options) NOTES We will initialize the value that is pointed to by options->value. - If the value is of type GET_ASK_ADDR, we will also ask for the address + If the value is of type GET_ASK_ADDR, we will ask for the address for a value and initialize. */ @@ -1135,7 +1175,7 @@ static void init_variables(const struct my_option *options, DBUG_ENTER("init_variables"); for (; options->name; options++) { - uchar* *variable; + uchar **value; DBUG_PRINT("options", ("name: '%s'", options->name)); /* We must set u_max_value first as for some variables @@ -1144,15 +1184,22 @@ static void init_variables(const struct my_option *options, */ if (options->u_max_value) init_one_value(options, options->u_max_value, options->max_value); - if (options->value) - init_one_value(options, options->value, options->def_value); - if (options->var_type & GET_ASK_ADDR && - (variable= (*getopt_get_addr)("", 0, options, 0))) - init_one_value(options, variable, options->def_value); + value= (options->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, options, 0) : options->value); + if (value) + init_one_value(options, value, options->def_value); } DBUG_VOID_RETURN; } +/** Prints variable or option name, replacing _ with - */ +static uint print_name(const struct my_option *optp) +{ + const char *s= optp->name; + for (;*s;s++) + putchar(*s == '_' ? '-' : *s); + return s - optp->name; +} /* function: my_print_options @@ -1168,9 +1215,9 @@ void my_print_help(const struct my_option *options) const char *line_end; const struct my_option *optp; - for (optp= options; optp->id; optp++) + for (optp= options; optp->name; optp++) { - if (optp->id < 256) + if (optp->id && optp->id < 256) { printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " "); col= 6; @@ -1182,21 +1229,24 @@ void my_print_help(const struct my_option *options) } if (strlen(optp->name)) { - printf("--%s", optp->name); - col+= 2 + (uint) strlen(optp->name); - if ((optp->var_type & GET_TYPE_MASK) == GET_STR || - (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC) + printf("--"); + col+= 2 + print_name(optp); + if (optp->arg_type == NO_ARG || + (optp->var_type & GET_TYPE_MASK) == GET_BOOL) + { + putchar(' '); + col++; + } + else if ((optp->var_type & GET_TYPE_MASK) == GET_STR || + (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC || + (optp->var_type & GET_TYPE_MASK) == GET_ENUM || + (optp->var_type & GET_TYPE_MASK) == GET_SET || + (optp->var_type & GET_TYPE_MASK) == GET_FLAGSET ) { printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "", optp->arg_type == OPT_ARG ? "]" : ""); col+= (optp->arg_type == OPT_ARG) ? 8 : 6; } - else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG || - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) - { - putchar(' '); - col++; - } else { printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "", @@ -1228,12 +1278,13 @@ void my_print_help(const struct my_option *options) printf("%s", comment); } putchar('\n'); - if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG || - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) + if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) { if (optp->def_value != 0) { - printf("%*s(Defaults to on; use --skip-%s to disable.)\n", name_space, "", optp->name); + printf("%*s(Defaults to on; use --skip-", name_space, ""); + print_name(optp); + printf(" to disable.)\n"); } } } @@ -1249,36 +1300,53 @@ void my_print_help(const struct my_option *options) void my_print_variables(const struct my_option *options) { uint name_space= 34, length, nr; - ulonglong bit, llvalue; + ulonglong llvalue; char buff[255]; const struct my_option *optp; + for (optp= options; optp->name; optp++) + { + length= strlen(optp->name)+1; + if (length > name_space) + name_space= length; + } + printf("\nVariables (--variable-name=value)\n"); - printf("and boolean options {FALSE|TRUE} Value (after reading options)\n"); - printf("--------------------------------- -----------------------------\n"); - for (optp= options; optp->id; optp++) + printf("%-*s%s", name_space, "and boolean options {FALSE|TRUE}", + "Value (after reading options)\n"); + for (length=1; length < 75; length++) + putchar(length == name_space ? ' ' : '-'); + putchar('\n'); + + for (optp= options; optp->name; optp++) { - uchar* *value= (optp->var_type & GET_ASK_ADDR ? + uchar **value= (optp->var_type & GET_ASK_ADDR ? (*getopt_get_addr)("", 0, optp, 0) : optp->value); if (value) { - printf("%s ", optp->name); - length= (uint) strlen(optp->name)+1; + length= print_name(optp); for (; length < name_space; length++) putchar(' '); switch ((optp->var_type & GET_TYPE_MASK)) { case GET_SET: if (!(llvalue= *(ulonglong*) value)) - printf("%s\n", "(No default value)"); + printf("%s\n", ""); else - for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1) + for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1) { - if (!(bit & llvalue)) - continue; - llvalue&= ~bit; - printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr)); + if (llvalue & 1) + printf( llvalue > 1 ? "%s," : "%s\n", get_type(optp->typelib, nr)); } break; + case GET_FLAGSET: + llvalue= *(ulonglong*) value; + for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1) + { + printf("%s%s=", (nr ? "," : ""), get_type(optp->typelib, nr)); + printf(llvalue & 1 ? "on" : "off"); + } + printf("\n"); + break; case GET_ENUM: printf("%s\n", get_type(optp->typelib, *(uint*) value)); break; @@ -1312,6 +1380,9 @@ void my_print_variables(const struct my_option *options) case GET_DOUBLE: printf("%g\n", *(double*) value); break; + case GET_NO_ARG: + printf("(No default value)\n"); + break; default: printf("(Disabled)\n"); break; diff --git a/mysys/my_once.c b/mysys/my_once.c index b6f6656fce2..727b8477365 100644 --- a/mysys/my_once.c +++ b/mysys/my_once.c @@ -25,7 +25,8 @@ #include <m_string.h> /* - Alloc for things we don't nead to free + Alloc for things we don't nend to free run-time (that only + should be free'd on exit) SYNOPSIS my_once_alloc() @@ -100,7 +101,7 @@ void *my_once_memdup(const void *src, size_t len, myf myflags) /* - Deallocate everything used by my_once_alloc + Deallocate everything that was allocated with my_once_alloc SYNOPSIS my_once_free() diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 675fa62380a..efe281ba1bb 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -158,7 +158,7 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH)); } DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'", - sf_malloc_max_memory,lineno, filename)); + (long)sf_malloc_max_memory,lineno, filename)); if (MyFlags & MY_FAE) exit(1); DBUG_RETURN ((void*) 0); diff --git a/mysys/typelib.c b/mysys/typelib.c index cb72c91e20d..73dab610bed 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -20,7 +20,7 @@ #include <m_ctype.h> -static const char field_separator=','; +#define is_field_separator(X) ((X) == ',' || (X) == '=') int find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) { @@ -44,26 +44,26 @@ int find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) } -/* +/** Search after a string in a list of strings. Endspace in x is not compared. - SYNOPSIS - find_type() - x String to find - lib TYPELIB (struct of pointer to values + count) - full_name bitmap of what to do - If & 1 accept only whole names - If & 2 don't expand if half field - If & 4 allow #number# as type - If & 8 use ',' as string terminator - - NOTES - If part, uniq field is found and full_name == 0 then x is expanded - to full field. - - RETURN - -1 Too many matching values - 0 No matching value + @param x String to find + @param lib TYPELIB (struct of pointer to values + count) + @param full_name bitmap of what to do + If & 1 accept only whole names + If & 2 don't expand if half field + If & 4 allow #number# as type + If & 8 use ',' as string terminator + + @note + If part, uniq field is found and full_name == 0 then x is expanded + to full field. + + @retval + -1 Too many matching values + @retval + 0 No matching value + @retval >0 Offset+1 in typelib for matched string */ @@ -86,17 +86,17 @@ int find_type(char *x, const TYPELIB *typelib, uint full_name) for (pos=0 ; (j=typelib->type_names[pos]) ; pos++) { for (i=x ; - *i && (!(full_name & 8) || *i != field_separator) && + *i && (!(full_name & 8) || !is_field_separator(*i)) && my_toupper(&my_charset_latin1,*i) == my_toupper(&my_charset_latin1,*j) ; i++, j++) ; if (! *j) { while (*i == ' ') i++; /* skip_end_space */ - if (! *i || ((full_name & 8) && *i == field_separator)) + if (! *i || ((full_name & 8) && is_field_separator(*i))) DBUG_RETURN(pos+1); } - if ((!*i && (!(full_name & 8) || *i != field_separator)) && + if ((!*i && (!(full_name & 8) || !is_field_separator(*i))) && (!*j || !(full_name & 1))) { find++; @@ -122,8 +122,12 @@ int find_type(char *x, const TYPELIB *typelib, uint full_name) } /* find_type */ - /* Get name of type nr 'nr' */ - /* Warning first type is 1, 0 = empty field */ +/** + Get name of type nr + + @note + first type is 1, 0 = empty field +*/ void make_type(register char * to, register uint nr, register TYPELIB *typelib) @@ -137,8 +141,12 @@ void make_type(register char * to, register uint nr, } /* make_type */ - /* Get type */ - /* Warning first type is 0 */ +/** + Get type + + @note + first type is 0 +*/ const char *get_type(TYPELIB *typelib, uint nr) { @@ -148,18 +156,16 @@ const char *get_type(TYPELIB *typelib, uint nr) } -/* +/** Create an integer value to represent the supplied comma-seperated string where each string in the TYPELIB denotes a bit position. - SYNOPSIS - find_typeset() - x string to decompose - lib TYPELIB (struct of pointer to values + count) - err index (not char position) of string element which was not + @param x string to decompose + @param lib TYPELIB (struct of pointer to values + count) + @param err index (not char position) of string element which was not found or 0 if there was no error - RETURN + @retval a integer representation of the supplied string */ @@ -182,9 +188,9 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) { (*err)++; i= x; - while (*x && *x != field_separator) + while (*x && !is_field_separator(*x)) x++; - if (x[0] && x[1]) /* skip separator if found */ + if (x[0] && x[1]) /* skip separator if found */ x++; if ((find= find_type(i, lib, 2 | 8) - 1) < 0) DBUG_RETURN(0); @@ -195,16 +201,15 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) } /* find_set */ -/* +/** Create a copy of a specified TYPELIB structure. - SYNOPSIS - copy_typelib() - root pointer to a MEM_ROOT object for allocations - from pointer to a source TYPELIB structure + @param root pointer to a MEM_ROOT object for allocations + @param from pointer to a source TYPELIB structure - RETURN - pointer to the new TYPELIB structure on successful copy, or + @retval + pointer to the new TYPELIB structure on successful copy + @retval NULL otherwise */ @@ -244,3 +249,140 @@ TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from) return to; } + + +static const char *on_off_default_names[]= { "off","on","default", 0}; +static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1, + "", on_off_default_names, 0}; + +/** + Parse a TYPELIB name from the buffer + + @param lib Set of names to scan for. + @param strpos INOUT Start of the buffer (updated to point to the next + character after the name) + @param end End of the buffer + + @note + The buffer is assumed to contain one of the names specified in the TYPELIB, + followed by comma, '=', or end of the buffer. + + @retval + 0 No matching name + @retval + >0 Offset+1 in typelib for matched name +*/ + +static uint parse_name(const TYPELIB *lib, const char **strpos, const char *end) +{ + const char *pos= *strpos; + uint find= find_type((char*)pos, lib, 8); + for (; pos != end && *pos != '=' && *pos !=',' ; pos++); + *strpos= pos; + return find; +} + +/** + Parse and apply a set of flag assingments + + @param lib Flag names + @param default_name Number of "default" in the typelib + @param cur_set Current set of flags (start from this state) + @param default_set Default set of flags (use this for assign-default + keyword and flag=default assignments) + @param str String to be parsed + @param length Length of the string + @param err_pos OUT If error, set to point to start of wrong set string + NULL on success + @param err_len OUT If error, set to the length of wrong set string + + @details + Parse a set of flag assignments, that is, parse a string in form: + + param_name1=value1,param_name2=value2,... + + where the names are specified in the TYPELIB, and each value can be + either 'on','off', or 'default'. Setting the same name twice is not + allowed. + + Besides param=val assignments, we support the "default" keyword (keyword + #default_name in the typelib). It can be used one time, if specified it + causes us to build the new set over the default_set rather than cur_set + value. + + @note + it's not charset aware + + @retval + Parsed set value if (*errpos == NULL), otherwise undefined +*/ + +my_ulonglong find_set_from_flags(const TYPELIB *lib, uint default_name, + my_ulonglong cur_set, my_ulonglong default_set, + const char *str, uint length, + char **err_pos, uint *err_len) +{ + const char *end= str + length; + my_ulonglong flags_to_set= 0, flags_to_clear= 0, res; + my_bool set_defaults= 0; + + *err_pos= 0; // No error yet + if (str != end) + { + const char *start= str; + for (;;) + { + const char *pos= start; + uint flag_no, value; + + if (!(flag_no= parse_name(lib, &pos, end))) + goto err; + + if (flag_no == default_name) + { + /* Using 'default' twice isn't allowed. */ + if (set_defaults) + goto err; + set_defaults= TRUE; + } + else + { + my_ulonglong bit= (1ULL << (flag_no - 1)); + /* parse the '=on|off|default' */ + if ((flags_to_clear | flags_to_set) & bit || + pos >= end || *pos++ != '=' || + !(value= parse_name(&on_off_default_typelib, &pos, end))) + goto err; + + if (value == 1) // this is '=off' + flags_to_clear|= bit; + else if (value == 2) // this is '=on' + flags_to_set|= bit; + else // this is '=default' + { + if (default_set & bit) + flags_to_set|= bit; + else + flags_to_clear|= bit; + } + } + if (pos >= end) + break; + + if (*pos++ != ',') + goto err; + + start=pos; + continue; + err: + *err_pos= (char*)start; + *err_len= end - start; + break; + } + } + res= set_defaults? default_set : cur_set; + res|= flags_to_set; + res&= ~flags_to_clear; + return res; +} + |