~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

Use List::begin()

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
#include <sys/stat.h>
57
57
#include <sys/types.h>
58
58
#include <fcntl.h>
 
59
#include <boost/array.hpp>
 
60
#include <boost/foreach.hpp>
59
61
#include <boost/program_options.hpp>
 
62
#include <boost/smart_ptr.hpp>
60
63
 
61
64
#include PCRE_HEADER
62
65
 
64
67
#include <boost/unordered_map.hpp>
65
68
 
66
69
/* Added this for string translation. */
67
 
#include "drizzled/gettext.h"
68
 
#include "drizzled/drizzle_time.h"
69
 
#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>
70
74
#include <drizzled/configmake.h>
71
75
 
 
76
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
 
77
 
72
78
#ifndef DRIZZLE_RETURN_SERVER_GONE
73
79
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
74
80
#endif
115
121
static bool is_windows= false;
116
122
static bool use_drizzle_protocol= false;
117
123
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
 
124
static void free_all_replace();
118
125
 
119
126
std::string opt_basedir,
120
127
  opt_charsets_dir,
164
171
  uint32_t lineno; /* Current line in file */
165
172
};
166
173
 
167
 
static struct st_test_file file_stack[16];
168
 
static struct st_test_file* cur_file;
169
 
static struct st_test_file* file_stack_end;
170
 
 
 
174
static boost::array<st_test_file, 16> file_stack;
 
175
static st_test_file* cur_file;
171
176
 
172
177
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
173
178
 
177
182
*/
178
183
static char *timer_file = NULL;
179
184
static uint64_t timer_start;
180
 
static void timer_output(void);
181
 
static uint64_t timer_now(void);
 
185
static void timer_output();
 
186
static uint64_t timer_now();
182
187
 
183
188
static uint64_t progress_start= 0;
184
189
 
199
204
 
200
205
/* if set, all results are concated and compared against this file */
201
206
 
202
 
typedef struct st_var
 
207
class VAR
203
208
{
 
209
public:
204
210
  char *name;
205
211
  int name_len;
206
212
  char *str_val;
210
216
  int int_dirty; /* do not update string if int is updated until first read */
211
217
  int alloced;
212
218
  char *env_s;
213
 
} VAR;
 
219
};
214
220
 
215
221
/*Perl/shell-like variable registers */
216
 
VAR var_reg[10];
217
 
 
218
 
 
219
 
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;
220
226
 
221
227
struct st_connection
222
228
{
389
395
  struct st_match_err err[10];
390
396
  uint32_t count;
391
397
};
392
 
static struct st_expected_errors saved_expected_errors;
393
 
 
394
 
struct st_command
 
398
 
 
399
static st_expected_errors saved_expected_errors;
 
400
 
 
401
class st_command
395
402
{
 
403
public:
396
404
  char *query, *query_buf,*first_argument,*last_argument,*end;
397
405
  int first_word_len, query_len;
398
406
  bool abort_on_error;
399
407
  st_expected_errors expected_errors;
400
408
  string require_file;
401
 
  enum enum_commands type;
 
409
  enum_commands type;
402
410
 
403
411
  st_command()
404
412
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
410
418
 
411
419
  ~st_command()
412
420
  {
413
 
    if (query_buf != NULL)
414
 
    {
415
 
      free(query_buf);
416
 
    }
 
421
    free(query_buf);
417
422
  }
418
423
};
419
424
 
438
443
VAR* var_from_env(const char *, const char *);
439
444
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
440
445
              int val_len);
441
 
void var_free(pair<string, VAR*> v);
442
446
VAR* var_get(const char *var_name, const char** var_name_end,
443
447
             bool raw, bool ignore_not_existing);
444
448
void eval_expr(VAR* v, const char *p, const char** p_end);
445
449
bool match_delimiter(int c, const char *delim, uint32_t length);
446
450
void dump_result_to_reject_file(char *buf, int size);
447
451
void dump_result_to_log_file(const char *buf, int size);
448
 
void dump_warning_messages(void);
449
 
void dump_progress(void);
 
452
void dump_warning_messages();
 
453
void dump_progress();
450
454
 
451
455
void do_eval(string *query_eval, const char *query,
452
456
             const char *query_end, bool pass_through_escape_chars);
457
461
static char *replace_column[MAX_COLUMNS];
458
462
static uint32_t max_replace_column= 0;
459
463
void do_get_replace_column(struct st_command*);
460
 
void free_replace_column(void);
 
464
void free_replace_column();
461
465
 
462
466
/* For replace */
463
467
void do_get_replace(struct st_command *command);
464
 
void free_replace(void);
 
468
void free_replace();
465
469
 
466
470
/* For replace_regex */
467
471
void do_get_replace_regex(struct st_command *command);
468
 
void free_replace_regex(void);
469
 
 
470
 
 
471
 
void free_all_replace(void);
472
 
 
473
 
 
474
 
void free_all_replace(void){
475
 
  free_replace();
476
 
  free_replace_regex();
477
 
  free_replace_column();
478
 
}
479
472
 
480
473
void replace_append_mem(string *ds, const char *val,
481
474
                        int len);
492
485
void do_eval(string *query_eval, const char *query,
493
486
             const char *query_end, bool pass_through_escape_chars)
494
487
{
495
 
  const char *p;
496
 
  register char c, next_c;
497
 
  register int escaped = 0;
 
488
  char c, next_c;
 
489
  int escaped = 0;
498
490
  VAR *v;
499
491
 
500
 
 
501
 
  for (p= query; (c= *p) && p < query_end; ++p)
 
492
  for (const char *p= query; (c= *p) && p < query_end; ++p)
502
493
  {
503
494
    switch(c) {
504
495
    case '$':
843
834
 
844
835
static void handle_command_error(struct st_command *command, uint32_t error)
845
836
{
846
 
 
847
837
  if (error != 0)
848
838
  {
849
839
    uint32_t i;
870
860
        command->first_word_len, command->query,
871
861
        command->expected_errors.err[0].code.errnum);
872
862
  }
873
 
  return;
874
863
}
875
864
 
876
865
 
877
 
static void close_connections(void)
 
866
static void close_connections()
878
867
{
879
868
  for (--next_con; next_con >= connections; --next_con)
880
869
  {
885
874
    }
886
875
    free(next_con->name);
887
876
  }
888
 
  return;
889
877
}
890
878
 
891
879
 
892
 
static void close_files(void)
 
880
static void close_files()
893
881
{
894
 
 
895
 
  for (; cur_file >= file_stack; cur_file--)
 
882
  for (; cur_file >= file_stack.data(); cur_file--)
896
883
  {
897
884
    if (cur_file->file && cur_file->file != stdin)
898
 
    {
899
885
      fclose(cur_file->file);
900
 
    }
901
 
    free((unsigned char*) cur_file->file_name);
 
886
    free(const_cast<char*>(cur_file->file_name));
902
887
    cur_file->file_name= 0;
903
888
  }
904
 
  return;
905
889
}
906
890
 
907
 
 
908
 
static void free_used_memory(void)
 
891
static void free_used_memory()
909
892
{
910
 
  uint32_t i;
911
 
 
912
 
 
913
893
  close_connections();
914
894
  close_files();
915
 
  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
  }
916
902
  var_hash.clear();
917
 
 
918
 
  vector<st_command *>::iterator iter;
919
 
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
920
 
  {
921
 
    struct st_command * q_line= *iter;
922
 
    delete q_line;
923
 
  }
924
 
 
925
 
  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++)
