~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Lee Bieber
  • Date: 2011-01-25 17:15:03 UTC
  • mfrom: (1994.4.55 drizzle)
  • mto: This revision was merged to the branch mainline in revision 2115.
  • Revision ID: kalebral@gmail.com-20110125171503-zyx91pfdyyw9lty5
Merge Marisa - 684803: Need to update Drizzledump documentation with migration conversions / caveats
Merge Marisa - 686641: Need to document removal of multi-table update/delete from Drizzle

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
#include <sys/stat.h>
57
57
#include <sys/types.h>
58
58
#include <fcntl.h>
59
 
#include <boost/array.hpp>
60
 
#include <boost/foreach.hpp>
61
59
#include <boost/program_options.hpp>
62
 
#include <boost/smart_ptr.hpp>
63
60
 
64
61
#include PCRE_HEADER
65
62
 
67
64
#include <boost/unordered_map.hpp>
68
65
 
69
66
/* Added this for string translation. */
70
 
#include <drizzled/gettext.h>
71
 
#include <drizzled/type/time.h>
72
 
#include <drizzled/charset.h>
73
 
#include <drizzled/typelib.h>
 
67
#include "drizzled/gettext.h"
 
68
#include "drizzled/type/time.h"
 
69
#include "drizzled/charset.h"
74
70
#include <drizzled/configmake.h>
75
71
 
76
 
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
77
 
 
78
72
#ifndef DRIZZLE_RETURN_SERVER_GONE
79
73
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
80
74
#endif
121
115
static bool is_windows= false;
122
116
static bool use_drizzle_protocol= false;
123
117
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
124
 
static void free_all_replace();
125
118
 
126
119
std::string opt_basedir,
127
120
  opt_charsets_dir,
171
164
  uint32_t lineno; /* Current line in file */
172
165
};
173
166
 
174
 
static boost::array<st_test_file, 16> file_stack;
175
 
static st_test_file* cur_file;
 
167
static struct st_test_file file_stack[16];
 
168
static struct st_test_file* cur_file;
 
169
static struct st_test_file* file_stack_end;
 
170
 
176
171
 
177
172
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
178
173
 
182
177
*/
183
178
static char *timer_file = NULL;
184
179
static uint64_t timer_start;
185
 
static void timer_output();
186
 
static uint64_t timer_now();
 
180
static void timer_output(void);
 
181
static uint64_t timer_now(void);
187
182
 
188
183
static uint64_t progress_start= 0;
189
184
 
204
199
 
205
200
/* if set, all results are concated and compared against this file */
206
201
 
207
 
class VAR
 
202
typedef struct st_var
208
203
{
209
 
public:
210
204
  char *name;
211
205
  int name_len;
212
206
  char *str_val;
216
210
  int int_dirty; /* do not update string if int is updated until first read */
217
211
  int alloced;
218
212
  char *env_s;
219
 
};
 
213
} VAR;
220
214
 
221
215
/*Perl/shell-like variable registers */
222
 
boost::array<VAR, 10> var_reg;
223
 
 
224
 
typedef boost::unordered_map<string, VAR *> var_hash_t;
225
 
var_hash_t var_hash;
 
216
VAR var_reg[10];
 
217
 
 
218
 
 
219
boost::unordered_map<string, VAR *> var_hash;
226
220
 
227
221
struct st_connection
228
222
{
395
389
  struct st_match_err err[10];
396
390
  uint32_t count;
397
391
};
398
 
 
399
 
static st_expected_errors saved_expected_errors;
400
 
 
401
 
class st_command
 
392
static struct st_expected_errors saved_expected_errors;
 
393
 
 
394
struct st_command
402
395
{
403
 
public:
404
396
  char *query, *query_buf,*first_argument,*last_argument,*end;
405
397
  int first_word_len, query_len;
406
398
  bool abort_on_error;
407
399
  st_expected_errors expected_errors;
408
400
  string require_file;
409
 
  enum_commands type;
 
401
  enum enum_commands type;
410
402
 
411
403
  st_command()
412
404
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
418
410
 
419
411
  ~st_command()
420
412
  {
421
 
    free(query_buf);
 
413
    if (query_buf != NULL)
 
414
    {
 
415
      free(query_buf);
 
416
    }
422
417
  }
423
418
};
424
419
 
443
438
VAR* var_from_env(const char *, const char *);
444
439
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
445
440
              int val_len);
 
441
void var_free(pair<string, VAR*> v);
446
442
VAR* var_get(const char *var_name, const char** var_name_end,
447
443
             bool raw, bool ignore_not_existing);
448
444
void eval_expr(VAR* v, const char *p, const char** p_end);
449
445
bool match_delimiter(int c, const char *delim, uint32_t length);
450
446
void dump_result_to_reject_file(char *buf, int size);
451
447
void dump_result_to_log_file(const char *buf, int size);
452
 
void dump_warning_messages();
453
 
void dump_progress();
 
448
void dump_warning_messages(void);
 
449
void dump_progress(void);
454
450
 
455
451
void do_eval(string *query_eval, const char *query,
456
452
             const char *query_end, bool pass_through_escape_chars);
461
457
static char *replace_column[MAX_COLUMNS];
462
458
static uint32_t max_replace_column= 0;
463
459
void do_get_replace_column(struct st_command*);
464
 
void free_replace_column();
 
460
void free_replace_column(void);
465
461
 
466
462
/* For replace */
467
463
void do_get_replace(struct st_command *command);
468
 
void free_replace();
 
464
void free_replace(void);
469
465
 
470
466
/* For replace_regex */
471
467
void do_get_replace_regex(struct st_command *command);
 
468
void free_replace_regex(void);
 
469
 
 
470
 
 
471
void free_all_replace(void);
 
472
 
 
473
 
 
474
void free_all_replace(void){
 
475
  free_replace();
 
476
  free_replace_regex();
 
477
  free_replace_column();
 
478
}
472
479
 
473
480
void replace_append_mem(string *ds, const char *val,
474
481
                        int len);
485
492
void do_eval(string *query_eval, const char *query,
486
493
             const char *query_end, bool pass_through_escape_chars)
487
494
{
488
 
  char c, next_c;
489
 
  int escaped = 0;
 
495
  const char *p;
 
496
  register char c, next_c;
 
497
  register int escaped = 0;
490
498
  VAR *v;
491
499
 
492
 
  for (const char *p= query; (c= *p) && p < query_end; ++p)
 
500
 
 
501
  for (p= query; (c= *p) && p < query_end; ++p)
493
502
  {
494
503
    switch(c) {
495
504
    case '$':
863
872
}
864
873
 
865
874
 
866
 
static void close_connections()
 
875
static void close_connections(void)
867
876
{
868
877
  for (--next_con; next_con >= connections; --next_con)
869
878
  {
874
883
    }
875
884
    free(next_con->name);
876
885
  }
 
886
  return;
877
887
}
878
888
 
879
889
 
880
 
static void close_files()
 
890
static void close_files(void)
881
891
{
882
 
  for (; cur_file >= file_stack.data(); cur_file--)
 
892
 
 
893
  for (; cur_file >= file_stack; cur_file--)
883
894
  {
884
895
    if (cur_file->file && cur_file->file != stdin)
 
896
    {
885
897
      fclose(cur_file->file);
886
 
    free(const_cast<char*>(cur_file->file_name));
 
898
    }
 
899
    free((unsigned char*) cur_file->file_name);
887
900
    cur_file->file_name= 0;
888
901
  }
 
902
  return;
889
903
}
890
904
 
891
 
static void free_used_memory()
 
905
 
 
906
static void free_used_memory(void)
892
907
{
 
908
  uint32_t i;
 
909
 
 
910
 
893
911
  close_connections();
894
912
  close_files();
895
 
  BOOST_FOREACH(var_hash_t::reference i, var_hash)
896
 
  {
897
 
    free(i.second->str_val);
898
 
    free(i.second->env_s);
899
 
    if (i.second->alloced)
900
 
      free(i.second);
901
 
  }
 
913
  for_each(var_hash.begin(), var_hash.end(), var_free);
902
914
  var_hash.clear();
903
 
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
904
 
    delete i;
905
 
  for (size_t i= 0; i < var_reg.size(); i++)
 
915
 
 
916
  vector<st_command *>::iterator iter;
 
917
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
918
  {
 
919
    struct st_command * q_line= *iter;
 
920
    delete q_line;
 
921
  }
 
922
 
 
923
  for (i= 0; i < 10; i++)
906
924
  {
907
925
    if (var_reg[i].alloced_len)
908
926
      free(var_reg[i].str_val);
909
927
  }
 
928
 
910
929
  free_all_replace();
911
930
  free(opt_pass);
 
931
 
 
932
  return;
912
933
}
913
934
 
914
935
 
933
954
      assert(0);
934
955
    }
