~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

Show diffs side-by-side

added added

removed removed

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