926
906
  {
927
907
    if (var_reg[i].alloced_len)
928
908
      free(var_reg[i].str_val);
929
909
  }
930
 
 
931
910
  free_all_replace();
932
911
  free(opt_pass);
933
 
 
934
 
  return;
935
912
}
936
913
 
937
914
 
956
933
      assert(0);
957
934
    }
958
935
  }
959
 
 
960
936
  exit(exit_code);
961
937
}
962
938
 
976
952
 
977
953
  /* Print the error message */
978
954
  fprintf(stderr, "drizzletest: ");
979
 
  if (cur_file && cur_file != file_stack)
 
955
  if (cur_file && cur_file != file_stack.data())
980
956
    fprintf(stderr, "In included file \"%s\": ",
981
957
            cur_file->file_name);
982
958
  if (start_lineno > 0)
1037
1013
 
1038
1014
  /* Print include filestack */
1039
1015
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1040
 
          file_stack->file_name);
 
1016
          file_stack[0].file_name);
1041
1017
  fprintf(stderr, "Detected in file %s at line %d\n",
1042
1018
          err_file->file_name, err_file->lineno);
1043
 
  while (err_file != file_stack)
 
1019
  while (err_file != file_stack.data())
1044
1020
  {
1045
1021
    err_file--;
1046
1022
    fprintf(stderr, "included from %s at line %d\n",
1071
1047
 
1072
1048
  va_start(args, fmt);
1073
1049
  fprintf(stderr, "drizzletest: ");
1074
 
  if (cur_file && cur_file != file_stack)
 
1050
  if (cur_file && cur_file != file_stack.data())
1075
1051
    fprintf(stderr, "In included file \"%s\": ",
1076
1052
            cur_file->file_name);
1077
1053
  if (start_lineno != 0)
1079
1055
  vfprintf(stderr, fmt, args);
1080
1056
  fprintf(stderr, "\n");
1081
1057
  va_end(args);
1082
 
 
1083
 
  return;
1084
1058
}
1085
1059
 
1086
1060
 
1096
1070
  if (start_lineno != 0)
1097
1071
  {
1098
1072
    ds_warning_messages.append("Warning detected ");
1099
 
    if (cur_file && cur_file != file_stack)
 
1073
    if (cur_file && cur_file != file_stack.data())
1100
1074
    {
1101
1075
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1102
1076
                    cur_file->file_name);
1629
1603
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1630
1604
              int val_len)
1631
1605
{
1632
 
  int val_alloc_len;
1633
 
  VAR *tmp_var;
1634
1606
  if (!name_len && name)
1635
1607
    name_len = strlen(name);
1636
1608
  if (!val_len && val)
1637
1609
    val_len = strlen(val) ;
1638
 
  val_alloc_len = val_len + 16; /* room to grow */
1639
 
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
1640
 
                                               + name_len+1)))
1641
 
    die("Out of memory");
 
1610
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
1642
1611
 
1643
 
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
 
1612
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
1644
1613
  tmp_var->alloced = (v == 0);
1645
1614
 
1646
 
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
1647
 
    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);
1648
1617
 
1649
1618
  memcpy(tmp_var->name, name, name_len);
1650
1619
  if (val)
1655
1624
  tmp_var->name_len = name_len;
1656
1625
  tmp_var->str_val_len = val_len;
1657
1626
  tmp_var->alloced_len = val_alloc_len;
1658
 
  tmp_var->int_val = (val) ? atoi(val) : 0;
1659
 
  tmp_var->int_dirty = 0;
 
1627
  tmp_var->int_val = val ? atoi(val) : 0;
 
1628
  tmp_var->int_dirty = false;
1660
1629
  tmp_var->env_s = 0;
1661
1630
  return tmp_var;
1662
1631
}
1663
1632
 
1664
 
 
1665
 
void var_free(pair<string, VAR *> v)
1666
 
{
1667
 
  free(v.second->str_val);
1668
 
  free(v.second->env_s);
1669
 
  if (v.second->alloced)
1670
 
    free(v.second);
1671
 
}
1672
 
 
1673
 
 
1674
1633
VAR* var_from_env(const char *name, const char *def_val)
1675
1634
{
1676
 
  const char *tmp;
1677
 
  VAR *v;
1678
 
  if (!(tmp = getenv(name)))
 
1635
  const char *tmp= getenv(name);
 
1636
  if (!tmp)
1679
1637
    tmp = def_val;
1680
 
 
1681
 
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1682
 
  string var_name(name);
1683
 
  var_hash.insert(make_pair(var_name, v));
1684
 
  return v;
 
1638
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
1685
1639
}
1686
1640
 
1687
 
 
1688
1641
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1689
1642
             bool ignore_not_existing)
1690
1643
{
1691
1644
  int digit;
1692
1645
  VAR *v;
1693
 
 
1694
1646
  if (*var_name != '$')
1695
1647
    goto err;
1696
1648
  digit = *++var_name - '0';
1712
1664
      die("Too long variable name: %s", save_var_name);
1713
1665
 
1714
1666
    string save_var_name_str(save_var_name, length);
1715
 
    boost::unordered_map<string, VAR*>::iterator iter=
1716
 
      var_hash.find(save_var_name_str);
 
1667
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
1717
1668
    if (iter == var_hash.end())
1718
1669
    {
1719
1670
      char buff[MAX_VAR_NAME_LENGTH+1];
1723
1674
    }
1724
1675
    else
1725
1676
    {
1726
 
      v= (*iter).second;
 
1677
      v= iter->second;
1727
1678
    }
1728
1679
    var_name--;  /* Point at last character */
1729
1680
  }
1730
1681
  else
1731
 
    v = var_reg + digit;
 
1682
    v = &var_reg[digit];
1732
1683
 
1733
1684
  if (!raw && v->int_dirty)
1734
1685
  {
1750
1701
static VAR *var_obtain(const char *name, int len)
1751
1702
{
1752
1703
  string var_name(name, len);
1753
 
  boost::unordered_map<string, VAR*>::iterator iter=
1754
 
    var_hash.find(var_name);
 
1704
  var_hash_t::iterator iter= var_hash.find(var_name);
1755
1705
  if (iter != var_hash.end())
1756
 
    return (*iter).second;
1757
 
  VAR *v = var_init(0, name, len, "", 0);
1758
 
  var_hash.insert(make_pair(var_name, v));
1759
 
  return v;
 
1706
    return iter->second;
 
1707
  return var_hash[var_name] = var_init(0, name, len, "", 0);
1760
1708
}
1761
1709
 
1762
1710
 
1783
1731
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1784
1732
  }
1785
1733
  else
1786
 
    v= var_reg + digit;
 
1734
    v= &var_reg[digit];
1787
1735
 
1788
1736
  eval_expr(v, var_val, (const char**) &var_val_end);
1789
1737
 
2067
2015
    eval_expr(var, value, 0);
2068
2016
  }
2069
2017
  drizzle_result_free(&res);
2070
 
 
2071
 
  return;
2072
2018
}
2073
2019
 
2074
2020
 
2099
2045
{
2100
2046
  if (*p == '$')
2101
2047
  {
2102
 
    VAR *vp;
2103
 
    if ((vp= var_get(p, p_end, 0, 0)))
 
2048
    VAR *vp= var_get(p, p_end, 0, 0);
 
2049
    if (vp)
2104
2050
      var_copy(v, vp);
2105
2051
    return;
2106
2052
  }
2161
2107
  }
