~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
#include <sys/stat.h>
57
57
#include <sys/types.h>
58
58
#include <fcntl.h>
59
 
#include <boost/array.hpp>
60
 
#include <boost/foreach.hpp>
61
59
#include <boost/program_options.hpp>
62
 
#include <boost/smart_ptr.hpp>
63
60
 
64
61
#include PCRE_HEADER
65
62
 
67
64
#include <boost/unordered_map.hpp>
68
65
 
69
66
/* Added this for string translation. */
70
 
#include <drizzled/gettext.h>
71
 
 
72
 
#include <drizzled/definitions.h>
73
 
#include <drizzled/internal/my_sys.h>
74
 
#include <drizzled/type/time.h>
75
 
#include <drizzled/charset.h>
76
 
#include <drizzled/typelib.h>
 
67
#include "drizzled/gettext.h"
 
68
#include "drizzled/type/time.h"
 
69
#include "drizzled/charset.h"
 
70
#include "drizzled/typelib.h"
77
71
#include <drizzled/configmake.h>
78
 
#include <drizzled/util/find_ptr.h>
79
 
 
80
 
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
81
72
 
82
73
#ifndef DRIZZLE_RETURN_SERVER_GONE
83
74
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
86
77
using namespace std;
87
78
using namespace drizzled;
88
79
 
 
80
extern "C"
89
81
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
90
82
 
91
83
int get_one_option(int optid, const struct option *, char *argument);
124
116
static bool is_windows= false;
125
117
static bool use_drizzle_protocol= false;
126
118
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
127
 
static void free_all_replace();
128
119
 
129
120
std::string opt_basedir,
130
121
  opt_charsets_dir,
174
165
  uint32_t lineno; /* Current line in file */
175
166
};
176
167
 
177
 
static boost::array<st_test_file, 16> file_stack;
178
 
static st_test_file* cur_file;
179
 
 
180
 
static const charset_info_st *charset_info= &my_charset_utf8_general_ci; /* Default charset */
 
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
 
 
173
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
181
174
 
182
175
/*
183
176
  Timer related variables
185
178
*/
186
179
static char *timer_file = NULL;
187
180
static uint64_t timer_start;
188
 
static void timer_output();
189
 
static uint64_t timer_now();
 
181
static void timer_output(void);
 
182
static uint64_t timer_now(void);
190
183
 
191
184
static uint64_t progress_start= 0;
192
185
 
207
200
 
208
201
/* if set, all results are concated and compared against this file */
209
202
 
210
 
class VAR
 
203
typedef struct st_var
211
204
{
212
 
public:
213
205
  char *name;
214
206
  int name_len;
215
207
  char *str_val;
219
211
  int int_dirty; /* do not update string if int is updated until first read */
220
212
  int alloced;
221
213
  char *env_s;
222
 
};
 
214
} VAR;
223
215
 
224
216
/*Perl/shell-like variable registers */
225
 
boost::array<VAR, 10> var_reg;
226
 
 
227
 
typedef boost::unordered_map<string, VAR *> var_hash_t;
228
 
var_hash_t var_hash;
 
217
VAR var_reg[10];
 
218
 
 
219
 
 
220
boost::unordered_map<string, VAR *> var_hash;
229
221
 
230
222
struct st_connection
231
223
{
398
390
  struct st_match_err err[10];
399
391
  uint32_t count;
400
392
};
401
 
 
402
 
static st_expected_errors saved_expected_errors;
403
 
 
404
 
class st_command
 
393
static struct st_expected_errors saved_expected_errors;
 
394
 
 
395
struct st_command
405
396
{
406
 
public:
407
397
  char *query, *query_buf,*first_argument,*last_argument,*end;
408
398
  int first_word_len, query_len;
409
399
  bool abort_on_error;
410
400
  st_expected_errors expected_errors;
411
401
  string require_file;
412
 
  enum_commands type;
 
402
  enum enum_commands type;
413
403
 
414
404
  st_command()
415
405
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
421
411
 
422
412
  ~st_command()
423
413
  {
424
 
    free(query_buf);
 
414
    if (query_buf != NULL)
 
415
    {
 
416
      free(query_buf);
 
417
    }
425
418
  }
426
419
};
427
420
 
446
439
VAR* var_from_env(const char *, const char *);
447
440
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
448
441
              int val_len);
 
442
void var_free(pair<string, VAR*> v);
449
443
VAR* var_get(const char *var_name, const char** var_name_end,
450
444
             bool raw, bool ignore_not_existing);
451
445
void eval_expr(VAR* v, const char *p, const char** p_end);
452
446
bool match_delimiter(int c, const char *delim, uint32_t length);
453
447
void dump_result_to_reject_file(char *buf, int size);
454
448
void dump_result_to_log_file(const char *buf, int size);
455
 
void dump_warning_messages();
456
 
void dump_progress();
 
449
void dump_warning_messages(void);
 
450
void dump_progress(void);
457
451
 
458
452
void do_eval(string *query_eval, const char *query,
459
453
             const char *query_end, bool pass_through_escape_chars);
464
458
static char *replace_column[MAX_COLUMNS];
465
459
static uint32_t max_replace_column= 0;
466
460
void do_get_replace_column(struct st_command*);
467
 
void free_replace_column();
 
461
void free_replace_column(void);
468
462
 
469
463
/* For replace */
470
464
void do_get_replace(struct st_command *command);
471
 
void free_replace();
 
465
void free_replace(void);
472
466
 
473
467
/* For replace_regex */
474
468
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
}
475
480
 
476
481
void replace_append_mem(string *ds, const char *val,
477
482
                        int len);
488
493
void do_eval(string *query_eval, const char *query,
489
494
             const char *query_end, bool pass_through_escape_chars)
490
495
{
491
 
  char c, next_c;
492
 
  int escaped = 0;
 
496
  const char *p;
 
497
  register char c, next_c;
 
498
  register int escaped = 0;
493
499
  VAR *v;
494
500
 
495
 
  for (const char *p= query; (c= *p) && p < query_end; ++p)
 
501
 
 
502
  for (p= query; (c= *p) && p < query_end; ++p)
496
503
  {
497
504
    switch(c) {
498
505
    case '$':
866
873
}
867
874
 
868
875
 
869
 
static void close_connections()
 
876
static void close_connections(void)
870
877
{
871
878
  for (--next_con; next_con >= connections; --next_con)
872
879
  {
877
884
    }
878
885
    free(next_con->name);
879
886
  }
 
887
  return;
880
888
}
881
889
 
882
890
 
883
 
static void close_files()
 
891
static void close_files(void)
884
892
{
885
 
  for (; cur_file >= file_stack.data(); cur_file--)
 
893
 
 
894
  for (; cur_file >= file_stack; cur_file--)
886
895
  {
887
896
    if (cur_file->file && cur_file->file != stdin)
 
897
    {
888
898
      fclose(cur_file->file);
889
 
    free(const_cast<char*>(cur_file->file_name));
 
899
    }
 
900
    free((unsigned char*) cur_file->file_name);
890
901
    cur_file->file_name= 0;
891
902
  }
 
903
  return;
892
904
}
893
905
 
894
 
static void free_used_memory()
 
906
 
 
907
static void free_used_memory(void)
895
908
{
 
909
  uint32_t i;
 
910
 
 
911
 
896
912
  close_connections();
897
913
  close_files();
898
 
  BOOST_FOREACH(var_hash_t::reference i, var_hash)
899
 
  {
900
 
    free(i.second->str_val);
901
 
    free(i.second->env_s);
902
 
    if (i.second->alloced)
903
 
      free(i.second);
904
 
  }
 
914
  for_each(var_hash.begin(), var_hash.end(), var_free);
905
915
  var_hash.clear();
906
 
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
907
 
    delete i;
908
 
  for (size_t i= 0; i < var_reg.size(); i++)
 
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++)
909
925
  {
910
926
    if (var_reg[i].alloced_len)
911
927
      free(var_reg[i].str_val);
912
928
  }
 
929
 
913
930
  free_all_replace();
914
931
  free(opt_pass);
 
932
 
 
933
  return;
915
934
}
916
935
 