935
956
  }
 
957
 
936
958
  exit(exit_code);
937
959
}
938
960
 
952
974
 
953
975
  /* Print the error message */
954
976
  fprintf(stderr, "drizzletest: ");
955
 
  if (cur_file && cur_file != file_stack.data())
 
977
  if (cur_file && cur_file != file_stack)
956
978
    fprintf(stderr, "In included file \"%s\": ",
957
979
            cur_file->file_name);
958
980
  if (start_lineno > 0)
1013
1035
 
1014
1036
  /* Print include filestack */
1015
1037
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1016
 
          file_stack[0].file_name);
 
1038
          file_stack->file_name);
1017
1039
  fprintf(stderr, "Detected in file %s at line %d\n",
1018
1040
          err_file->file_name, err_file->lineno);
1019
 
  while (err_file != file_stack.data())
 
1041
  while (err_file != file_stack)
1020
1042
  {
1021
1043
    err_file--;
1022
1044
    fprintf(stderr, "included from %s at line %d\n",
1047
1069
 
1048
1070
  va_start(args, fmt);
1049
1071
  fprintf(stderr, "drizzletest: ");
1050
 
  if (cur_file && cur_file != file_stack.data())
 
1072
  if (cur_file && cur_file != file_stack)
1051
1073
    fprintf(stderr, "In included file \"%s\": ",
1052
1074
            cur_file->file_name);
1053
1075
  if (start_lineno != 0)
1055
1077
  vfprintf(stderr, fmt, args);
1056
1078
  fprintf(stderr, "\n");
1057
1079
  va_end(args);
 
1080
 
 
1081
  return;
1058
1082
}
1059
1083
 
1060
1084
 
1070
1094
  if (start_lineno != 0)
1071
1095
  {
1072
1096
    ds_warning_messages.append("Warning detected ");
1073
 
    if (cur_file && cur_file != file_stack.data())
 
1097
    if (cur_file && cur_file != file_stack)
1074
1098
    {
1075
1099
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1076
1100
                    cur_file->file_name);
1603
1627
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1604
1628
              int val_len)
1605
1629
{
 
1630
  int val_alloc_len;
 
1631
  VAR *tmp_var;
1606
1632
  if (!name_len && name)
1607
1633
    name_len = strlen(name);
1608
1634
  if (!val_len && val)
1609
1635
    val_len = strlen(val) ;
1610
 
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
 
1636
  val_alloc_len = val_len + 16; /* room to grow */
 
1637
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
 
1638
                                               + name_len+1)))
 
1639
    die("Out of memory");
1611
1640
 
1612
 
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
 
1641
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1613
1642
  tmp_var->alloced = (v == 0);
1614
1643
 
1615
 
  int val_alloc_len = val_len + 16; /* room to grow */
1616
 
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
 
1644
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1645
    die("Out of memory");
1617
1646
 
1618
1647
  memcpy(tmp_var->name, name, name_len);
1619
1648
  if (val)
1624
1653
  tmp_var->name_len = name_len;
1625
1654
  tmp_var->str_val_len = val_len;
1626
1655
  tmp_var->alloced_len = val_alloc_len;
1627
 
  tmp_var->int_val = val ? atoi(val) : 0;
1628
 
  tmp_var->int_dirty = false;
 
1656
  tmp_var->int_val = (val) ? atoi(val) : 0;
 
1657
  tmp_var->int_dirty = 0;
1629
1658
  tmp_var->env_s = 0;
1630
1659
  return tmp_var;
1631
1660
}
1632
1661
 
 
1662
 
 
1663
void var_free(pair<string, VAR *> v)
 
1664
{
 
1665
  free(v.second->str_val);
 
1666
  free(v.second->env_s);
 
1667
  if (v.second->alloced)
 
1668
    free(v.second);
 
1669
}
 
1670
 
 
1671
 
1633
1672
VAR* var_from_env(const char *name, const char *def_val)
1634
1673
{
1635
 
  const char *tmp= getenv(name);
1636
 
  if (!tmp)
 
1674
  const char *tmp;
 
1675
  VAR *v;
 
1676
  if (!(tmp = getenv(name)))
1637
1677
    tmp = def_val;
1638
 
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1678
 
 
1679
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1680
  string var_name(name);
 
1681
  var_hash.insert(make_pair(var_name, v));
 
1682
  return v;
1639
1683
}
1640
1684
 
 
1685
 
1641
1686
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1642
1687
             bool ignore_not_existing)
1643
1688
{
1644
1689
  int digit;
1645
1690
  VAR *v;
 
1691
 
1646
1692
  if (*var_name != '$')
1647
1693
    goto err;
1648
1694
  digit = *++var_name - '0';
1664
1710
      die("Too long variable name: %s", save_var_name);
1665
1711
 
1666
1712
    string save_var_name_str(save_var_name, length);
1667
 
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
 
1713
    boost::unordered_map<string, VAR*>::iterator iter=
 
1714
      var_hash.find(save_var_name_str);
1668
1715
    if (iter == var_hash.end())
1669
1716
    {
1670
1717
      char buff[MAX_VAR_NAME_LENGTH+1];
1674
1721
    }
1675
1722
    else
1676
1723
    {
1677
 
      v= iter->second;
 
1724
      v= (*iter).second;
1678
1725
    }
1679
1726
    var_name--;  /* Point at last character */
1680
1727
  }
1681
1728
  else
1682
 
    v = &var_reg[digit];
 
1729
    v = var_reg + digit;
1683
1730
 
1684
1731
  if (!raw && v->int_dirty)
1685
1732
  {
1701
1748
static VAR *var_obtain(const char *name, int len)
1702
1749
{
1703
1750
  string var_name(name, len);
1704
 
  var_hash_t::iterator iter= var_hash.find(var_name);
 
1751
  boost::unordered_map<string, VAR*>::iterator iter=
 
1752
    var_hash.find(var_name);
1705
1753
  if (iter != var_hash.end())
1706
 
    return iter->second;
1707
 
  return var_hash[var_name] = var_init(0, name, len, "", 0);
 
1754
    return (*iter).second;
 
1755
  VAR *v = var_init(0, name, len, "", 0);
 
1756
  var_hash.insert(make_pair(var_name, v));
 
1757
  return v;
1708
1758
}
1709
1759
 
1710
1760
 
1731
1781
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1732
1782
  }