2162
2108
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2163
2109
 
2164
 
  if (cur_file == file_stack_end)
 
2110
  cur_file++;
 
2111
  if (cur_file == &*file_stack.end())
2165
2112
    die("Source directives are nesting too deep");
2166
 
  cur_file++;
2167
2113
  if (!(cur_file->file= fopen(buff, "r")))
2168
2114
  {
2169
2115
    cur_file--;
2225
2171
}
2226
2172
 
2227
2173
 
2228
 
static void init_builtin_echo(void)
 
2174
static void init_builtin_echo()
2229
2175
{
2230
2176
  builtin_echo[0]= 0;
2231
 
  return;
2232
2177
}
2233
2178
 
2234
2179
 
2480
2425
 
2481
2426
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
2482
2427
  handle_command_error(command, error);
2483
 
  return;
2484
2428
}
2485
2429
 
2486
2430
 
2515
2459
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2516
2460
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2517
2461
  handle_command_error(command, error);
2518
 
  return;
2519
2462
}
2520
2463
 
2521
2464
 
2553
2496
    die("You must write a 4 digit octal number for mode");
2554
2497
 
2555
2498
  handle_command_error(command, chmod(ds_file.c_str(), mode));
2556
 
  return;
2557
2499
}
2558
2500
 
2559
2501
 
2583
2525
 
2584
2526
  error= (access(ds_filename.c_str(), F_OK) != 0);
2585
2527
  handle_command_error(command, error);
2586
 
  return;
2587
2528
}
2588
2529
 
2589
2530
 
2612
2553
 
2613
2554
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
2614
2555
  handle_command_error(command, error);
2615
 
  return;
2616
2556
}
2617
2557
 
2618
2558
/*
2640
2580
 
2641
2581
  error= rmdir(ds_dirname.c_str()) != 0;
2642
2582
  handle_command_error(command, error);
2643
 
  return;
2644
2583
}
2645
2584
 
2646
2585
 
2879
2818
  }
2880
2819
 
2881
2820
  handle_command_error(command, error);
2882
 
  return;
2883
2821
}
2884
2822
 
2885
2823
 
2929
2867
 
2930
2868
  if (drizzle_quit(&con->con,&result, &ret))
2931
2869
    drizzle_result_free(&result);
2932
 
 
2933
 
  return;
2934
2870
}
2935
2871
 
2936
2872
 
3027
2963
  internal::my_delete(temp_file_path, MYF(0));
3028
2964
 
3029
2965
  handle_command_error(command, WEXITSTATUS(error));
3030
 
  return;
3031
2966
}
3032
2967
 
3033
2968
 
3201
3136
  when ndb binlog is on, this call will wait until last updated epoch
3202
3137
  (locally in the drizzled) has been received into the binlog
3203
3138
*/
3204
 
static int do_save_master_pos(void)
 
3139
static int do_save_master_pos()
3205
3140
{
3206
3141
  drizzle_result_st res;
3207
3142
  drizzle_return_t ret;
3340
3275
    sleep_val= opt_sleep;
3341
3276
 
3342
3277
  if (sleep_val)
3343
 
    usleep((uint32_t) (sleep_val * 1000000L));
 
3278
    usleep(sleep_val * 1000000);
3344
3279
  command->last_argument= sleep_end;
3345
3280
  return 0;
3346
3281
}
3347
3282
 
3348
3283
 
3349
 
static void do_get_file_name(struct st_command *command, string &dest)
 