917
936
 
936
955
      assert(0);
937
956
    }
938
957
  }
 
958
 
939
959
  exit(exit_code);
940
960
}
941
961
 
955
975
 
956
976
  /* Print the error message */
957
977
  fprintf(stderr, "drizzletest: ");
958
 
  if (cur_file && cur_file != file_stack.data())
 
978
  if (cur_file && cur_file != file_stack)
959
979
    fprintf(stderr, "In included file \"%s\": ",
960
980
            cur_file->file_name);
961
981
  if (start_lineno > 0)
1016
1036
 
1017
1037
  /* Print include filestack */
1018
1038
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1019
 
          file_stack[0].file_name);
 
1039
          file_stack->file_name);
1020
1040
  fprintf(stderr, "Detected in file %s at line %d\n",
1021
1041
          err_file->file_name, err_file->lineno);
1022
 
  while (err_file != file_stack.data())
 
1042
  while (err_file != file_stack)
1023
1043
  {
1024
1044
    err_file--;
1025
1045
    fprintf(stderr, "included from %s at line %d\n",
1050
1070
 
1051
1071
  va_start(args, fmt);
1052
1072
  fprintf(stderr, "drizzletest: ");
1053
 
  if (cur_file && cur_file != file_stack.data())
 
1073
  if (cur_file && cur_file != file_stack)
1054
1074
    fprintf(stderr, "In included file \"%s\": ",
1055
1075
            cur_file->file_name);
1056
1076
  if (start_lineno != 0)
1058
1078
  vfprintf(stderr, fmt, args);
1059
1079
  fprintf(stderr, "\n");
1060
1080
  va_end(args);
 
1081
 
 
1082
  return;
1061
1083
}
1062
1084
 
1063
1085
 
1073
1095
  if (start_lineno != 0)
1074
1096
  {
1075
1097
    ds_warning_messages.append("Warning detected ");
1076
 
    if (cur_file && cur_file != file_stack.data())
 
1098
    if (cur_file && cur_file != file_stack)
1077
1099
    {
1078
1100
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1079
1101
                    cur_file->file_name);
1406
1428
 
1407
1429
static int compare_files(const char* filename1, const char* filename2)
1408
1430
{
1409
 
  int fd= internal::my_open(filename1, O_RDONLY, MYF(0));
1410
 
  if (fd < 0)
 
1431
  int fd;
 
1432
  int error;
 
1433
 
 
1434
  if ((fd= internal::my_open(filename1, O_RDONLY, MYF(0))) < 0)
1411
1435
    die("Failed to open first file: '%s'", filename1);
1412
 
  int error= compare_files2(fd, filename2);
 
1436
 
 
1437
  error= compare_files2(fd, filename2);
 
1438
 
1413
1439
  internal::my_close(fd, MYF(0));
 
1440
 
1414
1441
  return error;
1415
1442
}
1416
1443
 
1601
1628
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1602
1629
              int val_len)
1603
1630
{
 
1631
  int val_alloc_len;
 
1632
  VAR *tmp_var;
1604
1633
  if (!name_len && name)
1605
1634
    name_len = strlen(name);
1606
1635
  if (!val_len && val)
1607
1636
    val_len = strlen(val) ;
1608
 
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
 
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");
1609
1641
 
1610
 
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
 
1642
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1611
1643
  tmp_var->alloced = (v == 0);
1612
1644
 
1613
 
  int val_alloc_len = val_len + 16; /* room to grow */
1614
 
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
 
1645
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1646
    die("Out of memory");
1615
1647
 
1616
1648
  memcpy(tmp_var->name, name, name_len);
1617
1649
  if (val)
1622
1654
  tmp_var->name_len = name_len;
1623
1655
  tmp_var->str_val_len = val_len;
1624
1656
  tmp_var->alloced_len = val_alloc_len;
1625
 
  tmp_var->int_val = val ? atoi(val) : 0;
1626
 
  tmp_var->int_dirty = false;
 
1657
  tmp_var->int_val = (val) ? atoi(val) : 0;
 
1658
  tmp_var->int_dirty = 0;
1627
1659
  tmp_var->env_s = 0;
1628
1660
  return tmp_var;
1629
1661
}
1630
1662
 
 
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
 
1631
1673
VAR* var_from_env(const char *name, const char *def_val)
1632
1674
{
1633
 
  const char *tmp= getenv(name);
1634
 
  if (!tmp)
 
1675
  const char *tmp;
 
1676
  VAR *v;
 
1677
  if (!(tmp = getenv(name)))
1635
1678
    tmp = def_val;
1636
 
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
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;
1637
1684
}
1638
1685
 
 
1686
 
1639
1687
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1640
1688
             bool ignore_not_existing)
1641
1689
{
1642
1690
  int digit;
1643
1691
  VAR *v;
 
1692
 
1644
1693
  if (*var_name != '$')
1645
1694
    goto err;
1646
1695
  digit = *++var_name - '0';
1662
1711
      die("Too long variable name: %s", save_var_name);
1663
1712
 
1664
1713
    string save_var_name_str(save_var_name, length);
1665
 
    if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, save_var_name_str))
1666
 
      v= *ptr;
1667
 
    else
 
1714
    boost::unordered_map<string, VAR*>::iterator iter=
 
1715
      var_hash.find(save_var_name_str);
 
1716
    if (iter == var_hash.end())
1668
1717
    {
1669
1718
      char buff[MAX_VAR_NAME_LENGTH+1];
1670
1719
      strncpy(buff, save_var_name, length);
1671
1720
      buff[length]= '\0';
1672
1721
      v= var_from_env(buff, "");
1673
1722
    }
 
1723
    else
 
1724
    {
 
1725
      v= (*iter).second;
 
1726
    }
1674
1727
    var_name--;  /* Point at last character */
1675
1728
  }
1676
1729
  else
1677
 
    v = &var_reg[digit];
 
1730
    v = var_reg + digit;
1678
1731
 
1679
1732
  if (!raw && v->int_dirty)
1680
1733
  {
1696
1749
static VAR *var_obtain(const char *name, int len)
1697
1750
{
1698
1751
  string var_name(name, len);
1699
 
  if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, var_name))
1700
 
    return *ptr;