1733
1783
  else
1734
 
    v= &var_reg[digit];
 
1784
    v= var_reg + digit;
1735
1785
 
1736
1786
  eval_expr(v, var_val, (const char**) &var_val_end);
1737
1787
 
2015
2065
    eval_expr(var, value, 0);
2016
2066
  }
2017
2067
  drizzle_result_free(&res);
 
2068
 
 
2069
  return;
2018
2070
}
2019
2071
 
2020
2072
 
2045
2097
{
2046
2098
  if (*p == '$')
2047
2099
  {
2048
 
    VAR *vp= var_get(p, p_end, 0, 0);
2049
 
    if (vp)
 
2100
    VAR *vp;
 
2101
    if ((vp= var_get(p, p_end, 0, 0)))
2050
2102
      var_copy(v, vp);
2051
2103
    return;
2052
2104
  }
2107
2159
  }
2108
2160
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2109
2161
 
 
2162
  if (cur_file == file_stack_end)
 
2163
    die("Source directives are nesting too deep");
2110
2164
  cur_file++;
2111
 
  if (cur_file == &*file_stack.end())
2112
 
    die("Source directives are nesting too deep");
2113
2165
  if (!(cur_file->file= fopen(buff, "r")))
2114
2166
  {
2115
2167
    cur_file--;
2171
2223
}
2172
2224
 
2173
2225
 
2174
 
static void init_builtin_echo()
 
2226
static void init_builtin_echo(void)
2175
2227
{
2176
2228
  builtin_echo[0]= 0;
 
2229
  return;
2177
2230
}
2178
2231
 
2179
2232
 
3136
3189
  when ndb binlog is on, this call will wait until last updated epoch
3137
3190
  (locally in the drizzled) has been received into the binlog
3138
3191
*/
3139
 
static int do_save_master_pos()
 
3192
static int do_save_master_pos(void)
3140
3193
{
3141
3194
  drizzle_result_st res;
3142
3195
  drizzle_return_t ret;
3275
3328
    sleep_val= opt_sleep;
3276
3329
 
3277
3330
  if (sleep_val)
3278
 
    usleep(sleep_val * 1000000);
 
3331
    usleep((uint32_t) (sleep_val * 1000000L));
3279
3332
  command->last_argument= sleep_end;
3280
3333
  return 0;
3281
3334
}
3282
3335
 
3283
3336
 
3284
 
static void do_get_file_name(st_command *command, string &dest)
 
