~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Barry.Leslie at PrimeBase
  • Date: 2011-02-21 16:33:37 UTC
  • mfrom: (2187 drizzle-build)
  • mto: (2228.1.4 build)
  • mto: This revision was merged to the branch mainline in revision 2230.
  • Revision ID: barry.leslie@primebase.com-20110221163337-cq8dq6u3ga9suxt7
Merged with trunk.

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>
59
61
#include <boost/program_options.hpp>
 
62
#include <boost/smart_ptr.hpp>
60
63
 
61
64
#include PCRE_HEADER
62
65
 
64
67
#include <boost/unordered_map.hpp>
65
68
 
66
69
/* Added this for string translation. */
67
 
#include "drizzled/gettext.h"
68
 
#include "drizzled/type/time.h"
69
 
#include "drizzled/charset.h"
70
 
#include "drizzled/typelib.h"
 
70
#include <drizzled/gettext.h>
 
71
#include <drizzled/type/time.h>
 
72
#include <drizzled/charset.h>
 
73
#include <drizzled/typelib.h>
71
74
#include <drizzled/configmake.h>
72
75
 
 
76
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
 
77
 
73
78
#ifndef DRIZZLE_RETURN_SERVER_GONE
74
79
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
75
80
#endif
116
121
static bool is_windows= false;
117
122
static bool use_drizzle_protocol= false;
118
123
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
 
124
static void free_all_replace();
119
125
 
120
126
std::string opt_basedir,
121
127
  opt_charsets_dir,
165
171
  uint32_t lineno; /* Current line in file */
166
172
};
167
173
 
168
 
static struct st_test_file file_stack[16];
169
 
static struct st_test_file* cur_file;
170
 
static struct st_test_file* file_stack_end;
171
 
 
 
174
static boost::array<st_test_file, 16> file_stack;
 
175
static st_test_file* cur_file;
172
176
 
173
177
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
174
178
 
178
182
*/
179
183
static char *timer_file = NULL;
180
184
static uint64_t timer_start;
181
 
static void timer_output(void);
182
 
static uint64_t timer_now(void);
 
185
static void timer_output();
 
186
static uint64_t timer_now();
183
187
 
184
188
static uint64_t progress_start= 0;
185
189
 
200
204
 
201
205
/* if set, all results are concated and compared against this file */
202
206
 
203
 
typedef struct st_var
 
207
class VAR
204
208
{
 
209
public:
205
210
  char *name;
206
211
  int name_len;
207
212
  char *str_val;
211
216
  int int_dirty; /* do not update string if int is updated until first read */
212
217
  int alloced;
213
218
  char *env_s;
214
 
} VAR;
 
219
};
215
220
 
216
221
/*Perl/shell-like variable registers */
217
 
VAR var_reg[10];
218
 
 
219
 
 
220
 
boost::unordered_map<string, VAR *> var_hash;
 
222
boost::array<VAR, 10> var_reg;
 
223
 
 
224
typedef boost::unordered_map<string, VAR *> var_hash_t;
 
225
var_hash_t var_hash;
221
226
 
222
227
struct st_connection
223
228
{
390
395
  struct st_match_err err[10];
391
396
  uint32_t count;
392
397
};
393
 
static struct st_expected_errors saved_expected_errors;
394
 
 
395
 
struct st_command
 
398
 
 
399
static st_expected_errors saved_expected_errors;
 
400
 
 
401
class st_command
396
402
{
 
403
public:
397
404
  char *query, *query_buf,*first_argument,*last_argument,*end;
398
405
  int first_word_len, query_len;
399
406
  bool abort_on_error;
400
407
  st_expected_errors expected_errors;
401
408
  string require_file;
402
 
  enum enum_commands type;
 
409
  enum_commands type;
403
410
 
404
411
  st_command()
405
412
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
411
418
 
412
419
  ~st_command()
413
420
  {
414
 
    if (query_buf != NULL)
415
 
    {
416
 
      free(query_buf);
417
 
    }
 
421
    free(query_buf);
418
422
  }
419
423
};
420
424
 
439
443
VAR* var_from_env(const char *, const char *);
440
444
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
441
445
              int val_len);
442
 
void var_free(pair<string, VAR*> v);
443
446
VAR* var_get(const char *var_name, const char** var_name_end,
444
447
             bool raw, bool ignore_not_existing);
445
448
void eval_expr(VAR* v, const char *p, const char** p_end);
446
449
bool match_delimiter(int c, const char *delim, uint32_t length);
447
450
void dump_result_to_reject_file(char *buf, int size);
448
451
void dump_result_to_log_file(const char *buf, int size);
449
 
void dump_warning_messages(void);
450
 
void dump_progress(void);
 
452
void dump_warning_messages();
 
453
void dump_progress();
451
454
 
452
455
void do_eval(string *query_eval, const char *query,
453
456
             const char *query_end, bool pass_through_escape_chars);
458
461
static char *replace_column[MAX_COLUMNS];
459
462
static uint32_t max_replace_column= 0;
460
463
void do_get_replace_column(struct st_command*);
461
 
void free_replace_column(void);
 
464
void free_replace_column();
462
465
 
463
466
/* For replace */
464
467
void do_get_replace(struct st_command *command);
465
 
void free_replace(void);
 
468
void free_replace();
466
469
 
467
470
/* For replace_regex */
468
471
void do_get_replace_regex(struct st_command *command);
469
 
void free_replace_regex(void);
470
 
 
471
 
 
472
 
void free_all_replace(void);
473
 
 
474
 
 
475
 
void free_all_replace(void){
476
 
  free_replace();
477
 
  free_replace_regex();
478
 
  free_replace_column();
479
 
}
480
472
 
481
473
void replace_append_mem(string *ds, const char *val,
482
474
                        int len);
493
485
void do_eval(string *query_eval, const char *query,
494
486
             const char *query_end, bool pass_through_escape_chars)