1701
 
  return var_hash[var_name] = var_init(0, name, len, "", 0);
 
1752
  boost::unordered_map<string, VAR*>::iterator iter=
 
1753
    var_hash.find(var_name);
 
1754
  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;
1702
1759
}
1703
1760
 
1704
1761
 
1725
1782
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1726
1783
  }
1727
1784
  else
1728
 
    v= &var_reg[digit];
 
1785
    v= var_reg + digit;
1729
1786
 
1730
1787
  eval_expr(v, var_val, (const char**) &var_val_end);
1731
1788
 
2009
2066
    eval_expr(var, value, 0);
2010
2067
  }
2011
2068
  drizzle_result_free(&res);
 
2069
 
 
2070
  return;
2012
2071
}
2013
2072
 
2014
2073
 
2039
2098
{
2040
2099
  if (*p == '$')
2041
2100
  {
2042
 
    VAR *vp= var_get(p, p_end, 0, 0);
2043
 
    if (vp)
 
2101
    VAR *vp;
 
2102
    if ((vp= var_get(p, p_end, 0, 0)))
2044
2103
      var_copy(v, vp);
2045
2104
    return;
2046
2105
  }
2101
2160
  }
2102
2161
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2103
2162
 
 
2163
  if (cur_file == file_stack_end)
 
2164
    die("Source directives are nesting too deep");
2104
2165
  cur_file++;
2105
 
  if (cur_file == &*file_stack.end())
2106
 
    die("Source directives are nesting too deep");
2107
2166
  if (!(cur_file->file= fopen(buff, "r")))
2108
2167
  {
2109
2168
    cur_file--;
2165
2224
}
2166
2225
 
2167
2226
 
2168
 
static void init_builtin_echo()
 
2227
static void init_builtin_echo(void)
2169
2228
{
2170
2229
  builtin_echo[0]= 0;
 
2230
  return;
2171
2231
}
2172
2232
 
2173
2233
 
3130
3190
  when ndb binlog is on, this call will wait until last updated epoch
3131
3191
  (locally in the drizzled) has been received into the binlog
3132
3192
*/
3133
 
static int do_save_master_pos()
 
3193
static int do_save_master_pos(void)
3134
3194
{
3135
3195
  drizzle_result_st res;
3136
3196
  drizzle_return_t ret;
3269
3329
    sleep_val= opt_sleep;
3270
3330
 
3271
3331
  if (sleep_val)
3272
 
    usleep(sleep_val * 1000000);
 
3332
    usleep((uint32_t) (sleep_val * 1000000L));
3273
3333
  command->last_argument= sleep_end;
3274
3334
  return 0;
3275
3335
}
3276
3336
 
3277
3337
 
3278
 
static void do_get_file_name(st_command *command, string &dest)
 
