~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Monty Taylor
  • Date: 2010-10-21 23:10:12 UTC
  • mto: (1879.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1880.
  • Revision ID: mordred@inaugust.com-20101021231012-uhsebiqo23xi0ygy
Updated AUTHORS list with everyone from bzr logs.

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
 
66
63
#include <stdarg.h>
67
64
#include <boost/unordered_map.hpp>
68
65
 
 
66
#include "errname.h"
 
67
 
69
68
/* Added this for string translation. */
70
 
#include <drizzled/gettext.h>
71
 
#include <drizzled/type/time.h>
72
 
#include <drizzled/charset.h>
73
 
#include <drizzled/typelib.h>
 
69
#include "drizzled/gettext.h"
 
70
#include "drizzled/drizzle_time.h"
 
71
#include "drizzled/charset.h"
74
72
#include <drizzled/configmake.h>
75
73
 
76
 
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
77
 
 
78
74
#ifndef DRIZZLE_RETURN_SERVER_GONE
79
75
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
80
76
#endif
94
90
#define QUERY_SEND_FLAG  1
95
91
#define QUERY_REAP_FLAG  2
96
92
 
97
 
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
98
93
ErrorCodes global_error_names;
99
94
 
100
95
enum {
121
116
static bool is_windows= false;
122
117
static bool use_drizzle_protocol= false;
123
118
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
124
 
static void free_all_replace();
125
119
 
126
120
std::string opt_basedir,
127
121
  opt_charsets_dir,
171
165
  uint32_t lineno; /* Current line in file */
172
166
};
173
167
 
174
 
static boost::array<st_test_file, 16> file_stack;
175
 
static st_test_file* cur_file;
 
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
 
176
172
 
177
173
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
178
174
 
182
178
*/
183
179
static char *timer_file = NULL;
184
180
static uint64_t timer_start;
185
 
static void timer_output();
186
 
static uint64_t timer_now();
 
181
static void timer_output(void);
 
182
static uint64_t timer_now(void);
187
183
 
188
184
static uint64_t progress_start= 0;
189
185
 
204
200
 
205
201
/* if set, all results are concated and compared against this file */
206
202
 
207
 
class VAR
 
203
typedef struct st_var
208
204
{
209
 
public:
210
205
  char *name;
211
206
  int name_len;
212
207
  char *str_val;
216
211
  int int_dirty; /* do not update string if int is updated until first read */
217
212
  int alloced;
218
213
  char *env_s;
219
 
};
 
214
} VAR;
220
215
 
221
216
/*Perl/shell-like variable registers */
222
 
boost::array<VAR, 10> var_reg;
223
 
 
224
 
typedef boost::unordered_map<string, VAR *> var_hash_t;
225
 
var_hash_t var_hash;
 
217
VAR var_reg[10];
 
218
 
 
219
 
 
220
boost::unordered_map<string, VAR *> var_hash;
226
221
 
227
222
struct st_connection
228
223
{
395
390
  struct st_match_err err[10];
396
391
  uint32_t count;
397
392
};
398
 
 
399
 
static st_expected_errors saved_expected_errors;
400
 
 
401
 
class st_command
 
393
static struct st_expected_errors saved_expected_errors;
 
394
 
 
395
struct st_command
402
396
{
403
 
public:
404
397
  char *query, *query_buf,*first_argument,*last_argument,*end;
405
398
  int first_word_len, query_len;
406
399
  bool abort_on_error;
407
400
  st_expected_errors expected_errors;
408
401
  string require_file;
409
 
  enum_commands type;
 
402
  enum enum_commands type;
410
403
 
411
404
  st_command()
412
405
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
418
411
 
419
412
  ~st_command()
420
413
  {
421
 
    free(query_buf);
 
414
    if (query_buf != NULL)
 
415
    {
 
416
      free(query_buf);
 
417
    }
422
418
  }
423
419
};
424
420
 
443
439
VAR* var_from_env(const char *, const char *);
444
440
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
445
441
              int val_len);
 
442
void var_free(pair<string, VAR*> v);
446
443
VAR* var_get(const char *var_name, const char** var_name_end,
447
444
             bool raw, bool ignore_not_existing);
448
445
void eval_expr(VAR* v, const char *p, const char** p_end);
449
446
bool match_delimiter(int c, const char *delim, uint32_t length);
450
447
void dump_result_to_reject_file(char *buf, int size);
451
448
void dump_result_to_log_file(const char *buf, int size);
452
 
void dump_warning_messages();
453
 
void dump_progress();
 
449
void dump_warning_messages(void);
 
450
void dump_progress(void);
454
451
 
455
452
void do_eval(string *query_eval, const char *query,
456
453
             const char *query_end, bool pass_through_escape_chars);
461
458
static char *replace_column[MAX_COLUMNS];
462
459
static uint32_t max_replace_column= 0;
463
460
void do_get_replace_column(struct st_command*);
464
 
void free_replace_column();
 
461
void free_replace_column(void);
465
462
 
466
463
/* For replace */
467
464
void do_get_replace(struct st_command *command);
468
 
void free_replace();
 
465
void free_replace(void);
469
466
 
470
467
/* For replace_regex */
471
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
}
472
480
 
473
481
void replace_append_mem(string *ds, const char *val,
474
482
                        int len);
485
493
void do_eval(string *query_eval, const char *query,
486
494
             const char *query_end, bool pass_through_escape_chars)
487
495
{
488
 
  char c, next_c;
489
 
  int escaped = 0;
 
496
  const char *p;
 
497
  register char c, next_c;
 
498
  register int escaped = 0;
490
499
  VAR *v;
491
500
 
492
 
  for (const char *p= query; (c= *p) && p < query_end; ++p)
 
501
 
 
502
  for (p= query; (c= *p) && p < query_end; ++p)
493
503
  {
494
504
    switch(c) {
495
505
    case '$':
834
844
 
835
845
static void handle_command_error(struct st_command *command, uint32_t error)
836
846
{
 
847
 
837
848
  if (error != 0)
838
849
  {
839
850
    uint32_t i;
860
871
        command->first_word_len, command->query,
861
872
        command->expected_errors.err[0].code.errnum);
862
873
  }
 
874
  return;
863
875
}
864
876
 
865
877
 
866
 
static void close_connections()
 
878
static void close_connections(void)
867
879
{
868
880
  for (--next_con; next_con >= connections; --next_con)
869
881
  {
874
886
    }
875
887
    free(next_con->name);
876
888
  }
 
889
  return;
877
890
}
878
891
 
879
892
 
880
 
static void close_files()
 
893
static void close_files(void)
881
894
{
882
 
  for (; cur_file >= file_stack.data(); cur_file--)
 
895
 
 
896
  for (; cur_file >= file_stack; cur_file--)
883
897
  {
884
898
    if (cur_file->file && cur_file->file != stdin)
 
899
    {
885
900
      fclose(cur_file->file);
886
 
    free(const_cast<char*>(cur_file->file_name));
 
901
    }
 
902
    free((unsigned char*) cur_file->file_name);
887
903
    cur_file->file_name= 0;
888
904
  }
 
905
  return;
889
906
}
890
907
 
891
 
static void free_used_memory()
 
908
 
 
909
static void free_used_memory(void)
892
910
{
 
911
  uint32_t i;
 
912
 
 
913
 
893
914
  close_connections();
894
915
  close_files();
895
 
  BOOST_FOREACH(var_hash_t::reference i, var_hash)
896
 
  {
897
 
    free(i.second->str_val);
898
 
    free(i.second->env_s);
899
 
    if (i.second->alloced)
900
 
      free(i.second);
901
 
  }
 
916
  for_each(var_hash.begin(), var_hash.end(), var_free);
902
917
  var_hash.clear();
903
 
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
904
 
    delete i;
905
 
  for (size_t i= 0; i < var_reg.size(); i++)
 
918
 
 
919
  vector<st_command *>::iterator iter;
 
920
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
921
  {
 
922
    struct st_command * q_line= *iter;
 
923
    delete q_line;
 
924
  }
 
925
 
 
926
  for (i= 0; i < 10; i++)
906
927
  {
907
928
    if (var_reg[i].alloced_len)
908
929
      free(var_reg[i].str_val);
909
930
  }
 
931
 
910
932
  free_all_replace();
911
933
  free(opt_pass);
 
934
 
 
935
  return;
912
936
}
913
937
 
914
938
 
933
957
      assert(0);
934
958
    }