3284
static void do_get_file_name(st_command *command, string &dest)
3350
3285
{
3351
 
  char *p= command->first_argument, *name;
 
3286
  char *p= command->first_argument;
3352
3287
  if (!*p)
3353
3288
    die("Missing file name argument");
3354
 
  name= p;
 
3289
  char *name= p;
3355
3290
  while (*p && !my_isspace(charset_info,*p))
3356
3291
    p++;
3357
3292
  if (*p)
3426
3361
      and assign that string to the $variable
3427
3362
    */
3428
3363
    size_t *lengths= drizzle_row_field_sizes(&res);
3429
 
    const std::string error_name(row[0], lengths[0]);
3430
 
    const std::string error_code(row[1], lengths[1]);
3431
 
 
3432
3364
    try
3433
3365
    {
3434
 
      global_error_names.insert(ErrorCodes::value_type(error_name,
3435
 
                                                       boost::lexical_cast<uint32_t>(error_code)));
 
3366
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3436
3367
    }
3437
3368
    catch (boost::bad_lexical_cast &ex)
3438
3369
    {
3452
3383
 
3453
3384
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3454
3385
  if (it != global_error_names.end())
3455
 
  {
3456
 
    return (*it).second;
3457
 
  }
 
3386
    return it->second;
3458
3387
 
3459
3388
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3460
3389
  return 0;
3525
3454
    {
3526
3455
      die("The error name definition must start with an uppercase E");
3527
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
    }
3528
3464
    else
3529
3465
    {
3530
 
      long val;
3531
 
      char *start= p;
3532
 
      /* Check that the string passed to str2int only contain digits */
3533
 
      while (*p && p != end)
3534
 
      {
3535
 
        if (!my_isdigit(charset_info, *p))
3536
 
          die("Invalid argument to error: '%s' - "              \
3537
 
              "the errno may only consist of digits[0-9]",
3538
 
              command->first_argument);
3539
 
        p++;
3540
 
      }
3541
 
 
3542
 
      /* Convert the sting to int */
3543
 
      istringstream buff(start);
3544
 
      if ((buff >> val).fail())
3545
 
        die("Invalid argument to error: '%s'", command->first_argument);
3546
 
 
3547
 
      to->code.errnum= (uint32_t) val;
3548
 
      to->type= ERR_ERRNO;
 
3466
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3549
3467
    }
3550
3468
    to++;
3551
3469
    count++;
4086
4004
{
4087
4005
  char *p= command->first_argument;
4088
4006
  const char *expr_start, *expr_end;
4089
 
  VAR v;
4090
4007
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4091
4008
  bool not_expr= false;
4092
4009
 
4129
4046
  if (*p && *p != '{')
4130
4047
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4131
4048
 
 
4049
  VAR v;
4132
4050
  var_init(&v,0,0,0,0);
4133
4051
  eval_expr(&v, expr_start, &expr_end);
4134
4052
 
4264
4182
      }
4265
4183
      free((unsigned char*) cur_file->file_name);
4266
4184
      cur_file->file_name= 0;
4267
 
      if (cur_file == file_stack)
 
4185
      if (cur_file == file_stack.data())
4268
4186
      {
4269
4187
        /* We're back at the first file, check if
4270
4188
           all { have matching }
4498
4416
        end++;
4499
4417
      save= *end;
4500
4418
      *end= 0;
4501
 
      type= find_type(start, &command_typelib, 1+2);
 
4419
      type= command_typelib.find_type(start, 1+2);
4502
4420
      if (type)
4503
4421
        warning_msg("Embedded drizzletest command '--%s' detected in "
4504
4422
                    "query '%s' was this intentional? ",
4704
4622
          log_file);
4705
4623
}
4706
4624
 
4707
 
void dump_progress(void)
 
4625
void dump_progress()
4708
4626
{
4709
4627
  char progress_file[FN_REFLEN];
4710
4628
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4714
4632
              ds_progress.c_str(), ds_progress.length());
4715
4633
}
4716
4634
 
4717
 
void dump_warning_messages(void)
 
4635
void dump_warning_messages()
4718
4636
{
4719
4637
  char warn_file[FN_REFLEN];
4720
4638
 
5321
5239
 
5322
5240
  save= command->query[command->first_word_len];
5323
5241
  command->query[command->first_word_len]= 0;
5324
 
  type= find_type(command->query, &command_typelib, 1+2);
 
5242
  type= command_typelib.find_type(command->query, 1+2);
5325
5243
  command->query[command->first_word_len]= save;
5326
5244
  if (type > 0)
5327
5245
  {
5365
5283
        */
5366
5284
        save= command->query[command->first_word_len-1];
5367
5285
        command->query[command->first_word_len-1]= 0;
5368
 
        if (find_type(command->query, &command_typelib, 1+2) > 0)
 
5286
        if (command_typelib.find_type(command->query, 1+2) > 0)
5369
5287
          die("Extra delimiter \";\" found");
5370
5288
        command->query[command->first_word_len-1]= save;
5371
5289
 
5539
5457
 
5540
5458
  if (user_config_dir.compare(0, 2, "~/") == 0)
5541
5459
  {
5542
 
    char *homedir;
5543
 
    homedir= getenv("HOME");
 
5460
    const char *homedir= getenv("HOME");
5544
5461
    if (homedir != NULL)
5545
5462
      user_config_dir.replace(0, 1, homedir);
5546
5463
  }
5587
5504
  next_con= connections + 1;
5588
5505
 
5589
5506
  /* Init file stack */
5590
 
  memset(file_stack, 0, sizeof(file_stack));
5591
 
  file_stack_end=
5592
 
    file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
5593
 
  cur_file= file_stack;
 
5507
  memset(file_stack.data(), 0, sizeof(file_stack));
 
5508
  cur_file= file_stack.data();
5594
5509
 
5595
5510
  /* Init block stack */
5596
5511
  memset(block_stack, 0, sizeof(block_stack));
5629
5544
      tmp= buff;
5630
5545
    }
5631
5546
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5632
 
    assert(cur_file == file_stack && cur_file->file == 0);
 
5547
    assert(cur_file == file_stack.data() && cur_file->file == 0);
5633
5548
    if (!(cur_file->file= fopen(buff, "r")))
5634
5549
    {
5635
5550
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5734
5649
  }
5735
5650
 
5736
5651
  server_initialized= 1;
5737
 
  if (cur_file == file_stack && cur_file->file == 0)
 
5652
  if (cur_file == file_stack.data() && cur_file->file == 0)
5738
5653
  {
5739
5654
    cur_file->file= stdin;
5740
5655
    cur_file->file_name= strdup("<stdin>");
6159
6074
  the time between executing the two commands.
6160
6075
*/
6161
6076
 
6162
 
void timer_output(void)
 
6077
void timer_output()
6163
6078
{
6164
6079
  if (timer_file)
6165
6080
  {
6173
6088
}
6174
6089
 
6175
6090
 
6176
 
uint64_t timer_now(void)
 
6091
uint64_t timer_now()
6177
6092
{
6178
6093
#if defined(HAVE_GETHRTIME)
6179
6094
  return gethrtime()/1000/1000;
6213
6128
  start= buff= (char *)malloc(strlen(from)+1);
6214
6129
  while (*from)
6215
6130
  {
6216
 
    char *to;
6217
6131
    uint32_t column_number;
6218
6132
 
6219
 
    to= get_string(&buff, &from, command);
 
6133
    char *to= get_string(&buff, &from, command);
6220
6134
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6221
6135
      die("Wrong column number to replace_column in '%s'", command->query);
6222
6136
    if (!*from)
6235
6149
 
6236
6150
void free_replace_column()
6237
6151
{
6238
 
  uint32_t i;
6239
 
  for (i=0 ; i < max_replace_column ; i++)
 
6152
  for (uint32_t i= 0 ; i < max_replace_column; i++)
6240
6153
  {
6241
 
    if (replace_column[i])
6242
 
    {
6243
 
      free(replace_column[i]);
6244
 
      replace_column[i]= 0;
6245
 
    }
 
6154
    free(replace_column[i]);
 
6155
    replace_column[i]= 0;
6246
6156
  }
6247
6157
  max_replace_column= 0;
6248
6158
}
6263
6173
} POINTER_ARRAY;
6264
6174
 
6265
6175
struct st_replace;
6266
 
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
6267
 
                                char * word_end_chars);
 
6176
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
 
6177
                                char *word_end_chars);
6268
6178
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6269
6179
void replace_strings_append(struct st_replace *rep, string* ds,
6270
6180
                            const char *from, int len);
6271
 
void free_pointer_array(POINTER_ARRAY *pa);
6272
6181
 
6273
 
struct st_replace *glob_replace= NULL;
 
6182
st_replace *glob_replace= NULL;
 
6183
// boost::scoped_ptr<st_replace> glob_replace;
6274
6184
 
6275
6185
/*
6276
6186
  Get arguments for replace. The syntax is:
6280
6190
  variable is replaced.
6281
6191
*/
6282
6192
 
 
6193
static void free_pointer_array(POINTER_ARRAY *pa)
 
6194
{
 
6195
  if (!pa->typelib.count)
 
6196
    return;
 
6197
  pa->typelib.count=0;
 
6198
  free((char*) pa->typelib.type_names);
 
6199
  pa->typelib.type_names=0;
 
6200
  free(pa->str);
 
6201
}
 
6202
 
6283
6203
void do_get_replace(struct st_command *command)
6284
6204
{
6285
6205
  uint32_t i;
6311
6231
    if (my_isspace(charset_info,i))
6312
6232
      *pos++= i;
6313
6233
  *pos=0;          /* End pointer */
6314
 
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6315
 
                                   (char**) to_array.typelib.type_names,
6316
 
                                   (uint32_t) from_array.typelib.count,
 
6234
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
 
6235
                                   to_array.typelib.type_names,
 
6236
                                   from_array.typelib.count,
6317
6237
                                   word_end_chars)))
6318
6238
    die("Can't initialize replace from '%s'", command->query);
6319
6239
  free_pointer_array(&from_array);
6326
6246
 
6327
6247
void free_replace()
6328
6248
{
6329
 
 
6330
 
  if (glob_replace)
6331
 
  {
6332
 
    free(glob_replace);
6333
 
    glob_replace=0;
6334
 
  }
6335
 
  return;
 
6249
  free(glob_replace);
 
6250
  glob_replace=0;
6336
6251
}
6337
6252
 
6338
6253
 
6352
6267
void replace_strings_append(REPLACE *rep, string* ds,
6353
6268
                            const char *str, int len)
6354
6269
{
6355
 
  register REPLACE *rep_pos;
6356
 
  register REPLACE_STRING *rep_str;
 
6270
  REPLACE *rep_pos;
 
6271
  REPLACE_STRING *rep_str;
6357
6272
  const char *start, *from;
6358
6273
 
6359
6274
 
6406
6321
                 i.e. repeat the matching until the end of the string */
6407
6322
};
6408
6323
 
6409
 
struct st_replace_regex
 
6324
class st_replace_regex
6410
6325
{
6411
 
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
 
6326
public:
 
6327
  st_replace_regex(char* expr);
 
6328
  int multi_reg_replace(char* val);
6412
6329
 
6413
6330
  /*
6414
6331
    Temporary storage areas for substitutions. To reduce unnessary copying
6417
6334
    st_regex substition. At the end of substitutions  buf points to the
6418
6335
    one containing the final result.
6419
6336
  */
6420
 
  char* buf;
 
6337
  typedef vector<st_regex> regex_arr_t;
 
6338
 
 
6339
  char* buf_;
6421
6340
  char* even_buf;
6422
6341
  char* odd_buf;
6423
6342
  int even_buf_len;
6424
6343
  int odd_buf_len;
 
6344
  boost::array<char, 8 << 10> buf0_;
 
6345
  boost::array<char, 8 << 10> buf1_;
 
6346
  regex_arr_t regex_arr;
6425
6347
};
6426
6348
 
6427
 
struct st_replace_regex *glob_replace_regex= 0;
 
6349
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
6428
6350
 
6429
6351
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6430
6352
                char *string, int icase, int global);