3338
static void do_get_file_name(struct st_command *command, string &dest)
3279
3339
{
3280
 
  char *p= command->first_argument;
 
3340
  char *p= command->first_argument, *name;
3281
3341
  if (!*p)
3282
3342
    die("Missing file name argument");
3283
 
  char *name= p;
 
3343
  name= p;
3284
3344
  while (*p && !my_isspace(charset_info,*p))
3285
3345
    p++;
3286
3346
  if (*p)
3355
3415
      and assign that string to the $variable
3356
3416
    */
3357
3417
    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
 
3358
3421
    try
3359
3422
    {
3360
 
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
 
3423
      global_error_names.insert(ErrorCodes::value_type(error_name,
 
3424
                                                       boost::lexical_cast<uint32_t>(error_code)));
3361
3425
    }
3362
3426
    catch (boost::bad_lexical_cast &ex)
3363
3427
    {
3370
3434
  drizzle_result_free(&res);
3371
3435
}
3372
3436
 
3373
 
static uint32_t get_errcode_from_name(const char *error_name, const char *error_end)
 
3437
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3374
3438
{
3375
 
  string error_name_s(error_name, error_end);
 
3439
  size_t err_name_len= error_end - error_name;
 
3440
  string error_name_s(error_name, err_name_len);
3376
3441
 
3377
 
  if (ErrorCodes::mapped_type* ptr= find_ptr(global_error_names, error_name_s))
3378
 
    return *ptr;
 
3442
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
 
3443
  if (it != global_error_names.end())
 
3444
  {
 
3445
    return (*it).second;
 
3446
  }
3379
3447
 
3380
3448
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3381
3449
  return 0;
3818
3886
{
3819
3887
  uint32_t con_port= opt_port;
3820
3888
  const char *con_options;
 
3889
  bool con_ssl= 0;
3821
3890
  struct st_connection* con_slot;
3822
3891
 
3823
3892
  string ds_connection_name;
3881
3950
    end= con_options;
3882
3951
    while (*end && !my_isspace(charset_info, *end))
3883
3952
      end++;
3884
 
    die("Illegal option to connect: %.*s",
3885
 
        (int) (end - con_options), con_options);
 
3953
    if (!strncmp(con_options, "SSL", 3))
 
3954
      con_ssl= 1;
 
3955
    else
 
3956
      die("Illegal option to connect: %.*s",
 
3957
          (int) (end - con_options), con_options);
3886
3958
    /* Process next option */
3887
3959
    con_options= end;
3888
3960
  }
3992
4064
{
3993
4065
  char *p= command->first_argument;
3994
4066
  const char *expr_start, *expr_end;
 
4067
  VAR v;
3995
4068
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
3996
4069
  bool not_expr= false;
3997
4070
 
4034
4107
  if (*p && *p != '{')
4035
4108
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4036
4109
 
4037
 
  VAR v;
4038
4110
  var_init(&v,0,0,0,0);
4039
4111
  eval_expr(&v, expr_start, &expr_end);
4040
4112
 
4126
4198
*/
4127
4199
 
4128
4200
 
4129
 
static int my_strnncoll_simple(const charset_info_st * const  cs, const unsigned char *s, size_t slen,
 
4201
static int my_strnncoll_simple(const CHARSET_INFO * const  cs, const unsigned char *s, size_t slen,
4130
4202
                               const unsigned char *t, size_t tlen,
4131
4203
                               bool t_is_prefix)
4132
4204
{
4170
4242
      }
4171
4243
      free((unsigned char*) cur_file->file_name);
4172
4244
      cur_file->file_name= 0;
4173
 
      if (cur_file == file_stack.data())
 
4245
      if (cur_file == file_stack)
4174
4246
      {
4175
4247
        /* We're back at the first file, check if
4176
4248
           all { have matching }
4404
4476
        end++;
4405
4477
      save= *end;
4406
4478
      *end= 0;
4407
 
      type= command_typelib.find_type(start, TYPELIB::e_default);
 
4479
      type= command_typelib.find_type(start, 1+2);
4408
4480
      if (type)
4409
4481
        warning_msg("Embedded drizzletest command '--%s' detected in "
4410
4482
                    "query '%s' was this intentional? ",
4610
4682
          log_file);
4611
4683
}
4612
4684
 
4613
 
void dump_progress()
 
4685
void dump_progress(void)
4614
4686
{
4615
4687
  char progress_file[FN_REFLEN];
4616
4688
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4620
4692
              ds_progress.c_str(), ds_progress.length());
4621
4693
}
4622
4694
 
4623
 
void dump_warning_messages()
 
4695
void dump_warning_messages(void)
4624
4696
{
4625
4697
  char warn_file[FN_REFLEN];
4626
4698
 
4685
4757
    for (i = 0; i < num_fields; i++)
4686
4758
    {
4687
4759
      column= drizzle_column_next(res);
4688
 
      if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
4689
 
      {
4690
 
        if (boost::lexical_cast<uint32_t>(row[i]))
4691
 
        {
4692
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4693
 
          {
4694
 
            append_field(ds, i, column, "YES", 3, false);
4695
 
          }
4696
 
          else
4697
 
          {
4698
 
            append_field(ds, i, column, "TRUE", 4, false);
4699
 
          }
4700
 
        }
4701
 
        else
4702
 
        {
4703
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4704
 
          {
4705
 
            append_field(ds, i, column, "NO", 2, false);
4706
 
          }
4707
 
          else
4708
 
          {
4709
 
            append_field(ds, i, column, "FALSE", 5, false);
4710
 
          }
4711
 
        }
4712
 
      }
4713
 
      else
4714
 
      {
4715
 
        append_field(ds, i, column,
4716
 
                     (const char*)row[i], lengths[i], !row[i]);
4717
 
      }
 
4760
      append_field(ds, i, column,
 
4761
                   (const char*)row[i], lengths[i], !row[i]);
4718
4762
    }
4719
4763
    if (!display_result_vertically)
4720
4764
      ds->append("\n");
4758
4802
    ds->append("\t", 1);
4759
4803
    replace_append_uint(ds, drizzle_column_size(column));
4760
4804
    ds->append("\t", 1);
4761
 
    if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
4762
 
    {
4763
 
      replace_append_uint(ds, 1);
4764
 
    }
4765
 
    else
4766
 
    {
4767
 
      replace_append_uint(ds, drizzle_column_max_size(column));
4768
 
    }
 
4805
    replace_append_uint(ds, drizzle_column_max_size(column));
4769
4806
    ds->append("\t", 1);
4770
4807
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4771
4808
    ds->append("\t", 1);
5262
5299
 
5263
5300
  save= command->query[command->first_word_len];
5264
5301
  command->query[command->first_word_len]= 0;
5265
 
  type= command_typelib.find_type(command->query, TYPELIB::e_default);
 
5302
  type= command_typelib.find_type(command->query, 1+2);
5266
5303
  command->query[command->first_word_len]= save;
5267
5304
  if (type > 0)
5268
5305
  {
5306
5343
        */
5307
5344
        save= command->query[command->first_word_len-1];
5308
5345
        command->query[command->first_word_len-1]= 0;
5309
 
        if (command_typelib.find_type(command->query, TYPELIB::e_default) > 0)
 
5346
        if (command_typelib.find_type(command->query, 1+2) > 0)
5310
5347
          die("Extra delimiter \";\" found");
5311
5348
        command->query[command->first_word_len-1]= save;
5312
5349
 
5480
5517
 
5481
5518
  if (user_config_dir.compare(0, 2, "~/") == 0)
5482
5519
  {
5483
 
    const char *homedir= getenv("HOME");
 
5520
    char *homedir;
 
5521
    homedir= getenv("HOME");
5484
5522
    if (homedir != NULL)
5485
5523
      user_config_dir.replace(0, 1, homedir);
5486
5524
  }
5527
5565
  next_con= connections + 1;
5528
5566
 
5529
5567
  /* Init file stack */
5530
 
  memset(file_stack.data(), 0, sizeof(file_stack));
5531
 
  cur_file= file_stack.data();
 
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;
5532
5572
 
5533
5573
  /* Init block stack */
5534
5574
  memset(block_stack, 0, sizeof(block_stack));
5567
5607
      tmp= buff;
5568
5608
    }
5569
5609
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5570
 
    assert(cur_file == file_stack.data() && cur_file->file == 0);
 
5610
    assert(cur_file == file_stack && cur_file->file == 0);
5571
5611
    if (!(cur_file->file= fopen(buff, "r")))
5572
5612
    {
5573
5613
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5672
5712
  }
5673
5713
 
5674
5714
  server_initialized= 1;
5675
 
  if (cur_file == file_stack.data() && cur_file->file == 0)
 
5715
  if (cur_file == file_stack && cur_file->file == 0)
5676
5716
  {
5677
5717
    cur_file->file= stdin;
5678
5718
    cur_file->file_name= strdup("<stdin>");
6097
6137
  the time between executing the two commands.
6098
6138
*/
6099
6139
 
6100
 
void timer_output()
 
6140
void timer_output(void)
6101
6141
{
6102
6142
  if (timer_file)
6103
6143
  {
6111
6151
}
6112
6152
 
6113
6153
 
6114
 
uint64_t timer_now()
 
6154
uint64_t timer_now(void)
6115
6155
{
6116
6156
#if defined(HAVE_GETHRTIME)
6117
6157
  return gethrtime()/1000/1000;
6151
6191
  start= buff= (char *)malloc(strlen(from)+1);
6152
6192
  while (*from)
6153
6193
  {
 
6194
    char *to;
6154
6195
    uint32_t column_number;
6155
6196
 
6156
 
    char *to= get_string(&buff, &from, command);
 
6197
    to= get_string(&buff, &from, command);
6157
6198
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6158
6199
      die("Wrong column number to replace_column in '%s'", command->query);
6159
6200
    if (!*from)
6172
6213
 
6173
6214
void free_replace_column()
6174
6215
{
6175
 
  for (uint32_t i= 0 ; i < max_replace_column; i++)
 
6216
  uint32_t i;
 
6217
  for (i=0 ; i < max_replace_column ; i++)
6176
6218
  {
6177
 
    free(replace_column[i]);
6178
 
    replace_column[i]= 0;
 
6219
    if (replace_column[i])
 
6220
    {
 
6221
      free(replace_column[i]);
 
6222
      replace_column[i]= 0;
 
6223
    }
6179
6224
  }
6180
6225
  max_replace_column= 0;
6181
6226
}
6188
6233
 
6189
6234
/* Definitions for replace result */
6190
6235
 
6191
 
class POINTER_ARRAY
6192
 
{    /* when using array-strings */
6193
 
public:
6194
 
  ~POINTER_ARRAY();
6195
 
  int insert(char* name);
6196
 
 
6197
 
  POINTER_ARRAY()
6198
 
  {
6199
 
    memset(this, 0, sizeof(*this));
6200
 
  }
6201
 
 
 
6236
typedef struct st_pointer_array {    /* when using array-strings */
6202
6237
  TYPELIB typelib;        /* Pointer to strings */
6203
 
  unsigned char *str;          /* Strings is here */
6204
 
  uint8_t* flag;          /* Flag about each var. */
6205
 
  uint32_t array_allocs;
6206
 
  uint32_t max_count;
6207
 
  uint32_t length;
6208
 
  uint32_t max_length;
6209
 
};
 
6238
  unsigned char  *str;          /* Strings is here */
 
6239
  uint8_t *flag;          /* Flag about each var. */
 
6240
  uint32_t  array_allocs,max_count,length,max_length;
 
6241
} POINTER_ARRAY;
6210
6242
 
6211
6243
struct st_replace;
6212
 
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6213
 
                                char *word_end_chars);
6214
 
 
 
6244
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
6245
                                char * word_end_chars);
 
6246
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6215
6247
void replace_strings_append(struct st_replace *rep, string* ds,
6216
6248
                            const char *from, int len);
 
6249
void free_pointer_array(POINTER_ARRAY *pa);
6217
6250
 
6218
 
st_replace *glob_replace= NULL;
6219
 
// boost::scoped_ptr<st_replace> glob_replace;
 
6251
struct st_replace *glob_replace= NULL;
6220
6252
 
6221
6253
/*
6222
6254
  Get arguments for replace. The syntax is:
6226
6258
  variable is replaced.
6227
6259
*/
6228
6260
 
6229
 
POINTER_ARRAY::~POINTER_ARRAY()
6230
 
{
6231
 
  if (!typelib.count)
6232
 
    return;
6233
 
  typelib.count= 0;
6234
 
  free((char*) typelib.type_names);
6235
 
  typelib.type_names=0;
6236
 
  free(str);
6237
 
}
6238
 
 
6239
 
void do_get_replace(st_command *command)
6240
 
{
 
6261
void do_get_replace(struct st_command *command)
 
6262
{
 
6263
  uint32_t i;
6241
6264
  char *from= command->first_argument;
6242
 
  if (!*from)
6243
 
    die("Missing argument in %s", command->query);
6244
 
  free_replace();
 
6265
  char *buff, *start;
 
6266
  char word_end_chars[256], *pos;
6245
6267
  POINTER_ARRAY to_array, from_array;
6246
 
  char* start= (char*)malloc(strlen(from) + 1);
6247
 
  char* buff= start;
 
6268
 
 
6269
 
 
6270
  free_replace();
 
6271
 
 
6272
  memset(&to_array, 0, sizeof(to_array));
 
6273
  memset(&from_array, 0, sizeof(from_array));
 
6274
  if (!*from)
 
6275
    die("Missing argument in %s", command->query);
 
6276
  start= buff= (char *)malloc(strlen(from)+1);
6248
6277
  while (*from)
6249
6278
  {
6250
 
    char *to= get_string(&buff, &from, command);
 
6279
    char *to= buff;
 
6280
    to= get_string(&buff, &from, command);
6251
6281
    if (!*from)
6252
 
      die("Wrong number of arguments to replace_result in '%s'", command->query);
6253
 
    from_array.insert(to);
 
6282
      die("Wrong number of arguments to replace_result in '%s'",
 
6283
          command->query);
 
6284
    insert_pointer_name(&from_array,to);
6254
6285
    to= get_string(&buff, &from, command);
6255
 
    to_array.insert(to);
 
6286
    insert_pointer_name(&to_array,to);
6256
6287
  }
6257
 
  char word_end_chars[256];
6258
 
  char* pos= word_end_chars;
6259
 
  for (int i= 1; i < 256; i++)
6260
 
  {
6261
 
    if (my_isspace(charset_info, i))
 
6288
  for (i= 1,pos= word_end_chars ; i < 256 ; i++)
 
6289
    if (my_isspace(charset_info,i))
6262
6290
      *pos++= i;
6263
 
  }
6264
6291
  *pos=0;          /* End pointer */
6265
 
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
6266
 
                                   to_array.typelib.type_names,
6267
 
                                   from_array.typelib.count,
 
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,
6268
6295
                                   word_end_chars)))
6269
6296
    die("Can't initialize replace from '%s'", command->query);
 
6297
  free_pointer_array(&from_array);
 
6298
  free_pointer_array(&to_array);
6270
6299
  free(start);
6271
6300
  command->last_argument= command->end;
6272
6301
  return;
6275
6304
 
6276
6305
void free_replace()
6277
6306
{
6278
 
  free(glob_replace);
6279
 
  glob_replace=0;
 
6307
 
 
6308
  if (glob_replace)
 
6309
  {
 
6310
    free(glob_replace);
 
6311
    glob_replace=0;
 
6312
  }
 
6313
  return;
6280
6314
}
6281
6315
 
6282
6316
 
6296
6330
void replace_strings_append(REPLACE *rep, string* ds,
6297
6331
                            const char *str, int len)
6298
6332
{
6299
 
  REPLACE *rep_pos;
6300
 
  REPLACE_STRING *rep_str;
 
6333
  register REPLACE *rep_pos;
 
6334
  register REPLACE_STRING *rep_str;
6301
6335
  const char *start, *from;
6302
6336
 
6303
6337
 
6350
6384
                 i.e. repeat the matching until the end of the string */
6351
6385
};
6352
6386
 
6353
 
class st_replace_regex
 
6387
struct st_replace_regex
6354
6388
{
6355
 
public:
6356
 
  st_replace_regex(char* expr);
6357
 
  int multi_reg_replace(char* val);
 
6389
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
6358
6390
 
6359
6391
  /*
6360
6392
    Temporary storage areas for substitutions. To reduce unnessary copying
6363
6395
    st_regex substition. At the end of substitutions  buf points to the
6364
6396
    one containing the final result.
6365
6397
  */
6366
 
  typedef vector<st_regex> regex_arr_t;
6367
 
 
6368
 
  char* buf_;
 
6398
  char* buf;
6369
6399
  char* even_buf;
6370
6400
  char* odd_buf;
6371
6401
  int even_buf_len;
6372
6402
  int odd_buf_len;
6373
 
  boost::array<char, 8 << 10> buf0_;
6374
 
  boost::array<char, 8 << 10> buf1_;
6375
 
  regex_arr_t regex_arr;
6376
6403
};
6377
6404
 
6378
 
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
 
6405
struct st_replace_regex *glob_replace_regex= 0;
6379
6406
 
6380
6407
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6381
6408
                char *string, int icase, int global);
6417
6444
  Returns: st_replace_regex struct with pairs of substitutions
6418
6445
*/
6419
6446
 
6420
 
st_replace_regex::st_replace_regex(char* expr)
 
6447
static struct st_replace_regex* init_replace_regex(char* expr)
6421
6448
{
 
6449
  struct st_replace_regex* res;
 
6450
  char* buf,*expr_end;
 
6451
  char* p;
 
6452
  char* buf_p;
6422
6453
  uint32_t expr_len= strlen(expr);
6423
6454
  char last_c = 0;
6424
 
  st_regex reg;
6425
 
 
6426
 
  char* buf= new char[expr_len];
6427
 
  char* expr_end= expr + expr_len;
6428
 
  char* p= expr;
6429
 
  char* buf_p= buf;
 
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;
6430
6466
 
6431
6467
  /* for each regexp substitution statement */
6432
6468
  while (p < expr_end)
6442
6478
 
6443
6479
    if (p == expr_end || ++p == expr_end)
6444
6480
    {
6445
 
      if (!regex_arr.empty())
 
6481
      if (res->regex_arr.elements)
6446
6482
        break;
6447
6483
      else
6448
6484
        goto err;
6481
6517
      p++;
6482
6518
      reg.global= 1;
6483
6519
    }
6484
 
    regex_arr.push_back(reg);
 
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");
6485
6524
  }
6486
 
  odd_buf_len= even_buf_len= buf0_.size();
6487
 
  even_buf= buf0_.data();
6488
 
  odd_buf= buf1_.data();
6489
 
  buf_= even_buf;
 
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;
6490
6529
 
6491
 
  return;
 
6530
  return res;
6492
6531
 
6493
6532
err:
 
6533
  free(res);
6494
6534
  die("Error parsing replace_regex \"%s\"", expr);
 
6535
  return 0;
6495
6536
}
6496
6537
 
6497
6538
/*
6513
6554
  in one pass
6514
6555
*/
6515
6556
 
6516
 
int st_replace_regex::multi_reg_replace(char* val)
 
6557
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6517
6558
{
6518
 
  char* in_buf= val;
6519
 
  char* out_buf= even_buf;
6520
 
  int* buf_len_p= &even_buf_len;
6521
 
  buf_= 0;
 
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;
6522
6567
 
6523
6568
  /* For each substitution, do the replace */
6524
 
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
 
6569
  for (i= 0; i < r->regex_arr.elements; i++)
6525
6570
  {
 
6571
    struct st_regex re;
6526
6572
    char* save_out_buf= out_buf;
6527
 
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6528
 
                     in_buf, i.icase, i.global))
 
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))
6529
6578
    {
6530
6579
      /* if the buffer has been reallocated, make adjustements */
6531
6580
      if (save_out_buf != out_buf)
6532
6581
      {
6533
 
        if (save_out_buf == even_buf)
6534
 
          even_buf= out_buf;
 
6582
        if (save_out_buf == r->even_buf)
 
6583
          r->even_buf= out_buf;
6535
6584
        else
6536
 
          odd_buf= out_buf;
 
6585
          r->odd_buf= out_buf;
6537
6586
      }
6538
 
      buf_= out_buf;
 
6587
 
 
6588
      r->buf= out_buf;
6539
6589
      if (in_buf == val)
6540
 
        in_buf= odd_buf;
6541
 
      std::swap(in_buf, out_buf);
6542
 
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
 
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;
6543
6596
    }
6544
6597
  }