495
487
{
496
 
  const char *p;
497
 
  register char c, next_c;
498
 
  register int escaped = 0;
 
488
  char c, next_c;
 
489
  int escaped = 0;
499
490
  VAR *v;
500
491
 
501
 
 
502
 
  for (p= query; (c= *p) && p < query_end; ++p)
 
492
  for (const char *p= query; (c= *p) && p < query_end; ++p)
503
493
  {
504
494
    switch(c) {
505
495
    case '$':
873
863
}
874
864
 
875
865
 
876
 
static void close_connections(void)
 
866
static void close_connections()
877
867
{
878
868
  for (--next_con; next_con >= connections; --next_con)
879
869
  {
884
874
    }
885
875
    free(next_con->name);
886
876
  }
887
 
  return;
888
877
}
889
878
 
890
879
 
891
 
static void close_files(void)
 
880
static void close_files()
892
881
{
893
 
 
894
 
  for (; cur_file >= file_stack; cur_file--)
 
882
  for (; cur_file >= file_stack.data(); cur_file--)
895
883
  {
896
884
    if (cur_file->file && cur_file->file != stdin)
897
 
    {
898
885
      fclose(cur_file->file);
899
 
    }
900
 
    free((unsigned char*) cur_file->file_name);
 
886
    free(const_cast<char*>(cur_file->file_name));
901
887
    cur_file->file_name= 0;
902
888
  }
903
 
  return;
904
889
}
905
890
 
906
 
 
907
 
static void free_used_memory(void)
 
891
static void free_used_memory()
908
892
{
909
 
  uint32_t i;
910
 
 
911
 
 
912
893
  close_connections();
913
894
  close_files();
914
 
  for_each(var_hash.begin(), var_hash.end(), var_free);
 
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
  }
915
902
  var_hash.clear();
916
 
 
917
 
  vector<st_command *>::iterator iter;
918
 
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
919
 
  {
920
 
    struct st_command * q_line= *iter;
921
 
    delete q_line;
922
 
  }
923
 
 
924
 
  for (i= 0; i < 10; i++)
 
903
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
 
904
    delete i;
 
905
  for (size_t i= 0; i < var_reg.size(); i++)
925
906
  {
926
907
    if (var_reg[i].alloced_len)
927
908
      free(var_reg[i].str_val);
928
909
  }
929
 
 
930
910
  free_all_replace();
931
911
  free(opt_pass);
932
 
 
933
 
  return;
934
912
}
935
913
 
936
914
 
955
933
      assert(0);
956
934
    }
957
935
  }
958
 
 
959
936
  exit(exit_code);
960
937
}
961
938
 
975
952
 
976
953
  /* Print the error message */
977
954
  fprintf(stderr, "drizzletest: ");
978
 
  if (cur_file && cur_file != file_stack)
 
955
  if (cur_file && cur_file != file_stack.data())
979
956
    fprintf(stderr, "In included file \"%s\": ",
980
957
            cur_file->file_name);
981
958
  if (start_lineno > 0)
1036
1013
 
1037
1014
  /* Print include filestack */
1038
1015
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1039
 
          file_stack->file_name);
 
1016
          file_stack[0].file_name);
1040
1017
  fprintf(stderr, "Detected in file %s at line %d\n",
1041
1018
          err_file->file_name, err_file->lineno);
1042
 
  while (err_file != file_stack)
 
1019
  while (err_file != file_stack.data())
1043
1020
  {
1044
1021
    err_file--;
1045
1022
    fprintf(stderr, "included from %s at line %d\n",
1070
1047
 
1071
1048
  va_start(args, fmt);
1072
1049
  fprintf(stderr, "drizzletest: ");
1073
 
  if (cur_file && cur_file != file_stack)
 
1050
  if (cur_file && cur_file != file_stack.data())
1074
1051
    fprintf(stderr, "In included file \"%s\": ",
1075
1052
            cur_file->file_name);
1076
1053
  if (start_lineno != 0)
1078
1055
  vfprintf(stderr, fmt, args);
1079
1056
  fprintf(stderr, "\n");
1080
1057
  va_end(args);
1081
 
 
1082
 
  return;
1083
1058
}
1084
1059
 
1085
1060
 
1095
1070
  if (start_lineno != 0)
1096
1071
  {
1097
1072
    ds_warning_messages.append("Warning detected ");
1098
 
    if (cur_file && cur_file != file_stack)
 
1073
    if (cur_file && cur_file != file_stack.data())
1099
1074
    {
1100
1075
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1101
1076
                    cur_file->file_name);
1628
1603
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1629
1604
              int val_len)
1630
1605
{
1631
 
  int val_alloc_len;
1632
 
  VAR *tmp_var;
1633
1606
  if (!name_len && name)
1634
1607
    name_len = strlen(name);
1635
1608
  if (!val_len && val)
1636
1609
    val_len = strlen(val) ;
1637
 
  val_alloc_len = val_len + 16; /* room to grow */
1638
 
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
1639
 
                                               + name_len+1)))
1640
 
    die("Out of memory");
 
1610
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
1641
1611
 
1642
 
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
 
1612
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
1643
1613
  tmp_var->alloced = (v == 0);
1644
1614
 
1645
 
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
1646
 
    die("Out of memory");
 
1615
  int val_alloc_len = val_len + 16; /* room to grow */
 
1616
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
1647
1617
 
1648
1618
  memcpy(tmp_var->name, name, name_len);
1649
1619
  if (val)
1654
1624
  tmp_var->name_len = name_len;
1655
1625
  tmp_var->str_val_len = val_len;
1656
1626
  tmp_var->alloced_len = val_alloc_len;
1657
 
  tmp_var->int_val = (val) ? atoi(val) : 0;
1658
 
  tmp_var->int_dirty = 0;
 
1627
  tmp_var->int_val = val ? atoi(val) : 0;
 
1628
  tmp_var->int_dirty = false;
1659
1629
  tmp_var->env_s = 0;
1660
1630
  return tmp_var;
1661
1631
}
1662
1632
 
1663
 
 
1664
 
void var_free(pair<string, VAR *> v)
1665
 
{
1666
 
  free(v.second->str_val);
1667
 
  free(v.second->env_s);
1668
 
  if (v.second->alloced)
1669
 
    free(v.second);
1670
 
}
1671
 
 
1672
 
 
1673
1633
VAR* var_from_env(const char *name, const char *def_val)
1674
1634
{
1675
 
  const char *tmp;
1676
 
  VAR *v;
1677
 
  if (!(tmp = getenv(name)))
 
1635
  const char *tmp= getenv(name);
 
1636
  if (!tmp)
1678
1637
    tmp = def_val;
1679
 
 
1680
 
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1681
 
  string var_name(name);
1682
 
  var_hash.insert(make_pair(var_name, v));
1683
 
  return v;
 
1638
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
1684
1639
}
1685
1640
 
1686
 
 
1687
1641
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1688
1642
             bool ignore_not_existing)
1689
1643
{
1690
1644
  int digit;
1691
1645
  VAR *v;
1692
 
 
1693
1646
  if (*var_name != '$')
1694
1647
    goto err;
1695
1648
  digit = *++var_name - '0';
1711
1664
      die("Too long variable name: %s", save_var_name);
1712
1665
 
1713
1666
    string save_var_name_str(save_var_name, length);
1714
 
    boost::unordered_map<string, VAR*>::iterator iter=
1715
 
      var_hash.find(save_var_name_str);
 
1667
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
1716
1668
    if (iter == var_hash.end())
1717
1669
    {
1718
1670
      char buff[MAX_VAR_NAME_LENGTH+1];
1722
1674
    }
1723
1675
    else
1724
1676
    {
1725
 
      v= (*iter).second;
 
1677
      v= iter->second;
1726
1678
    }
1727
1679
    var_name--;  /* Point at last character */
1728
1680
  }
1729
1681
  else
1730
 
    v = var_reg + digit;
 
1682
    v = &var_reg[digit];
1731
1683
 
1732
1684
  if (!raw && v->int_dirty)