6466
6388
  Returns: st_replace_regex struct with pairs of substitutions
6467
6389
*/
6468
6390
 
6469
 
static struct st_replace_regex* init_replace_regex(char* expr)
 
6391
st_replace_regex::st_replace_regex(char* expr)
6470
6392
{
6471
 
  struct st_replace_regex* res;
6472
 
  char* buf,*expr_end;
6473
 
  char* p;
6474
 
  char* buf_p;
6475
6393
  uint32_t expr_len= strlen(expr);
6476
6394
  char last_c = 0;
6477
 
  struct st_regex reg;
6478
 
 
6479
 
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
6480
 
  if (!res)
6481
 
    return NULL;
6482
 
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
6483
 
 
6484
 
  buf= (char*)res + sizeof(*res);
6485
 
  expr_end= expr + expr_len;
6486
 
  p= expr;
6487
 
  buf_p= buf;
 
6395
  st_regex reg;
 
6396
 
 
6397
  char* buf= new char[expr_len];
 
6398
  char* expr_end= expr + expr_len;
 
6399
  char* p= expr;
 
6400
  char* buf_p= buf;
6488
6401
 
6489
6402
  /* for each regexp substitution statement */
6490
6403
  while (p < expr_end)
6500
6413
 
6501
6414
    if (p == expr_end || ++p == expr_end)
6502
6415
    {
6503
 
      if (res->regex_arr.elements)
 
6416
      if (!regex_arr.empty())
6504
6417
        break;
6505
6418
      else
6506
6419
        goto err;
6539
6452
      p++;
6540
6453
      reg.global= 1;
6541
6454
    }
6542
 
 
6543
 
    /* done parsing the statement, now place it in regex_arr */
6544
 
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
6545
 
      die("Out of memory");
 
6455
    regex_arr.push_back(reg);
6546
6456
  }
6547
 
  res->odd_buf_len= res->even_buf_len= 8192;
6548
 
  res->even_buf= (char*)malloc(res->even_buf_len);
6549
 
  res->odd_buf= (char*)malloc(res->odd_buf_len);
6550
 
  res->buf= res->even_buf;
 
6457
  odd_buf_len= even_buf_len= buf0_.size();
 
6458
  even_buf= buf0_.data();
 
6459
  odd_buf= buf1_.data();
 
6460
  buf_= even_buf;
6551
6461
 
6552
 
  return res;
 
6462
  return;
6553
6463
 
6554
6464
err:
6555
 
  free(res);
6556
6465
  die("Error parsing replace_regex \"%s\"", expr);
6557
 
  return 0;
6558
6466
}
6559
6467
 
6560
6468
/*
6576
6484
  in one pass
6577
6485
*/
6578
6486
 
6579
 
static int multi_reg_replace(struct st_replace_regex* r,char* val)
 
6487
int st_replace_regex::multi_reg_replace(char* val)
6580
6488
{
6581
 
  uint32_t i;
6582
 
  char* in_buf, *out_buf;
6583
 
  int* buf_len_p;
6584
 
 
6585
 
  in_buf= val;
6586
 
  out_buf= r->even_buf;
6587
 
  buf_len_p= &r->even_buf_len;
6588
 
  r->buf= 0;
 
6489
  char* in_buf= val;
 
6490
  char* out_buf= even_buf;
 
6491
  int* buf_len_p= &even_buf_len;
 
6492
  buf_= 0;
6589
6493
 
6590
6494
  /* For each substitution, do the replace */
6591
 
  for (i= 0; i < r->regex_arr.elements; i++)
 
6495
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
6592
6496
  {
6593
 
    struct st_regex re;
6594
6497
    char* save_out_buf= out_buf;
6595
 
 
6596
 
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
6597
 
 
6598
 
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6599
 
                     in_buf, re.icase, re.global))
 
6498
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
 
6499
                     in_buf, i.icase, i.global))
6600
6500
    {
6601
6501
      /* if the buffer has been reallocated, make adjustements */
6602
6502
      if (save_out_buf != out_buf)
6603
6503
      {
6604
 
        if (save_out_buf == r->even_buf)
6605
 
          r->even_buf= out_buf;
 
6504
        if (save_out_buf == even_buf)
 
6505
          even_buf= out_buf;
6606
6506
        else
6607
 
          r->odd_buf= out_buf;
 
6507
          odd_buf= out_buf;
6608
6508
      }
6609
 
 
6610
 
      r->buf= out_buf;
 
6509
      buf_= out_buf;
6611
6510
      if (in_buf == val)
6612
 
        in_buf= r->odd_buf;
6613
 
 
6614
 
      std::swap(in_buf,out_buf);
6615
 
 
6616
 
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6617
 
        &r->odd_buf_len;
 
6511
        in_buf= odd_buf;
 
6512
      std::swap(in_buf, out_buf);
 
6513
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
6618
6514
    }
6619
6515
  }
6620
 
 
6621
 
  return (r->buf == 0);
 
6516
  return buf_ == 0;
6622
6517
}
6623
6518
 
6624
6519
/*
6633
6528
void do_get_replace_regex(struct st_command *command)
6634
6529
{
6635
6530
  char *expr= command->first_argument;
6636
 
  free_replace_regex();
6637
 
  if (!(glob_replace_regex=init_replace_regex(expr)))
6638
 
    die("Could not init replace_regex");
 
6531
  glob_replace_regex.reset(new st_replace_regex(expr));
6639
6532
  command->last_argument= command->end;
6640
6533
}
6641
6534
 
6642
 
void free_replace_regex()
6643
 
{
6644
 
  if (glob_replace_regex)
6645
 
  {
6646
 
    delete_dynamic(&glob_replace_regex->regex_arr);
6647
 
    free(glob_replace_regex->even_buf);
6648
 
    free(glob_replace_regex->odd_buf);
6649
 
    free(glob_replace_regex);
6650
 
    glob_replace_regex=0;
6651
 
  }
6652
 
}
6653
 
 
6654
 
 
6655
 
 
6656
6535
/*
6657
6536
  Performs a regex substitution
6658
6537
 
6759
6638
#define SET_MALLOC_HUNC 64
6760
6639
#define LAST_CHAR_CODE 259
6761
6640
 
6762
 
typedef struct st_rep_set {
 
6641
class REP_SET
 
6642
{
 
6643
public:
 
6644
  void internal_set_bit(uint32_t bit);
 
6645
  void internal_clear_bit(uint32_t bit);
 
6646
  void or_bits(const REP_SET *from);
 
6647
  void copy_bits(const REP_SET *from);
 
6648
  int cmp_bits(const REP_SET *set2) const;
 
6649
  int get_next_bit(uint32_t lastpos) const;
 
6650
 
6763
6651
  uint32_t  *bits;        /* Pointer to used sets */