6545
 
  return buf_ == 0;
 
6598
 
 
6599
  return (r->buf == 0);
6546
6600
}
6547
6601
 
6548
6602
/*
6557
6611
void do_get_replace_regex(struct st_command *command)
6558
6612
{
6559
6613
  char *expr= command->first_argument;
6560
 
  glob_replace_regex.reset(new st_replace_regex(expr));
 
6614
  free_replace_regex();
 
6615
  if (!(glob_replace_regex=init_replace_regex(expr)))
 
6616
    die("Could not init replace_regex");
6561
6617
  command->last_argument= command->end;
6562
6618
}
6563
6619
 
 
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
 
6564
6634
/*
6565
6635
  Performs a regex substitution
6566
6636
 
6667
6737
#define SET_MALLOC_HUNC 64
6668
6738
#define LAST_CHAR_CODE 259
6669
6739
 
6670
 
class REP_SET
6671
 
{
6672
 
public:
6673
 
  void internal_set_bit(uint32_t bit);
6674
 
  void internal_clear_bit(uint32_t bit);
6675
 
  void or_bits(const REP_SET *from);
6676
 
  void copy_bits(const REP_SET *from);
6677
 
  int cmp_bits(const REP_SET *set2) const;
6678
 
  int get_next_bit(uint32_t lastpos) const;
6679
 
 
 
6740
typedef struct st_rep_set {
6680
6741
  uint32_t  *bits;        /* Pointer to used sets */