1733
1685
  {
1749
1701
static VAR *var_obtain(const char *name, int len)
1750
1702
{
1751
1703
  string var_name(name, len);
1752
 
  boost::unordered_map<string, VAR*>::iterator iter=
1753
 
    var_hash.find(var_name);
 
1704
  var_hash_t::iterator iter= var_hash.find(var_name);
1754
1705
  if (iter != var_hash.end())
1755
 
    return (*iter).second;
1756
 
  VAR *v = var_init(0, name, len, "", 0);
1757
 
  var_hash.insert(make_pair(var_name, v));
1758
 
  return v;
 
1706
    return iter->second;
 
1707
  return var_hash[var_name] = var_init(0, name, len, "", 0);
1759
1708
}
1760
1709
 
1761
1710
 
1782
1731
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1783
1732
  }
1784
1733
  else
1785
 
    v= var_reg + digit;
 
1734
    v= &var_reg[digit];
1786
1735
 
1787
1736
  eval_expr(v, var_val, (const char**) &var_val_end);
1788
1737
 
2066
2015
    eval_expr(var, value, 0);
2067
2016
  }
2068
2017
  drizzle_result_free(&res);
2069
 
 
2070
 
  return;
2071
2018
}
2072
2019
 
2073
2020
 
2098
2045
{
2099
2046
  if (*p == '$')
2100
2047
  {
2101
 
    VAR *vp;
2102
 
    if ((vp= var_get(p, p_end, 0, 0)))
 
2048
    VAR *vp= var_get(p, p_end, 0, 0);
 
2049
    if (vp)
2103
2050
      var_copy(v, vp);
2104
2051
    return;
2105
2052
  }
2160
2107
  }
2161
2108
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2162
2109
 
2163
 
  if (cur_file == file_stack_end)
 
2110
  cur_file++;
 
2111
  if (cur_file == &*file_stack.end())
2164
2112
    die("Source directives are nesting too deep");
2165
 
  cur_file++;
2166
2113
  if (!(cur_file->file= fopen(buff, "r")))
2167
2114
  {
2168
2115
    cur_file--;
2224
2171
}
2225
2172
 
2226
2173
 
2227
 
static void init_builtin_echo(void)
 
2174
static void init_builtin_echo()
2228
2175
{
2229
2176
  builtin_echo[0]= 0;
2230
 
  return;
2231
2177
}
2232
2178
 
2233
2179
 
3190
3136
  when ndb binlog is on, this call will wait until last updated epoch
3191
3137
  (locally in the drizzled) has been received into the binlog
3192
3138
*/
3193
 
static int do_save_master_pos(void)
 
3139
static int do_save_master_pos()
3194
3140
{
3195
3141
  drizzle_result_st res;
3196
3142
  drizzle_return_t ret;
3329
3275
    sleep_val= opt_sleep;
3330
3276
 
3331
3277
  if (sleep_val)
3332
 
    usleep((uint32_t) (sleep_val * 1000000L));
 
3278
    usleep(sleep_val * 1000000);
3333
3279
  command->last_argument= sleep_end;
3334
3280
  return 0;
3335
3281
}
3336
3282
 
3337
3283
 
3338
 
static void do_get_file_name(struct st_command *command, string &dest)
 
