~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

Namespace the parser just a bit, and update our call for the type of parser
we want.

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