6681
6742
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6682
6743
  uint32_t  found_len;      /* Best match to date */
6683
6744
  int  found_offset;
6684
6745
  uint32_t  table_offset;
6685
6746
  uint32_t  size_of_bits;      /* For convinience */
6686
 
};
6687
 
 
6688
 
class REP_SETS
6689
 
{
6690
 
public:
6691
 
  int find_set(const REP_SET *find);
6692
 
  void free_last_set();
6693
 
  void free_sets();
6694
 
  void make_sets_invisible();
6695
 
 
 
6747
} REP_SET;
 
6748
 
 
6749
typedef struct st_rep_sets {
6696
6750
  uint32_t    count;      /* Number of sets */
6697
6751
  uint32_t    extra;      /* Extra sets in buffer */
6698
 
  uint32_t    invisible;    /* Sets not shown */
 
6752
  uint32_t    invisible;    /* Sets not chown */
6699
6753
  uint32_t    size_of_bits;
6700
6754
  REP_SET  *set,*set_buffer;
6701
6755
  uint32_t    *bit_buffer;
6702
 
};
 
6756
} REP_SETS;
6703
6757
 
6704
 
struct FOUND_SET 
6705
 
{
 
6758
typedef struct st_found_set {
6706
6759
  uint32_t table_offset;
6707
6760
  int found_offset;
6708
 
};
 
6761
} FOUND_SET;
6709
6762
 
6710
 
struct FOLLOWS
6711
 
{
 
6763
typedef struct st_follow {
6712
6764
  int chr;
6713
6765
  uint32_t table_offset;
6714
6766
  uint32_t len;
6715
 
};
6716
 
 
6717
 
int init_sets(REP_SETS *sets, uint32_t states);
 
6767
} FOLLOWS;
 
6768
 
 
6769
 
 
6770
int init_sets(REP_SETS *sets,uint32_t states);
6718
6771
REP_SET *make_new_set(REP_SETS *sets);
6719
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6720
 
 
6721
 
static uint32_t found_sets= 0;
6722
 
 
6723
 
static uint32_t replace_len(const char *str)
 
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)
6724
6791
{
6725
6792
  uint32_t len=0;
6726
6793
  while (*str)
6733
6800
  return len;
6734
6801
}
6735
6802
 
6736
 
/* Return 1 if regexp starts with \b or ends with \b*/
6737
 
 
6738
 
static bool start_at_word(const char *pos)
6739
 
{
6740
 
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6741
 
}
6742
 
 
6743
 
static bool end_of_word(const char *pos)
6744
 
{
6745
 
  const char *end= strchr(pos, '\0');
6746
 
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6747
 
}
6748
 
 
6749
6803
/* Init a replace structure for further calls */
6750
6804
 
6751
 
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
 
6805
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6806
                      char * word_end_chars)