3284
static void do_get_file_name(st_command *command, string &dest)
3339
3285
{
3340
 
  char *p= command->first_argument, *name;
 
3286
  char *p= command->first_argument;
3341
3287
  if (!*p)
3342
3288
    die("Missing file name argument");
3343
 
  name= p;
 
3289
  char *name= p;
3344
3290
  while (*p && !my_isspace(charset_info,*p))
3345
3291
    p++;
3346
3292
  if (*p)
3415
3361
      and assign that string to the $variable
3416
3362
    */
3417
3363
    size_t *lengths= drizzle_row_field_sizes(&res);
3418
 
    const std::string error_name(row[0], lengths[0]);
3419
 
    const std::string error_code(row[1], lengths[1]);
3420
 
 
3421
3364
    try
3422
3365
    {
3423
 
      global_error_names.insert(ErrorCodes::value_type(error_name,
3424
 
                                                       boost::lexical_cast<uint32_t>(error_code)));
 
3366
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3425
3367
    }
3426
3368
    catch (boost::bad_lexical_cast &ex)
3427
3369
    {
3441
3383
 
3442
3384
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3443
3385
  if (it != global_error_names.end())
3444
 
  {
3445
 
    return (*it).second;
3446
 
  }
 
3386
    return it->second;
3447
3387
 
3448
3388
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3449
3389
  return 0;
4064
4004
{
4065
4005
  char *p= command->first_argument;
4066
4006
  const char *expr_start, *expr_end;
4067
 
  VAR v;
4068
4007
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4069
4008
  bool not_expr= false;
4070
4009
 
4107
4046
  if (*p && *p != '{')
4108
4047
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4109
4048
 
 
4049
  VAR v;
4110
4050
  var_init(&v,0,0,0,0);
4111
4051
  eval_expr(&v, expr_start, &expr_end);
4112
4052
 
4242
4182
      }
4243
4183
      free((unsigned char*) cur_file->file_name);
4244
4184
      cur_file->file_name= 0;
4245
 
      if (cur_file == file_stack)
 
4185
      if (cur_file == file_stack.data())
4246
4186
      {
4247
4187
        /* We're back at the first file, check if
4248
4188
           all { have matching }
4682
4622
          log_file);
4683
4623
}
4684
4624
 
4685
 
void dump_progress(void)
 
4625
void dump_progress()
4686
4626
{
4687
4627
  char progress_file[FN_REFLEN];
4688
4628
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4692
4632
              ds_progress.c_str(), ds_progress.length());
4693
4633
}
4694
4634
 
4695
 
void dump_warning_messages(void)
 
4635
void dump_warning_messages()
4696
4636
{
4697
4637
  char warn_file[FN_REFLEN];
4698
4638
 
5517
5457
 
5518
5458
  if (user_config_dir.compare(0, 2, "~/") == 0)
5519
5459
  {
5520
 
    char *homedir;
5521
 
    homedir= getenv("HOME");
 
5460
    const char *homedir= getenv("HOME");
5522
5461
    if (homedir != NULL)
5523
5462
      user_config_dir.replace(0, 1, homedir);
5524
5463
  }
5565
5504
  next_con= connections + 1;
5566
5505
 
5567
5506
  /* Init file stack */
5568
 
  memset(file_stack, 0, sizeof(file_stack));
5569
 
  file_stack_end=
5570
 
    file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
5571
 
  cur_file= file_stack;
 
5507
  memset(file_stack.data(), 0, sizeof(file_stack));
 
5508
  cur_file= file_stack.data();
5572
5509
 
5573
5510
  /* Init block stack */
5574
5511
  memset(block_stack, 0, sizeof(block_stack));
5607
5544
      tmp= buff;
5608
5545
    }
5609
5546
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5610
 
    assert(cur_file == file_stack && cur_file->file == 0);
 
5547
    assert(cur_file == file_stack.data() && cur_file->file == 0);
5611
5548
    if (!(cur_file->file= fopen(buff, "r")))
5612
5549
    {
5613
5550
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5712
5649
  }
5713
5650
 
5714
5651
  server_initialized= 1;
5715
 
  if (cur_file == file_stack && cur_file->file == 0)
 
5652
  if (cur_file == file_stack.data() && cur_file->file == 0)
5716
5653
  {
5717
5654
    cur_file->file= stdin;
5718
5655
    cur_file->file_name= strdup("<stdin>");
6137
6074
  the time between executing the two commands.
6138
6075
*/
6139
6076
 
6140
 
void timer_output(void)
 
6077
void timer_output()
6141
6078
{
6142
6079
  if (timer_file)
6143
6080
  {
6151
6088
}
6152
6089
 
6153
6090
 
6154
 
uint64_t timer_now(void)
 
6091
uint64_t timer_now()
6155
6092
{
6156
6093
#if defined(HAVE_GETHRTIME)
6157
6094
  return gethrtime()/1000/1000;
6191
6128
  start= buff= (char *)malloc(strlen(from)+1);
6192
6129
  while (*from)
6193
6130
  {
6194
 
    char *to;
6195
6131
    uint32_t column_number;
6196
6132
 
6197
 
    to= get_string(&buff, &from, command);
 
6133
    char *to= get_string(&buff, &from, command);
6198
6134
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6199
6135
      die("Wrong column number to replace_column in '%s'", command->query);
6200
6136
    if (!*from)
6213
6149
 
6214
6150
void free_replace_column()
6215
6151
{
6216
 
  uint32_t i;
6217
 
  for (i=0 ; i < max_replace_column ; i++)
 
6152
  for (uint32_t i= 0 ; i < max_replace_column; i++)
6218
6153
  {
6219
 
    if (replace_column[i])
6220
 
    {
6221
 
      free(replace_column[i]);
6222
 
      replace_column[i]= 0;
6223
 
    }
 
6154
    free(replace_column[i]);
 
6155
    replace_column[i]= 0;
6224
6156
  }
6225
6157
  max_replace_column= 0;
6226
6158
}
6241
6173
} POINTER_ARRAY;
6242
6174
 
6243
6175
struct st_replace;
6244
 
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
6245
 
                                char * word_end_chars);
 
6176
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
 
6177
                                char *word_end_chars);
6246
6178
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6247
6179
void replace_strings_append(struct st_replace *rep, string* ds,
6248
6180
                            const char *from, int len);
6249
 
void free_pointer_array(POINTER_ARRAY *pa);
6250
6181
 
6251
 
struct st_replace *glob_replace= NULL;
 
6182
st_replace *glob_replace= NULL;
 
6183
// boost::scoped_ptr<st_replace> glob_replace;
6252
6184
 
6253
6185
/*
6254
6186
  Get arguments for replace. The syntax is:
6258
6190
  variable is replaced.
6259
6191
*/
6260
6192
 
 
6193
static void free_pointer_array(POINTER_ARRAY *pa)
 
6194
{
 
6195
  if (!pa->typelib.count)
 
6196
    return;
 
6197
  pa->typelib.count=0;
 
6198
  free((char*) pa->typelib.type_names);
 
6199
  pa->typelib.type_names=0;
 
6200
  free(pa->str);
 
6201
}
 
6202
 
6261
6203
void do_get_replace(struct st_command *command)
6262
6204
{
6263
6205
  uint32_t i;
6289
6231
    if (my_isspace(charset_info,i))
6290
6232
      *pos++= i;
6291
6233
  *pos=0;          /* End pointer */
6292
 
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6293
 
                                   (char**) to_array.typelib.type_names,
6294
 
                                   (uint32_t) from_array.typelib.count,
 
6234
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
 
6235
                                   to_array.typelib.type_names,
 
6236
                                   from_array.typelib.count,
6295
6237
                                   word_end_chars)))
6296
6238
    die("Can't initialize replace from '%s'", command->query);
6297
6239
  free_pointer_array(&from_array);
6304
6246
 
6305
6247
void free_replace()
6306
6248
{
6307
 
 
6308
 
  if (glob_replace)
6309
 
  {
6310
 
    free(glob_replace);
6311
 
    glob_replace=0;
6312
 
  }
6313
 
  return;
 
6249
  free(glob_replace);
 
6250
  glob_replace=0;
6314
6251
}
6315
6252
 
6316
6253
 
6330
6267
void replace_strings_append(REPLACE *rep, string* ds,
6331
6268
                            const char *str, int len)
6332
6269
{
6333
 
  register REPLACE *rep_pos;
6334
 
  register REPLACE_STRING *rep_str;
 
6270
  REPLACE *rep_pos;
 
6271
  REPLACE_STRING *rep_str;
6335
6272
  const char *start, *from;
6336
6273
 
6337
6274
 
6384
6321
                 i.e. repeat the matching until the end of the string */
6385
6322
};
6386
6323
 
6387
 
struct st_replace_regex
 
6324
class st_replace_regex
6388
6325
{
6389
 
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
 
6326
public:
 
6327
  st_replace_regex(char* expr);
 
6328
  int multi_reg_replace(char* val);
6390
6329
 
6391
6330
  /*
6392
6331
    Temporary storage areas for substitutions. To reduce unnessary copying
6395
6334
    st_regex substition. At the end of substitutions  buf points to the
6396
6335
    one containing the final result.
6397
6336
  */
6398
 
  char* buf;
 
6337
  typedef vector<st_regex> regex_arr_t;
 
6338
 
 
6339
  char* buf_;
6399
6340
  char* even_buf;
6400
6341
  char* odd_buf;
6401
6342
  int even_buf_len;
6402
6343
  int odd_buf_len;
 
6344
  boost::array<char, 8 << 10> buf0_;
 
6345
  boost::array<char, 8 << 10> buf1_;
 
6346
  regex_arr_t regex_arr;
6403
6347
};
6404
6348
 
6405
 
struct st_replace_regex *glob_replace_regex= 0;
 
6349
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
6406
6350
 
6407
6351
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6408
6352
                char *string, int icase, int global);
6444
6388
  Returns: st_replace_regex struct with pairs of substitutions
6445
6389
*/
6446
6390
 
6447
 
static struct st_replace_regex* init_replace_regex(char* expr)
 
