diff options
author | unknown <jani@rhols221.adsl.netsonic.fi> | 2002-01-25 23:34:37 +0200 |
---|---|---|
committer | unknown <jani@rhols221.adsl.netsonic.fi> | 2002-01-25 23:34:37 +0200 |
commit | 06b282aac05ccc2dc60769a8c989e6bfc4fa59fb (patch) | |
tree | ebdc1f846c1fa8a627690099d9a418063625577e | |
parent | f817081b6cb42265e14c3a3e42b6d9152b7f5878 (diff) | |
download | mariadb-git-06b282aac05ccc2dc60769a8c989e6bfc4fa59fb.tar.gz |
Added my_getopt struct and modified myisamchk to the bk tree.
include/Makefile.am:
Added my_getopt.h
myisam/myisamchk.c:
myisamcheck is using my_getopt struct now. Old code left:
changeable_var[], will be changed later.
mysys/Makefile.am:
added my_getopt.c
mysys/getvar.c:
Added my_set_changeable_var. This is not being used yet, and
is mostly a copy of set_changeable_var still.
BitKeeper/etc/logging_ok:
Logging to logging@openlogging.org accepted
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | include/Makefile.am | 2 | ||||
-rw-r--r-- | include/my_getopt.h | 46 | ||||
-rw-r--r-- | myisam/myisamchk.c | 404 | ||||
-rw-r--r-- | mysys/Makefile.am | 2 | ||||
-rw-r--r-- | mysys/getvar.c | 77 | ||||
-rw-r--r-- | mysys/my_getopt.c | 313 |
7 files changed, 658 insertions, 187 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 7957579ec8f..4986ccbba58 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -42,3 +42,4 @@ bell@sanja.is.com.ua kaj@work.mysql.com mwagner@cash.mwagner.org tom@basil-firewall.home.com +jani@rhols221.adsl.netsonic.fi diff --git a/include/Makefile.am b/include/Makefile.am index 54451e9d4f6..b943e8d76e6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -28,7 +28,7 @@ noinst_HEADERS = config-win.h \ my_dir.h mysys_err.h my_base.h \ my_nosys.h my_alarm.h queues.h \ my_tree.h hash.h thr_alarm.h thr_lock.h \ - getopt.h t_ctype.h violite.h md5.h \ + getopt.h my_getopt.h t_ctype.h violite.h md5.h \ mysql_version.h.in # mysql_version.h are generated diff --git a/include/my_getopt.h b/include/my_getopt.h new file mode 100644 index 00000000000..3132d6a1672 --- /dev/null +++ b/include/my_getopt.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +struct my_optarg +{ + char *arg; /* option argument */ + int pos; /* next element in ARGV */ + int verbose; /* 0 = inhibit warnings of unrecognized options */ + int unrecognized; /* position of the unrecognized option */ +}; + + +enum get_opt_var_type { GET_NO_ARG, GET_INT, GET_LL, GET_STR }; +enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; + +struct my_option +{ + const char *name; /* Name of the option */ + const char *comment; /* option comment, for autom. --help */ + char *value; /* The variable value */ + const char **str_values; /* Pointer to possible values */ + enum get_opt_var_type var_type; + enum get_opt_arg_type arg_type; + int id; /* unique id or short option */ + long long def_value; /* Default value */ + long long min_value; /* Min allowed value */ + long long max_value; /* Max allowed value */ + long long sub_size; /* Subtract this from given value */ + long block_size; /* Value should be a mult. of this */ + int app_type; /* To be used by an application */ + my_bool changeable_var; /* If true, the option is a variable */ +}; + diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 1ed23ffe4f6..eedbb6af940 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -20,7 +20,7 @@ #include <m_ctype.h> #include <stdarg.h> -#include <getopt.h> +#include <my_getopt.h> #include <assert.h> #ifdef HAVE_SYS_VADVICE_H #include <sys/vadvise.h> @@ -169,58 +169,75 @@ static CHANGEABLE_VAR changeable_vars[] = { enum options { OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS, - OPT_CORRECT_CHECKSUM + OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE, + OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, + OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, + OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT }; - -static struct option long_options[] = +static struct my_option my_long_options[] = { - {"analyze", no_argument, 0, 'a'}, - {"block-search", required_argument,0, 'b'}, - {"backup", no_argument, 0, 'B'}, - {"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR}, - {"check", no_argument, 0, 'c'}, - {"check-only-changed",no_argument, 0, 'C'}, - {"correct-checksum", no_argument, 0, OPT_CORRECT_CHECKSUM}, + {"analyze", "", 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0, 0, 0, 0, 0, 0}, + {"block-search", "", 0, 0, GET_LL, REQUIRED_ARG, 'b', 0, 0, 0, 0, 0, 0, 0}, + {"backup", "", 0, 0, GET_NO_ARG, NO_ARG, 'B', 0, 0, 0, 0, 0, 0, 0}, + {"character-sets-dir", "", 0, 0, GET_STR, REQUIRED_ARG, OPT_CHARSETS_DIR, 0, 0, 0, 0, 0, 0, 0}, + + {"check", "", 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0, 0, 0, 0, 0, 0}, + {"check-only-changed", "", 0, 0, GET_NO_ARG, NO_ARG, 'C', 0, 0, 0, 0, 0, 0, 0}, + + {"correct-checksum", "", 0, 0, GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 0, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF - {"debug", optional_argument, 0, '#'}, + {"debug", "", 0, 0, GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0, 0}, #endif - {"description", no_argument, 0, 'd'}, - {"data-file-length", required_argument, 0, 'D'}, - {"extend-check", no_argument, 0, 'e'}, - {"fast", no_argument, 0, 'F'}, - {"force", no_argument, 0, 'f'}, - {"help", no_argument, 0, '?'}, - {"information", no_argument, 0, 'i'}, - {"keys-used", required_argument, 0, 'k'}, - {"medium-check", no_argument, 0, 'm'}, - {"quick", no_argument, 0, 'q'}, - {"read-only", no_argument, 0, 'T'}, - {"recover", no_argument, 0, 'r'}, - {"safe-recover", no_argument, 0, 'o'}, - {"start-check-pos", required_argument, 0, OPT_START_CHECK_POS}, - {"set-auto-increment",optional_argument, 0, 'A'}, - {"set-character-set",required_argument,0,OPT_SET_CHARSET}, - {"set-variable", required_argument, 0, 'O'}, - {"silent", no_argument, 0, 's'}, - {"sort-index", no_argument, 0, 'S'}, - {"sort-records", required_argument, 0, 'R'}, - {"sort-recover", no_argument, 0, 'n'}, - {"tmpdir", required_argument, 0, 't'}, - {"update-state", no_argument, 0, 'U'}, - {"unpack", no_argument, 0, 'u'}, - {"verbose", no_argument, 0, 'v'}, - {"version", no_argument, 0, 'V'}, - {"wait", no_argument, 0, 'w'}, - {0, 0, 0, 0} + {"description", "", 0, 0, GET_NO_ARG, NO_ARG, 'd', 0, 0, 0, 0, 0, 0, 0}, + {"data-file-length", "", 0, 0, GET_LL, REQUIRED_ARG, 'D', 0, 0, 0, 0, 0, 0, 0}, + {"extend-check", "", 0, 0, GET_NO_ARG, NO_ARG, 'e', 0, 0, 0, 0, 0, 0, 0}, + {"fast", "", 0, 0, GET_NO_ARG, NO_ARG, 'F', 0, 0, 0, 0, 0, 0, 0}, + {"force", "", 0, 0, GET_NO_ARG, NO_ARG, 'f', 0, 0, 0, 0, 0, 0, 0}, + {"help", "", 0, 0, GET_NO_ARG, NO_ARG, '?', 0, 0, 0, 0, 0, 0, 0}, + {"information", "", 0, 0, GET_NO_ARG, NO_ARG, 'i', 0, 0, 0, 0, 0, 0, 0}, + {"keys-used", "", 0, 0, GET_LL, REQUIRED_ARG, 'k', 0, 0, 0, 0, 0, 0, 0}, + {"medium-check", "", 0, 0, GET_NO_ARG, NO_ARG, 'm', 0, 0, 0, 0, 0, 0, 0}, + {"quick", "", 0, 0, GET_NO_ARG, NO_ARG, 'q', 0, 0, 0, 0, 0, 0, 0}, + {"read-only", "", 0, 0, GET_NO_ARG, NO_ARG, 'T', 0, 0, 0, 0, 0, 0, 0}, + {"recover", "", 0, 0, GET_NO_ARG, NO_ARG, 'r', 0, 0, 0, 0, 0, 0, 0}, + {"safe-recover", "", 0, 0, GET_NO_ARG, NO_ARG, 'o', 0, 0, 0, 0, 0, 0, 0}, + {"start-check-pos", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_START_CHECK_POS, 0, 0, 0, 0, 0, 0, 0}, + {"set-auto-increment", "", 0, 0, GET_LL, OPT_ARG, 'A', 0, 0, 0, 0, 0, 0, 0}, + {"set-character-set", "", 0, 0, GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 0, 0, 0, 0, 0, 0, 0}, + {"set-variable", "", 0, 0, GET_STR, REQUIRED_ARG, 'O', 0, 0, 0, 0, 0, 0, 0}, + {"silent", "", 0, 0, GET_NO_ARG, NO_ARG, 's', 0, 0, 0, 0, 0, 0, 0}, + {"sort-index", "", 0, 0, GET_NO_ARG, NO_ARG, 'S', 0, 0, 0, 0, 0, 0, 0}, + {"sort-records", "", 0, 0, GET_INT, REQUIRED_ARG, 'R', 0, 0, 0, 0, 0, 0, 0}, + {"sort-recover", "", 0, 0, GET_NO_ARG, NO_ARG, 'n', 0, 0, 0, 0, 0, 0, 0}, + {"tmpdir", "", 0, 0, GET_STR, REQUIRED_ARG, 't', 0, 0, 0, 0, 0, 0, 0}, + {"update-state", "", 0, 0, GET_NO_ARG, NO_ARG, 'U', 0, 0, 0, 0, 0, 0, 0}, + {"unpack", "", 0, 0, GET_NO_ARG, NO_ARG, 'u', 0, 0, 0, 0, 0, 0, 0}, + {"verbose", "", 0, 0, GET_NO_ARG, NO_ARG, 'v', 0, 0, 0, 0, 0, 0, 0}, + {"version", "", 0, 0, GET_NO_ARG, NO_ARG, 'V', 0, 0, 0, 0, 0, 0, 0}, + {"wait", "", 0, 0, GET_NO_ARG, NO_ARG, 'w', 0, 0, 0, 0, 0, 0, 0}, + /* variables begin here */ + { "key_buffer_size", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_KEY_BUFFER_SIZE, 0, 0, 0, 0, 0, 0, 1}, + { "myisam_block_size", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_MYISAM_BLOCK_SIZE, 0, 0, 0, 0, 0, 0, 1}, + { "read_buffer_size", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_READ_BUFFER_SIZE, 0, 0, 0, 0, 0, 0, 1}, + { "write_buffer_size", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_WRITE_BUFFER_SIZE, 0, 0, 0, 0, 0, 0, 1}, + { "sort_buffer_size", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_SORT_BUFFER_SIZE, 0, 0, 0, 0, 0, 0, 1}, + { "sort_key_blocks", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_SORT_KEY_BLOCKS, 0, 0, 0, 0, 0, 0, 1}, + { "decode_bits", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_DECODE_BITS, 0, 0, 0, 0, 0, 0, 1}, + { "ft_min_word_len", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 0, 0, 0, 0, 0, 0, 1}, + { "ft_max_word_len", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, 0, 0, 0, 0, 0, 0, 1}, + { "ft_max_word_len_for_sort", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN_FOR_SORT, 0, 0, 0, 0, 0, 0, 1}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; + static void print_version(void) { - printf("%s Ver 2.0 for %s at %s\n",my_progname,SYSTEM_TYPE, + printf("%s Ver 2.1 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); } + static void usage(void) { uint i; @@ -315,163 +332,182 @@ static void usage(void) /* Read options */ +static my_bool get_one_option(int optid, const struct my_option *opt, + char *argument) +{ + uint old_testflag; + char buff[255], *end; + + switch(optid) { + case 'a': + check_param.testflag|= T_STATISTICS; + break; + case 'A': + if (argument) + check_param.auto_increment_value=strtoull(argument, NULL, 0); + else + check_param.auto_increment_value=0; /* Set to max used value */ + check_param.testflag|= T_AUTO_INC; + break; + case 'b': + check_param.search_after_block=strtoul(argument, NULL, 10); + break; + case 'B': + check_param.testflag|= T_BACKUP_DATA; + break; + case 'c': + check_param.testflag|= T_CHECK; + break; + case 'C': + check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED; + break; + case 'D': + check_param.max_data_file_length=strtoll(argument, NULL, 10); + break; + case 's': /* silent */ + if (check_param.testflag & T_SILENT) + check_param.testflag|=T_VERY_SILENT; + check_param.testflag|= T_SILENT; + check_param.testflag&= ~T_WRITE_LOOP; + break; + case 'w': + check_param.testflag|= T_WAIT_FOREVER; + break; + case 'd': /* description if isam-file */ + check_param.testflag|= T_DESCRIPT; + break; + case 'e': /* extend check */ + check_param.testflag|= T_EXTEND; + break; + case 'i': + check_param.testflag|= T_INFO; + break; + case 'f': + check_param.tmpfile_createflag= O_RDWR | O_TRUNC; + check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE; + break; + case 'F': + check_param.testflag|=T_FAST; + break; + case 'k': + check_param.keys_in_use= (ulonglong) strtoll(argument, NULL, 10); + break; + case 'm': + check_param.testflag|= T_MEDIUM; /* Medium check */ + break; + case 'r': /* Repair table */ + check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT; + break; + case 'o': + check_param.testflag= (check_param.testflag & ~T_REP_BY_SORT) | T_REP; + check_param.force_sort=0; + my_disable_async_io=1; /* More safety */ + break; + case 'n': + check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT; + check_param.force_sort=1; + break; + case 'q': + check_param.opt_rep_quick++; + break; + case 'u': + check_param.testflag|= T_UNPACK | T_REP_BY_SORT; + break; + case 'v': /* Verbose */ + check_param.testflag|= T_VERBOSE; + check_param.verbose++; + break; + case 'O': + /* this is a temporary fix for variables to work until my_getopt */ + /* can my_set_changeable_vars */ + case OPT_KEY_BUFFER_SIZE: + case OPT_MYISAM_BLOCK_SIZE: + case OPT_READ_BUFFER_SIZE: + case OPT_WRITE_BUFFER_SIZE: + case OPT_SORT_BUFFER_SIZE: + case OPT_SORT_KEY_BLOCKS: + case OPT_DECODE_BITS: + case OPT_FT_MIN_WORD_LEN: + case OPT_FT_MAX_WORD_LEN: + case OPT_FT_MAX_WORD_LEN_FOR_SORT: + end= buff; + end= strmov(strmov(strmov(end, opt->name), "="), argument); + if (set_changeable_var(buff, changeable_vars)) + { + usage(); + exit(1); + } + break; + case 'R': /* Sort records */ + old_testflag=check_param.testflag; + check_param.testflag|= T_SORT_RECORDS; + check_param.opt_sort_key=(uint) atoi(argument) - 1; + if (check_param.opt_sort_key >= MI_MAX_KEY) + { + fprintf(stderr, + "The value of the sort key is bigger than max key: %d.\n", + MI_MAX_KEY); + exit(1); + } + break; + case 'S': /* Sort index */ + old_testflag=check_param.testflag; + check_param.testflag|= T_SORT_INDEX; + break; + case 't': + check_param.tmpdir=argument; + break; + case 'T': + check_param.testflag|= T_READONLY; + break; + case 'U': + check_param.testflag|= T_UPDATE_STATE; + break; + case '#': + DBUG_PUSH(argument ? argument : "d:t:o,/tmp/myisamchk.trace"); + break; + case 'V': + print_version(); + exit(0); + case OPT_CORRECT_CHECKSUM: + check_param.testflag|=T_CALC_CHECKSUM; + break; + case OPT_CHARSETS_DIR: + charsets_dir= argument; + break; + case OPT_SET_CHARSET: + set_charset_name= argument; + break; +#ifdef DEBUG /* Only useful if debugging */ + case OPT_START_CHECK_POS: + check_param.start_check_pos=strtoull(argument, NULL, 0); + break; +#endif + case '?': + usage(); + exit(0); + } +} + + static void get_options(register int *argc,register char ***argv) { int c,option_index=0; - uint old_testflag; load_defaults("my",load_default_groups,argc,argv); default_argv= *argv; set_all_changeable_vars(changeable_vars); if (isatty(fileno(stdout))) check_param.testflag|=T_WRITE_LOOP; - while ((c=getopt_long(*argc,*argv, - "aBcCdeifF?lqrmnosSTuUvVw#:b:D:k:O:R:A::t:", - long_options, &option_index)) != EOF) - { - switch(c) { - case 'a': - check_param.testflag|= T_STATISTICS; - break; - case 'A': - if (optarg) - check_param.auto_increment_value=strtoull(optarg,NULL,0); - else - check_param.auto_increment_value=0; /* Set to max used value */ - check_param.testflag|= T_AUTO_INC; - break; - case 'b': - check_param.search_after_block=strtoul(optarg,NULL,10); - break; - case 'B': - check_param.testflag|= T_BACKUP_DATA; - break; - case 'c': - check_param.testflag|= T_CHECK; - break; - case 'C': - check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED; - break; - case 'D': - check_param.max_data_file_length=strtoll(optarg,NULL,10); - break; - case 's': /* silent */ - if (check_param.testflag & T_SILENT) - check_param.testflag|=T_VERY_SILENT; - check_param.testflag|= T_SILENT; - check_param.testflag&= ~T_WRITE_LOOP; - break; - case 'w': - check_param.testflag|= T_WAIT_FOREVER; - break; - case 'd': /* description if isam-file */ - check_param.testflag|= T_DESCRIPT; - break; - case 'e': /* extend check */ - check_param.testflag|= T_EXTEND; - break; - case 'i': - check_param.testflag|= T_INFO; - break; - case 'f': - check_param.tmpfile_createflag= O_RDWR | O_TRUNC; - check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE; - break; - case 'F': - check_param.testflag|=T_FAST; - break; - case 'k': - check_param.keys_in_use= (ulonglong) strtoll(optarg,NULL,10); - break; - case 'm': - check_param.testflag|= T_MEDIUM; /* Medium check */ - break; - case 'r': /* Repair table */ - check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT; - break; - case 'o': - check_param.testflag= (check_param.testflag & ~T_REP_BY_SORT) | T_REP; - check_param.force_sort=0; - my_disable_async_io=1; /* More safety */ - break; - case 'n': - check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT; - check_param.force_sort=1; - break; - case 'q': - check_param.opt_rep_quick++; - break; - case 'u': - check_param.testflag|= T_UNPACK | T_REP_BY_SORT; - break; - case 'v': /* Verbose */ - check_param.testflag|= T_VERBOSE; - check_param.verbose++; - break; - case 'O': - if (set_changeable_var(optarg, changeable_vars)) - { - usage(); - exit(1); - } - break; - case 'R': /* Sort records */ - old_testflag=check_param.testflag; - check_param.testflag|= T_SORT_RECORDS; - check_param.opt_sort_key=(uint) atoi(optarg)-1; - if (check_param.opt_sort_key >= MI_MAX_KEY) - { - fprintf(stderr, - "The value of the sort key is bigger than max key: %d.\n", - MI_MAX_KEY); - exit(1); - } - break; - case 'S': /* Sort index */ - old_testflag=check_param.testflag; - check_param.testflag|= T_SORT_INDEX; - break; - case 't': - check_param.tmpdir=optarg; - break; - case 'T': - check_param.testflag|= T_READONLY; - break; - case 'U': - check_param.testflag|= T_UPDATE_STATE; - break; - case '#': - DBUG_PUSH(optarg ? optarg : "d:t:o,/tmp/myisamchk.trace"); - break; - case 'V': - print_version(); - exit(0); - case OPT_CORRECT_CHECKSUM: - check_param.testflag|=T_CALC_CHECKSUM; - break; - case OPT_CHARSETS_DIR: - charsets_dir = optarg; - break; - case OPT_SET_CHARSET: - set_charset_name=optarg; - break; -#ifdef DEBUG /* Only useful if debugging */ - case OPT_START_CHECK_POS: - check_param.start_check_pos=strtoull(optarg,NULL,0); - break; -#endif - case '?': - usage(); - exit(0); - } - } + + if (handle_options(argc, argv, my_long_options, get_one_option)) + exit(1); + /* If using repair, then update checksum if one uses --update-state */ if ((check_param.testflag & T_UPDATE_STATE) && (check_param.testflag & (T_REP | T_REP_BY_SORT))) check_param.testflag|= T_CALC_CHECKSUM; - (*argc)-=optind; - (*argv)+=optind; if (*argc == 0) { usage(); diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 97f065bc7e2..287dc357b3d 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -44,7 +44,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ my_delete.c my_rename.c my_redel.c my_tempnam.c \ my_chsize.c my_lread.c my_lwrite.c my_clock.c \ my_quick.c my_lockmem.c my_static.c \ - getopt.c getopt1.c getvar.c my_mkdir.c \ + getopt.c getopt1.c my_getopt.c getvar.c my_mkdir.c \ default.c my_compress.c checksum.c raid.cc my_net.c \ my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ diff --git a/mysys/getvar.c b/mysys/getvar.c index 49b321f592e..1a2adc10e62 100644 --- a/mysys/getvar.c +++ b/mysys/getvar.c @@ -19,7 +19,7 @@ #include "mysys_priv.h" #include <m_string.h> #include <m_ctype.h> - +#include <my_getopt.h> /* set all changeable variables */ void set_all_changeable_vars(CHANGEABLE_VAR *vars) @@ -109,3 +109,78 @@ my_bool set_changeable_var(my_string str,CHANGEABLE_VAR *vars) } DBUG_RETURN(1); } + +my_bool my_set_changeable_var(my_string str, const struct my_option *vars) +{ + char endchar; + my_string end; + DBUG_ENTER("my_set_changeable_var"); + DBUG_PRINT("enter",("%s",str)); + + if (str) + { + if (!(end=strchr(str,'='))) + fprintf(stderr,"Can't find '=' in expression '%s' to option -O\n",str); + else + { + uint length,found_count=0; + const struct my_option *var, *found; + my_string var_end; + const char *name; + longlong num; + + /* Skip end space from variable */ + for (var_end=end ; end > str && isspace(var_end[-1]) ; var_end--) ; + length=(uint) (var_end-str); + /* Skip start space from argument */ + for (end++ ; isspace(*end) ; end++) ; + + for (var= vars, found= 0; (name= var->name); var++) + { + if (var->changeable_var) + { + if (!my_casecmp(name, str, length)) + { + found= var; found_count++; + if (!name[length]) + { + found_count=1; + break; + } + } + } + } + if (found_count == 0) + { + fprintf(stderr,"No variable match for: -O '%s'\n",str); + DBUG_RETURN(1); + } + if (found_count > 1) + { + fprintf(stderr,"Variable prefix '%*s' is not unique\n",length,str); + DBUG_RETURN(1); + } + + num=strtoll(end, (char **)NULL, 10); endchar=strend(end)[-1]; + if (endchar == 'k' || endchar == 'K') + num*=1024; + else if (endchar == 'm' || endchar == 'M') + num*=1024L*1024L; + else if (endchar == 'g' || endchar == 'G') + num*=1024L*1024L*1024L; + else if (!isdigit(endchar)) + { + fprintf(stderr,"Unknown prefix used for variable value '%s'\n",str); + DBUG_RETURN(1); + } + if (num < (longlong) found->min_value) + num=(longlong) found->min_value; + else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) found->max_value) + num=(longlong) (ulong) found->max_value; + num=((num- (longlong) found->sub_size) / (ulonglong) found->block_size); + /* (*found->varptr)= (long) (num*(ulonglong) found->block_size);*/ + DBUG_RETURN(0); + } + } + DBUG_RETURN(1); +} diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c new file mode 100644 index 00000000000..afe3da214bf --- /dev/null +++ b/mysys/my_getopt.c @@ -0,0 +1,313 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <my_config.h> +#include <my_global.h> +#include <m_string.h> +#include <stdlib.h> +#include <my_getopt.h> +#include <assert.h> + +static int sortopt (int *argc, char ***argv); +static int findopt (char *optpat, uint length, + const struct my_option **opt_res, + char **ffname); + +#define DISABLE_OPTION_COUNT 2 + +static char *special_opt_prefix[] = {"skip", "disable", "enable", 0}; + + +/* function: handle_options + Sort options; put options first, until special end of options (--), or + until end of argv. Parse options; check that the given option matches with + one of the options in struct 'my_option', return error in case of ambiguous + or unknown option. Check that option was given an argument if it requires + one. Call function 'get_one_option()' once for each option. +*/ +extern int handle_options (int *argc, char ***argv, + const struct my_option *longopts, + my_bool (*get_one_option)(int, + const struct my_option *, + char *)) +{ + uint opt_found, argvpos = 0, length, spec_len, i; + my_bool end_of_options = 0, must_be_var = 0; + char *progname = *(*argv), **pos, *optend, *prev_found; + const struct my_option *optp; + + (*argc)--; + (*argv)++; + for (pos = *argv; *pos; pos++) + { + char *cur_arg= *pos; + if (*cur_arg == '-' && *(cur_arg + 1) && !end_of_options) // must be opt. + { + char *argument = 0; + must_be_var= 0; + + // check for long option, or --set-variable (-O) + if (*(cur_arg + 1) == '-' || *(cur_arg + 1) == 'O') + { + if (*(cur_arg + 1) == 'O' || !strncmp(cur_arg, "--set-variable", 14)) + { + must_be_var= 1; + + if (*(cur_arg + 1) == 'O') + { + cur_arg+= 2; + if (!(*cur_arg)) + { + // the argument must be in next argv + if (!(*(pos + 1))) + { + fprintf(stderr, "%s: Option '-O' requires an argument\n", + progname); + return 4; + } + pos++; + cur_arg= *pos; + (*argc)--; + } + } + else // Option argument begins with string '--set-variable' + { + cur_arg+= 14; + if (*cur_arg == '=') + { + cur_arg++; + if (!(*cur_arg)) + { + fprintf(stderr, + "%s: Option '--set-variable' requires an argument\n", + progname); + return 4; + } + } + else if (*cur_arg) // garbage, or another option. break out + { + cur_arg-= 14; + must_be_var= 0; + } + else + { + // the argument must be in next argv + if (!(*(pos + 1))) + { + fprintf(stderr, + "%s: Option '--set-variable' requires an argument\n", + progname); + return 4; + } + pos++; + cur_arg= *pos; + (*argc)--; + } + } + } + else if (!must_be_var) + { + if (!*(cur_arg + 2)) // '--' means end of options, look no further + { + end_of_options = 1; + (*argc)--; + continue; + } + cur_arg+= 2; // skip the double dash + } + for (optend = cur_arg; *optend && *optend != '='; optend++) ; + length = optend - cur_arg; + /* + Find first the right option. Return error in case of an ambiguous, + or unknown option + */ + optp = longopts; + if (!(opt_found = findopt(cur_arg, length, &optp, &prev_found))) + { + /* + Didn't find any matching option. Let's see if someone called + option with a special option prefix + */ + if (*optend != '=' && !must_be_var) + { + for (i = 0; special_opt_prefix[i]; i++) + { + spec_len = strlen(special_opt_prefix[i]); + if (!strncmp(special_opt_prefix[i], cur_arg, spec_len) && + cur_arg[spec_len] == '-') + { + // We were called with a special prefix, we can reuse opt_found + cur_arg += (spec_len + 1); + if ((opt_found = findopt(cur_arg, length - (spec_len + 1), + &optp, &prev_found))) + { + if (opt_found > 1) + { + fprintf(stderr, + "%s: ambiguous option '--%s-%s' (--%s-%s)\n", + progname, special_opt_prefix[i], cur_arg, + special_opt_prefix[i], prev_found); + return 2; + } + if (i < DISABLE_OPTION_COUNT) + optend= "=0"; + else // enable + optend= "=1"; + break; // note break from the inner loop, main loop continues + } + } + } + } + if (!opt_found) + { + if (must_be_var) + { + fprintf(stderr, + "%s: unknown variable '%s'\n", progname, cur_arg); + return 7; + } + else + { + fprintf(stderr, + "%s: unknown option '--%s'\n", progname, cur_arg); + return 1; + } + } + } + if (opt_found > 1) + { + if (must_be_var) + { + fprintf(stderr, "%s: variable prefix '%s' is not unique\n", + progname, cur_arg); + return 6; + } + else + { + fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n", + progname, cur_arg, prev_found, optp->name); + return 2; + } + } + if (must_be_var && !optp->changeable_var) + { + fprintf(stderr, "%s: the argument to -O must be a variable\n", + progname); + return 8; + } + if (optp->arg_type == NO_ARG && *optend == '=') + { + fprintf(stderr, "%s: option '--%s' cannot take an argument\n", + progname, optp->name); + return 3; + } + else if (optp->arg_type == REQUIRED_ARG && !*optend) + { + /* Check if there are more arguments after this one */ + if (!(*(pos + 1))) + { + fprintf(stderr, "%s: option '--%s' requires an argument\n", + progname, optp->name); + return 4; + } + pos++; + argument = *pos; + (*argc)--; + } + else if (*optend == '=') + argument = *(optend + 1) ? optend + 1 : ""; + } + else // must be short option + { + my_bool skip; + for (skip = 0, optend = (cur_arg + 1); *optend && !skip; optend++) + { + for (optp = longopts; optp->id ; optp++) + { + if (optp->id == (int) (uchar) *optend) + { + /* Option recognized. Find next what to do with it */ + if (optp->arg_type == REQUIRED_ARG || optp->arg_type == OPT_ARG) + { + if (*(optend + 1)) + { + argument = (optend + 1); + /* + The rest of the option is option argument + This is in effect a jump out of this loop + */ + skip = 1; + } + else if (optp->arg_type == REQUIRED_ARG) + { + /* Check if there are more arguments after this one */ + if (!(*(pos + 1))) + { + fprintf(stderr, "%s: option '-%c' requires an argument\n", + progname, optp->id); + return 4; + } + pos++; + argument = *pos; + (*argc)--; + } + } + else if (*(optend + 1)) // we are hitting many options in 1 argv + get_one_option(optp->id, optp, 0); + break; + } + } + } + } + get_one_option(optp->id, optp, argument); + (*argc)--; // option handled (short or long), decrease argument count + } + else // non-option found + (*argv)[argvpos++] = cur_arg; + } + return 0; +} + +/* function: findopt + Arguments: opt_pattern, length of opt_pattern, opt_struct, first found + name (ffname) + + Go through all options in the my_option struct. Return number + of options found that match the pattern and in the argument + list the option found, if any. In case of ambiguous option, store + the name in ffname argument +*/ +static int findopt (char *optpat, uint length, + const struct my_option **opt_res, + char **ffname) +{ + int count; + struct my_option *opt= (struct my_option *) *opt_res; + + for (count = 0; opt->id; opt++) + { + if (!strncmp(opt->name, optpat, length)) // match found + { + (*opt_res) = opt; + if (!count) + *ffname = (char *) opt->name; // we only need to know one prev + if (length == strlen(opt->name)) // exact match + return 1; + count++; + } + } + return count; +} |