Commit 784e1d8b authored by jani@hynda.mysql.fi's avatar jani@hynda.mysql.fi
Browse files

New functionality to my_getopt. myisamchk now uses my_getopt

only.
parent 2c24b6fb
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -23,14 +23,15 @@ struct my_optarg
};


enum get_opt_var_type { GET_NO_ARG, GET_INT, GET_LL, GET_STR };
enum get_opt_var_type { GET_NO_ARG, GET_LONG, 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 */
  gptr       *value;                    /* The variable value */
  gptr       *u_max_value;              /* The user def. max variable value */
  const char **str_values;              /* Pointer to possible values */
  enum get_opt_var_type var_type;
  enum get_opt_arg_type arg_type;
@@ -41,6 +42,6 @@ struct my_option
  longlong   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 */
  my_bool    opt_is_var;                /* If true, the option is a variable */
};
+56 −99
Original line number Diff line number Diff line
@@ -142,31 +142,6 @@ int main(int argc, char **argv)
#endif
} /* main */


static CHANGEABLE_VAR changeable_vars[] = {
  { "key_buffer_size",(long*) &check_param.use_buffers,(long) USE_BUFFER_INIT,
    (long) MALLOC_OVERHEAD, (long) ~0L,(long) MALLOC_OVERHEAD,(long) IO_SIZE },
  { "myisam_block_size", (long*) &opt_myisam_block_size,
      MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH,
    0, MI_MIN_KEY_BLOCK_LENGTH },
  { "read_buffer_size", (long*) &check_param.read_buffer_length,(long) READ_BUFFER_INIT,
      (long) MALLOC_OVERHEAD,(long) ~0L,(long) MALLOC_OVERHEAD,(long) 1L },
  { "write_buffer_size", (long*) &check_param.write_buffer_length,(long) READ_BUFFER_INIT,
      (long) MALLOC_OVERHEAD,(long) ~0L,(long) MALLOC_OVERHEAD,(long) 1L },
  { "sort_buffer_size",(long*) &check_param.sort_buffer_length,(long) SORT_BUFFER_INIT,
      (long) (MIN_SORT_BUFFER+MALLOC_OVERHEAD),(long) ~0L,
      (long) MALLOC_OVERHEAD,(long) 1L },
  { "sort_key_blocks",(long*) &check_param.sort_key_blocks,BUFFERS_WHEN_SORTING,4L,100L,0L,
    1L },
  { "decode_bits",(long*) &decode_bits,9L,4L,17L,0L,1L },
  { "ft_min_word_len",         (long*) &ft_min_word_len,
      4, 1, HA_FT_MAXLEN, 0, 1 },
  { "ft_max_word_len",         (long*) &ft_max_word_len,
      HA_FT_MAXLEN, 10, HA_FT_MAXLEN, 0, 1 },
  { "ft_max_word_len_for_sort",(long*) &ft_max_word_len_for_sort,
      20, 4, HA_FT_MAXLEN, 0, 1 },
  { NullS,(long*) 0,0L,0L,0L,0L,0L,} };