3337
static void do_get_file_name(struct st_command *command, string &dest)
3285
3338
{
3286
 
  char *p= command->first_argument;
 
3339
  char *p= command->first_argument, *name;
3287
3340
  if (!*p)
3288
3341
    die("Missing file name argument");
3289
 
  char *name= p;
 
3342
  name= p;
3290
3343
  while (*p && !my_isspace(charset_info,*p))
3291
3344
    p++;
3292
3345
  if (*p)
3361
3414
      and assign that string to the $variable
3362
3415
    */
3363
3416
    size_t *lengths= drizzle_row_field_sizes(&res);
 
3417
    const std::string error_name(row[0], lengths[0]);
 
3418
    const std::string error_code(row[1], lengths[1]);
 
3419
 
3364
3420
    try
3365
3421
    {
3366
 
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
 
3422
      global_error_names.insert(ErrorCodes::value_type(error_name,
 
3423
                                                       boost::lexical_cast<uint32_t>(error_code)));
3367
3424
    }
3368
3425
    catch (boost::bad_lexical_cast &ex)
3369
3426
    {
3383
3440
 
3384
3441
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3385
3442
  if (it != global_error_names.end())
3386
 
    return it->second;
 
3443
  {
 
3444
    return (*it).second;
 
3445
  }
3387
3446
 
3388
3447
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3389
3448
  return 0;
3454
3513
    {
3455
3514
      die("The error name definition must start with an uppercase E");
3456
3515
    }
3457
 
    else if (*p == 'H')
 
3516
    else
3458
3517
    {
3459
 
      /* Error name string */
3460
 
 
3461
 
      to->code.errnum= get_errcode_from_name(p, end);
 
3518
      long val;
 
3519
      char *start= p;
 
3520
      /* Check that the string passed to str2int only contain digits */
 
3521
      while (*p && p != end)
 
3522
      {
 
3523
        if (!my_isdigit(charset_info, *p))
 
3524
          die("Invalid argument to error: '%s' - "              \
 
3525
              "the errno may only consist of digits[0-9]",
 
3526
              command->first_argument);
 
3527
        p++;
 
3528
      }
 
3529
 
 
3530
      /* Convert the sting to int */
 
3531
      istringstream buff(start);
 
3532
      if ((buff >> val).fail())
 
3533
        die("Invalid argument to error: '%s'", command->first_argument);
 
3534
 
 
3535
      to->code.errnum= (uint32_t) val;
3462
3536
      to->type= ERR_ERRNO;
3463
3537
    }
3464
 
    else
3465
 
    {
3466
 
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3467
 
    }
3468
3538
    to++;
3469
3539
    count++;
3470
3540
 
4004
4074
{
4005
4075
  char *p= command->first_argument;
4006
4076
  const char *expr_start, *expr_end;
 
4077
  VAR v;
4007
4078
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4008
4079
  bool not_expr= false;
4009
4080
 
4046
4117
  if (*p && *p != '{')
4047
4118
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4048
4119
 
4049
 
  VAR v;
4050
4120
  var_init(&v,0,0,0,0);
4051
4121
  eval_expr(&v, expr_start, &expr_end);
4052
4122
 
4182
4252
      }
4183
4253
      free((unsigned char*) cur_file->file_name);
4184
4254
      cur_file->file_name= 0;
4185
 
      if (cur_file == file_stack.data())
 
4255
      if (cur_file == file_stack)
4186
4256
      {
4187
4257
        /* We're back at the first file, check if
4188
4258
           all { have matching }
4416
4486
        end++;
4417
4487
      save= *end;
4418
4488
      *end= 0;
4419
 
      type= command_typelib.find_type(start, 1+2);
 
4489
      type= find_type(start, &command_typelib, 1+2);
4420
4490
      if (type)
4421
4491
        warning_msg("Embedded drizzletest command '--%s' detected in "
4422
4492
                    "query '%s' was this intentional? ",
4622
4692
          log_file);
4623
4693
}
4624
4694
 
4625
 
void dump_progress()
 
4695
void dump_progress(void)
4626
4696
{
4627
4697
  char progress_file[FN_REFLEN];
4628
4698
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4632
4702
              ds_progress.c_str(), ds_progress.length());
4633
4703
}
4634
4704
 
4635
 
void dump_warning_messages()
 
4705
void dump_warning_messages(void)
4636
4706
{
4637
4707
  char warn_file[FN_REFLEN];
4638
4708
 
4697
4767
    for (i = 0; i < num_fields; i++)
4698
4768
    {
4699
4769
      column= drizzle_column_next(res);
4700
 
      if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
4701
 
      {
4702
 
        if (boost::lexical_cast<uint32_t>(row[i]))
4703
 
        {
4704
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4705
 
          {
4706
 
            append_field(ds, i, column, "YES", 3, false);
4707
 
          }
4708
 
          else
4709
 
          {
4710
 
            append_field(ds, i, column, "TRUE", 4, false);
4711
 
          }
4712
 
        }
4713
 
        else
4714
 
        {
4715
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4716
 
          {
4717
 
            append_field(ds, i, column, "NO", 2, false);
4718
 
          }
4719
 
          else
4720
 
          {
4721
 
            append_field(ds, i, column, "FALSE", 5, false);
4722
 
          }
4723
 
        }
4724
 
      }
4725
 
      else
4726
 
      {
4727
 
        append_field(ds, i, column,
4728
 
                     (const char*)row[i], lengths[i], !row[i]);
4729
 
      }
 
4770
      append_field(ds, i, column,
 
4771
                   (const char*)row[i], lengths[i], !row[i]);
4730
4772
    }
4731
4773
    if (!display_result_vertically)
4732
4774
      ds->append("\n");
4770
4812
    ds->append("\t", 1);
4771
4813
    replace_append_uint(ds, drizzle_column_size(column));
4772
4814
    ds->append("\t", 1);
4773
 
    if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
4774
 
    {
4775
 
      replace_append_uint(ds, 1);
4776
 
    }
4777
 
    else
4778
 
    {
4779
 
      replace_append_uint(ds, drizzle_column_max_size(column));
4780
 
    }
 
4815
    replace_append_uint(ds, drizzle_column_max_size(column));
4781
4816
    ds->append("\t", 1);
4782
4817
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4783
4818
    ds->append("\t", 1);
5274
5309
 
5275
5310
  save= command->query[command->first_word_len];
5276
5311
  command->query[command->first_word_len]= 0;
5277
 
  type= command_typelib.find_type(command->query, 1+2);
 
5312
  type= find_type(command->query, &command_typelib, 1+2);
5278
5313
  command->query[command->first_word_len]= save;
5279
5314
  if (type > 0)
5280
5315
  {
5318
5353
        */
5319
5354
        save= command->query[command->first_word_len-1];
5320
5355
        command->query[command->first_word_len-1]= 0;
5321
 
        if (command_typelib.find_type(command->query, 1+2) > 0)
 
5356
        if (find_type(command->query, &command_typelib, 1+2) > 0)
5322
5357
          die("Extra delimiter \";\" found");
5323
5358
        command->query[command->first_word_len-1]= save;
5324
5359
 
5492
5527
 
5493
5528
  if (user_config_dir.compare(0, 2, "~/") == 0)
5494
5529
  {
5495
 
    const char *homedir= getenv("HOME");
 
5530
    char *homedir;
 
5531
    homedir= getenv("HOME");
5496
5532
    if (homedir != NULL)
5497
5533
      user_config_dir.replace(0, 1, homedir);
5498
5534
  }
5539
5575
  next_con= connections + 1;
5540
5576
 
5541
5577
  /* Init file stack */
5542
 
  memset(file_stack.data(), 0, sizeof(file_stack));
5543
 
  cur_file= file_stack.data();
 
5578
  memset(file_stack, 0, sizeof(file_stack));
 
5579
  file_stack_end=
 
5580
    file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
 
5581
  cur_file= file_stack;
5544
5582
 
5545
5583
  /* Init block stack */
5546
5584
  memset(block_stack, 0, sizeof(block_stack));
5579
5617
      tmp= buff;
5580
5618
    }
5581
5619
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5582
 
    assert(cur_file == file_stack.data() && cur_file->file == 0);
 
5620
    assert(cur_file == file_stack && cur_file->file == 0);
5583
5621
    if (!(cur_file->file= fopen(buff, "r")))
5584
5622
    {
5585
5623
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5684
5722
  }
5685
5723
 
5686
5724
  server_initialized= 1;
5687
 
  if (cur_file == file_stack.data() && cur_file->file == 0)
 
5725
  if (cur_file == file_stack && cur_file->file == 0)
5688
5726
  {
5689
5727
    cur_file->file= stdin;
5690
5728
    cur_file->file_name= strdup("<stdin>");
6109
6147
  the time between executing the two commands.
6110
6148
*/
6111
6149
 
6112
 
void timer_output()
 
6150
void timer_output(void)
6113
6151
{
6114
6152
  if (timer_file)
6115
6153
  {
6123
6161
}
6124
6162
 
6125
6163
 
6126
 
uint64_t timer_now()
 
6164
uint64_t timer_now(void)
6127
6165
{
6128
6166
#if defined(HAVE_GETHRTIME)
6129
6167
  return gethrtime()/1000/1000;
6163
6201
  start= buff= (char *)malloc(strlen(from)+1);
6164
6202
  while (*from)
6165
6203
  {
 
6204
    char *to;
6166
6205
    uint32_t column_number;
6167
6206
 
6168
 
    char *to= get_string(&buff, &from, command);
 
6207
    to= get_string(&buff, &from, command);
6169
6208
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6170
6209
      die("Wrong column number to replace_column in '%s'", command->query);
6171
6210
    if (!*from)
6184
6223
 
6185
6224
void free_replace_column()
6186
6225
{
6187
 
  for (uint32_t i= 0 ; i < max_replace_column; i++)
 
6226
  uint32_t i;
 
6227
  for (i=0 ; i < max_replace_column ; i++)
6188
6228
  {
6189
 
    free(replace_column[i]);
6190
 
    replace_column[i]= 0;
 
6229
    if (replace_column[i])
 
6230
    {
 
6231
      free(replace_column[i]);
 
6232
      replace_column[i]= 0;
 
6233
    }
6191
6234
  }
6192
6235
  max_replace_column= 0;
6193
6236
}
6208
6251
} POINTER_ARRAY;
6209
6252
 
6210
6253
struct st_replace;
6211
 
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6212
 
                                char *word_end_chars);
 
6254
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
6255
                                char * word_end_chars);
6213
6256
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6214
6257
void replace_strings_append(struct st_replace *rep, string* ds,
6215
6258
                            const char *from, int len);
 
6259
void free_pointer_array(POINTER_ARRAY *pa);
6216
6260
 
6217
 
st_replace *glob_replace= NULL;
6218
 
// boost::scoped_ptr<st_replace> glob_replace;
 
6261
struct st_replace *glob_replace= NULL;
6219
6262
 
6220
6263
/*
6221
6264
  Get arguments for replace. The syntax is:
6225
6268
  variable is replaced.
6226
6269
*/
6227
6270
 
6228
 
static void free_pointer_array(POINTER_ARRAY *pa)
6229
 
{
6230
 
  if (!pa->typelib.count)
6231
 
    return;
6232
 
  pa->typelib.count=0;
6233
 
  free((char*) pa->typelib.type_names);
6234
 
  pa->typelib.type_names=0;
6235
 
  free(pa->str);
6236
 
}
6237
 
 
6238
6271
void do_get_replace(struct st_command *command)
6239
6272
{
6240
6273
  uint32_t i;
6266
6299
    if (my_isspace(charset_info,i))
6267
6300
      *pos++= i;
6268
6301
  *pos=0;          /* End pointer */
6269
 
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
6270
 
                                   to_array.typelib.type_names,
6271
 
                                   from_array.typelib.count,
 
6302
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
 
6303
                                   (char**) to_array.typelib.type_names,
 
6304
                                   (uint32_t) from_array.typelib.count,
6272
6305
                                   word_end_chars)))
6273
6306
    die("Can't initialize replace from '%s'", command->query);
6274
6307
  free_pointer_array(&from_array);
6281
6314
 
6282
6315
void free_replace()
6283
6316
{
6284
 
  free(glob_replace);
6285
 
  glob_replace=0;
 
6317
 
 
6318
  if (glob_replace)
 
6319
  {
 
6320
    free(glob_replace);
 
6321
    glob_replace=0;
 
6322
  }
 
6323
  return;
6286
6324
}
6287
6325
 
6288
6326
 
6302
6340
void replace_strings_append(REPLACE *rep, string* ds,
6303
6341
                            const char *str, int len)
6304
6342
{
6305
 
  REPLACE *rep_pos;
6306
 
  REPLACE_STRING *rep_str;
 
6343
  register REPLACE *rep_pos;
 
6344
  register REPLACE_STRING *rep_str;
6307
6345
  const char *start, *from;
6308
6346
 
6309
6347
 
6356
6394
                 i.e. repeat the matching until the end of the string */
6357
6395
};
6358
6396
 
6359
 
class st_replace_regex
 
6397
struct st_replace_regex
6360
6398
{
6361
 
public:
6362
 
  st_replace_regex(char* expr);
6363
 
  int multi_reg_replace(char* val);
 
6399
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
6364
6400
 
6365
6401
  /*
6366
6402
    Temporary storage areas for substitutions. To reduce unnessary copying
6369
6405
    st_regex substition. At the end of substitutions  buf points to the
6370
6406
    one containing the final result.
6371
6407
  */
6372
 
  typedef vector<st_regex> regex_arr_t;
6373
 
 
6374
 
  char* buf_;
 
6408
  char* buf;
6375
6409
  char* even_buf;
6376
6410
  char* odd_buf;
6377
6411
  int even_buf_len;
6378
6412
  int odd_buf_len;
6379
 
  boost::array<char, 8 << 10> buf0_;
6380
 
  boost::array<char, 8 << 10> buf1_;
6381
 
  regex_arr_t regex_arr;
6382
6413
};
6383
6414
 
6384
 
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
 
6415
struct st_replace_regex *glob_replace_regex= 0;
6385
6416
 
6386
6417
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6387
6418
                char *string, int icase, int global);
