~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Lee Bieber
  • Date: 2011-02-14 19:50:07 UTC
  • mfrom: (2167.1.3 build)
  • Revision ID: kalebral@gmail.com-20110214195007-om9fjrqy5ziqwrlw
Merge Andrew - 718224: Minor changes to migration docs needed 
Merge Olaf - updating old style casts
Merge Olaf - drizzletest re-factoring

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