enum options {
  OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS,
  OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE,
@@ -177,63 +152,63 @@ enum options {

static struct my_option my_long_options[] =
{
  {"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},
  {"analyze", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0, 0, 0, 0, 0, 0},
  {"block-search", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'b', 0, 0, 0, 0, 0, 0, 0},
  {"backup", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'B', 0, 0, 0, 0, 0, 0, 0},
  {"character-sets-dir", "", 0, 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},
  {"check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0, 0, 0, 0, 0, 0},
  {"check-only-changed", "", 0, 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},
  {"correct-checksum", "", 0, 0, 0, GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 0, 0, 0, 0, 0, 0, 0},
#ifndef DBUG_OFF
  {"debug", "", 0, 0, GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0, 0},
  {"debug", "", 0, 0, 0, GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0, 0},
#endif
  {"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},
  {"description", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'd', 0, 0, 0, 0, 0, 0, 0},
  {"data-file-length", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'D', 0, 0, 0, 0, 0, 0, 0},
  {"extend-check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'e', 0, 0, 0, 0, 0, 0, 0},
  {"fast", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'F', 0, 0, 0, 0, 0, 0, 0},
  {"force", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'f', 0, 0, 0, 0, 0, 0, 0},
  {"help", "", 0, 0, 0, GET_NO_ARG, NO_ARG, '?', 0, 0, 0, 0, 0, 0, 0},
  {"information", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'i', 0, 0, 0, 0, 0, 0, 0},
  {"keys-used", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'k', 0, 0, 0, 0, 0, 0, 0},
  {"medium-check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'm', 0, 0, 0, 0, 0, 0, 0},
  {"quick", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'q', 0, 0, 0, 0, 0, 0, 0},
  {"read-only", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'T', 0, 0, 0, 0, 0, 0, 0},
  {"recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'r', 0, 0, 0, 0, 0, 0, 0},
  {"safe-recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'o', 0, 0, 0, 0, 0, 0, 0},
  {"start-check-pos", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, OPT_START_CHECK_POS, 0, 0, 0, 0, 0, 0, 0},
  {"set-auto-increment", "", 0, 0, 0, GET_LONG, OPT_ARG, 'A', 0, 0, 0, 0, 0, 0, 0},
  {"set-character-set", "", 0, 0, 0, GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 0, 0, 0, 0, 0, 0, 0},
  {"set-variable", "", 0, 0, 0, GET_STR, REQUIRED_ARG, 'O', 0, 0, 0, 0, 0, 0, 0},
  {"silent", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 's', 0, 0, 0, 0, 0, 0, 0},
  {"sort-index", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'S', 0, 0, 0, 0, 0, 0, 0},
  {"sort-records", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'R', 0, 0, 0, 0, 0, 0, 0},
  {"sort-recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'n', 0, 0, 0, 0, 0, 0, 0},
  {"tmpdir", "", 0, 0, 0, GET_STR, REQUIRED_ARG, 't', 0, 0, 0, 0, 0, 0, 0},
  {"update-state", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'U', 0, 0, 0, 0, 0, 0, 0},
  {"unpack", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'u', 0, 0, 0, 0, 0, 0, 0},
  {"verbose", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'v', 0, 0, 0, 0, 0, 0, 0},
  {"version", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'V', 0, 0, 0, 0, 0, 0, 0},
  {"wait", "", 0, 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},
  { "key_buffer_size", "", (gptr*) &check_param.use_buffers, (gptr*) &check_param.use_buffers, 0, GET_LONG, REQUIRED_ARG, OPT_KEY_BUFFER_SIZE, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0, 1}, 
  { "myisam_block_size", "", (gptr*) &opt_myisam_block_size, (gptr*) &opt_myisam_block_size, 0, GET_LONG, REQUIRED_ARG, OPT_MYISAM_BLOCK_SIZE, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0, 1}, 
  { "read_buffer_size", "", (gptr*) &check_param.read_buffer_length, (gptr*) &check_param.read_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_READ_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1}, 
  { "write_buffer_size", "", (gptr*) &check_param.write_buffer_length, (gptr*) &check_param.write_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_WRITE_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1}, 
  { "sort_buffer_size", "", (gptr*) &check_param.sort_buffer_length, (gptr*) &check_param.sort_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_SORT_BUFFER_SIZE, (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1}, 
  { "sort_key_blocks", "", (gptr*) &check_param.sort_key_blocks, (gptr*) &check_param.sort_key_blocks, 0, GET_LONG, REQUIRED_ARG, OPT_SORT_KEY_BLOCKS, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0, 1},
  { "decode_bits", "", (gptr*) &decode_bits, (gptr*) &decode_bits, 0, GET_LONG, REQUIRED_ARG, OPT_DECODE_BITS, 9L, 4L, 17L, 0L, 1L, 0, 1},
  { "ft_min_word_len", "", (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 4, 1, HA_FT_MAXLEN, 0, 1, 0, 1},
  { "ft_max_word_len", "", (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, HA_FT_MAXLEN, 10, HA_FT_MAXLEN, 0, 1, 0, 1},
  { "ft_max_word_len_for_sort", "", (gptr*) &ft_max_word_len_for_sort, (gptr*) &ft_max_word_len_for_sort, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN_FOR_SORT, 20, 4, HA_FT_MAXLEN, 0, 1, 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.1 for %s at %s\n", my_progname, SYSTEM_TYPE,
  printf("%s  Ver 2.2 for %s at %s\n", my_progname, SYSTEM_TYPE,
	 MACHINE_TYPE);
}

@@ -323,10 +298,14 @@ static void usage(void)

  print_defaults("my",load_default_groups);
  printf("\nPossible variables for option --set-variable (-O) are:\n");
  for (i=0; changeable_vars[i].name ; i++)
    printf("%-20s  current value: %lu\n",
	   changeable_vars[i].name,
	   *changeable_vars[i].varptr);
  for (i=0; my_long_options[i].name ; i++)
  {
    if (!my_long_options[i].opt_is_var)
      continue;
    printf("%-20s  current value: %lu\n", my_long_options[i].name, 
	   *my_long_options[i].value);
  }

}


@@ -417,27 +396,6 @@ static my_bool get_one_option(int optid, const struct my_option *opt,
    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;
@@ -496,7 +454,6 @@ static void get_options(register int *argc,register char ***argv)

  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;

+0 −75
Original line number Diff line number Diff line
@@ -109,78 +109,3 @@ 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);
}
+186 −62
Original line number Diff line number Diff line
@@ -21,17 +21,31 @@
#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);
static my_bool compare_strings (register const char *s, register const char *t,
				uint length);
static longlong getopt_ll (char *arg, const struct my_option *optp, int *err);
static void init_variables(const struct my_option *options);

#define DISABLE_OPTION_COUNT      2

static char *special_opt_prefix[] = {"skip", "disable", "enable", 0};
#define ERR_UNKNOWN_OPTION        1
#define ERR_AMBIGUOUS_OPTION      2
#define ERR_NO_ARGUMENT_ALLOWED   3
#define ERR_ARGUMENT_REQUIRED     4
#define ERR_VAR_PREFIX_NOT_UNIQUE 5
#define ERR_UNKNOWN_VARIABLE      6
#define ERR_MUST_BE_VARIABLE      7
#define ERR_UNKNOWN_SUFFIX        8

static char *special_opt_prefix[]= {"skip", "disable", "enable", "maximum", 0};


/* 
  function: handle_options

/* 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
@@ -45,12 +59,14 @@ extern int handle_options (int *argc, char ***argv,
						     char *))
{
  uint opt_found, argvpos= 0, length, spec_len, i;
  my_bool end_of_options = 0, must_be_var = 0;
  int err;
  my_bool end_of_options= 0, must_be_var, set_maximum_value;
  char *progname= *(*argv), **pos, *optend, *prev_found;
  const struct my_option *optp;

  (*argc)--; 
  (*argv)++; 
  (*argc)--; /* Skip the program name */
  (*argv)++; /*      --- || ----      */
  init_variables(longopts);
  for (pos= *argv; *pos; pos++)
  {
    char *cur_arg= *pos;
@@ -58,11 +74,13 @@ extern int handle_options (int *argc, char ***argv,
    {
      char *argument= 0;
      must_be_var= 0;
      set_maximum_value= 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))
	if (*(cur_arg + 1) == 'O' || 
	    !compare_strings(cur_arg, "--set-variable", 14))
	{
	  must_be_var= 1;

@@ -76,7 +94,7 @@ extern int handle_options (int *argc, char ***argv,
	      {
		fprintf(stderr, "%s: Option '-O' requires an argument\n",
			progname);
		return 4;
		return ERR_ARGUMENT_REQUIRED;
	      }
	      pos++;
	      cur_arg= *pos;
@@ -94,7 +112,7 @@ extern int handle_options (int *argc, char ***argv,
		fprintf(stderr,
			"%s: Option '--set-variable' requires an argument\n",
			progname);
		return 4;
		return ERR_ARGUMENT_REQUIRED;
	      }
	    }
	    else if (*cur_arg) // garbage, or another option. break out
@@ -110,7 +128,7 @@ extern int handle_options (int *argc, char ***argv,
		fprintf(stderr,
			"%s: Option '--set-variable' requires an argument\n",
			progname);
		return 4;
		return ERR_ARGUMENT_REQUIRED;
	      }
	      pos++;
	      cur_arg= *pos;
@@ -141,12 +159,14 @@ extern int handle_options (int *argc, char ***argv,
	    Didn't find any matching option. Let's see if someone called
	    option with a special option prefix
	  */
	  if (*optend != '=' && !must_be_var)
	  if (!must_be_var)
	  {
	    if (*optend == '=')
	      must_be_var= 1;
	    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) &&
	      if (!compare_strings(special_opt_prefix[i], cur_arg, spec_len) &&
		  cur_arg[spec_len] == '-')
	      {
		// We were called with a special prefix, we can reuse opt_found
@@ -160,12 +180,17 @@ extern int handle_options (int *argc, char ***argv,
			    "%s: ambiguous option '--%s-%s' (--%s-%s)\n",
			    progname, special_opt_prefix[i], cur_arg,
			    special_opt_prefix[i], prev_found);
		    return 2;
		    return ERR_AMBIGUOUS_OPTION;
		  }
		  if (i < DISABLE_OPTION_COUNT)
		    optend= "=0";
		  else                       // enable
		  else if (!compare_strings(special_opt_prefix[i],"enable",6))
		    optend= "=1";
		  else if (!compare_strings(special_opt_prefix[i],"maximum",7))
		  {
		    set_maximum_value= 1;
		    must_be_var= 1;
		  }
		  break; // note break from the inner loop, main loop continues
		}
	      }
@@ -177,13 +202,13 @@ extern int handle_options (int *argc, char ***argv,
	    {
	      fprintf(stderr,
		      "%s: unknown variable '%s'\n", progname, cur_arg);
	      return 7;
	      return ERR_UNKNOWN_VARIABLE;
	    }
	    else
	    {
	      fprintf(stderr,
		      "%s: unknown option '--%s'\n", progname, cur_arg);
	      return 1;
	      return ERR_UNKNOWN_OPTION;
	    }
	  }
	}
@@ -193,26 +218,26 @@ extern int handle_options (int *argc, char ***argv,
	  {
	    fprintf(stderr, "%s: variable prefix '%s' is not unique\n",
		    progname, cur_arg);
	    return 6;
	    return ERR_VAR_PREFIX_NOT_UNIQUE;
	  }
	  else
	  {
	    fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n",
		    progname, cur_arg, prev_found, optp->name);
	    return 2;
	    return ERR_AMBIGUOUS_OPTION;
	  }
	}
	if (must_be_var && !optp->changeable_var)
	if (must_be_var && !optp->opt_is_var)
	{
	  fprintf(stderr, "%s: the argument to -O must be a variable\n",
		  progname);
	  return 8;
	  return ERR_MUST_BE_VARIABLE;
	}
	if (optp->arg_type == NO_ARG && *optend == '=')
	{
	  fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
		  progname, optp->name);
	  return 3;
	  return ERR_NO_ARGUMENT_ALLOWED;
	}
	else if (optp->arg_type == REQUIRED_ARG && !*optend)
	{
@@ -221,7 +246,7 @@ extern int handle_options (int *argc, char ***argv,
	  {
	    fprintf(stderr, "%s: option '--%s' requires an argument\n",
		    progname, optp->name);
	    return 4;
	    return ERR_ARGUMENT_REQUIRED;
	  }
	  pos++;
	  argument= *pos;
@@ -258,7 +283,7 @@ extern int handle_options (int *argc, char ***argv,
		  {
		    fprintf(stderr, "%s: option '-%c' requires an argument\n",
			    progname, optp->id);
		    return 4;
		    return ERR_ARGUMENT_REQUIRED;
		  }
		  pos++;
		  argument= *pos;
@@ -272,7 +297,22 @@ extern int handle_options (int *argc, char ***argv,
	  }
	}
      }
      if (optp->opt_is_var)
      {
	gptr *result_pos= (set_maximum_value) ?
	  optp->u_max_value : optp->value;
	if (optp->var_type == GET_LONG)
	 *((long*) result_pos)= (long) getopt_ll(argument, optp, &err);
	else if (optp->var_type == GET_LL)
	  *((longlong*) result_pos)=   getopt_ll(argument, optp, &err);
	else if (optp->var_type == GET_STR)
	  *((char**) result_pos)= argument;
	if (err)
	  return ERR_UNKNOWN_SUFFIX;
      }
      else
	get_one_option(optp->id, optp, argument);

      (*argc)--; // option handled (shortorlong), decrease argument count
    }
    else // non-option found
@@ -281,7 +321,10 @@ extern int handle_options (int *argc, char ***argv,
  return 0;
}

/* function: findopt

/* 
  function: findopt

  Arguments: opt_pattern, length of opt_pattern, opt_struct, first found
  name (ffname)

@@ -299,7 +342,7 @@ static int findopt (char *optpat, uint length,

  for (count= 0; opt->id; opt++)
  {
    if (!strncmp(opt->name, optpat, length)) // match found
    if (!compare_strings(opt->name, optpat, length)) // match found
    {
      (*opt_res)= opt;
      if (!count)
@@ -311,3 +354,84 @@ static int findopt (char *optpat, uint length,
  }
  return count;
}


/* 
  function: compare_strings

  Works like strncmp, other than 1.) considers '-' and '_' the same.
  2.) Returns -1 if strings differ, 0 if they are equal
*/
static my_bool compare_strings(register const char *s, register const char *t,
			       uint length)
{
  char const *end= s + length;
  for (;s != end ; s++, t++)
  {
    if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
      return 1;
  }
  return 0;
}


/* 
  function: getopt_ll

  Evaluates and returns the value that user gave as an argument
  to a variable. Recognizes (case insensitive) K as KILO, M as MEGA
  and G as GIGA bytes. Some values must be in certain blocks, as
  defined in the given my_option struct, this function will check
  that those values are honored.
  In case of an error, set error value in *err.
*/
static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
{
  char *endchar;
  longlong num;
  
  *err= 0;
  num= strtoll(arg, &endchar, 10);
  if (*endchar == 'k' || *endchar == 'K')
    num*= 1024L;
  else if (*endchar == 'm' || *endchar == 'M')
    num*= 1024L * 1024L;
  else if (*endchar == 'g' || *endchar == 'G')
    num*= 1024L * 1024L * 1024L;
  else if (*endchar)
  {
    fprintf(stderr,
	    "Unknown suffix '%c' used for variable '%s' (value '%s')\n",
	    *endchar, optp->name, arg);
    *err= 1;
  }
  if (num < (longlong) optp->min_value)
    num= (longlong) optp->min_value;
  else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value)
    num= (longlong) (ulong) optp->max_value;
  num= ((num - (longlong) optp->sub_size) / (ulonglong) optp->block_size);

  return (longlong) (num * (ulonglong) optp->block_size);
}


/* 
  function: init_variables

  initialize all variables to their default values
*/
static void init_variables(const struct my_option *options)
{
  for ( ; options->name ; options++)
  {
    if (options->opt_is_var)
    {
      if (options->var_type == GET_LONG)
	*((long*) options->u_max_value)= *((long*) options->value)=
	  options->def_value;
      else if (options->var_type == GET_LL)
	*((longlong*) options->u_max_value)= *((longlong*) options->value)=
	  options->def_value;
    }
  }
}