935
959
  }
 
960
 
936
961
  exit(exit_code);
937
962
}
938
963
 
952
977
 
953
978
  /* Print the error message */
954
979
  fprintf(stderr, "drizzletest: ");
955
 
  if (cur_file && cur_file != file_stack.data())
 
980
  if (cur_file && cur_file != file_stack)
956
981
    fprintf(stderr, "In included file \"%s\": ",
957
982
            cur_file->file_name);
958
983
  if (start_lineno > 0)
1013
1038
 
1014
1039
  /* Print include filestack */
1015
1040
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1016
 
          file_stack[0].file_name);
 
1041
          file_stack->file_name);
1017
1042
  fprintf(stderr, "Detected in file %s at line %d\n",
1018
1043
          err_file->file_name, err_file->lineno);
1019
 
  while (err_file != file_stack.data())
 
1044
  while (err_file != file_stack)
1020
1045
  {
1021
1046
    err_file--;
1022
1047
    fprintf(stderr, "included from %s at line %d\n",
1047
1072
 
1048
1073
  va_start(args, fmt);
1049
1074
  fprintf(stderr, "drizzletest: ");
1050
 
  if (cur_file && cur_file != file_stack.data())
 
1075
  if (cur_file && cur_file != file_stack)
1051
1076
    fprintf(stderr, "In included file \"%s\": ",
1052
1077
            cur_file->file_name);
1053
1078
  if (start_lineno != 0)
1055
1080
  vfprintf(stderr, fmt, args);
1056
1081
  fprintf(stderr, "\n");
1057
1082
  va_end(args);
 
1083
 
 
1084
  return;
1058
1085
}
1059
1086
 
1060
1087
 
1070
1097
  if (start_lineno != 0)
1071
1098
  {
1072
1099
    ds_warning_messages.append("Warning detected ");
1073
 
    if (cur_file && cur_file != file_stack.data())
 
1100
    if (cur_file && cur_file != file_stack)
1074
1101
    {
1075
1102
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1076
1103
                    cur_file->file_name);
1435
1462
  int fd;
1436
1463
  char temp_file_path[FN_REFLEN];
1437
1464
 
1438
 
  if ((fd= internal::create_temp_file(temp_file_path, TMPDIR,
 
1465
  if ((fd= internal::create_temp_file(temp_file_path, NULL,
1439
1466
                            "tmp", MYF(MY_WME))) < 0)
1440
1467
    die("Failed to create temporary file for ds");
1441
1468
 
1603
1630
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1604
1631
              int val_len)
1605
1632
{
 
1633
  int val_alloc_len;
 
1634
  VAR *tmp_var;
1606
1635
  if (!name_len && name)
1607
1636
    name_len = strlen(name);
1608
1637
  if (!val_len && val)
1609
1638
    val_len = strlen(val) ;
1610
 
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
 
1639
  val_alloc_len = val_len + 16; /* room to grow */
 
1640
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
 
1641
                                               + name_len+1)))
 
1642
    die("Out of memory");
1611
1643
 
1612
 
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
 
1644
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1613
1645
  tmp_var->alloced = (v == 0);
1614
1646
 
1615
 
  int val_alloc_len = val_len + 16; /* room to grow */
1616
 
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
 
1647
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1648
    die("Out of memory");
1617
1649
 
1618
1650
  memcpy(tmp_var->name, name, name_len);
1619
1651
  if (val)
1624
1656
  tmp_var->name_len = name_len;
1625
1657
  tmp_var->str_val_len = val_len;
1626
1658
  tmp_var->alloced_len = val_alloc_len;
1627
 
  tmp_var->int_val = val ? atoi(val) : 0;
1628
 
  tmp_var->int_dirty = false;
 
1659
  tmp_var->int_val = (val) ? atoi(val) : 0;
 
1660
  tmp_var->int_dirty = 0;
1629
1661
  tmp_var->env_s = 0;
1630
1662
  return tmp_var;
1631
1663
}
1632
1664
 
 
1665
 
 
1666
void var_free(pair<string, VAR *> v)
 
1667
{
 
1668
  free(v.second->str_val);
 
1669
  free(v.second->env_s);
 
1670
  if (v.second->alloced)
 
1671
    free(v.second);
 
1672
}
 
1673
 
 
1674
 
1633
1675
VAR* var_from_env(const char *name, const char *def_val)
1634
1676
{
1635
 
  const char *tmp= getenv(name);
1636
 
  if (!tmp)
 
1677
  const char *tmp;
 
1678
  VAR *v;
 
1679
  if (!(tmp = getenv(name)))
1637
1680
    tmp = def_val;
1638
 
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1681
 
 
1682
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1683
  string var_name(name);
 
1684
  var_hash.insert(make_pair(var_name, v));
 
1685
  return v;
1639
1686
}
1640
1687
 
 
1688
 
1641
1689
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1642
1690
             bool ignore_not_existing)
1643
1691
{
1644
1692
  int digit;
1645
1693
  VAR *v;
 
1694
 
1646
1695
  if (*var_name != '$')
1647
1696
    goto err;
1648
1697
  digit = *++var_name - '0';
1664
1713
      die("Too long variable name: %s", save_var_name);
1665
1714
 
1666
1715
    string save_var_name_str(save_var_name, length);
1667
 
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
 
1716
    boost::unordered_map<string, VAR*>::iterator iter=
 
1717
      var_hash.find(save_var_name_str);
1668
1718
    if (iter == var_hash.end())
1669
1719
    {
1670
1720
      char buff[MAX_VAR_NAME_LENGTH+1];
1674
1724
    }
1675
1725
    else
1676
1726
    {
1677
 
      v= iter->second;
 
1727
      v= (*iter).second;
1678
1728
    }
1679
1729
    var_name--;  /* Point at last character */
1680
1730
  }
1681
1731
  else
1682
 
    v = &var_reg[digit];
 
1732
    v = var_reg + digit;
1683
1733
 
1684
1734
  if (!raw && v->int_dirty)
1685
1735
  {
1701
1751
static VAR *var_obtain(const char *name, int len)
1702
1752
{
1703
1753
  string var_name(name, len);
1704
 
  var_hash_t::iterator iter= var_hash.find(var_name);
 
1754
  boost::unordered_map<string, VAR*>::iterator iter=
 
1755
    var_hash.find(var_name);
1705
1756
  if (iter != var_hash.end())
1706
 
    return iter->second;
1707
 
  return var_hash[var_name] = var_init(0, name, len, "", 0);
 
1757
    return (*iter).second;
 
1758
  VAR *v = var_init(0, name, len, "", 0);
 
1759
  var_hash.insert(make_pair(var_name, v));
 
1760
  return v;
1708
1761
}
1709
1762
 
1710
1763
 
1731
1784
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1732
1785
  }
1733
1786
  else
1734
 
    v= &var_reg[digit];
 
1787
    v= var_reg + digit;
1735
1788
 
1736
1789
  eval_expr(v, var_val, (const char**) &var_val_end);
1737
1790
 
2015
2068
    eval_expr(var, value, 0);
2016
2069
  }
2017
2070
  drizzle_result_free(&res);
 
2071
 
 
2072
  return;
2018
2073
}
2019
2074
 
2020
2075
 
2045
2100
{
2046
2101
  if (*p == '$')
2047
2102
  {
2048
 
    VAR *vp= var_get(p, p_end, 0, 0);
2049
 
    if (vp)
 
2103
    VAR *vp;
 
2104
    if ((vp= var_get(p, p_end, 0, 0)))
2050
2105
      var_copy(v, vp);
2051
2106
    return;
2052
2107
  }
2107
2162
  }
2108
2163
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2109
2164
 
 
2165
  if (cur_file == file_stack_end)
 