6764
6652
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6765
6653
  uint32_t  found_len;      /* Best match to date */
6766
6654
  int  found_offset;
6767
6655
  uint32_t  table_offset;
6768
6656
  uint32_t  size_of_bits;      /* For convinience */
6769
 
} REP_SET;
6770
 
 
6771
 
typedef struct st_rep_sets {
 
6657
};
 
6658
 
 
6659
class REP_SETS
 
6660
{
 
6661
public:
 
6662
  int find_set(const REP_SET *find);
 
6663
  void free_last_set();
 
6664
  void free_sets();
 
6665
  void make_sets_invisible();
 
6666
 
6772
6667
  uint32_t    count;      /* Number of sets */
6773
6668
  uint32_t    extra;      /* Extra sets in buffer */
6774
 
  uint32_t    invisible;    /* Sets not chown */
 
6669
  uint32_t    invisible;    /* Sets not shown */
6775
6670
  uint32_t    size_of_bits;
6776
6671
  REP_SET  *set,*set_buffer;
6777
6672
  uint32_t    *bit_buffer;
6778
 
} REP_SETS;
 
6673
};
6779
6674
 
6780
 
typedef struct st_found_set {
 
6675
struct FOUND_SET 
 
6676
{
6781
6677
  uint32_t table_offset;
6782
6678
  int found_offset;
6783
 
} FOUND_SET;
 
6679
};
6784
6680
 
6785
 
typedef struct st_follow {
 
6681
struct FOLLOWS
 
6682
{
6786
6683
  int chr;
6787
6684
  uint32_t table_offset;
6788
6685
  uint32_t len;
6789
 
} FOLLOWS;
6790
 
 
6791
 
 
6792
 
int init_sets(REP_SETS *sets,uint32_t states);
 
6686
};
 
6687
 
 
6688
int init_sets(REP_SETS *sets, uint32_t states);
6793
6689
REP_SET *make_new_set(REP_SETS *sets);
6794
 
void make_sets_invisible(REP_SETS *sets);
6795
 
void free_last_set(REP_SETS *sets);
6796
 
void free_sets(REP_SETS *sets);
6797
 
void internal_set_bit(REP_SET *set, uint32_t bit);
6798
 
void internal_clear_bit(REP_SET *set, uint32_t bit);
6799
 
void or_bits(REP_SET *to,REP_SET *from);
6800
 
void copy_bits(REP_SET *to,REP_SET *from);
6801
 
int cmp_bits(REP_SET *set1,REP_SET *set2);
6802
 
int get_next_bit(REP_SET *set,uint32_t lastpos);
6803
 
int find_set(REP_SETS *sets,REP_SET *find);
6804
 
int find_found(FOUND_SET *found_set,uint32_t table_offset,
6805
 
               int found_offset);
6806
 
uint32_t start_at_word(char * pos);
6807
 
uint32_t end_of_word(char * pos);
6808
 
 
6809
 
static uint32_t found_sets=0;
6810
 
 
6811
 
 
6812
 
static uint32_t replace_len(char * str)
 
6690
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
 
6691
 
 
6692
static uint32_t found_sets= 0;
 
6693
 
 
6694
static uint32_t replace_len(const char *str)
6813
6695
{
6814
6696
  uint32_t len=0;
6815
6697
  while (*str)
6822
6704
  return len;
6823
6705
}
6824
6706
 
 
6707
/* Return 1 if regexp starts with \b or ends with \b*/
 
6708
 
 
6709
static bool start_at_word(const char *pos)
 
6710
{
 
6711
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
 
6712
}
 
6713
 
 
6714
static bool end_of_word(const char *pos)
 
6715
{
 
6716
  const char *end= strchr(pos, '\0');
 
6717
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
 
6718
}
 
6719
 
6825
6720
/* Init a replace structure for further calls */
6826
6721
 
6827
 
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
6828
 
                      char * word_end_chars)
 