6752
6807
{
6753
 
  const int SPACE_CHAR= 256;
6754
 
  const int START_OF_LINE= 257;
6755
 
  const int END_OF_LINE= 258;
 
6808
  static const int SPACE_CHAR= 256;
 
6809
  static const int START_OF_LINE= 257;
 
6810
  static const int END_OF_LINE= 258;
6756
6811
 
6757
6812
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6758
6813
  int used_sets,chr,default_state;
6759
6814
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6760
 
  char *to_pos, **to_array;
 
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
 
6761
6823
 
6762
6824
  /* Count number of states */
6763
6825
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6777
6839
  for (i=0 ; word_end_chars[i] ; i++)
6778
6840
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6779
6841
 
6780
 
  REP_SETS sets;
6781
 
  REP_SET *set,*start_states,*word_states,*new_set;
6782
 
  REPLACE_STRING *rep_str;
6783
 
  if (init_sets(&sets, states))
6784
 
    return 0;
 
6842
  if (init_sets(&sets,states))
 
6843
    return(0);
6785
6844
  found_sets=0;
6786
 
  vector<FOUND_SET> found_set(max_length * count);
 
6845
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
 
6846
                                
 
6847
  {
 
6848
    free_sets(&sets);
 
6849
    return(0);
 
6850
  }
6787
6851
  make_new_set(&sets);      /* Set starting set */
6788
 
  sets.make_sets_invisible();      /* Hide previus sets */
 
6852
  make_sets_invisible(&sets);      /* Hide previus sets */
6789
6853
  used_sets=-1;
6790
6854
  word_states=make_new_set(&sets);    /* Start of new word */
6791
6855
  start_states=make_new_set(&sets);    /* This is first state */
6792
 
  vector<FOLLOWS> follow(states + 2);
6793
 
  FOLLOWS *follow_ptr= &follow[1];
 
6856
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6857
  {
 
6858
    free_sets(&sets);
 
6859
    free(found_set);
 
6860
    return(0);
 
6861
  }
 
6862
 
6794
6863
  /* Init follow_ptr[] */
6795
 
  for (i=0, states=1; i < count; i++)
 
6864
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6796
6865
  {
6797
6866
    if (from[i][0] == '\\' && from[i][1] == '^')
6798
6867
    {
6799
 
      start_states->internal_set_bit(states + 1);
 
6868
      internal_set_bit(start_states,states+1);
6800
6869
      if (!from[i][2])
6801
6870
      {
6802
6871
        start_states->table_offset=i;
6805
6874
    }
6806
6875
    else if (from[i][0] == '\\' && from[i][1] == '$')
6807
6876
    {
6808
 
      start_states->internal_set_bit(states);
6809
 
      word_states->internal_set_bit(states);
 
6877
      internal_set_bit(start_states,states);
 
6878
      internal_set_bit(word_states,states);
6810
6879
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6811
6880
      {
6812
6881
        start_states->table_offset=i;
6815
6884
    }
6816
6885
    else
6817
6886
    {
6818
 
      word_states->internal_set_bit(states);
 
6887
      internal_set_bit(word_states,states);
6819
6888
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6820
 
        start_states->internal_set_bit(states + 1);
 
6889
        internal_set_bit(start_states,states+1);
6821
6890
      else
6822
 
        start_states->internal_set_bit(states);
 
6891
        internal_set_bit(start_states,states);
6823
6892
    }
6824
 
    const char *pos;
6825
 
    for (pos= from[i], len=0; *pos ; pos++)
 
6893
    for (pos=from[i], len=0; *pos ; pos++)
6826
6894
    {
6827
6895
      if (*pos == '\\' && *(pos+1))
6828
6896
      {
6865
6933
  }
6866
6934
 
6867
6935
 
6868
 
  for (set_nr=0; set_nr < sets.count ; set_nr++)
 
6936
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6869
6937
  {
6870
6938
    set=sets.set+set_nr;
6871
6939
    default_state= 0;        /* Start from beginning */
6872
6940
 
6873
6941
    /* If end of found-string not found or start-set with current set */
6874
6942
 
6875
 
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
 
6943
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6876
6944
    {
6877
 
      if (!follow[i].chr && !default_state)
6878
 
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
 
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
      }
6879
6951
    }
6880
 
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
 
6952
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6881
6953
    if (!default_state)
6882
 
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
 
6954
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
6883
6955
 
6884
6956
    /* Find all chars that follows current sets */
6885
6957
    memset(used_chars, 0, sizeof(used_chars));
6886
 
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
 
6958
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6887
6959
    {
6888
6960
      used_chars[follow[i].chr]=1;
6889
6961
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6893
6965
 
6894
6966
    /* Mark word_chars used if \b is in state */
6895
6967
    if (used_chars[SPACE_CHAR])
6896
 
      for (const char *pos= word_end_chars ; *pos ; pos++)
 
6968
      for (pos= word_end_chars ; *pos ; pos++)
6897
6969
        used_chars[(int) (unsigned char) *pos] = 1;
6898
6970
 
6899
6971
    /* Handle other used characters */
6910
6982
        new_set->found_offset=set->found_offset+1;
6911
6983
        found_end=0;
6912
6984
 
6913
 
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
 
6985
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6914
6986
        {
6915
6987
          if (!follow[i].chr || follow[i].chr == chr ||
6916
6988
              (follow[i].chr == SPACE_CHAR &&
6922
6994
                follow[i].len > found_end)
6923
6995
              found_end=follow[i].len;
6924
6996
            if (chr && follow[i].chr)
6925
 
              new_set->internal_set_bit(i + 1);    /* To next set */
 
6997
              internal_set_bit(new_set,i+1);    /* To next set */
6926
6998
            else
6927
 
              new_set->internal_set_bit(i);
 
6999
              internal_set_bit(new_set,i);
6928
7000
          }
6929
7001
        }
6930
7002
        if (found_end)
6931
7003
        {
6932
7004
          new_set->found_len=0;      /* Set for testing if first */
6933
7005
          bits_set=0;
6934
 
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
 
7006
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6935
7007
          {
6936
7008
            if ((follow[i].chr == SPACE_CHAR ||
6937
7009
                 follow[i].chr == END_OF_LINE) && ! chr)
6941
7013
            if (follow[bit_nr-1].len < found_end ||
6942
7014
                (new_set->found_len &&
6943
7015
                 (chr == 0 || !follow[bit_nr].chr)))
6944
 
              new_set->internal_clear_bit(i);
 
7016
              internal_clear_bit(new_set,i);
6945
7017
            else
6946
7018
            {
6947
7019
              if (chr == 0 || !follow[bit_nr].chr)
6957
7029
          }
6958
7030
          if (bits_set == 1)
6959
7031
          {
6960
 
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6961
 
            sets.free_last_set();
 
7032
            set->next[chr] = find_found(found_set,
 
7033
                                        new_set->table_offset,
 
7034
                                        new_set->found_offset);
 
7035
            free_last_set(&sets);
6962
7036
          }
6963
7037
          else
6964
 
            set->next[chr] = sets.find_set(new_set);
 
7038
            set->next[chr] = find_set(&sets,new_set);
6965
7039
        }
6966
7040
        else
6967
 
          set->next[chr] = sets.find_set(new_set);
 
7041
          set->next[chr] = find_set(&sets,new_set);
6968
7042
      }
6969
7043
    }
6970
7044
  }
6971
7045
 
6972
7046
  /* Alloc replace structure for the replace-state-machine */
6973
7047
 
6974
 
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6975
 
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
6976
 
  if (replace)
 
7048
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
 
7049
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
 
7050
                                 sizeof(char *)*count+result_len)))
6977
7051
  {
6978
7052
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6979
7053
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6990
7064
    rep_str[0].replace_string=0;
6991
7065
    for (i=1 ; i <= found_sets ; i++)
6992
7066
    {
6993
 
      const char *pos= from[found_set[i-1].table_offset];
 
7067
      pos=from[found_set[i-1].table_offset];
6994
7068
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
6995
 
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
6996
 
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
6997
 
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
 
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);
6998
7073
    }
6999
7074
    for (i=0 ; i < sets.count ; i++)
7000
7075
    {
7005
7080
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7006
7081
    }
7007
7082
  }