6423
6454
  Returns: st_replace_regex struct with pairs of substitutions
6424
6455
*/
6425
6456
 
6426
 
st_replace_regex::st_replace_regex(char* expr)
 
6457
static struct st_replace_regex* init_replace_regex(char* expr)
6427
6458
{
 
6459
  struct st_replace_regex* res;
 
6460
  char* buf,*expr_end;
 
6461
  char* p;
 
6462
  char* buf_p;
6428
6463
  uint32_t expr_len= strlen(expr);
6429
6464
  char last_c = 0;
6430
 
  st_regex reg;
6431
 
 
6432
 
  char* buf= new char[expr_len];
6433
 
  char* expr_end= expr + expr_len;
6434
 
  char* p= expr;
6435
 
  char* buf_p= buf;
 
6465
  struct st_regex reg;
 
6466
 
 
6467
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
 
6468
  if (!res)
 
6469
    return NULL;
 
6470
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
 
6471
 
 
6472
  buf= (char*)res + sizeof(*res);
 
6473
  expr_end= expr + expr_len;
 
6474
  p= expr;
 
6475
  buf_p= buf;
6436
6476
 
6437
6477
  /* for each regexp substitution statement */
6438
6478
  while (p < expr_end)
6448
6488
 
6449
6489
    if (p == expr_end || ++p == expr_end)
6450
6490
    {
6451
 
      if (!regex_arr.empty())
 
6491
      if (res->regex_arr.elements)
6452
6492
        break;
6453
6493
      else
6454
6494
        goto err;
6487
6527
      p++;
6488
6528
      reg.global= 1;
6489
6529
    }
6490
 
    regex_arr.push_back(reg);
 
6530
 
 
6531
    /* done parsing the statement, now place it in regex_arr */
 
6532
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6533
      die("Out of memory");
6491
6534
  }
6492
 
  odd_buf_len= even_buf_len= buf0_.size();
6493
 
  even_buf= buf0_.data();
6494
 
  odd_buf= buf1_.data();
6495
 
  buf_= even_buf;
 
6535
  res->odd_buf_len= res->even_buf_len= 8192;
 
6536
  res->even_buf= (char*)malloc(res->even_buf_len);
 
6537
  res->odd_buf= (char*)malloc(res->odd_buf_len);
 
6538
  res->buf= res->even_buf;
6496
6539
 
6497
 
  return;
 
6540
  return res;
6498
6541
 
6499
6542
err:
 
6543
  free(res);
6500
6544
  die("Error parsing replace_regex \"%s\"", expr);
 
6545
  return 0;
6501
6546
}
6502
6547
 
6503
6548
/*
6519
6564
  in one pass
6520
6565
*/
6521
6566
 
6522
 
int st_replace_regex::multi_reg_replace(char* val)
 
6567
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6523
6568
{
6524
 
  char* in_buf= val;
6525
 
  char* out_buf= even_buf;
6526
 
  int* buf_len_p= &even_buf_len;
6527
 
  buf_= 0;
 
6569
  uint32_t i;
 
6570
  char* in_buf, *out_buf;
 
6571
  int* buf_len_p;
 
6572
 
 
6573
  in_buf= val;
 
6574
  out_buf= r->even_buf;
 
6575
  buf_len_p= &r->even_buf_len;
 
6576
  r->buf= 0;
6528
6577
 
6529
6578
  /* For each substitution, do the replace */
6530
 
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
 
6579
  for (i= 0; i < r->regex_arr.elements; i++)
6531
6580
  {
 
6581
    struct st_regex re;
6532
6582
    char* save_out_buf= out_buf;
6533
 
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6534
 
                     in_buf, i.icase, i.global))
 
6583
 
 
6584
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6585
 
 
6586
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
 
6587
                     in_buf, re.icase, re.global))
6535
6588
    {
6536
6589
      /* if the buffer has been reallocated, make adjustements */
6537
6590
      if (save_out_buf != out_buf)
6538
6591
      {
6539
 
        if (save_out_buf == even_buf)
6540
 
          even_buf= out_buf;
 
6592
        if (save_out_buf == r->even_buf)
 
6593
          r->even_buf= out_buf;
6541
6594
        else
6542
 
          odd_buf= out_buf;
 
6595
          r->odd_buf= out_buf;
6543
6596
      }
6544
 
      buf_= out_buf;
 
6597
 
 
6598
      r->buf= out_buf;
6545
6599
      if (in_buf == val)
6546
 
        in_buf= odd_buf;
6547
 
      std::swap(in_buf, out_buf);
6548
 
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
 
6600
        in_buf= r->odd_buf;
 
6601
 
 
6602
      std::swap(in_buf,out_buf);
 
6603
 
 
6604
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
 
6605
        &r->odd_buf_len;
6549
6606
    }
6550
6607
  }
6551
 
  return buf_ == 0;
 
6608
 
 
6609
  return (r->buf == 0);
6552
6610
}
6553
6611
 
6554
6612
/*
6563
6621
void do_get_replace_regex(struct st_command *command)
6564
6622
{
6565
6623
  char *expr= command->first_argument;
6566
 
  glob_replace_regex.reset(new st_replace_regex(expr));
 
6624
  free_replace_regex();
 
6625
  if (!(glob_replace_regex=init_replace_regex(expr)))
 
6626
    die("Could not init replace_regex");
6567
6627
  command->last_argument= command->end;
6568
6628
}
6569
6629
 
 
6630
void free_replace_regex()
 
6631
{
 
6632
  if (glob_replace_regex)
 
6633
  {
 
6634
    delete_dynamic(&glob_replace_regex->regex_arr);
 
6635
    free(glob_replace_regex->even_buf);
 
6636
    free(glob_replace_regex->odd_buf);
 
6637
    free(glob_replace_regex);
 
6638
    glob_replace_regex=0;
 
6639
  }
 
6640
}
 
6641
 
 
6642
 
 
6643
 
6570
6644
/*
6571
6645
  Performs a regex substitution
6572
6646
 
6673
6747
#define SET_MALLOC_HUNC 64
6674
6748
#define LAST_CHAR_CODE 259
6675
6749
 
6676
 
class REP_SET
6677
 
{
6678
 
public:
6679
 
  void internal_set_bit(uint32_t bit);
6680
 
  void internal_clear_bit(uint32_t bit);
6681
 
  void or_bits(const REP_SET *from);
6682
 
  void copy_bits(const REP_SET *from);
6683
 
  int cmp_bits(const REP_SET *set2) const;
6684
 
  int get_next_bit(uint32_t lastpos) const;
6685
 
 
 
6750
typedef struct st_rep_set {
6686
6751
  uint32_t  *bits;        /* Pointer to used sets */
