summaryrefslogtreecommitdiff
path: root/mysys
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
commit845db7c20ba28e014c5a36a6c95afd8ed111f316 (patch)
treeebdc1f846c1fa8a627690099d9a418063625577e /mysys
parentaa166cbd983d28e31e23c096ca360a641de98c00 (diff)
downloadmariadb-git-845db7c20ba28e014c5a36a6c95afd8ed111f316.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
Diffstat (limited to 'mysys')
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/getvar.c77
-rw-r--r--mysys/my_getopt.c313
3 files changed, 390 insertions, 2 deletions
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;
+}