2166
    die("Source directives are nesting too deep");
2110
2167
  cur_file++;
2111
 
  if (cur_file == &*file_stack.end())
2112
 
    die("Source directives are nesting too deep");
2113
2168
  if (!(cur_file->file= fopen(buff, "r")))
2114
2169
  {
2115
2170
    cur_file--;
2171
2226
}
2172
2227
 
2173
2228
 
2174
 
static void init_builtin_echo()
 
2229
static void init_builtin_echo(void)
2175
2230
{
2176
2231
  builtin_echo[0]= 0;
 
2232
  return;
2177
2233
}
2178
2234
 
2179
2235
 
2425
2481
 
2426
2482
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
2427
2483
  handle_command_error(command, error);
 
2484
  return;
2428
2485
}
2429
2486
 
2430
2487
 
2459
2516
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2460
2517
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2461
2518
  handle_command_error(command, error);
 
2519
  return;
2462
2520
}
2463
2521
 
2464
2522
 
2496
2554
    die("You must write a 4 digit octal number for mode");
2497
2555
 
2498
2556
  handle_command_error(command, chmod(ds_file.c_str(), mode));
 
2557
  return;
2499
2558
}
2500
2559
 
2501
2560
 
2525
2584
 
2526
2585
  error= (access(ds_filename.c_str(), F_OK) != 0);
2527
2586
  handle_command_error(command, error);
 
2587
  return;
2528
2588
}
2529
2589
 
2530
2590
 
2553
2613
 
2554
2614
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
2555
2615
  handle_command_error(command, error);
 
2616
  return;
2556
2617
}
2557
2618
 
2558
2619
/*
2580
2641
 
2581
2642
  error= rmdir(ds_dirname.c_str()) != 0;
2582
2643
  handle_command_error(command, error);
 
2644
  return;
2583
2645
}
2584
2646
 
2585
2647
 
2818
2880
  }
2819
2881
 
2820
2882
  handle_command_error(command, error);
 
2883
  return;
2821
2884
}
2822
2885
 
2823
2886
 
2867
2930
 
2868
2931
  if (drizzle_quit(&con->con,&result, &ret))
2869
2932
    drizzle_result_free(&result);
 
2933
 
 
2934
  return;
2870
2935
}
2871
2936
 
2872
2937
 
2963
3028
  internal::my_delete(temp_file_path, MYF(0));
2964
3029
 
2965
3030
  handle_command_error(command, WEXITSTATUS(error));
 
3031
  return;
2966
3032
}
2967
3033
 
2968
3034
 
3136
3202
  when ndb binlog is on, this call will wait until last updated epoch
3137
3203
  (locally in the drizzled) has been received into the binlog
3138
3204
*/
3139
 
static int do_save_master_pos()
 
3205
static int do_save_master_pos(void)
3140
3206
{
3141
3207
  drizzle_result_st res;
3142
3208
  drizzle_return_t ret;
3252
3318
  bool error= false;
3253
3319
  char *p= command->first_argument;
3254
3320
  char *sleep_start, *sleep_end= command->end;
3255
 
  double sleep_val= 0;
 
3321
  double sleep_val;
3256
3322
 
3257
3323
  while (my_isspace(charset_info, *p))
3258
3324
    p++;
3275
3341
    sleep_val= opt_sleep;
3276
3342
 
3277
3343
  if (sleep_val)
3278
 
    usleep(sleep_val * 1000000);
 
3344
    usleep((uint32_t) (sleep_val * 1000000L));
3279
3345
  command->last_argument= sleep_end;
3280
3346
  return 0;
3281
3347
}
3282
3348
 
3283
3349
 
3284
 
static void do_get_file_name(st_command *command, string &dest)
 
3350
static void do_get_file_name(struct st_command *command, string &dest)
3285
3351
{
3286
 
  char *p= command->first_argument;
 
3352
  char *p= command->first_argument, *name;
3287
3353
  if (!*p)
3288
3354
    die("Missing file name argument");
3289
 
  char *name= p;
 
3355
  name= p;
3290
3356
  while (*p && !my_isspace(charset_info,*p))
3291
3357
    p++;
3292
3358
  if (*p)
3321
3387
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3322
3388
}
3323
3389
 
3324
 
static void fill_global_error_names()
3325
 
{
3326
 
  drizzle_result_st res;
3327
 
  drizzle_return_t ret;
3328
 
  drizzle_row_t row;
3329
 
  drizzle_con_st *con= &cur_con->con;
3330
 
 
3331
 
  global_error_names.clear();
3332
 
 
3333
 
  const std::string ds_query("select error_name, error_code "
3334
 
                             "from data_dictionary.errors");
3335
 
  if (drizzle_query_str(con, &res, ds_query.c_str(), &ret) == NULL ||
3336
 
      ret != DRIZZLE_RETURN_OK)
3337
 
  {
3338
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3339
 
    {
3340
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
3341
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
3342
 
      drizzle_result_free(&res);
3343
 
    }
3344
 
    else
3345
 
    {
3346
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
3347
 
          drizzle_con_error(con));
3348
 
    }
3349
 
  }
3350
 
  if (drizzle_result_column_count(&res) == 0 ||
3351
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3352
 
  {
3353
 
    drizzle_result_free(&res);
3354
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
3355
 
  }
3356
 
 
3357
 
  while ((row= drizzle_row_next(&res)) && row[0])
3358
 
  {
3359
 
    /*
3360
 
      Concatenate all fields in the first row with tab in between
3361
 
      and assign that string to the $variable
3362
 
    */
3363
 
    size_t *lengths= drizzle_row_field_sizes(&res);
3364
 
    try
3365
 
    {
3366
 
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3367
 
    }
3368
 
    catch (boost::bad_lexical_cast &ex)
3369
 
    {
3370
 
      drizzle_result_free(&res);
3371
 
      die("Invalid error_code from Drizzle: %s", ex.what());
3372
 
    }
3373
 
 
3374
 
  }
3375
 
 
3376
 
  drizzle_result_free(&res);
3377
 
}
3378
 
 
3379
3390
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3380
3391
{
3381
3392
  size_t err_name_len= error_end - error_name;
3382
3393
  string error_name_s(error_name, err_name_len);
3383
3394
 
3384
 
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3385
 
  if (it != global_error_names.end())
3386
 
    return it->second;
3387
 
 
3388
 
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3389
 
  return 0;
 
3395
  uint32_t code= global_error_names.getErrorCode(error_name_s);
 
3396
 
 
3397
  if (!code)
 
3398
    die("Unknown SQL error name '%s'", error_name_s.c_str());
 
3399
 
 
3400
  return(code);
3390
3401
}
3391
3402
 
3392
3403
static void do_get_errcodes(struct st_command *command)
3454
3465
    {
3455
3466
      die("The error name definition must start with an uppercase E");
3456
3467
    }
3457
 
    else if (*p == 'H')
 
3468
    else
3458
3469
    {
3459
 
      /* Error name string */
3460
 
 
3461
 
      to->code.errnum= get_errcode_from_name(p, end);
 
3470
      long val;
 
3471
      char *start= p;
 
3472
      /* Check that the string passed to str2int only contain digits */
 
3473
      while (*p && p != end)
 
3474
      {
 
3475
        if (!my_isdigit(charset_info, *p))
 
3476
          die("Invalid argument to error: '%s' - "              \
 
3477
              "the errno may only consist of digits[0-9]",
 
3478
              command->first_argument);
 
3479
        p++;
 
3480
      }
 
3481
 
 
3482
      /* Convert the sting to int */
 
3483
      istringstream buff(start);
 
3484
      if ((buff >> val).fail())
 
3485
        die("Invalid argument to error: '%s'", command->first_argument);
 
3486
 
 
3487
      to->code.errnum= (uint32_t) val;
3462
3488
      to->type= ERR_ERRNO;
3463
3489
    }
3464
 
    else
3465
 
    {
3466
 
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3467
 
    }
3468
3490
    to++;
3469
3491
    count++;
3470
3492
 