6722
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
6829
6723
{
6830
 
  static const int SPACE_CHAR= 256;
6831
 
  static const int START_OF_LINE= 257;
6832
 
  static const int END_OF_LINE= 258;
 
6724
  const int SPACE_CHAR= 256;
 
6725
  const int START_OF_LINE= 257;
 
6726
  const int END_OF_LINE= 258;
6833
6727
 
6834
6728
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6835
6729
  int used_sets,chr,default_state;
6836
6730
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6837
 
  char * pos, *to_pos, **to_array;
6838
 
  REP_SETS sets;
6839
 
  REP_SET *set,*start_states,*word_states,*new_set;
6840
 
  FOLLOWS *follow,*follow_ptr;
6841
 
  REPLACE *replace;
6842
 
  FOUND_SET *found_set;
6843
 
  REPLACE_STRING *rep_str;
6844
 
 
 
6731
  char *to_pos, **to_array;
6845
6732
 
6846
6733
  /* Count number of states */
6847
6734
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6861
6748
  for (i=0 ; word_end_chars[i] ; i++)
6862
6749
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6863
6750
 
6864
 
  if (init_sets(&sets,states))
6865
 
    return(0);
 
6751
  REP_SETS sets;
 
6752
  REP_SET *set,*start_states,*word_states,*new_set;
 
6753
  REPLACE_STRING *rep_str;
 
6754
  if (init_sets(&sets, states))
 
6755
    return 0;
6866
6756
  found_sets=0;
6867
 
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
6868
 
                                
6869
 
  {
6870
 
    free_sets(&sets);
6871
 
    return(0);
6872
 
  }
 
6757
  vector<FOUND_SET> found_set(max_length * count);
6873
6758
  make_new_set(&sets);      /* Set starting set */
6874
 
  make_sets_invisible(&sets);      /* Hide previus sets */
 
6759
  sets.make_sets_invisible();      /* Hide previus sets */
6875
6760
  used_sets=-1;
6876
6761
  word_states=make_new_set(&sets);    /* Start of new word */
6877
6762
  start_states=make_new_set(&sets);    /* This is first state */
6878
 
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
6879
 
  {
6880
 
    free_sets(&sets);
6881
 
    free(found_set);
6882
 
    return(0);
6883
 
  }
6884
 
 
 
6763
  vector<FOLLOWS> follow(states + 2);
 
6764
  FOLLOWS *follow_ptr= &follow[1];
6885
6765
  /* Init follow_ptr[] */
6886
 
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
 
6766
  for (i=0, states=1; i < count; i++)
6887
6767
  {
6888
6768
    if (from[i][0] == '\\' && from[i][1] == '^')
6889
6769
    {
6890
 
      internal_set_bit(start_states,states+1);
 
6770
      start_states->internal_set_bit(states + 1);
6891
6771
      if (!from[i][2])
6892
6772
      {
6893
6773
        start_states->table_offset=i;
6896
6776
    }
6897
6777
    else if (from[i][0] == '\\' && from[i][1] == '$')
6898
6778
    {
6899
 
      internal_set_bit(start_states,states);
6900
 
      internal_set_bit(word_states,states);
 
6779
      start_states->internal_set_bit(states);
 
6780
      word_states->internal_set_bit(states);
6901
6781
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6902
6782
      {
6903
6783
        start_states->table_offset=i;
6906
6786
    }
6907
6787
    else
6908
6788
    {
6909
 
      internal_set_bit(word_states,states);
 
6789
      word_states->internal_set_bit(states);
6910
6790
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6911
 
        internal_set_bit(start_states,states+1);
 
6791
        start_states->internal_set_bit(states + 1);
6912
6792
      else
6913
 
        internal_set_bit(start_states,states);
 
6793
        start_states->internal_set_bit(states);
6914
6794
    }
6915
 
    for (pos=from[i], len=0; *pos ; pos++)
 
6795
    const char *pos;
 
6796
    for (pos= from[i], len=0; *pos ; pos++)
6916
6797
    {
6917
6798
      if (*pos == '\\' && *(pos+1))
6918
6799
      {
6955
6836
  }
6956
6837
 
6957
6838
 
6958
 
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
 
6839
  for (set_nr=0; set_nr < sets.count ; set_nr++)
6959
6840
  {
6960
6841
    set=sets.set+set_nr;
6961
6842
    default_state= 0;        /* Start from beginning */
6962
6843
 
6963
6844
    /* If end of found-string not found or start-set with current set */
6964
6845
 
6965
 
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
 
6846
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
6966
6847
    {
6967
 
      if (!follow[i].chr)
6968
 
      {
6969
 
        if (! default_state)
6970
 
          default_state= find_found(found_set,set->table_offset,
6971
 
                                    set->found_offset+1);
6972
 
      }
 
6848
      if (!follow[i].chr && !default_state)
 
6849
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
6973
6850
    }
6974
 
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
 
6851
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
6975
6852
    if (!default_state)
6976
 
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
 
6853
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
6977
6854
 
6978
6855
    /* Find all chars that follows current sets */
6979
6856
    memset(used_chars, 0, sizeof(used_chars));
6980
 
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
 
6857
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
6981
6858
    {
6982
6859
      used_chars[follow[i].chr]=1;
6983
6860
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6987
6864
 
6988
6865
    /* Mark word_chars used if \b is in state */
6989
6866
    if (used_chars[SPACE_CHAR])
6990
 
      for (pos= word_end_chars ; *pos ; pos++)
 
6867
      for (const char *pos= word_end_chars ; *pos ; pos++)
6991
6868
        used_chars[(int) (unsigned char) *pos] = 1;
6992
6869
 
6993
6870
    /* Handle other used characters */
7004
6881
        new_set->found_offset=set->found_offset+1;
7005
6882
        found_end=0;
7006
6883
 
7007
 
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
6884
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
7008
6885
        {
7009
6886
          if (!follow[i].chr || follow[i].chr == chr ||
7010
6887
              (follow[i].chr == SPACE_CHAR &&
7016
6893
                follow[i].len > found_end)
7017
6894
              found_end=follow[i].len;
7018
6895
            if (chr && follow[i].chr)
7019
 
              internal_set_bit(new_set,i+1);    /* To next set */
 
6896
              new_set->internal_set_bit(i + 1);    /* To next set */
7020
6897
            else
7021
 
              internal_set_bit(new_set,i);
 
6898
              new_set->internal_set_bit(i);
7022
6899
          }
7023
6900
        }
7024
6901
        if (found_end)
7025
6902
        {
7026
6903
          new_set->found_len=0;      /* Set for testing if first */
7027
6904
          bits_set=0;
7028
 
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
 
6905
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
7029
6906
          {
7030
6907
            if ((follow[i].chr == SPACE_CHAR ||
7031
6908
                 follow[i].chr == END_OF_LINE) && ! chr)
7035
6912
            if (follow[bit_nr-1].len < found_end ||
7036
6913
                (new_set->found_len &&
7037
6914
                 (chr == 0 || !follow[bit_nr].chr)))
7038
 
              internal_clear_bit(new_set,i);
 
6915
              new_set->internal_clear_bit(i);
7039
6916
            else
7040
6917
            {
7041
6918
              if (chr == 0 || !follow[bit_nr].chr)
7051
6928
          }
7052
6929
          if (bits_set == 1)
7053
6930
          {
7054
 
            set->next[chr] = find_found(found_set,
7055
 
                                        new_set->table_offset,
7056
 
                                        new_set->found_offset);
7057
 
            free_last_set(&sets);
 
6931
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
 
6932
            sets.free_last_set();
7058
6933
          }
7059
6934
          else
7060
 
            set->next[chr] = find_set(&sets,new_set);
 
6935
            set->next[chr] = sets.find_set(new_set);
7061
6936
        }
7062
6937
        else
7063
 
          set->next[chr] = find_set(&sets,new_set);
 
6938
          set->next[chr] = sets.find_set(new_set);
7064
6939
      }
7065
6940
    }
7066
6941
  }
7067
6942
 
7068
6943
  /* Alloc replace structure for the replace-state-machine */
7069
6944
 
7070
 
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
7071
 
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
7072
 
                                 sizeof(char *)*count+result_len)))
 
6945
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
 
6946
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
 
6947
  if (replace)
7073
6948
  {
7074
6949
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
7075
6950
                       sizeof(REPLACE_STRING)*(found_sets+1)+
7086
6961
    rep_str[0].replace_string=0;
7087
6962
    for (i=1 ; i <= found_sets ; i++)
7088
6963
    {
7089
 
      pos=from[found_set[i-1].table_offset];
 
6964
      const char *pos= from[found_set[i-1].table_offset];
7090
6965
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7091
 
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
7092
 
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
7093
 
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
7094
 
        end_of_word(pos);
 
6966
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
 
6967
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
 
6968
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
7095
6969
    }
7096
6970
    for (i=0 ; i < sets.count ; i++)
7097
6971
    {
7102
6976
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7103
6977
    }
7104
6978
  }
7105
 
  free(follow);
7106
 
  free_sets(&sets);
7107
 
  free(found_set);
7108
 
  return(replace);
 
6979
  sets.free_sets();
 
6980
  return replace;
7109
6981
}
7110
6982
 
7111
6983
 
7126
6998
 
7127
6999
/* Make help sets invisible for nicer codeing */
7128
7000
 
7129
 
void make_sets_invisible(REP_SETS *sets)
 
7001
void REP_SETS::make_sets_invisible()
7130
7002
{
7131
 
  sets->invisible=sets->count;
7132
 
  sets->set+=sets->count;
7133
 
  sets->count=0;
 
7003
  invisible= count;
 
7004
  set += count;
 
7005
  count= 0;
7134
7006
}
7135
7007
 
7136
7008
REP_SET *make_new_set(REP_SETS *sets)
7168
7040
  return make_new_set(sets);
7169
7041
}
7170
7042
 
7171
 
void free_last_set(REP_SETS *sets)
7172
 
{
7173
 
  sets->count--;
7174
 
  sets->extra++;
7175
 
  return;
7176
 
}
7177
 
 
7178
 
void free_sets(REP_SETS *sets)
7179
 
{
7180
 
  free(sets->set_buffer);
7181
 
  free(sets->bit_buffer);
7182
 
  return;
7183
 
}
7184
 
 
7185
 
void internal_set_bit(REP_SET *set, uint32_t bit)
7186
 
{
7187
 
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7188
 
  return;
7189
 
}
7190
 
 
7191
 
void internal_clear_bit(REP_SET *set, uint32_t bit)
7192
 
