summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <jani@rhols221.adsl.netsonic.fi>2002-01-25 23:34:37 +0200
committerunknown <jani@rhols221.adsl.netsonic.fi>2002-01-25 23:34:37 +0200
commit06b282aac05ccc2dc60769a8c989e6bfc4fa59fb (patch)
treeebdc1f846c1fa8a627690099d9a418063625577e
parentf817081b6cb42265e14c3a3e42b6d9152b7f5878 (diff)
downloadmariadb-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_ok1
-rw-r--r--include/Makefile.am2
-rw-r--r--include/my_getopt.h46
-rw-r--r--myisam/myisamchk.c404
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/getvar.c77
-rw-r--r--mysys/my_getopt.c313
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;
+}