4004
4026
{
4005
4027
  char *p= command->first_argument;
4006
4028
  const char *expr_start, *expr_end;
 
4029
  VAR v;
4007
4030
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4008
4031
  bool not_expr= false;
4009
4032
 
4046
4069
  if (*p && *p != '{')
4047
4070
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4048
4071
 
4049
 
  VAR v;
4050
4072
  var_init(&v,0,0,0,0);
4051
4073
  eval_expr(&v, expr_start, &expr_end);
4052
4074
 
4182
4204
      }
4183
4205
      free((unsigned char*) cur_file->file_name);
4184
4206
      cur_file->file_name= 0;
4185
 
      if (cur_file == file_stack.data())
 
4207
      if (cur_file == file_stack)
4186
4208
      {
4187
4209
        /* We're back at the first file, check if
4188
4210
           all { have matching }
4416
4438
        end++;
4417
4439
      save= *end;
4418
4440
      *end= 0;
4419
 
      type= command_typelib.find_type(start, 1+2);
 
4441
      type= find_type(start, &command_typelib, 1+2);
4420
4442
      if (type)
4421
4443
        warning_msg("Embedded drizzletest command '--%s' detected in "
4422
4444
                    "query '%s' was this intentional? ",
4622
4644
          log_file);
4623
4645
}
4624
4646
 
4625
 
void dump_progress()
 
4647
void dump_progress(void)
4626
4648
{
4627
4649
  char progress_file[FN_REFLEN];
4628
4650
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4632
4654
              ds_progress.c_str(), ds_progress.length());
4633
4655
}
4634
4656
 
4635
 
void dump_warning_messages()
 
4657
void dump_warning_messages(void)
4636
4658
{
4637
4659
  char warn_file[FN_REFLEN];
4638
4660
 
4697
4719
    for (i = 0; i < num_fields; i++)
4698
4720
    {
4699
4721
      column= drizzle_column_next(res);
4700
 
      if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
4701
 
      {
4702
 
        if (boost::lexical_cast<uint32_t>(row[i]))
4703
 
        {
4704
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4705
 
          {
4706
 
            append_field(ds, i, column, "YES", 3, false);
4707
 
          }
4708
 
          else
4709
 
          {
4710
 
            append_field(ds, i, column, "TRUE", 4, false);
4711
 
          }
4712
 
        }
4713
 
        else
4714
 
        {
4715
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4716
 
          {
4717
 
            append_field(ds, i, column, "NO", 2, false);
4718
 
          }
4719
 
          else
4720
 
          {
4721
 
            append_field(ds, i, column, "FALSE", 5, false);
4722
 
          }
4723
 
        }
4724
 
      }
4725
 
      else
4726
 
      {
4727
 
        append_field(ds, i, column,
4728
 
                     (const char*)row[i], lengths[i], !row[i]);
4729
 
      }
 
4722
      append_field(ds, i, column,
 
4723
                   (const char*)row[i], lengths[i], !row[i]);
4730
4724
    }
4731
4725
    if (!display_result_vertically)
4732
4726
      ds->append("\n");
4770
4764
    ds->append("\t", 1);
4771
4765
    replace_append_uint(ds, drizzle_column_size(column));
4772
4766
    ds->append("\t", 1);
4773
 
    if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
4774
 
    {
4775
 
      replace_append_uint(ds, 1);
4776
 
    }
4777
 
    else
4778
 
    {
4779
 
      replace_append_uint(ds, drizzle_column_max_size(column));
4780
 
    }
 
4767
    replace_append_uint(ds, drizzle_column_max_size(column));
4781
4768
    ds->append("\t", 1);
4782
4769
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4783
4770
    ds->append("\t", 1);
5274
5261
 
5275
5262
  save= command->query[command->first_word_len];
5276
5263
  command->query[command->first_word_len]= 0;
5277
 
  type= command_typelib.find_type(command->query, 1+2);
 
5264
  type= find_type(command->query, &command_typelib, 1+2);
5278
5265
  command->query[command->first_word_len]= save;
5279
5266
  if (type > 0)
5280
5267
  {
5318
5305
        */
5319
5306
        save= command->query[command->first_word_len-1];
5320
5307
        command->query[command->first_word_len-1]= 0;
5321
 
        if (command_typelib.find_type(command->query, 1+2) > 0)
 
5308
        if (find_type(command->query, &command_typelib, 1+2) > 0)
5322
5309
          die("Extra delimiter \";\" found");
5323
5310
        command->query[command->first_word_len-1]= save;
5324
5311
 
5490
5477
 
5491
5478
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5492
5479
 
5493
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
5494
 
  {
5495
 
    const char *homedir= getenv("HOME");
5496
 
    if (homedir != NULL)
5497
 
      user_config_dir.replace(0, 1, homedir);
5498
 
  }
5499
 
 
5500
5480
  po::variables_map vm;
5501
5481
 
5502
5482
  // Disable allow_guessing
5539
5519
  next_con= connections + 1;
5540
5520
 
5541
5521
  /* Init file stack */
5542
 
  memset(file_stack.data(), 0, sizeof(file_stack));
5543
 
  cur_file= file_stack.data();
 
5522
  memset(file_stack, 0, sizeof(file_stack));
 
5523
  file_stack_end=
 
5524
    file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
 
5525
  cur_file= file_stack;
5544
5526
 
5545
5527
  /* Init block stack */
5546
5528
  memset(block_stack, 0, sizeof(block_stack));
5579
5561
      tmp= buff;
5580
5562
    }
5581
5563
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5582
 
    assert(cur_file == file_stack.data() && cur_file->file == 0);
 
5564
    assert(cur_file == file_stack && cur_file->file == 0);
5583
5565
    if (!(cur_file->file= fopen(buff, "r")))
5584
5566
    {
5585
5567
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5684
5666
  }
5685
5667
 
5686
5668
  server_initialized= 1;
5687
 
  if (cur_file == file_stack.data() && cur_file->file == 0)
 
5669
  if (cur_file == file_stack && cur_file->file == 0)
5688
5670
  {
5689
5671
    cur_file->file= stdin;
5690
5672
    cur_file->file_name= strdup("<stdin>");
5704
5686
  safe_connect(&cur_con->con, cur_con->name, opt_host, opt_user, opt_pass,
5705
5687
               opt_db, opt_port);
5706
5688
 
5707
 
  fill_global_error_names();
5708
 
 
5709
5689
  /* Use all time until exit if no explicit 'start_timer' */
5710
5690
  timer_start= timer_now();
5711
5691
 
6109
6089
  the time between executing the two commands.
6110
6090
*/
6111
6091
 
6112
 
void timer_output()
 
6092
void timer_output(void)
6113
6093
{
6114
6094
  if (timer_file)
6115
6095
  {
6123
6103
}
6124
6104
 
6125
6105
 
6126
 
uint64_t timer_now()
 
6106
uint64_t timer_now(void)
6127
6107
{
6128
6108
#if defined(HAVE_GETHRTIME)
6129
6109
  return gethrtime()/1000/1000;
6163
6143
  start= buff= (char *)malloc(strlen(from)+1);
6164
6144
  while (*from)
6165
6145
  {
 
6146
    char *to;
6166
6147
    uint32_t column_number;
6167
6148
 
6168
 
    char *to= get_string(&buff, &from, command);
 
6149
    to= get_string(&buff, &from, command);
6169
6150
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6170
6151
      die("Wrong column number to replace_column in '%s'", command->query);
6171
6152
    if (!*from)
6184
6165
 
6185
6166
void free_replace_column()
6186
6167
{
6187
 
  for (uint32_t i= 0 ; i < max_replace_column; i++)
 
6168
  uint32_t i;
 
6169
  for (i=0 ; i < max_replace_column ; i++)
6188
6170
  {
6189
 
    free(replace_column[i]);
6190
 
    replace_column[i]= 0;
 
6171
    if (replace_column[i])
 
6172
    {
 
6173
      free(replace_column[i]);
 
6174
      replace_column[i]= 0;
 
6175
    }
6191
6176
  }
6192
6177
  max_replace_column= 0;
6193
6178
}
6208
6193
} POINTER_ARRAY;
6209
6194
 
6210
6195
struct st_replace;
6211
 
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6212
 
                                char *word_end_chars);
 
6196
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
6197
                                char * word_end_chars);
6213
6198
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6214
6199
void replace_strings_append(struct st_replace *rep, string* ds,
6215
6200
                            const char *from, int len);
 
6201
void free_pointer_array(POINTER_ARRAY *pa);
6216
6202
 
6217
 
st_replace *glob_replace= NULL;
6218
 
// boost::scoped_ptr<st_replace> glob_replace;
 
6203
struct st_replace *glob_replace= NULL;
6219
6204
 
6220
6205
/*
6221
6206
  Get arguments for replace. The syntax is:
6225
6210
  variable is replaced.
6226
6211
*/
6227
6212
 
6228
 
static void free_pointer_array(POINTER_ARRAY *pa)
6229
 
{
6230
 
  if (!pa->typelib.count)
6231
 
    return;
6232
 
  pa->typelib.count=0;
6233
 
  free((char*) pa->typelib.type_names);
6234
 
  pa->typelib.type_names=0;
6235
 
  free(pa->str);
6236
 
}
6237
 
 
6238
6213
void do_get_replace(struct st_command *command)
6239
6214
{
6240
6215
  uint32_t i;
6266
6241
    if (my_isspace(charset_info,i))
6267
6242
      *pos++= i;
6268
6243
  *pos=0;          /* End pointer */
6269
 
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
6270
 
                                   to_array.typelib.type_names,
6271
 
                                   from_array.typelib.count,
 
6244
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
 
6245
                                   (char**) to_array.typelib.type_names,
 
6246
                                   (uint32_t) from_array.typelib.count,
6272
6247
                                   word_end_chars)))