6391
st_replace_regex::st_replace_regex(char* expr)
6448
6392
{
6449
 
  struct st_replace_regex* res;
6450
 
  char* buf,*expr_end;
6451
 
  char* p;
6452
 
  char* buf_p;
6453
6393
  uint32_t expr_len= strlen(expr);
6454
6394
  char last_c = 0;
6455
 
  struct st_regex reg;
6456
 
 
6457
 
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
6458
 
  if (!res)
6459
 
    return NULL;
6460
 
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
6461
 
 
6462
 
  buf= (char*)res + sizeof(*res);
6463
 
  expr_end= expr + expr_len;
6464
 
  p= expr;
6465
 
  buf_p= buf;
 
6395
  st_regex reg;
 
6396
 
 
6397
  char* buf= new char[expr_len];
 
6398
  char* expr_end= expr + expr_len;
 
6399
  char* p= expr;
 
6400
  char* buf_p= buf;
6466
6401
 
6467
6402
  /* for each regexp substitution statement */
6468
6403
  while (p < expr_end)
6478
6413
 
6479
6414
    if (p == expr_end || ++p == expr_end)
6480
6415
    {
6481
 
      if (res->regex_arr.elements)
 
6416
      if (!regex_arr.empty())
6482
6417
        break;
6483
6418
      else
6484
6419
        goto err;
6517
6452
      p++;
6518
6453
      reg.global= 1;
6519
6454
    }
6520
 
 
6521
 
    /* done parsing the statement, now place it in regex_arr */
6522
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
6523
 
      die("Out of memory");
 
6455
    regex_arr.push_back(reg);
6524
6456
  }
6525
 
  res->odd_buf_len= res->even_buf_len= 8192;
6526
 
  res->even_buf= (char*)malloc(res->even_buf_len);
6527
 
  res->odd_buf= (char*)malloc(res->odd_buf_len);
6528
 
  res->buf= res->even_buf;
 
6457
  odd_buf_len= even_buf_len= buf0_.size();
 
6458
  even_buf= buf0_.data();
 
6459
  odd_buf= buf1_.data();
 
6460
  buf_= even_buf;
6529
6461
 
6530
 
  return res;
 
6462
  return;
6531
6463
 
6532
6464
err:
6533
 
  free(res);
6534
6465
  die("Error parsing replace_regex \"%s\"", expr);
6535
 
  return 0;
6536
6466
}
6537
6467
 
6538
6468
/*
6554
6484
  in one pass
6555
6485
*/
6556
6486
 
6557
 
static int multi_reg_replace(struct st_replace_regex* r,char* val)
 
6487
int st_replace_regex::multi_reg_replace(char* val)
6558
6488
{
6559
 
  uint32_t i;
6560
 
  char* in_buf, *out_buf;
6561
 
  int* buf_len_p;
6562
 
 
6563
 
  in_buf= val;
6564
 
  out_buf= r->even_buf;
6565
 
  buf_len_p= &r->even_buf_len;
6566
 
  r->buf= 0;
 
6489
  char* in_buf= val;
 
6490
  char* out_buf= even_buf;
 
6491
  int* buf_len_p= &even_buf_len;
 
6492
  buf_= 0;
6567
6493
 
6568
6494
  /* For each substitution, do the replace */
6569
 
  for (i= 0; i < r->regex_arr.elements; i++)
 
6495
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
6570
6496
  {
6571
 
    struct st_regex re;
6572
6497
    char* save_out_buf= out_buf;
6573
 
 
6574
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
6575
 
 
6576
 
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6577
 
                     in_buf, re.icase, re.global))
 
6498
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
 
6499
                     in_buf, i.icase, i.global))
6578
6500
    {
6579
6501
      /* if the buffer has been reallocated, make adjustements */
6580
6502
      if (save_out_buf != out_buf)
6581
6503
      {
6582
 
        if (save_out_buf == r->even_buf)
6583
 
          r->even_buf= out_buf;
 
6504
        if (save_out_buf == even_buf)
 
6505
          even_buf= out_buf;
6584
6506
        else
6585
 
          r->odd_buf= out_buf;
 
6507
          odd_buf= out_buf;
6586
6508
      }
6587
 
 
6588
 
      r->buf= out_buf;
 
6509
      buf_= out_buf;
6589
6510
      if (in_buf == val)
6590
 
        in_buf= r->odd_buf;
6591
 
 
6592
 
      std::swap(in_buf,out_buf);
6593
 
 
6594
 
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6595
 
        &r->odd_buf_len;
 
6511
        in_buf= odd_buf;
 
6512
      std::swap(in_buf, out_buf);
 
6513
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
6596
6514
    }
6597
6515
  }
6598
 
 
6599
 
  return (r->buf == 0);
 
6516
  return buf_ == 0;
6600
6517
}
6601
6518
 
6602
6519
/*
6611
6528
void do_get_replace_regex(struct st_command *command)
6612
6529
{
6613
6530
  char *expr= command->first_argument;
6614
 
  free_replace_regex();
6615
 
  if (!(glob_replace_regex=init_replace_regex(expr)))
6616
 
    die("Could not init replace_regex");
 
6531
  glob_replace_regex.reset(new st_replace_regex(expr));
6617
6532
  command->last_argument= command->end;
6618
6533
}
6619
6534
 
6620
 
void free_replace_regex()
6621
 
{
6622
 
  if (glob_replace_regex)
6623
 
  {
6624
 
    delete_dynamic(&glob_replace_regex->regex_arr);
6625
 
    free(glob_replace_regex->even_buf);
6626
 
    free(glob_replace_regex->odd_buf);
6627
 
    free(glob_replace_regex);
6628
 
    glob_replace_regex=0;
6629
 
  }
6630
 
}
6631
 
 
6632
 
 
6633
 
 
6634
6535
/*
6635
6536
  Performs a regex substitution
6636
6537
 
6737
6638
#define SET_MALLOC_HUNC 64
6738
6639
#define LAST_CHAR_CODE 259
6739
6640
 
6740
 
typedef struct st_rep_set {
 
6641
class REP_SET
 
6642
{
 
6643
public:
 
6644
  void internal_set_bit(uint32_t bit);
 
6645
  void internal_clear_bit(uint32_t bit);
 
6646
  void or_bits(const REP_SET *from);
 
6647
  void copy_bits(const REP_SET *from);
 
6648
  int cmp_bits(const REP_SET *set2) const;
 
6649
  int get_next_bit(uint32_t lastpos) const;
 
6650
 
6741
6651
  uint32_t  *bits;        /* Pointer to used sets */
6742
6652
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6743
6653
  uint32_t  found_len;      /* Best match to date */
6744
6654
  int  found_offset;
6745
6655
  uint32_t  table_offset;
6746
6656
  uint32_t  size_of_bits;      /* For convinience */
6747
 
} REP_SET;
6748
 
 
6749
 
typedef struct st_rep_sets {
 
6657
};
 
6658
 
 
6659
class REP_SETS
 
6660
{
 
6661
public:
 
6662
  int find_set(const REP_SET *find);
 
6663
  void free_last_set();
 
6664
  void free_sets();
 
6665
  void make_sets_invisible();
 
6666
 
6750
6667
  uint32_t    count;      /* Number of sets */
6751
6668
  uint32_t    extra;      /* Extra sets in buffer */
6752
 
  uint32_t    invisible;    /* Sets not chown */
 
6669
  uint32_t    invisible;    /* Sets not shown */
6753
6670
  uint32_t    size_of_bits;
6754
6671
  REP_SET  *set,*set_buffer;
6755
6672
  uint32_t    *bit_buffer;
6756
 
} REP_SETS;
 