6687
6752
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6688
6753
  uint32_t  found_len;      /* Best match to date */
6689
6754
  int  found_offset;
6690
6755
  uint32_t  table_offset;
6691
6756
  uint32_t  size_of_bits;      /* For convinience */
6692
 
};
6693
 
 
6694
 
class REP_SETS
6695
 
{
6696
 
public:
6697
 
  int find_set(const REP_SET *find);
6698
 
  void free_last_set();
6699
 
  void free_sets();
6700
 
  void make_sets_invisible();
6701
 
 
 
6757
} REP_SET;
 
6758
 
 
6759
typedef struct st_rep_sets {
6702
6760
  uint32_t    count;      /* Number of sets */
6703
6761
  uint32_t    extra;      /* Extra sets in buffer */
6704
 
  uint32_t    invisible;    /* Sets not shown */
 
6762
  uint32_t    invisible;    /* Sets not chown */
6705
6763
  uint32_t    size_of_bits;
6706
6764
  REP_SET  *set,*set_buffer;
6707
6765
  uint32_t    *bit_buffer;
6708
 
};
 
6766
} REP_SETS;
6709
6767
 
6710
 
struct FOUND_SET 
6711
 
{
 
6768
typedef struct st_found_set {
6712
6769
  uint32_t table_offset;
6713
6770
  int found_offset;
6714
 
};
 
6771
} FOUND_SET;
6715
6772
 
6716
 
struct FOLLOWS
6717
 
{
 
6773
typedef struct st_follow {
6718
6774
  int chr;
6719
6775
  uint32_t table_offset;
6720
6776
  uint32_t len;
6721
 
};
6722
 
 
6723
 
int init_sets(REP_SETS *sets, uint32_t states);
 
6777
} FOLLOWS;
 
6778
 
 
6779
 
 
6780
int init_sets(REP_SETS *sets,uint32_t states);
6724
6781
REP_SET *make_new_set(REP_SETS *sets);
6725
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6726
 
 
6727
 
static uint32_t found_sets= 0;
6728
 
 
6729
 
static uint32_t replace_len(const char *str)
 
6782
void make_sets_invisible(REP_SETS *sets);
 
6783
void free_last_set(REP_SETS *sets);
 
6784
void free_sets(REP_SETS *sets);
 
6785
void internal_set_bit(REP_SET *set, uint32_t bit);
 
6786
void internal_clear_bit(REP_SET *set, uint32_t bit);
 
6787
void or_bits(REP_SET *to,REP_SET *from);
 
6788
void copy_bits(REP_SET *to,REP_SET *from);
 
6789
int cmp_bits(REP_SET *set1,REP_SET *set2);
 
6790
int get_next_bit(REP_SET *set,uint32_t lastpos);
 
6791
int find_set(REP_SETS *sets,REP_SET *find);
 
6792
int find_found(FOUND_SET *found_set,uint32_t table_offset,
 
6793
               int found_offset);
 
6794
uint32_t start_at_word(char * pos);
 
6795
uint32_t end_of_word(char * pos);
 
6796
 
 
6797
static uint32_t found_sets=0;
 
6798
 
 
6799
 
 
6800
static uint32_t replace_len(char * str)
6730
6801
{
6731
6802
  uint32_t len=0;
6732
6803
  while (*str)
6739
6810
  return len;
6740
6811
}
6741
6812
 
6742
 
/* Return 1 if regexp starts with \b or ends with \b*/
6743
 
 
6744
 
static bool start_at_word(const char *pos)
6745
 
{
6746
 
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6747
 
}
6748
 
 
6749
 
static bool end_of_word(const char *pos)
6750
 
{
6751
 
  const char *end= strchr(pos, '\0');
6752
 
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6753
 
}
6754
 
 
6755
6813
/* Init a replace structure for further calls */
6756
6814
 
6757
 
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
 
6815
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6816
                      char * word_end_chars)