6273
6248
    die("Can't initialize replace from '%s'", command->query);
6274
6249
  free_pointer_array(&from_array);
6281
6256
 
6282
6257
void free_replace()
6283
6258
{
6284
 
  free(glob_replace);
6285
 
  glob_replace=0;
 
6259
 
 
6260
  if (glob_replace)
 
6261
  {
 
6262
    free(glob_replace);
 
6263
    glob_replace=0;
 
6264
  }
 
6265
  return;
6286
6266
}
6287
6267
 
6288
6268
 
6302
6282
void replace_strings_append(REPLACE *rep, string* ds,
6303
6283
                            const char *str, int len)
6304
6284
{
6305
 
  REPLACE *rep_pos;
6306
 
  REPLACE_STRING *rep_str;
 
6285
  register REPLACE *rep_pos;
 
6286
  register REPLACE_STRING *rep_str;
6307
6287
  const char *start, *from;
6308
6288
 
6309
6289
 
6356
6336
                 i.e. repeat the matching until the end of the string */
6357
6337
};
6358
6338
 
6359
 
class st_replace_regex
 
6339
struct st_replace_regex
6360
6340
{
6361
 
public:
6362
 
  st_replace_regex(char* expr);
6363
 
  int multi_reg_replace(char* val);
 
6341
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
6364
6342
 
6365
6343
  /*
6366
6344
    Temporary storage areas for substitutions. To reduce unnessary copying
6369
6347
    st_regex substition. At the end of substitutions  buf points to the
6370
6348
    one containing the final result.
6371
6349
  */
6372
 
  typedef vector<st_regex> regex_arr_t;
6373
 
 
6374
 
  char* buf_;
 
6350
  char* buf;
6375
6351
  char* even_buf;
6376
6352
  char* odd_buf;
6377
6353
  int even_buf_len;
6378
6354
  int odd_buf_len;
6379
 
  boost::array<char, 8 << 10> buf0_;
6380
 
  boost::array<char, 8 << 10> buf1_;
6381
 
  regex_arr_t regex_arr;
6382
6355
};
6383
6356
 
6384
 
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
 
6357
struct st_replace_regex *glob_replace_regex= 0;
6385
6358
 
6386
6359
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6387
6360
                char *string, int icase, int global);
6423
6396
  Returns: st_replace_regex struct with pairs of substitutions
6424
6397
*/
6425
6398
 
6426
 
st_replace_regex::st_replace_regex(char* expr)
 
6399
static struct st_replace_regex* init_replace_regex(char* expr)
6427
6400
{
 
6401
  struct st_replace_regex* res;
 
6402
  char* buf,*expr_end;
 
6403
  char* p;
 
6404
  char* buf_p;
6428
6405
  uint32_t expr_len= strlen(expr);
6429
6406
  char last_c = 0;
6430
 
  st_regex reg;
6431
 
 
6432
 
  char* buf= new char[expr_len];
6433
 
  char* expr_end= expr + expr_len;
6434
 
  char* p= expr;
6435
 
  char* buf_p= buf;
 
6407
  struct st_regex reg;
 
6408
 
 
6409
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
 
6410
  if (!res)
 
6411
    return NULL;
 
6412
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
 
6413
 
 
6414
  buf= (char*)res + sizeof(*res);
 
6415
  expr_end= expr + expr_len;
 
6416
  p= expr;
 
6417
  buf_p= buf;
6436
6418
 
6437
6419
  /* for each regexp substitution statement */
6438
6420
  while (p < expr_end)
6448
6430
 
6449
6431
    if (p == expr_end || ++p == expr_end)
6450
6432
    {
6451
 
      if (!regex_arr.empty())
 
6433
      if (res->regex_arr.elements)
6452
6434
        break;
6453
6435
      else
6454
6436
        goto err;
6487
6469
      p++;
6488
6470
      reg.global= 1;
6489
6471
    }
6490
 
    regex_arr.push_back(reg);
 
6472
 
 
6473
    /* done parsing the statement, now place it in regex_arr */
 
6474
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6475
      die("Out of memory");
6491
6476
  }
6492
 
  odd_buf_len= even_buf_len= buf0_.size();
6493
 
  even_buf= buf0_.data();
6494
 
  odd_buf= buf1_.data();
6495
 
  buf_= even_buf;
 
6477
  res->odd_buf_len= res->even_buf_len= 8192;
 
6478
  res->even_buf= (char*)malloc(res->even_buf_len);
 
6479
  res->odd_buf= (char*)malloc(res->odd_buf_len);
 
6480
  res->buf= res->even_buf;
6496
6481
 
6497
 
  return;
 
6482
  return res;
6498
6483
 
6499
6484
err:
 
6485
  free(res);
6500
6486
  die("Error parsing replace_regex \"%s\"", expr);
 
6487
  return 0;
6501
6488
}
6502
6489
 
6503
6490
/*
6519
6506
  in one pass
6520
6507
*/
6521
6508
 
6522
 
int st_replace_regex::multi_reg_replace(char* val)
 
6509
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6523
6510
{
6524
 
  char* in_buf= val;
6525
 
  char* out_buf= even_buf;
6526
 
  int* buf_len_p= &even_buf_len;
6527
 
  buf_= 0;
 
6511
  uint32_t i;
 
6512
  char* in_buf, *out_buf;
 
6513
  int* buf_len_p;
 
6514
 
 
6515
  in_buf= val;
 
6516
  out_buf= r->even_buf;
 
6517
  buf_len_p= &r->even_buf_len;
 
6518
  r->buf= 0;
6528
6519
 
6529
6520
  /* For each substitution, do the replace */
6530
 
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
 
6521
  for (i= 0; i < r->regex_arr.elements; i++)
6531
6522
  {
 
6523
    struct st_regex re;
6532
6524
    char* save_out_buf= out_buf;
6533
 
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6534
 
                     in_buf, i.icase, i.global))
 
6525
 
 
6526
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6527
 
 
6528
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
 
6529
                     in_buf, re.icase, re.global))