{
7193
 
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7194
 
  return;
7195
 
}
7196
 
 
7197
 
 
7198
 
void or_bits(REP_SET *to,REP_SET *from)
7199
 
{
7200
 
  register uint32_t i;
7201
 
  for (i=0 ; i < to->size_of_bits ; i++)
7202
 
    to->bits[i]|=from->bits[i];
7203
 
  return;
7204
 
}
7205
 
 
7206
 
void copy_bits(REP_SET *to,REP_SET *from)
7207
 
{
7208
 
  memcpy(to->bits,from->bits,
7209
 
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
7210
 
}
7211
 
 
7212
 
int cmp_bits(REP_SET *set1,REP_SET *set2)
7213
 
{
7214
 
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
7215
 
}
7216
 
 
 
7043
void REP_SETS::free_last_set()
 
7044
{
 
7045
  count--;
 
7046
  extra++;
 
7047
}
 
7048
 
 
7049
void REP_SETS::free_sets()
 
7050
{
 
7051
  free(set_buffer);
 
7052
  free(bit_buffer);
 
7053
}
 
7054
 
 
7055
void REP_SET::internal_set_bit(uint32_t bit)
 
7056
{
 
7057
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
7058
}
 
7059
 
 
7060
void REP_SET::internal_clear_bit(uint32_t bit)
 
7061
{
 
7062
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
7063
}
 
7064
 
 
7065
 
 
7066
void REP_SET::or_bits(const REP_SET *from)
 
7067
{
 
7068
  for (uint32_t i= 0 ; i < size_of_bits; i++)
 
7069
    bits[i]|=from->bits[i];
 
7070
}
 
7071
 
 
7072
void REP_SET::copy_bits(const REP_SET *from)
 
7073
{
 
7074
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
 
7075
}
 
7076
 
 
7077
int REP_SET::cmp_bits(const REP_SET *set2) const
 
7078
{
 
7079
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
 
7080
}
7217
7081
 
7218
7082
/* Get next set bit from set. */
7219
7083
 
7220
 
int get_next_bit(REP_SET *set,uint32_t lastpos)
 
7084
int REP_SET::get_next_bit(uint32_t lastpos) const
7221
7085
{
7222
 
  uint32_t pos,*start,*end,bits;
7223
 
 
7224
 
  start=set->bits+ ((lastpos+1) / WORD_BIT);
7225
 
  end=set->bits + set->size_of_bits;
7226
 
  bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7227
 
 
7228
 
  while (! bits && ++start < end)
7229
 
    bits=start[0];
7230
 
  if (!bits)
 
7086
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
 
7087
  uint32_t *end= bits + size_of_bits;
 
7088
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
7089
 
 
7090
  while (!bits0 && ++start < end)
 
7091
    bits0= start[0];
 
7092
  if (!bits0)
7231
7093
    return 0;
7232
 
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
7233
 
  while (! (bits & 1))
 
7094
  uint32_t pos= (start - bits) * WORD_BIT;
 
7095
  while (!(bits0 & 1))
7234
7096
  {
7235
 
    bits>>=1;
 
7097
    bits0 >>=1;
7236
7098
    pos++;
7237
7099
  }
7238
7100
  return pos;
7242
7104
   free given set, else put in given set in sets and return its
7243
7105
   position */
7244
7106
 
7245
 
int find_set(REP_SETS *sets,REP_SET *find)
 
7107
int REP_SETS::find_set(const REP_SET *find)
7246
7108
{
7247
 
  uint32_t i;
7248
 
  for (i=0 ; i < sets->count-1 ; i++)
 
7109
  uint32_t i= 0;
 
7110
  for (; i < count - 1; i++)
7249
7111
  {
7250
 
    if (!cmp_bits(sets->set+i,find))
 
7112
    if (!set[i].cmp_bits(find))
7251
7113
    {
7252
 
      free_last_set(sets);
 
7114
      free_last_set();
7253
7115
      return i;
7254
7116
    }
7255
7117
  }
7263
7125
   set->next[] == -1 is reserved for end without replaces.
7264
7126
*/
7265
7127
 
7266
 
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
 
7128
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
7267
7129
{
7268
 
  int i;
7269
 
  for (i=0 ; (uint32_t) i < found_sets ; i++)
 
7130
  uint32_t i= 0;
 
7131
  for (; i < found_sets; i++)
 
7132
  {
7270
7133
    if (found_set[i].table_offset == table_offset &&
7271
7134
        found_set[i].found_offset == found_offset)
7272
 
      return -i-2;
7273
 
  found_set[i].table_offset=table_offset;
7274
 
  found_set[i].found_offset=found_offset;
 
7135
      return - i - 2;
 
7136
  }
 
7137
  found_set[i].table_offset= table_offset;
 
7138
  found_set[i].found_offset= found_offset;
7275
7139
  found_sets++;
7276
 
  return -i-2;        /* return new postion */
7277
 
}
7278
 
 
7279
 
/* Return 1 if regexp starts with \b or ends with \b*/
7280
 
 
7281
 
uint32_t start_at_word(char * pos)
7282
 
{
7283
 
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
7284
 
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
7285
 
}
7286
 
 
7287
 
uint32_t end_of_word(char * pos)
7288
 
{
7289
 
  char * end= strchr(pos, '\0');
7290
 
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
7291
 
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
 
7140
  return - i - 2; // return new postion
7292
7141
}
7293
7142
 
7294
7143
/****************************************************************************
7367
7216
} /* insert_pointer_name */
7368
7217
 
7369
7218
 
7370
 
/* free pointer array */
7371
 
 
7372
 
void free_pointer_array(POINTER_ARRAY *pa)
7373
 
{
7374
 
  if (pa->typelib.count)
7375
 
  {
7376
 
    pa->typelib.count=0;
7377
 
    free((char*) pa->typelib.type_names);
7378
 
    pa->typelib.type_names=0;
7379
 
    free(pa->str);
7380
 
  }
7381
 
} /* free_pointer_array */
7382
 
 
7383
 
 
7384
7219
/* Functions that uses replace and replace_regex */
7385
7220
 
7386
7221
/* Append the string to ds, with optional replace */
7387
 
void replace_append_mem(string *ds,
7388
 
                        const char *val, int len)
 
7222
void replace_append_mem(string *ds, const char *val, int len)
7389
7223
{
7390
7224
  char *v= strdup(val);
7391
7225
 
7392
 
  if (glob_replace_regex)
 
7226
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
7393
7227
  {
7394
 
    /* Regex replace */
7395
 
    if (!multi_reg_replace(glob_replace_regex, v))
7396
 
    {
7397
 
      v= glob_replace_regex->buf;
7398
 
      len= strlen(v);
7399
 
    }
 
7228
    v= glob_replace_regex->buf_;
 
7229
    len= strlen(v);
7400
7230
  }
7401
 
 
7402
7231
  if (glob_replace)
7403
7232
  {
7404
7233
    /* Normal replace */
7405
7234
    replace_strings_append(glob_replace, ds, v, len);
7406
7235
  }
7407
7236
  else
7408
 
  {
7409
7237
    ds->append(v, len);
7410
 
  }
7411
7238
}
7412
7239
 
7413
7240
 
7476
7303
 
7477
7304
  return;
7478
7305
}
 
7306
 
 
7307
static void free_all_replace()
 
7308
{
 
7309
  free_replace();
 
7310
  glob_replace_regex.reset();
 
7311
  free_replace_column();
 
7312
}