6758
6817
{
6759
 
  const int SPACE_CHAR= 256;
6760
 
  const int START_OF_LINE= 257;
6761
 
  const int END_OF_LINE= 258;
 
6818
  static const int SPACE_CHAR= 256;
 
6819
  static const int START_OF_LINE= 257;
 
6820
  static const int END_OF_LINE= 258;
6762
6821
 
6763
6822
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6764
6823
  int used_sets,chr,default_state;
6765
6824
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6766
 
  char *to_pos, **to_array;
 
6825
  char * pos, *to_pos, **to_array;
 
6826
  REP_SETS sets;
 
6827
  REP_SET *set,*start_states,*word_states,*new_set;
 
6828
  FOLLOWS *follow,*follow_ptr;
 
6829
  REPLACE *replace;
 
6830
  FOUND_SET *found_set;
 
6831
  REPLACE_STRING *rep_str;
 
6832
 
6767
6833
 
6768
6834
  /* Count number of states */
6769
6835
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6783
6849
  for (i=0 ; word_end_chars[i] ; i++)
6784
6850
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6785
6851
 
6786
 
  REP_SETS sets;
6787
 
  REP_SET *set,*start_states,*word_states,*new_set;
6788
 
  REPLACE_STRING *rep_str;
6789
 
  if (init_sets(&sets, states))
6790
 
    return 0;
 
6852
  if (init_sets(&sets,states))
 
6853
    return(0);
6791
6854
  found_sets=0;
6792
 
  vector<FOUND_SET> found_set(max_length * count);
 
6855
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
 
6856
                                
 
6857
  {
 
6858
    free_sets(&sets);
 
6859
    return(0);
 
6860
  }
6793
6861
  make_new_set(&sets);      /* Set starting set */
6794
 
  sets.make_sets_invisible();      /* Hide previus sets */
 
6862
  make_sets_invisible(&sets);      /* Hide previus sets */
6795
6863
  used_sets=-1;
6796
6864
  word_states=make_new_set(&sets);    /* Start of new word */
6797
6865
  start_states=make_new_set(&sets);    /* This is first state */
6798
 
  vector<FOLLOWS> follow(states + 2);
6799
 
  FOLLOWS *follow_ptr= &follow[1];
 
6866
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6867
  {
 
6868
    free_sets(&sets);
 
6869
    free(found_set);
 
6870
    return(0);
 
6871
  }
 
6872
 
6800
6873
  /* Init follow_ptr[] */
6801
 
  for (i=0, states=1; i < count; i++)
 
6874
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6802
6875
  {
6803
6876
    if (from[i][0] == '\\' && from[i][1] == '^')
6804
6877
    {
6805
 
      start_states->internal_set_bit(states + 1);
 
6878
      internal_set_bit(start_states,states+1);
6806
6879
      if (!from[i][2])
6807
6880
      {
6808
6881
        start_states->table_offset=i;
6811
6884
    }
6812
6885
    else if (from[i][0] == '\\' && from[i][1] == '$')
6813
6886
    {
6814
 
      start_states->internal_set_bit(states);
6815
 
      word_states->internal_set_bit(states);
 
6887
      internal_set_bit(start_states,states);
 
6888
      internal_set_bit(word_states,states);
6816
6889
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6817
6890
      {
6818
6891
        start_states->table_offset=i;
6821
6894
    }
6822
6895
    else
6823
6896
    {
6824
 
      word_states->internal_set_bit(states);
 
6897
      internal_set_bit(word_states,states);
6825
6898
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6826
 
        start_states->internal_set_bit(states + 1);
 
6899
        internal_set_bit(start_states,states+1);
6827
6900
      else
6828
 
        start_states->internal_set_bit(states);
 
6901
        internal_set_bit(start_states,states);
6829
6902
    }
6830
 
    const char *pos;
6831
 
    for (pos= from[i], len=0; *pos ; pos++)
 
6903
    for (pos=from[i], len=0; *pos ; pos++)
6832
6904
    {
6833
6905
      if (*pos == '\\' && *(pos+1))
6834
6906
      {
6871
6943
  }
6872
6944
 
6873
6945
 
6874
 
  for (set_nr=0; set_nr < sets.count ; set_nr++)
 
6946
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6875
6947
  {
6876
6948
    set=sets.set+set_nr;
6877
6949
    default_state= 0;        /* Start from beginning */
6878
6950
 
6879
6951
    /* If end of found-string not found or start-set with current set */
6880
6952
 
6881
 
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
 
6953
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6882
6954
    {
6883
 
      if (!follow[i].chr && !default_state)
6884
 
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
 
6955
      if (!follow[i].chr)
 
6956
      {
 
6957
        if (! default_state)
 
6958
          default_state= find_found(found_set,set->table_offset,
 
6959
                                    set->found_offset+1);
 
6960
      }
6885
6961
    }
6886
 
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
 
6962
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6887
6963
    if (!default_state)
6888
 
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
 
6964
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
6889
6965
 
6890
6966
    /* Find all chars that follows current sets */
6891
6967
    memset(used_chars, 0, sizeof(used_chars));
6892
 
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
 
6968
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6893
6969
    {
6894
6970
      used_chars[follow[i].chr]=1;
6895
6971
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6899
6975
 
6900
6976
    /* Mark word_chars used if \b is in state */
6901
6977
    if (used_chars[SPACE_CHAR])
6902
 
      for (const char *pos= word_end_chars ; *pos ; pos++)
 
6978
      for (pos= word_end_chars ; *pos ; pos++)
6903
6979
        used_chars[(int) (unsigned char) *pos] = 1;
6904
6980
 
6905
6981
    /* Handle other used characters */
6916
6992
        new_set->found_offset=set->found_offset+1;
6917
6993
        found_end=0;
6918
6994
 
6919
 
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
 
6995
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6920
6996
        {
6921
6997
          if (!follow[i].chr || follow[i].chr == chr ||
6922
6998
              (follow[i].chr == SPACE_CHAR &&
6928
7004
                follow[i].len > found_end)
6929
7005
              found_end=follow[i].len;
6930
7006
            if (chr && follow[i].chr)
6931
 
              new_set->internal_set_bit(i + 1);    /* To next set */
 
7007
              internal_set_bit(new_set,i+1);    /* To next set */
6932
7008
            else
6933
 
              new_set->internal_set_bit(i);
 
7009
              internal_set_bit(new_set,i);
6934
7010
          }
6935
7011
        }
6936
7012
        if (found_end)
6937
7013
        {
6938
7014
          new_set->found_len=0;      /* Set for testing if first */
6939
7015
          bits_set=0;
6940
 
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
 
7016
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6941
7017
          {
6942
7018
            if ((follow[i].chr == SPACE_CHAR ||
6943
7019
                 follow[i].chr == END_OF_LINE) && ! chr)
6947
7023
            if (follow[bit_nr-1].len < found_end ||
6948
7024
                (new_set->found_len &&
6949
7025
                 (chr == 0 || !follow[bit_nr].chr)))
6950
 
              new_set->internal_clear_bit(i);
 
7026
              internal_clear_bit(new_set,i);
6951
7027
            else
6952
7028
            {
6953
7029
              if (chr == 0 || !follow[bit_nr].chr)
6963
7039
          }
6964
7040
          if (bits_set == 1)
6965
7041
          {
6966
 
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6967
 
            sets.free_last_set();
 
7042
            set->next[chr] = find_found(found_set,
 
7043
                                        new_set->table_offset,
 
7044
                                        new_set->found_offset);
 
7045
            free_last_set(&sets);
6968
7046
          }
6969
7047
          else
6970
 
            set->next[chr] = sets.find_set(new_set);
 
7048
            set->next[chr] = find_set(&sets,new_set);
6971
7049
        }
6972
7050
        else
6973
 
          set->next[chr] = sets.find_set(new_set);
 
7051
          set->next[chr] = find_set(&sets,new_set);
6974
7052
      }
6975
7053
    }
6976
7054
  }
6977
7055
 
6978
7056
  /* Alloc replace structure for the replace-state-machine */
6979
7057
 
6980
 
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6981
 
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
6982
 
  if (replace)
 
7058
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
 
7059
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
 
7060
                                 sizeof(char *)*count+result_len)))
6983
7061
  {
6984
7062
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6985
7063
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6996
7074
    rep_str[0].replace_string=0;
6997
7075
    for (i=1 ; i <= found_sets ; i++)
6998
7076
    {
6999
 
      const char *pos= from[found_set[i-1].table_offset];
 
7077
      pos=from[found_set[i-1].table_offset];
7000
7078
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7001
 
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
7002
 
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
7003
 
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
 
7079
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
 
7080
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
 
7081
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
 
7082
        end_of_word(pos);
7004
7083
    }
7005
7084
    for (i=0 ; i < sets.count ; i++)
7006
7085
    {
7011
7090
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7012
7091
    }
7013
7092
  }
7014
 
  sets.free_sets();
7015
 
  return replace;
 
7093
  free(follow);
 
7094
  free_sets(&sets);
 
7095
  free(found_set);
 
7096
  return(replace);
7016
7097
}
7017
7098
 
7018
7099
 
7033
7114
 
7034
7115
/* Make help sets invisible for nicer codeing */
7035
7116
 
7036
 
void REP_SETS::make_sets_invisible()
 
7117
void make_sets_invisible(REP_SETS *sets)
7037
7118
{
7038
 
  invisible= count;
7039
 
  set += count;
7040
 
  count= 0;
 
7119
  sets->invisible=sets->count;
 
7120
  sets->set+=sets->count;
 
7121
  sets->count=0;
7041
7122
}
7042
7123
 
7043
7124
REP_SET *make_new_set(REP_SETS *sets)
7075
7156
  return make_new_set(sets);
7076
7157
}
7077
7158
 
7078
 
void REP_SETS::free_last_set()
7079
 
{
7080
 
  count--;
7081
 
  extra++;
7082
 
}
7083
 
 
7084
 
void REP_SETS::free_sets()
7085
 
{
7086
 
  free(set_buffer);
7087
 
  free(bit_buffer);
7088
 
}
7089
 
 
7090
 
void REP_SET::internal_set_bit(uint32_t bit)
7091
 
{
7092
 
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7093
 
}
7094
 
 
7095
 
void REP_SET::internal_clear_bit(uint32_t bit)
7096
 