6535
6530
    {
6536
6531
      /* if the buffer has been reallocated, make adjustements */
6537
6532
      if (save_out_buf != out_buf)
6538
6533
      {
6539
 
        if (save_out_buf == even_buf)
6540
 
          even_buf= out_buf;
 
6534
        if (save_out_buf == r->even_buf)
 
6535
          r->even_buf= out_buf;
6541
6536
        else
6542
 
          odd_buf= out_buf;
 
6537
          r->odd_buf= out_buf;
6543
6538
      }
6544
 
      buf_= out_buf;
 
6539
 
 
6540
      r->buf= out_buf;
6545
6541
      if (in_buf == val)
6546
 
        in_buf= odd_buf;
6547
 
      std::swap(in_buf, out_buf);
6548
 
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
 
6542
        in_buf= r->odd_buf;
 
6543
 
 
6544
      std::swap(in_buf,out_buf);
 
6545
 
 
6546
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
 
6547
        &r->odd_buf_len;
6549
6548
    }
6550
6549
  }
6551
 
  return buf_ == 0;
 
6550
 
 
6551
  return (r->buf == 0);
6552
6552
}
6553
6553
 
6554
6554
/*
6563
6563
void do_get_replace_regex(struct st_command *command)
6564
6564
{
6565
6565
  char *expr= command->first_argument;
6566
 
  glob_replace_regex.reset(new st_replace_regex(expr));
 
6566
  free_replace_regex();
 
6567
  if (!(glob_replace_regex=init_replace_regex(expr)))
 
6568
    die("Could not init replace_regex");
6567
6569
  command->last_argument= command->end;
6568
6570
}
6569
6571
 
 
6572
void free_replace_regex()
 
6573
{
 
6574
  if (glob_replace_regex)
 
6575
  {
 
6576
    delete_dynamic(&glob_replace_regex->regex_arr);
 
6577
    free(glob_replace_regex->even_buf);
 
6578
    free(glob_replace_regex->odd_buf);
 
6579
    free(glob_replace_regex);
 
6580
    glob_replace_regex=0;
 
6581
  }
 
6582
}
 
6583
 
 
6584
 
 
6585
 
6570
6586
/*
6571
6587
  Performs a regex substitution
6572
6588
 
6673
6689
#define SET_MALLOC_HUNC 64
6674
6690
#define LAST_CHAR_CODE 259
6675
6691
 
6676
 
class REP_SET
6677
 
{
6678
 
public:
6679
 
  void internal_set_bit(uint32_t bit);
6680
 
  void internal_clear_bit(uint32_t bit);
6681
 
  void or_bits(const REP_SET *from);
6682
 
  void copy_bits(const REP_SET *from);
6683
 
  int cmp_bits(const REP_SET *set2) const;
6684
 
  int get_next_bit(uint32_t lastpos) const;
6685
 
 
 
6692
typedef struct st_rep_set {
6686
6693
  uint32_t  *bits;        /* Pointer to used sets */
6687
6694
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6688
6695
  uint32_t  found_len;      /* Best match to date */
6689
6696
  int  found_offset;
6690
6697
  uint32_t  table_offset;
6691
6698
  uint32_t  size_of_bits;      /* For convinience */
6692
 
};
6693
 
 
6694
 
class REP_SETS
6695
 
{
6696
 
public:
6697
 
  int find_set(const REP_SET *find);
6698
 
  void free_last_set();
6699
 
  void free_sets();
6700
 
  void make_sets_invisible();
6701
 
 
 
6699
} REP_SET;
 
6700
 
 
6701
typedef struct st_rep_sets {
6702
6702
  uint32_t    count;      /* Number of sets */
6703
6703
  uint32_t    extra;      /* Extra sets in buffer */
6704
 
  uint32_t    invisible;    /* Sets not shown */
 
6704
  uint32_t    invisible;    /* Sets not chown */
6705
6705
  uint32_t    size_of_bits;
6706
6706
  REP_SET  *set,*set_buffer;
6707
6707
  uint32_t    *bit_buffer;
6708
 
};
 
6708
} REP_SETS;
6709
6709
 
6710
 
struct FOUND_SET 
6711
 
{
 
6710
typedef struct st_found_set {
6712
6711
  uint32_t table_offset;
6713
6712
  int found_offset;
6714
 
};
 
6713
} FOUND_SET;
6715
6714
 
6716
 
struct FOLLOWS
6717
 
{
 
6715
typedef struct st_follow {
6718
6716
  int chr;
6719
6717
  uint32_t table_offset;
6720
6718
  uint32_t len;
6721
 
};
6722
 
 
6723
 
int init_sets(REP_SETS *sets, uint32_t states);
 
6719
} FOLLOWS;
 
6720
 
 
6721
 
 
6722
int init_sets(REP_SETS *sets,uint32_t states);
6724
6723
REP_SET *make_new_set(REP_SETS *sets);
6725
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6726
 
 
6727
 
static uint32_t found_sets= 0;
6728
 
 
6729
 
static uint32_t replace_len(const char *str)
 
6724
void make_sets_invisible(REP_SETS *sets);
 
6725
void free_last_set(REP_SETS *sets);
 
6726
void free_sets(REP_SETS *sets);
 
6727
void internal_set_bit(REP_SET *set, uint32_t bit);
 
6728
void internal_clear_bit(REP_SET *set, uint32_t bit);
 
6729
void or_bits(REP_SET *to,REP_SET *from);
 
6730
void copy_bits(REP_SET *to,REP_SET *from);
 
6731
int cmp_bits(REP_SET *set1,REP_SET *set2);
 
6732
int get_next_bit(REP_SET *set,uint32_t lastpos);
 
6733
int find_set(REP_SETS *sets,REP_SET *find);
 
6734
int find_found(FOUND_SET *found_set,uint32_t table_offset,
 
6735
               int found_offset);
 
6736
uint32_t start_at_word(char * pos);
 
6737
uint32_t end_of_word(char * pos);
 
6738
 
 
6739
static uint32_t found_sets=0;
 
6740
 
 
6741
 
 
6742
static uint32_t replace_len(char * str)
6730
6743
{
6731
6744
  uint32_t len=0;
6732
6745
  while (*str)
6739
6752
  return len;
6740
6753
}
6741
6754
 
6742
 
/* Return 1 if regexp starts with \b or ends with \b*/
6743
 
 
6744
 
static bool start_at_word(const char *pos)
6745
 
{
6746
 
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6747
 
}
6748
 
 
6749
 
static bool end_of_word(const char *pos)
6750
 
{
6751
 
  const char *end= strchr(pos, '\0');
6752
 
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6753
 
}
6754
 
 
6755
6755
/* Init a replace structure for further calls */
6756
6756
 
6757
 
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
 
6757
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6758
                      char * word_end_chars)