7008
 
  sets.free_sets();
7009
 
  return replace;
 
7083
  free(follow);
 
7084
  free_sets(&sets);
 
7085
  free(found_set);
 
7086
  return(replace);
7010
7087
}
7011
7088
 
7012
7089
 
7027
7104
 
7028
7105
/* Make help sets invisible for nicer codeing */
7029
7106
 
7030
 
void REP_SETS::make_sets_invisible()
 
7107
void make_sets_invisible(REP_SETS *sets)
7031
7108
{
7032
 
  invisible= count;
7033
 
  set += count;
7034
 
  count= 0;
 
7109
  sets->invisible=sets->count;
 
7110
  sets->set+=sets->count;
 
7111
  sets->count=0;
7035
7112
}
7036
7113
 
7037
7114
REP_SET *make_new_set(REP_SETS *sets)
7069
7146
  return make_new_set(sets);
7070
7147
}
7071
7148
 
7072
 
void REP_SETS::free_last_set()
7073
 
{
7074
 
  count--;
7075
 
  extra++;
7076
 
}
7077
 
 
7078
 
void REP_SETS::free_sets()
7079
 
{
7080
 
  free(set_buffer);
7081
 
  free(bit_buffer);
7082
 
}
7083
 
 
7084
 
void REP_SET::internal_set_bit(uint32_t bit)
7085
 
{
7086
 
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7087
 
}
7088
 
 
7089
 
void REP_SET::internal_clear_bit(uint32_t bit)
7090
 
{
7091
 
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7092
 
}
7093
 
 
7094
 
 
7095
 
void REP_SET::or_bits(const REP_SET *from)
7096
 
{
7097
 
  for (uint32_t i= 0 ; i < size_of_bits; i++)
7098
 
    bits[i]|=from->bits[i];
7099
 
}
7100
 
 
7101
 
void REP_SET::copy_bits(const REP_SET *from)
7102
 
{
7103
 
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
7104
 
}
7105
 
 
7106
 
int REP_SET::cmp_bits(const REP_SET *set2) const
7107
 
{
7108
 
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
7109
 
}
 
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
 
7110
7195
 
7111
7196
/* Get next set bit from set. */
7112
7197
 
7113
 
int REP_SET::get_next_bit(uint32_t lastpos) const
 
7198
int get_next_bit(REP_SET *set,uint32_t lastpos)
7114
7199
{
7115
 
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
7116
 
  uint32_t *end= bits + size_of_bits;
7117
 
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7118
 
 
7119
 
  while (!bits0 && ++start < end)
7120
 
    bits0= start[0];
7121
 
  if (!bits0)
 
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)
7122
7209
    return 0;
7123
 
  uint32_t pos= (start - bits) * WORD_BIT;
7124
 
  while (!(bits0 & 1))
 
7210
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
7211
  while (! (bits & 1))
7125
7212
  {
7126
 
    bits0 >>=1;
 
7213
    bits>>=1;
7127
7214
    pos++;
7128
7215
  }
7129
7216
  return pos;
7133
7220
   free given set, else put in given set in sets and return its
7134
7221
   position */
7135
7222
 
7136
 
int REP_SETS::find_set(const REP_SET *find)
 
7223
int find_set(REP_SETS *sets,REP_SET *find)
7137
7224
{
7138
 
  uint32_t i= 0;
7139
 
  for (; i < count - 1; i++)
 
7225
  uint32_t i;
 
7226
  for (i=0 ; i < sets->count-1 ; i++)
7140
7227
  {
7141
 
    if (!set[i].cmp_bits(find))
 
7228
    if (!cmp_bits(sets->set+i,find))
7142
7229
    {
7143
 
      free_last_set();
 
7230
      free_last_set(sets);
7144
7231
      return i;
7145
7232
    }
7146
7233
  }
7154
7241
   set->next[] == -1 is reserved for end without replaces.
7155
7242
*/
7156
7243
 
7157
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
 
7244
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7158
7245
{
7159
 
  uint32_t i= 0;
7160
 
  for (; i < found_sets; i++)
7161
 
  {
 
7246
  int i;
 
7247
  for (i=0 ; (uint32_t) i < found_sets ; i++)
7162
7248
    if (found_set[i].table_offset == table_offset &&
7163
7249
        found_set[i].found_offset == found_offset)
7164
 
      return - i - 2;
7165
 
  }
7166
 
  found_set[i].table_offset= table_offset;
7167
 
  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;
7168
7253
  found_sets++;
7169
 
  return - i - 2; // return new postion
 
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;
7170
7270
}
7171
7271
 
7172
7272
/****************************************************************************
7176
7276
#define PC_MALLOC    256  /* Bytes for pointers */
7177
7277
#define PS_MALLOC    512  /* Bytes for data */
7178
7278
 
7179
 
static int insert_pointer_name(POINTER_ARRAY* pa, char* name)
 
7279
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
7180
7280
{
7181
7281
  uint32_t i,length,old_count;
7182
7282
  unsigned char *new_pos;
7244
7344
  return(0);
7245
7345
} /* insert_pointer_name */
7246
7346
 
7247
 
int POINTER_ARRAY::insert(char* name)
 
7347
 
 
7348
/* free pointer array */
 
7349
 
 
7350
void free_pointer_array(POINTER_ARRAY *pa)
7248
7351
{
7249
 
  return insert_pointer_name(this, name);
7250
 
}
 
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 */
7251
7360
 
7252
7361
 
7253
7362
/* Functions that uses replace and replace_regex */
7254
7363
 
7255
7364
/* Append the string to ds, with optional replace */
7256
 
void replace_append_mem(string *ds, const char *val, int len)
 
7365
void replace_append_mem(string *ds,
 
7366
                        const char *val, int len)
7257
7367
{
7258
7368
  char *v= strdup(val);
7259
7369
 
7260
 
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
 
7370
  if (glob_replace_regex)
7261
7371
  {
7262
 
    v= glob_replace_regex->buf_;
7263
 
    len= strlen(v);
 
7372
    /* Regex replace */
 
7373
    if (!multi_reg_replace(glob_replace_regex, v))
 
7374
    {
 
7375
      v= glob_replace_regex->buf;
 
7376
      len= strlen(v);
 
7377
    }
7264
7378
  }
 
7379
 
7265
7380
  if (glob_replace)
7266
7381
  {
7267
7382
    /* Normal replace */
7268
7383
    replace_strings_append(glob_replace, ds, v, len);
7269
7384
  }
7270
7385
  else
 
7386
  {
7271
7387
    ds->append(v, len);
 
7388
  }
7272
7389
}
7273
7390
 
7274
7391
 
7337
7454
 
7338
7455
  return;
7339
7456
}
7340
 
 
7341
 
static void free_all_replace()
7342
 
{
7343
 
  free_replace();
7344
 
  glob_replace_regex.reset();
7345
 
  free_replace_column();
7346
 
}