Drizzled Public API Documentation

option.cc
00001 /* Copyright (C) 2002-2006 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 #include <config.h>
00017 #include <drizzled/definitions.h>
00018 #include <drizzled/charset.h>
00019 #include <drizzled/internal/my_sys.h>
00020 #include <drizzled/gettext.h>
00021 
00022 #include <drizzled/internal/m_string.h>
00023 #include <drizzled/internal/my_sys.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/option.h>
00026 #include <drizzled/typelib.h>
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <errno.h>
00031 #include <iostream>
00032 #include <algorithm>
00033 
00034 using namespace std;
00035 
00036 namespace drizzled {
00037 
00038 static void default_reporter(enum loglevel level, const char *format, ...)
00039 {
00040   va_list args;
00041   va_start(args, format);
00042 
00043   if (level == WARNING_LEVEL)
00044     fprintf(stderr, "%s", _("Warning: "));
00045   else if (level == INFORMATION_LEVEL)
00046     fprintf(stderr, "%s", _("Info: "));
00047 
00048   vfprintf(stderr, format, args);
00049   va_end(args);
00050   fputc('\n', stderr);
00051   fflush(stderr);
00052 }
00053 
00054 /*
00055 function: compare_strings
00056 
00057 Works like strncmp, other than 1.) considers '-' and '_' the same.
00058 2.) Returns -1 if strings differ, 0 if they are equal
00059    */
00060 
00061 bool getopt_compare_strings(const char *s, const char *t, uint32_t length)
00062 {
00063   char const *end= s + length;
00064   for (;s != end ; s++, t++)
00065   {
00066     if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
00067     {
00068       return true;
00069     }
00070   }
00071 
00072   return false;
00073 }
00074 
00075 /*
00076 function: getopt_ll_limit_value
00077 
00078 Applies min/max/block_size to a numeric value of an option.
00079 Returns "fixed" value.
00080    */
00081 
00082 int64_t getopt_ll_limit_value(int64_t num, const option& optp, bool *fix)
00083 {
00084   int64_t old= num;
00085   bool adjusted= false;
00086   char buf1[255], buf2[255];
00087   uint64_t block_size= optp.block_size ? optp.block_size : 1;
00088 
00089   if (num > 0 && ((uint64_t) num > (uint64_t) optp.max_value) &&
00090       optp.max_value) /* if max value is not set -> no upper limit */
00091   {
00092     num= (uint64_t) optp.max_value;
00093     adjusted= true;
00094   }
00095 
00096   switch ((optp.var_type & GET_TYPE_MASK)) {
00097   case GET_INT:
00098     if (num > (int64_t) INT_MAX)
00099     {
00100       num= ((int64_t) INT_MAX);
00101       adjusted= true;
00102     }
00103     break;
00104   case GET_LONG:
00105     if (num > (int64_t) INT32_MAX)
00106     {
00107       num= ((int64_t) INT32_MAX);
00108       adjusted= true;
00109     }
00110     break;
00111   default:
00112     assert((optp.var_type & GET_TYPE_MASK) == GET_LL);
00113     break;
00114   }
00115 
00116   num= ((num - optp.sub_size) / block_size);
00117   num= (int64_t) (num * block_size);
00118 
00119   if (num < optp.min_value)
00120   {
00121     num= optp.min_value;
00122     adjusted= true;
00123   }
00124 
00125   if (fix)
00126   {
00127     *fix= adjusted;
00128   }
00129   else if (adjusted)
00130   {
00131     default_reporter(WARNING_LEVEL,
00132                      "option '%s': signed value %s adjusted to %s",
00133                      optp.name, internal::llstr(old, buf1), internal::llstr(num, buf2));
00134   }
00135   return num;
00136 }
00137 
00138 /*
00139 function: getopt_ull
00140 
00141 This is the same as getopt_ll, but is meant for uint64_t
00142 values.
00143    */
00144 
00145 uint64_t getopt_ull_limit_value(uint64_t num, const option& optp, bool *fix)
00146 {
00147   bool adjusted= false;
00148   uint64_t old= num;
00149   char buf1[255], buf2[255];
00150 
00151   if ((uint64_t) num > (uint64_t) optp.max_value &&
00152       optp.max_value) /* if max value is not set -> no upper limit */
00153   {
00154     num= (uint64_t) optp.max_value;
00155     adjusted= true;
00156   }
00157 
00158   switch (optp.var_type & GET_TYPE_MASK)
00159   {
00160   case GET_UINT:
00161     if (num > UINT_MAX)
00162     {
00163       num= UINT_MAX;
00164       adjusted= true;
00165     }
00166     break;
00167   case GET_UINT32:
00168   case GET_ULONG_IS_FAIL:
00169     if (num > UINT32_MAX)
00170     {
00171       num= UINT32_MAX;
00172       adjusted= true;
00173     }
00174     break;
00175   case GET_SIZE:
00176     if (num > SIZE_MAX)
00177     {
00178       num= SIZE_MAX;
00179       adjusted= true;
00180     }
00181     break;
00182   default:
00183     assert((optp.var_type & GET_TYPE_MASK) == GET_ULL || (optp.var_type & GET_TYPE_MASK) == GET_UINT64);
00184   }
00185 
00186   if (optp.block_size > 1)
00187   {
00188     num/= optp.block_size;
00189     num*= optp.block_size;
00190   }
00191 
00192   if (num < (uint64_t) optp.min_value)
00193   {
00194     num= (uint64_t) optp.min_value;
00195     adjusted= true;
00196   }
00197 
00198   if (fix)
00199     *fix= adjusted;
00200   else if (adjusted)
00201     default_reporter(WARNING_LEVEL, "option '%s': unsigned value %s adjusted to %s",
00202                      optp.name, internal::ullstr(old, buf1), internal::ullstr(num, buf2));
00203 
00204   return num;
00205 }
00206 
00207 
00208 /*
00209 function: my_print_options
00210 
00211 Print help for all options and variables.
00212    */
00213 
00214 void my_print_help(const option* options)
00215 {
00216   uint32_t col, name_space= 22, comment_space= 57;
00217   const char *line_end;
00218   const struct option *optp;
00219 
00220   for (optp= options; optp->id; optp++)
00221   {
00222     if (optp->id < 256)
00223     {
00224       printf("  -%c%s", optp->id, strlen(optp->name) ? ", " : "  ");
00225       col= 6;
00226     }
00227     else
00228     {
00229       printf("  ");
00230       col= 2;
00231     }
00232     if (strlen(optp->name))
00233     {
00234       printf("--%s", optp->name);
00235       col+= 2 + (uint32_t) strlen(optp->name);
00236       if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
00237           (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
00238       {
00239         printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
00240                optp->arg_type == OPT_ARG ? "]" : "");
00241         col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
00242       }
00243       else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
00244                (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
00245       {
00246         putchar(' ');
00247         col++;
00248       }
00249       else
00250       {
00251         printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "",
00252                optp->arg_type == OPT_ARG ? "]" : "");
00253         col+= (optp->arg_type == OPT_ARG) ? 5 : 3;
00254       }
00255       if (col > name_space && optp->comment && *optp->comment)
00256       {
00257         putchar('\n');
00258         col= 0;
00259       }
00260     }
00261     for (; col < name_space; col++)
00262       putchar(' ');
00263     if (optp->comment && *optp->comment)
00264     {
00265       const char *comment= _(optp->comment), *end= strchr(comment, '\0');
00266 
00267       while ((uint32_t) (end - comment) > comment_space)
00268       {
00269         for (line_end= comment + comment_space; *line_end != ' '; line_end--)
00270         {}
00271         for (; comment != line_end; comment++)
00272           putchar(*comment);
00273         comment++; /* skip the space, as a newline will take it's place now */
00274         putchar('\n');
00275         for (col= 0; col < name_space; col++)
00276           putchar(' ');
00277       }
00278       printf("%s", comment);
00279     }
00280     putchar('\n');
00281     if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
00282         (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
00283     {
00284       if (optp->def_value != 0)
00285       {
00286         printf(_("%*s(Defaults to on; use --skip-%s to disable.)\n"), name_space, "", optp->name);
00287       }
00288     }
00289   }
00290 }
00291 
00292 
00293 } /* namespace drizzled */