6673
};
6757
6674
 
6758
 
typedef struct st_found_set {
 
6675
struct FOUND_SET 
 
6676
{
6759
6677
  uint32_t table_offset;
6760
6678
  int found_offset;
6761
 
} FOUND_SET;
 
6679
};
6762
6680
 
6763
 
typedef struct st_follow {
 
6681
struct FOLLOWS
 
6682
{
6764
6683
  int chr;
6765
6684
  uint32_t table_offset;
6766
6685
  uint32_t len;
6767
 
} FOLLOWS;
6768
 
 
6769
 
 
6770
 
int init_sets(REP_SETS *sets,uint32_t states);
 
6686
};
 
6687
 
 
6688
int init_sets(REP_SETS *sets, uint32_t states);
6771
6689
REP_SET *make_new_set(REP_SETS *sets);
6772
 
void make_sets_invisible(REP_SETS *sets);
6773
 
void free_last_set(REP_SETS *sets);
6774
 
void free_sets(REP_SETS *sets);
6775
 
void internal_set_bit(REP_SET *set, uint32_t bit);
6776
 
void internal_clear_bit(REP_SET *set, uint32_t bit);
6777
 
void or_bits(REP_SET *to,REP_SET *from);
6778
 
void copy_bits(REP_SET *to,REP_SET *from);
6779
 
int cmp_bits(REP_SET *set1,REP_SET *set2);
6780
 
int get_next_bit(REP_SET *set,uint32_t lastpos);
6781
 
int find_set(REP_SETS *sets,REP_SET *find);
6782
 
int find_found(FOUND_SET *found_set,uint32_t table_offset,
6783
 
               int found_offset);
6784
 
uint32_t start_at_word(char * pos);
6785
 
uint32_t end_of_word(char * pos);
6786
 
 
6787
 
static uint32_t found_sets=0;
6788
 
 
6789
 
 
6790
 
static uint32_t replace_len(char * str)
 
6690
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
 
6691
 
 
6692
static uint32_t found_sets= 0;
 
6693
 
 
6694
static uint32_t replace_len(const char *str)
6791
6695
{
6792
6696
  uint32_t len=0;
6793
6697
  while (*str)
6800
6704
  return len;
6801
6705
}
6802
6706
 
 
6707
/* Return 1 if regexp starts with \b or ends with \b*/
 
6708
 
 
6709
static bool start_at_word(const char *pos)
 
6710
{
 
6711
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
 
6712
}
 
6713
 
 
6714
static bool end_of_word(const char *pos)
 
6715
{
 
6716
  const char *end= strchr(pos, '\0');
 
6717
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
 
6718
}
 
6719
 
6803
6720
/* Init a replace structure for further calls */
6804
6721
 
6805
 
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
6806
 
                      char * word_end_chars)
 