{
7097
 
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7098
 
}
7099
 
 
7100
 
 
7101
 
void REP_SET::or_bits(const REP_SET *from)
7102
 
{
7103
 
  for (uint32_t i= 0 ; i < size_of_bits; i++)
7104
 
    bits[i]|=from->bits[i];
7105
 
}
7106
 
 
7107
 
void REP_SET::copy_bits(const REP_SET *from)
7108
 
{
7109
 
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
7110
 
}
7111
 
 
7112
 
int REP_SET::cmp_bits(const REP_SET *set2) const
7113
 
{
7114
 
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
7115
 
}
 
7159
void free_last_set(REP_SETS *sets)
 
7160
{
 
7161
  sets->count--;
 
7162
  sets->extra++;
 
7163
  return;
 
7164
}
 
7165
 
 
7166
void free_sets(REP_SETS *sets)
 
7167
{
 
7168
  free(sets->set_buffer);
 
7169
  free(sets->bit_buffer);
 
7170
  return;
 
7171
}
 
7172
 
 
7173
void internal_set_bit(REP_SET *set, uint32_t bit)
 
7174
{
 
7175
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
7176
  return;
 
7177
}
 
7178
 
 
7179
void internal_clear_bit(REP_SET *set, uint32_t bit)
 
7180
{
 
7181
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
7182
  return;
 
7183
}
 
7184
 
 
7185
 
 
7186
void or_bits(REP_SET *to,REP_SET *from)
 
7187
{
 
7188
  register uint32_t i;
 
7189
  for (i=0 ; i < to->size_of_bits ; i++)
 
7190
    to->bits[i]|=from->bits[i];
 
7191
  return;
 
7192
}
 
7193
 
 
7194
void copy_bits(REP_SET *to,REP_SET *from)
 
7195
{
 
7196
  memcpy(to->bits,from->bits,
 
7197
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
 
7198
}
 
7199
 
 
7200
int cmp_bits(REP_SET *set1,REP_SET *set2)
 
7201
{
 
7202
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
 
7203
}
 
7204
 
7116
7205
 
7117
7206
/* Get next set bit from set. */
7118
7207
 
7119
 
int REP_SET::get_next_bit(uint32_t lastpos) const
 
7208
int get_next_bit(REP_SET *set,uint32_t lastpos)
7120
7209
{
7121
 
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
7122
 
  uint32_t *end= bits + size_of_bits;
7123
 
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7124
 
 
7125
 
  while (!bits0 && ++start < end)
7126
 
    bits0= start[0];
7127
 
  if (!bits0)
 
7210
  uint32_t pos,*start,*end,bits;
 
7211
 
 
7212
  start=set->bits+ ((lastpos+1) / WORD_BIT);
 
7213
  end=set->bits + set->size_of_bits;
 
7214
  bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
7215
 
 
7216
  while (! bits && ++start < end)
 
7217
    bits=start[0];
 
7218
  if (!bits)
7128
7219
    return 0;
7129
 
  uint32_t pos= (start - bits) * WORD_BIT;
7130
 
  while (!(bits0 & 1))
 
7220
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
7221
  while (! (bits & 1))
7131
7222
  {
7132
 
    bits0 >>=1;
 
7223
    bits>>=1;
7133
7224
    pos++;
7134
7225
  }
7135
7226
  return pos;
7139
7230
   free given set, else put in given set in sets and return its
7140
7231
   position */
7141
7232
 
7142
 
int REP_SETS::find_set(const REP_SET *find)
 
7233
int find_set(REP_SETS *sets,REP_SET *find)
7143
7234
{
7144
 
  uint32_t i= 0;
7145
 
  for (; i < count - 1; i++)
 
7235
  uint32_t i;
 
7236
  for (i=0 ; i < sets->count-1 ; i++)
7146
7237
  {
7147
 
    if (!set[i].cmp_bits(find))
 
7238
    if (!cmp_bits(sets->set+i,find))
7148
7239
    {
7149
 
      free_last_set();
 
7240
      free_last_set(sets);
7150
7241
      return i;
7151
7242
    }
7152
7243
  }
7160
7251
   set->next[] == -1 is reserved for end without replaces.
7161
7252
*/
7162
7253
 
7163
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
 
7254
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7164
7255
{
7165
 
  uint32_t i= 0;
7166
 
  for (; i < found_sets; i++)
7167
 
  {
 
7256
  int i;
 
7257
  for (i=0 ; (uint32_t) i < found_sets ; i++)
7168
7258
    if (found_set[i].table_offset == table_offset &&
7169
7259
        found_set[i].found_offset == found_offset)
7170
 
      return - i - 2;
7171
 
  }
7172
 
  found_set[i].table_offset= table_offset;
7173
 
  found_set[i].found_offset= found_offset;
 
7260
      return -i-2;
 
7261
  found_set[i].table_offset=table_offset;
 
7262
  found_set[i].found_offset=found_offset;
7174
7263
  found_sets++;
7175
 
  return - i - 2; // return new postion
 
7264
  return -i-2;        /* return new postion */
 
7265
}
 
7266
 
 
7267
/* Return 1 if regexp starts with \b or ends with \b*/
 
7268
 
 
7269
uint32_t start_at_word(char * pos)
 
7270
{
 
7271
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
 
7272
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
7273
}
 
7274
 
 
7275
uint32_t end_of_word(char * pos)
 
7276
{
 
7277
  char * end= strchr(pos, '\0');
 
7278
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
 
7279
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7176
7280
}
7177
7281
 
7178
7282
/****************************************************************************
7251
7355
} /* insert_pointer_name */
7252
7356
 
7253
7357
 
 
7358
/* free pointer array */
 
7359
 
 
7360
void free_pointer_array(POINTER_ARRAY *pa)
 
7361
{
 
7362
  if (pa->typelib.count)
 
7363
  {
 
7364
    pa->typelib.count=0;
 
7365
    free((char*) pa->typelib.type_names);
 
7366
    pa->typelib.type_names=0;
 
7367
    free(pa->str);
 
7368
  }
 
7369
} /* free_pointer_array */
 
7370
 
 
7371
 
7254
7372
/* Functions that uses replace and replace_regex */
7255
7373
 
7256
7374
/* Append the string to ds, with optional replace */
7257
 
void replace_append_mem(string *ds, const char *val, int len)
 
7375
void replace_append_mem(string *ds,
 
7376
                        const char *val, int len)
7258
7377
{
7259
7378
  char *v= strdup(val);
7260
7379
 
7261
 
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
 
7380
  if (glob_replace_regex)
7262
7381
  {
7263
 
    v= glob_replace_regex->buf_;
7264
 
    len= strlen(v);
 
7382
    /* Regex replace */
 
7383
    if (!multi_reg_replace(glob_replace_regex, v))
 
7384
    {
 
7385
      v= glob_replace_regex->buf;
 
7386
      len= strlen(v);
 
7387
    }
7265
7388
  }
 
7389
 
7266
7390
  if (glob_replace)
7267
7391
  {
7268
7392
    /* Normal replace */
7269
7393
    replace_strings_append(glob_replace, ds, v, len);
7270
7394
  }
7271
7395
  else
 
7396
  {
7272
7397
    ds->append(v, len);
 
7398
  }
7273
7399
}
7274
7400
 
7275
7401
 
7338
7464
 
7339
7465
  return;
7340
7466
}
7341
 
 
7342
 
static void free_all_replace()
7343
 
{
7344
 
  free_replace();
7345
 
  glob_replace_regex.reset();
7346
 
  free_replace_column();
7347
 
}