6758
6759
{
6759
 
  const int SPACE_CHAR= 256;
6760
 
  const int START_OF_LINE= 257;
6761
 
  const int END_OF_LINE= 258;
 
6760
  static const int SPACE_CHAR= 256;
 
6761
  static const int START_OF_LINE= 257;
 
6762
  static const int END_OF_LINE= 258;
6762
6763
 
6763
6764
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6764
6765
  int used_sets,chr,default_state;
6765
6766
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6766
 
  char *to_pos, **to_array;
 
6767
  char * pos, *to_pos, **to_array;
 
6768
  REP_SETS sets;
 
6769
  REP_SET *set,*start_states,*word_states,*new_set;
 
6770
  FOLLOWS *follow,*follow_ptr;
 
6771
  REPLACE *replace;
 
6772
  FOUND_SET *found_set;
 
6773
  REPLACE_STRING *rep_str;
 
6774
 
6767
6775
 
6768
6776
  /* Count number of states */
6769
6777
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6783
6791
  for (i=0 ; word_end_chars[i] ; i++)
6784
6792
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6785
6793
 
6786
 
  REP_SETS sets;
6787
 
  REP_SET *set,*start_states,*word_states,*new_set;
6788
 
  REPLACE_STRING *rep_str;
6789
 
  if (init_sets(&sets, states))
6790
 
    return 0;
 
6794
  if (init_sets(&sets,states))
 
6795
    return(0);
6791
6796
  found_sets=0;
6792
 
  vector<FOUND_SET> found_set(max_length * count);
 
6797
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
 
6798
                                
 
6799
  {
 
6800
    free_sets(&sets);
 
6801
    return(0);
 
6802
  }
6793
6803
  make_new_set(&sets);      /* Set starting set */
6794
 
  sets.make_sets_invisible();      /* Hide previus sets */
 
6804
  make_sets_invisible(&sets);      /* Hide previus sets */
6795
6805
  used_sets=-1;
6796
6806
  word_states=make_new_set(&sets);    /* Start of new word */
6797
6807
  start_states=make_new_set(&sets);    /* This is first state */
6798
 
  vector<FOLLOWS> follow(states + 2);
6799
 
  FOLLOWS *follow_ptr= &follow[1];
 
6808
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6809
  {
 
6810
    free_sets(&sets);
 
6811
    free(found_set);
 
6812
    return(0);
 
6813
  }
 
6814
 
6800
6815
  /* Init follow_ptr[] */
6801
 
  for (i=0, states=1; i < count; i++)
 
6816
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6802
6817
  {
6803
6818
    if (from[i][0] == '\\' && from[i][1] == '^')
6804
6819
    {
6805
 
      start_states->internal_set_bit(states + 1);
 
6820
      internal_set_bit(start_states,states+1);
6806
6821
      if (!from[i][2])
6807
6822
      {
6808
6823
        start_states->table_offset=i;
6811
6826
    }
6812
6827
    else if (from[i][0] == '\\' && from[i][1] == '$')
6813
6828
    {
6814
 
      start_states->internal_set_bit(states);
6815
 
      word_states->internal_set_bit(states);
 
6829
      internal_set_bit(start_states,states);
 
6830
      internal_set_bit(word_states,states);
6816
6831
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6817
6832
      {
6818
6833
        start_states->table_offset=i;
6821
6836
    }
6822
6837
    else
6823
6838
    {
6824
 
      word_states->internal_set_bit(states);
 
6839
      internal_set_bit(word_states,states);
6825
6840
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6826
 
        start_states->internal_set_bit(states + 1);
 
6841
        internal_set_bit(start_states,states+1);
6827
6842
      else
6828
 
        start_states->internal_set_bit(states);
 
6843
        internal_set_bit(start_states,states);
6829
6844
    }
6830
 
    const char *pos;
6831
 
    for (pos= from[i], len=0; *pos ; pos++)
 
6845
    for (pos=from[i], len=0; *pos ; pos++)
6832
6846
    {
6833
6847
      if (*pos == '\\' && *(pos+1))
6834
6848
      {
6871
6885
  }
6872
6886
 
6873
6887
 
6874
 
  for (set_nr=0; set_nr < sets.count ; set_nr++)
 
6888
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6875
6889
  {
6876
6890
    set=sets.set+set_nr;
6877
6891
    default_state= 0;        /* Start from beginning */
6878
6892
 
6879
6893
    /* If end of found-string not found or start-set with current set */
6880
6894
 
6881
 
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
 
6895
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6882
6896
    {
6883
 
      if (!follow[i].chr && !default_state)
6884
 
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
 
6897
      if (!follow[i].chr)
 
6898
      {
 
6899
        if (! default_state)
 
6900
          default_state= find_found(found_set,set->table_offset,
 
6901
                                    set->found_offset+1);
 
6902
      }
6885
6903
    }
6886
 
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
 
6904
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6887
6905
    if (!default_state)
6888
 
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
 
6906
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
6889
6907
 
6890
6908
    /* Find all chars that follows current sets */
6891
6909
    memset(used_chars, 0, sizeof(used_chars));
6892
 
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
 
6910
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6893
6911
    {
6894
6912
      used_chars[follow[i].chr]=1;
6895
6913
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6899
6917
 
6900
6918
    /* Mark word_chars used if \b is in state */
6901
6919
    if (used_chars[SPACE_CHAR])
6902
 
      for (const char *pos= word_end_chars ; *pos ; pos++)
 
6920
      for (pos= word_end_chars ; *pos ; pos++)
6903
6921
        used_chars[(int) (unsigned char) *pos] = 1;
6904
6922
 
6905
6923
    /* Handle other used characters */
6916
6934
        new_set->found_offset=set->found_offset+1;
6917
6935
        found_end=0;
6918
6936
 
6919
 
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
 
6937
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6920
6938
        {
6921
6939
          if (!follow[i].chr || follow[i].chr == chr ||
6922
6940
              (follow[i].chr == SPACE_CHAR &&
6928
6946
                follow[i].len > found_end)
6929
6947
              found_end=follow[i].len;
6930
6948
            if (chr && follow[i].chr)
6931
 
              new_set->internal_set_bit(i + 1);    /* To next set */
 
6949
              internal_set_bit(new_set,i+1);    /* To next set */
6932
6950
            else
6933
 
              new_set->internal_set_bit(i);
 
6951
              internal_set_bit(new_set,i);
6934
6952
          }
6935
6953
        }
6936
6954
        if (found_end)
6937
6955
        {
6938
6956
          new_set->found_len=0;      /* Set for testing if first */
6939
6957
          bits_set=0;
6940
 
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
 
6958
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6941
6959
          {
6942
6960
            if ((follow[i].chr == SPACE_CHAR ||
6943
6961
                 follow[i].chr == END_OF_LINE) && ! chr)
6947
6965
            if (follow[bit_nr-1].len < found_end ||
6948
6966
                (new_set->found_len &&
6949
6967
                 (chr == 0 || !follow[bit_nr].chr)))
6950
 
              new_set->internal_clear_bit(i);
 
6968
              internal_clear_bit(new_set,i);
6951
6969
            else
6952
6970
            {
6953
6971
              if (chr == 0 || !follow[bit_nr].chr)
6963
6981
          }
6964
6982
          if (bits_set == 1)
6965
6983
          {
6966
 
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6967
 
            sets.free_last_set();
 
6984
            set->next[chr] = find_found(found_set,
 
6985
                                        new_set->table_offset,
 
6986
                                        new_set->found_offset);
 
6987
            free_last_set(&sets);
6968
6988
          }
6969
6989
          else
6970
 
            set->next[chr] = sets.find_set(new_set);
 
6990
            set->next[chr] = find_set(&sets,new_set);
6971
6991
        }
6972
6992
        else
6973
 
          set->next[chr] = sets.find_set(new_set);
 
6993
          set->next[chr] = find_set(&sets,new_set);
6974
6994
      }
6975
6995
    }
6976
6996
  }
6977
6997
 
6978
6998
  /* Alloc replace structure for the replace-state-machine */
6979
6999
 
6980
 
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6981
 
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
6982
 
  if (replace)
 
7000
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
 
7001
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
 
7002
                                 sizeof(char *)*count+result_len)))
6983
7003
  {
6984
7004
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6985
7005
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6996
7016
    rep_str[0].replace_string=0;
6997
7017
    for (i=1 ; i <= found_sets ; i++)
6998
7018
    {
6999
 
      const char *pos= from[found_set[i-1].table_offset];
 
7019
      pos=from[found_set[i-1].table_offset];
7000
7020
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7001
 
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
7002
 
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
7003
 
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
 
7021
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
 
7022
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
 
7023
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
 
7024
        end_of_word(pos);
7004
7025
    }
7005
7026
    for (i=0 ; i < sets.count ; i++)
7006
7027
    {
7011
7032
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7012
7033
    }
7013
7034
  }
7014
 
  sets.free_sets();
7015
 
  return replace;
 
7035
  free(follow);
 
7036
  free_sets(&sets);
 
7037
  free(found_set);
 
7038
  return(replace);
7016
7039
}
7017
7040
 
7018
7041
 
7033
7056
 
7034
7057
/* Make help sets invisible for nicer codeing */
7035
7058
 
7036
 
void REP_SETS::make_sets_invisible()
 
7059
void make_sets_invisible(REP_SETS *sets)
7037
7060
{
7038
 
  invisible= count;
7039
 
  set += count;
7040
 
  count= 0;
 
7061
  sets->invisible=sets->count;
 
7062
  sets->set+=sets->count;
 
7063
  sets->count=0;
7041
7064
}
7042
7065
 
7043
7066
REP_SET *make_new_set(REP_SETS *sets)
7075
7098
  return make_new_set(sets);
7076
7099
}
7077
7100
 
7078
 