6722
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
6807
6723
{
6808
 
  static const int SPACE_CHAR= 256;
6809
 
  static const int START_OF_LINE= 257;
6810
 
  static const int END_OF_LINE= 258;
 
6724
  const int SPACE_CHAR= 256;
 
6725
  const int START_OF_LINE= 257;
 
6726
  const int END_OF_LINE= 258;
6811
6727
 
6812
6728
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6813
6729
  int used_sets,chr,default_state;
6814
6730
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6815
 
  char * pos, *to_pos, **to_array;
6816
 
  REP_SETS sets;
6817
 
  REP_SET *set,*start_states,*word_states,*new_set;
6818
 
  FOLLOWS *follow,*follow_ptr;
6819
 
  REPLACE *replace;
6820
 
  FOUND_SET *found_set;
6821
 
  REPLACE_STRING *rep_str;
6822
 
 
 
6731
  char *to_pos, **to_array;
6823
6732
 
6824
6733
  /* Count number of states */
6825
6734
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6839
6748
  for (i=0 ; word_end_chars[i] ; i++)
6840
6749
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6841
6750
 
6842
 
  if (init_sets(&sets,states))
6843
 
    return(0);
 
6751
  REP_SETS sets;
 
6752
  REP_SET *set,*start_states,*word_states,*new_set;
 
6753
  REPLACE_STRING *rep_str;
 
6754
  if (init_sets(&sets, states))
 
6755
    return 0;
6844
6756
  found_sets=0;
6845
 
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
6846
 
                                
6847
 
  {
6848
 
    free_sets(&sets);
6849
 
    return(0);
6850
 
  }
 
6757
  vector<FOUND_SET> found_set(max_length * count);
6851
6758
  make_new_set(&sets);      /* Set starting set */
6852
 
  make_sets_invisible(&sets);      /* Hide previus sets */
 
6759
  sets.make_sets_invisible();      /* Hide previus sets */
6853
6760
  used_sets=-1;
6854
6761
  word_states=make_new_set(&sets);    /* Start of new word */
6855
6762
  start_states=make_new_set(&sets);    /* This is first state */
6856
 
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
6857
 
  {
6858
 
    free_sets(&sets);
6859
 
    free(found_set);
6860
 
    return(0);
6861
 
  }
6862
 
 
 
6763
  vector<FOLLOWS> follow(states + 2);
 
6764
  FOLLOWS *follow_ptr= &follow[1];
6863
6765
  /* Init follow_ptr[] */
6864
 
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
 
6766
  for (i=0, states=1; i < count; i++)
6865
6767
  {
6866
6768
    if (from[i][0] == '\\' && from[i][1] == '^')
6867
6769
    {
6868
 
      internal_set_bit(start_states,states+1);
 
6770
      start_states->internal_set_bit(states + 1);
6869
6771
      if (!from[i][2])
6870
6772
      {
6871
6773
        start_states->table_offset=i;
6874
6776
    }
6875
6777
    else if (from[i][0] == '\\' && from[i][1] == '$')
6876
6778
    {
6877
 
      internal_set_bit(start_states,states);
6878
 
      internal_set_bit(word_states,states);
 
6779
      start_states->internal_set_bit(states);
 
6780
      word_states->internal_set_bit(states);
6879
6781
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6880
6782
      {
6881
6783
        start_states->table_offset=i;
6884
6786
    }
6885
6787
    else
6886
6788
    {
6887
 
      internal_set_bit(word_states,states);
 
6789
      word_states->internal_set_bit(states);
6888
6790
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6889
 
        internal_set_bit(start_states,states+1);
 
6791
        start_states->internal_set_bit(states + 1);
6890
6792
      else
6891
 
        internal_set_bit(start_states,states);
 
6793
        start_states->internal_set_bit(states);
6892
6794
    }
6893
 
    for (pos=from[i], len=0; *pos ; pos++)
 
6795
    const char *pos;
 
6796
    for (pos= from[i], len=0; *pos ; pos++)
6894
6797
    {
6895
6798
      if (*pos == '\\' && *(pos+1))
6896
6799
      {
6933
6836
  }
6934
6837
 
6935
6838
 
6936
 
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
 
6839
  for (set_nr=0; set_nr < sets.count ; set_nr++)
6937
6840
  {
6938
6841
    set=sets.set+set_nr;
6939
6842
    default_state= 0;        /* Start from beginning */
6940
6843
 
6941
6844
    /* If end of found-string not found or start-set with current set */
6942
6845
 
6943
 
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
 
6846
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
6944
6847
    {
6945
 
      if (!follow[i].chr)
6946
 
      {
6947
 
        if (! default_state)
6948
 
          default_state= find_found(found_set,set->table_offset,
6949
 
                                    set->found_offset+1);
6950
 
      }
 
6848
      if (!follow[i].chr && !default_state)
 
6849
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
6951
6850
    }
6952
 
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
 
6851
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
6953
6852
    if (!default_state)
6954
 
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
 
6853
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
6955
6854
 
6956
6855
    /* Find all chars that follows current sets */
6957
6856
    memset(used_chars, 0, sizeof(used_chars));
6958
 
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
 
6857
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
6959
6858
    {
6960
6859
      used_chars[follow[i].chr]=1;
6961
6860
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6965
6864
 
6966
6865
    /* Mark word_chars used if \b is in state */
6967
6866
    if (used_chars[SPACE_CHAR])
6968
 
      for (pos= word_end_chars ; *pos ; pos++)
 
6867
      for (const char *pos= word_end_chars ; *pos ; pos++)
6969
6868
        used_chars[(int) (unsigned char) *pos] = 1;
6970
6869
 
6971
6870
    /* Handle other used characters */
6982
6881
        new_set->found_offset=set->found_offset+1;
6983
6882
        found_end=0;
6984
6883
 
6985
 
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
6884
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
6986
6885
        {
6987
6886
          if (!follow[i].chr || follow[i].chr == chr ||
6988
6887
              (follow[i].chr == SPACE_CHAR &&
6994
6893
                follow[i].len > found_end)
6995
6894
              found_end=follow[i].len;
6996
6895
            if (chr && follow[i].chr)
6997
 
              internal_set_bit(new_set,i+1);    /* To next set */
 
6896
              new_set->internal_set_bit(i + 1);    /* To next set */
6998
6897
            else
6999
 
              internal_set_bit(new_set,i);
 
6898
              new_set->internal_set_bit(i);
7000
6899
          }
7001
6900
        }
7002
6901
        if (found_end)
7003
6902
        {
7004
6903
          new_set->found_len=0;      /* Set for testing if first */
7005
6904
          bits_set=0;
7006
 
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
 
6905
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
7007
6906
          {
7008
6907
            if ((follow[i].chr == SPACE_CHAR ||
7009
6908
                 follow[i].chr == END_OF_LINE) && ! chr)
7013
6912
            if (follow[bit_nr-1].len < found_end ||
7014
6913
                (new_set->found_len &&
7015
6914
                 (chr == 0 || !follow[bit_nr].chr)))
7016
 
              internal_clear_bit(new_set,i);
 
6915
              new_set->internal_clear_bit(i);
7017
6916
            else
7018
6917
            {
7019
6918
              if (chr == 0 || !follow[bit_nr].chr)
7029
6928
          }
7030
6929
          if (bits_set == 1)
7031
6930
          {
7032
 
            set->next[chr] = find_found(found_set,
7033
 
                                        new_set->table_offset,
7034
 
                                        new_set->found_offset);
7035
 
            free_last_set(&sets);
 
6931
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
 
6932
            sets.free_last_set();
7036
6933
          }
7037
6934
          else
7038
 
            set->next[chr] = find_set(&sets,new_set);
 
6935
            set->next[chr] = sets.find_set(new_set);
7039
6936
        }
7040
6937
        else
7041
 
          set->next[chr] = find_set(&sets,new_set);
 
6938
          set->next[chr] = sets.find_set(new_set);
7042
6939
      }
7043
6940
    }
7044
6941
  }
7045
6942
 
7046
6943
  /* Alloc replace structure for the replace-state-machine */
7047
6944
 
7048
 
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
7049
 
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
7050
 
                                 sizeof(char *)*count+result_len)))
 
6945
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
 
6946
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
 
6947
  if (replace)
7051
6948
  {
7052
6949
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
7053
6950
                       sizeof(REPLACE_STRING)*(found_sets+1)+
7064
6961
    rep_str[0].replace_string=0;
7065
6962
    for (i=1 ; i <= found_sets ; i++)
7066
6963
    {
7067
 
      pos=from[found_set[i-1].table_offset];
 
6964
      const char *pos= from[found_set[i-1].table_offset];
7068
6965
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7069
 
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
7070
 
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
7071
 
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
7072
 
        end_of_word(pos);
 
6966
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
 
6967
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
 
6968
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
7073
6969
    }
7074
6970
    for (i=0 ; i < sets.count ; i++)
7075
6971
    {
7080
6976
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7081
6977
    }
7082
6978
  }
7083
 
  free(follow);
7084
 
  free_sets(&sets);
7085
 
  free(found_set);
7086
 
  return(replace);
 
6979
  sets.free_sets();
 
6980
  return replace;
7087
6981
}
7088
6982
 
7089
6983
 
7104
6998
 
7105
6999
/* Make help sets invisible for nicer codeing */
7106
7000
 
7107
 
void make_sets_invisible(REP_SETS *sets)
 
7001
void REP_SETS::make_sets_invisible()
7108
7002
{
7109
 
  sets->invisible=sets->count;
7110
 
  sets->set+=sets->count;
7111
 
  sets->count=0;
 
7003
  invisible= count;
 
7004
  set += count;
 
7005
  count= 0;
7112
7006
}
7113
7007
 
7114
7008
REP_SET *make_new_set(REP_SETS *sets)
7146
7040
  return make_new_set(sets);
7147
7041
}
7148
7042
 
7149
 
void free_last_set(REP_SETS *sets)
7150
 
{
7151
 
  sets->count--;
7152
 
  sets->extra++;
7153
 
  return;
7154
 
}
7155
 
 
7156
 
void free_sets(REP_SETS *sets)
7157
 
{
7158
 
  free(sets->set_buffer);
7159
 
  free(sets->bit_buffer);
7160
 
  return;
7161
 
}
7162
 
 
7163
 
void internal_set_bit(REP_SET *set, uint32_t bit)
7164
 
{
7165
 
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7166
 
  return;
7167
 
}
7168
 
 
7169
 
void internal_clear_bit(REP_SET *set, uint32_t bit)
7170
 
{
7171
 
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7172
 
  return;
7173
 
}
7174
 
 
7175
 
 
7176
 
void or_bits(REP_SET *to,REP_SET *from)
7177
 
{
7178
 
  register uint32_t i;
7179
 
  for (i=0 ; i < to->size_of_bits ; i++)
7180
 
    to->bits[i]|=from->bits[i];
7181
 
  return;
7182
 
}
7183
 
 
7184
 
void copy_bits(REP_SET *to,REP_SET *from)
7185
 
{
7186
 
  memcpy(to->bits,from->bits,
7187
 
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
7188
 
}
7189
 
 
7190
 
int cmp_bits(REP_SET *set1,REP_SET *set2)
7191
 
{
7192
 
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
7193
 
}
7194
 
 
 
7043
void REP_SETS::free_last_set()
 
7044
{
 
7045
  count--;
 
7046
  extra++;
 
7047
}
 
7048
 
 
7049
void REP_SETS::free_sets()
 
7050
{
 
7051
  free(set_buffer);
 
7052
  free(bit_buffer);
 
7053
}
 
7054
 
 
7055
void REP_SET::internal_set_bit(uint32_t bit)
 
7056
{
 
7057
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
7058
}
 
7059
 
 
7060
void REP_SET::internal_clear_bit(uint32_t bit)
 
7061
{
 
7062
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
7063
}
 
7064
 
 
7065
 
 
7066
void REP_SET::or_bits(const REP_SET *from)
 
7067
{
 
7068
  for (uint32_t i= 0 ; i < size_of_bits; i++)
 
7069
    bits[i]|=from->bits[i];
 
7070
}
 
7071
 
 
7072
void REP_SET::copy_bits(const REP_SET *from)
 
7073
{
 
7074
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
 
7075
}
 
7076
 
 
7077
int REP_SET::cmp_bits(const REP_SET *set2) const
 
7078
{
 
7079
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
 
7080
}
7195
7081
 
7196
7082
/* Get next set bit from set. */
7197
7083
 
7198
 
int get_next_bit(REP_SET *set,uint32_t lastpos)
 
7084
int REP_SET::get_next_bit(uint32_t lastpos) const
7199
7085
{
7200
 
  uint32_t pos,*start,*end,bits;
7201
 
 
7202
 
  start=set->bits+ ((lastpos+1) / WORD_BIT);
7203
 
  end=set->bits + set->size_of_bits;
7204
 
  bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7205
 
 
7206
 
  while (! bits && ++start < end)
7207
 
    bits=start[0];
7208
 
  if (!bits)
 
7086
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
 
7087
  uint32_t *end= bits + size_of_bits;
 
7088
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
7089
 
 
7090
  while (!bits0 && ++start < end)
 
7091
    bits0= start[0];
 
7092
  if (!bits0)
7209
7093
    return 0;
7210
 
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
7211
 
  while (! (bits & 1))
 
7094
  uint32_t pos= (start - bits) * WORD_BIT;
 
7095
  while (!(bits0 & 1))
7212
7096
  {
7213
 
    bits>>=1;
 
7097
    bits0 >>=1;
7214
7098
    pos++;
7215
7099
  }
7216
7100
  return pos;
7220
7104
   free given set, else put in given set in sets and return its
7221
7105
   position */
7222
7106
 
7223
 
int find_set(REP_SETS *sets,REP_SET *find)
 
7107
int REP_SETS::find_set(const REP_SET *find)
7224
7108
{
7225
 
  uint32_t i;
7226
 
  for (i=0 ; i < sets->count-1 ; i++)
 
7109
  uint32_t i= 0;
 
7110
  for (; i < count - 1; i++)
7227
7111
  {
7228
 
    if (!cmp_bits(sets->set+i,find))
 
7112
    if (!set[i].cmp_bits(find))
7229
7113
    {
7230
 
      free_last_set(sets);
 
7114
      free_last_set();
7231
7115
      return i;
7232
7116
    }
7233
7117
  }
7241
7125
   set->next[] == -1 is reserved for end without replaces.
7242
7126
*/
7243
7127
 
7244
 
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
 
7128
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
7245
7129
{
7246
 
  int i;
7247
 
  for (i=0 ; (uint32_t) i < found_sets ; i++)
 
7130
  uint32_t i= 0;
 
7131
  for (; i < found_sets; i++)
 
7132
  {
7248
7133
    if (found_set[i].table_offset == table_offset &&
7249
7134
        found_set[i].found_offset == found_offset)
7250
 
      return -i-2;
7251
 
  found_set[i].table_offset=table_offset;
7252
 
  found_set[i].found_offset=found_offset;
 
7135
      return - i - 2;
 
7136
  }
 
7137
  found_set[i].table_offset= table_offset;
 
7138
  found_set[i].found_offset= found_offset;
7253
7139
  found_sets++;
7254
 
  return -i-2;        /* return new postion */
7255
 
}
7256
 
 
7257
 
/* Return 1 if regexp starts with \b or ends with \b*/
7258
 
 
7259
 
uint32_t start_at_word(char * pos)
7260
 
{
7261
 
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
7262
 
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
7263
 
}
7264
 
 
7265
 
uint32_t end_of_word(char * pos)
7266
 
{
7267
 
  char * end= strchr(pos, '\0');
7268
 
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
7269
 
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
 
7140
  return - i - 2; // return new postion
7270
7141
}
7271
7142
 
7272
7143
/****************************************************************************
7345
7216
} /* insert_pointer_name */
7346
7217
 
7347
7218
 
7348
 
/* free pointer array */
7349
 
 
7350
 
void free_pointer_array(POINTER_ARRAY *pa)
7351
 
{
7352
 
  if (pa->typelib.count)
7353
 
  {
7354
 
    pa->typelib.count=0;
7355
 
    free((char*) pa->typelib.type_names);
7356
 
    pa->typelib.type_names=0;
7357
 
    free(pa->str);
7358
 
  }
7359
 
} /* free_pointer_array */
7360
 
 
7361
 
 
7362
7219
/* Functions that uses replace and replace_regex */
7363
7220
 
7364
7221
/* Append the string to ds, with optional replace */
7365
 
void replace_append_mem(string *ds,
7366
 
                        const char *val, int len)
 
7222
void replace_append_mem(string *ds, const char *val, int len)
7367
7223
{
7368
7224
  char *v= strdup(val);
7369
7225
 
7370
 
  if (glob_replace_regex)
 
7226
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
7371
7227
  {
7372
 
    /* Regex replace */
7373
 
    if (!multi_reg_replace(glob_replace_regex, v))
7374
 
    {
7375
 
      v= glob_replace_regex->buf;
7376
 
      len= strlen(v);
7377
 
    }
 
7228
    v= glob_replace_regex->buf_;
 
7229
    len= strlen(v);
7378
7230
  }
7379
 
 
7380
7231
  if (glob_replace)
7381
7232
  {
7382
7233
    /* Normal replace */
7383
7234
    replace_strings_append(glob_replace, ds, v, len);
7384
7235
  }
7385
7236
  else
7386
 
  {
7387
7237
    ds->append(v, len);
7388
 
  }
7389
7238
}
7390
7239
 
7391
7240
 
7454
7303
 
7455
7304
  return;
7456
7305
}
 
7306
 
 
7307
static void free_all_replace()
 
7308
{
 
7309
  free_replace();
 
7310
  glob_replace_regex.reset();
 
7311
  free_replace_column();
 
7312
}