void REP_SETS::free_last_set()
7079
 
{
7080
 
  count--;
7081
 
  extra++;
7082
 
}
7083
 
 
7084
 
void REP_SETS::free_sets()
7085
 
{
7086
 
  free(set_buffer);
7087
 
  free(bit_buffer);
7088
 
}
7089
 
 
7090
 
void REP_SET::internal_set_bit(uint32_t bit)
7091
 
{
7092
 
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7093
 
}
7094
 
 
7095
 
void REP_SET::internal_clear_bit(uint32_t bit)
7096
 
{
7097
 
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7098
 
}
7099
 
 
7100
 
 
7101
 
void REP_SET::or_bits(const REP_SET *from)
7102
 
{
7103
 
  for (uint32_t i= 0 ; i < size_of_bits; i++)
7104
 
    bits[i]|=from->bits[i];
7105
 
}
7106
 
 
7107
 
void REP_SET::copy_bits(const REP_SET *from)
7108
 
{
7109
 
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
7110
 
}
7111
 
 
7112
 
int REP_SET::cmp_bits(const REP_SET *set2) const
7113
 
{
7114
 
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
7115
 
}
 
7101
void free_last_set(REP_SETS *sets)
 
7102
{
 
7103
  sets->count--;
 
7104
  sets->extra++;
 
7105
  return;
 
7106
}
 
7107
 
 
7108
void free_sets(REP_SETS *sets)
 
7109
{
 
7110
  free(sets->set_buffer);
 
7111
  free(sets->bit_buffer);
 
7112
  return;
 
7113
}
 
7114
 
 
7115
void internal_set_bit(REP_SET *set, uint32_t bit)
 
7116
{
 
7117
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
7118
  return;
 
7119
}
 
7120
 
 
7121
void internal_clear_bit(REP_SET *set, uint32_t bit)
 
7122
{
 
7123
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
7124
  return;
 
7125
}
 
7126
 
 
7127
 
 
7128
void or_bits(REP_SET *to,REP_SET *from)
 
7129
{
 
7130
  register uint32_t i;
 
7131
  for (i=0 ; i < to->size_of_bits ; i++)
 
7132
    to->bits[i]|=from->bits[i];
 
7133
  return;
 
7134
}
 
7135
 
 
7136
void copy_bits(REP_SET *to,REP_SET *from)
 
7137
{
 
7138
  memcpy(to->bits,from->bits,
 
7139
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
 
7140
}
 
7141
 
 
7142
int cmp_bits(REP_SET *set1,REP_SET *set2)
 
7143
{
 
7144
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
 
7145
}
 
7146
 
7116
7147
 
7117
7148
/* Get next set bit from set. */
7118
7149
 
7119
 
int REP_SET::get_next_bit(uint32_t lastpos) const
 
7150
int get_next_bit(REP_SET *set,uint32_t lastpos)
7120
7151
{
7121
 
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
7122
 
  uint32_t *end= bits + size_of_bits;
7123
 
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7124
 
 
7125
 
  while (!bits0 && ++start < end)
7126
 
    bits0= start[0];
7127
 
  if (!bits0)
 
7152
  uint32_t pos,*start,*end,bits;
 
7153
 
 
7154
  start=set->bits+ ((lastpos+1) / WORD_BIT);
 
7155
  end=set->bits + set->size_of_bits;
 
7156
  bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
7157
 
 
7158
  while (! bits && ++start < end)
 
7159
    bits=start[0];
 
7160
  if (!bits)
7128
7161
    return 0;
7129
 
  uint32_t pos= (start - bits) * WORD_BIT;
7130
 
  while (!(bits0 & 1))
 
7162
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
7163
  while (! (bits & 1))
7131
7164
  {
7132
 
    bits0 >>=1;
 
7165
    bits>>=1;
7133
7166
    pos++;
7134
7167
  }
7135
7168
  return pos;
7139
7172
   free given set, else put in given set in sets and return its
7140
7173
   position */
7141
7174
 
7142
 
int REP_SETS::find_set(const REP_SET *find)
 
7175
int find_set(REP_SETS *sets,REP_SET *find)
7143
7176
{
7144
 
  uint32_t i= 0;
7145
 
  for (; i < count - 1; i++)
 
7177
  uint32_t i;
 
7178
  for (i=0 ; i < sets->count-1 ; i++)
7146
7179
  {
7147
 
    if (!set[i].cmp_bits(find))
 
7180
    if (!cmp_bits(sets->set+i,find))
7148
7181
    {
7149
 
      free_last_set();
 
7182
      free_last_set(sets);
7150
7183
      return i;
7151
7184
    }
7152
7185
  }
7160
7193
   set->next[] == -1 is reserved for end without replaces.
7161
7194
*/
7162
7195
 
7163
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
 
7196
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7164
7197
{
7165
 
  uint32_t i= 0;
7166
 
  for (; i < found_sets; i++)
7167
 
  {
 
7198
  int i;
 
7199
  for (i=0 ; (uint32_t) i < found_sets ; i++)
7168
7200
    if (found_set[i].table_offset == table_offset &&
7169
7201
        found_set[i].found_offset == found_offset)
7170
 
      return - i - 2;
7171
 
  }
7172
 
  found_set[i].table_offset= table_offset;
7173
 
  found_set[i].found_offset= found_offset;
 
7202
      return -i-2;
 
7203
  found_set[i].table_offset=table_offset;
 
7204
  found_set[i].found_offset=found_offset;
7174
7205
  found_sets++;
7175
 
  return - i - 2; // return new postion
 
7206
  return -i-2;        /* return new postion */
 
7207
}
 
7208
 
 
7209
/* Return 1 if regexp starts with \b or ends with \b*/
 
7210
 
 
7211
uint32_t start_at_word(char * pos)
 
7212
{
 
7213
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
 
7214
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
7215
}
 
7216
 
 
7217
uint32_t end_of_word(char * pos)
 
7218
{
 
7219
  char * end= strchr(pos, '\0');
 
7220
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
 
7221
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7176
7222
}
7177
7223
 
7178
7224
/****************************************************************************
7251
7297
} /* insert_pointer_name */
7252
7298
 
7253
7299
 
 
7300
/* free pointer array */
 
7301
 
 
7302
void free_pointer_array(POINTER_ARRAY *pa)
 
7303
{
 
7304
  if (pa->typelib.count)
 
7305
  {
 
7306
    pa->typelib.count=0;
 
7307
    free((char*) pa->typelib.type_names);
 
7308
    pa->typelib.type_names=0;
 
7309
    free(pa->str);
 
7310
  }
 
7311
} /* free_pointer_array */
 
7312
 
 
7313
 
7254
7314
/* Functions that uses replace and replace_regex */
7255
7315
 
7256
7316
/* Append the string to ds, with optional replace */
7257
 
void replace_append_mem(string *ds, const char *val, int len)
 
7317
void replace_append_mem(string *ds,
 
7318
                        const char *val, int len)
7258
7319
{
7259
7320
  char *v= strdup(val);
7260
7321
 
7261
 
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
 
7322
  if (glob_replace_regex)
7262
7323
  {
7263
 
    v= glob_replace_regex->buf_;
7264
 
    len= strlen(v);
 
7324
    /* Regex replace */
 
7325
    if (!multi_reg_replace(glob_replace_regex, v))
 
7326
    {
 
7327
      v= glob_replace_regex->buf;
 
7328
      len= strlen(v);
 
7329
    }
7265
7330
  }
 
7331
 
7266
7332
  if (glob_replace)
7267
7333
  {
7268
7334
    /* Normal replace */
7269
7335
    replace_strings_append(glob_replace, ds, v, len);
7270
7336
  }
7271
7337
  else
 
7338
  {
7272
7339
    ds->append(v, len);
 
7340
  }
7273
7341
}
7274
7342
 
7275
7343
 
7338
7406
 
7339
7407
  return;
7340
7408
}
7341
 
 
7342
 
static void free_all_replace()
7343
 
{
7344
 
  free_replace();
7345
 
  glob_replace_regex.reset();
7346
 
  free_replace_column();
7347
 
}