~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

new date/time additions

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
#include <sys/stat.h>
57
57
#include <sys/types.h>
58
58
#include <fcntl.h>
59
 
#include <boost/array.hpp>
60
 
#include <boost/foreach.hpp>
61
59
#include <boost/program_options.hpp>
62
 
#include <boost/smart_ptr.hpp>
63
60
 
64
61
#include PCRE_HEADER
65
62
 
67
64
#include <boost/unordered_map.hpp>
68
65
 
69
66
/* Added this for string translation. */
70
 
#include <drizzled/gettext.h>
71
 
#include <drizzled/type/time.h>
72
 
#include <drizzled/charset.h>
73
 
#include <drizzled/typelib.h>
 
67
#include "drizzled/gettext.h"
 
68
#include "drizzled/type/time.h"
 
69
#include "drizzled/charset.h"
74
70
#include <drizzled/configmake.h>
75
71
 
76
 
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
77
 
 
78
72
#ifndef DRIZZLE_RETURN_SERVER_GONE
79
73
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
80
74
#endif
121
115
static bool is_windows= false;
122
116
static bool use_drizzle_protocol= false;
123
117
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
124
 
static void free_all_replace();
125
118
 
126
119
std::string opt_basedir,
127
120
  opt_charsets_dir,
171
164
  uint32_t lineno; /* Current line in file */
172
165
};
173
166
 
174
 
static boost::array<st_test_file, 16> file_stack;
175
 
static st_test_file* cur_file;
 
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
 
176
171
 
177
172
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
178
173
 
182
177
*/
183
178
static char *timer_file = NULL;
184
179
static uint64_t timer_start;
185
 
static void timer_output();
186
 
static uint64_t timer_now();
 
180
static void timer_output(void);
 
181
static uint64_t timer_now(void);
187
182
 
188
183
static uint64_t progress_start= 0;
189
184
 
204
199
 
205
200
/* if set, all results are concated and compared against this file */
206
201
 
207
 
class VAR
 
202
typedef struct st_var
208
203
{
209
 
public:
210
204
  char *name;
211
205
  int name_len;
212
206
  char *str_val;
216
210
  int int_dirty; /* do not update string if int is updated until first read */
217
211
  int alloced;
218
212
  char *env_s;
219
 
};
 
213
} VAR;
220
214
 
221
215
/*Perl/shell-like variable registers */
222
 
boost::array<VAR, 10> var_reg;
223
 
 
224
 
typedef boost::unordered_map<string, VAR *> var_hash_t;
225
 
var_hash_t var_hash;
 
216
VAR var_reg[10];
 
217
 
 
218
 
 
219
boost::unordered_map<string, VAR *> var_hash;
226
220
 
227
221
struct st_connection
228
222
{
395
389
  struct st_match_err err[10];
396
390
  uint32_t count;
397
391
};
398
 
 
399
 
static st_expected_errors saved_expected_errors;
400
 
 
401
 
class st_command
 
392
static struct st_expected_errors saved_expected_errors;
 
393
 
 
394
struct st_command
402
395
{
403
 
public:
404
396
  char *query, *query_buf,*first_argument,*last_argument,*end;
405
397
  int first_word_len, query_len;
406
398
  bool abort_on_error;
407
399
  st_expected_errors expected_errors;
408
400
  string require_file;
409
 
  enum_commands type;
 
401
  enum enum_commands type;
410
402
 
411
403
  st_command()
412
404
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
418
410
 
419
411
  ~st_command()
420
412
  {
421
 
    free(query_buf);
 
413
    if (query_buf != NULL)
 
414
    {
 
415
      free(query_buf);
 
416
    }
422
417
  }
423
418
};
424
419
 
443
438
VAR* var_from_env(const char *, const char *);
444
439
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
445
440
              int val_len);
 
441
void var_free(pair<string, VAR*> v);
446
442
VAR* var_get(const char *var_name, const char** var_name_end,
447
443
             bool raw, bool ignore_not_existing);
448
444
void eval_expr(VAR* v, const char *p, const char** p_end);
449
445
bool match_delimiter(int c, const char *delim, uint32_t length);
450
446
void dump_result_to_reject_file(char *buf, int size);
451
447
void dump_result_to_log_file(const char *buf, int size);
452
 
void dump_warning_messages();
453
 
void dump_progress();
 
448
void dump_warning_messages(void);
 
449
void dump_progress(void);
454
450
 
455
451
void do_eval(string *query_eval, const char *query,
456
452
             const char *query_end, bool pass_through_escape_chars);
461
457
static char *replace_column[MAX_COLUMNS];
462
458
static uint32_t max_replace_column= 0;
463
459
void do_get_replace_column(struct st_command*);
464
 
void free_replace_column();
 
460
void free_replace_column(void);
465
461
 
466
462
/* For replace */
467
463
void do_get_replace(struct st_command *command);
468
 
void free_replace();
 
464
void free_replace(void);
469
465
 
470
466
/* For replace_regex */
471
467
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
}
472
479
 
473
480
void replace_append_mem(string *ds, const char *val,
474
481
                        int len);
485
492
void do_eval(string *query_eval, const char *query,
486
493
             const char *query_end, bool pass_through_escape_chars)
487
494
{
488
 
  char c, next_c;
489
 
  int escaped = 0;
 
495
  const char *p;
 
496
  register char c, next_c;
 
497
  register int escaped = 0;
490
498
  VAR *v;
491
499
 
492
 
  for (const char *p= query; (c= *p) && p < query_end; ++p)
 
500
 
 
501
  for (p= query; (c= *p) && p < query_end; ++p)
493
502
  {
494
503
    switch(c) {
495
504
    case '$':
834
843
 
835
844
static void handle_command_error(struct st_command *command, uint32_t error)
836
845
{
 
846
 
837
847
  if (error != 0)
838
848
  {
839
849
    uint32_t i;
860
870
        command->first_word_len, command->query,
861
871
        command->expected_errors.err[0].code.errnum);
862
872
  }
 
873
  return;
863
874
}
864
875
 
865
876
 
866
 
static void close_connections()
 
877
static void close_connections(void)
867
878
{
868
879
  for (--next_con; next_con >= connections; --next_con)
869
880
  {
874
885
    }
875
886
    free(next_con->name);
876
887
  }
 
888
  return;
877
889
}
878
890
 
879
891
 
880
 
static void close_files()
 
892
static void close_files(void)
881
893
{
882
 
  for (; cur_file >= file_stack.data(); cur_file--)
 
894
 
 
895
  for (; cur_file >= file_stack; cur_file--)
883
896
  {
884
897
    if (cur_file->file && cur_file->file != stdin)
 
898
    {
885
899
      fclose(cur_file->file);
886
 
    free(const_cast<char*>(cur_file->file_name));
 
900
    }
 
901
    free((unsigned char*) cur_file->file_name);
887
902
    cur_file->file_name= 0;
888
903
  }
 
904
  return;
889
905
}
890
906
 
891
 
static void free_used_memory()
 
907
 
 
908
static void free_used_memory(void)
892
909
{
 
910
  uint32_t i;
 
911
 
 
912
 
893
913
  close_connections();
894
914
  close_files();
895
 
  BOOST_FOREACH(var_hash_t::reference i, var_hash)
896
 
  {
897
 
    free(i.second->str_val);
898
 
    free(i.second->env_s);
899
 
    if (i.second->alloced)
900
 
      free(i.second);
901
 
  }
 
915
  for_each(var_hash.begin(), var_hash.end(), var_free);
902
916
  var_hash.clear();
903
 
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
904
 
    delete i;
905
 
  for (size_t i= 0; i < var_reg.size(); i++)
 
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++)
906
926
  {
907
927
    if (var_reg[i].alloced_len)
908
928
      free(var_reg[i].str_val);
909
929
  }
 
930
 
910
931
  free_all_replace();
911
932
  free(opt_pass);
 
933
 
 
934
  return;
912
935
}
913
936
 
914
937
 
933
956
      assert(0);
934
957
    }
935
958
  }
 
959
 
936
960
  exit(exit_code);
937
961
}
938
962
 
952
976
 
953
977
  /* Print the error message */
954
978
  fprintf(stderr, "drizzletest: ");
955
 
  if (cur_file && cur_file != file_stack.data())
 
979
  if (cur_file && cur_file != file_stack)
956
980
    fprintf(stderr, "In included file \"%s\": ",
957
981
            cur_file->file_name);
958
982
  if (start_lineno > 0)
1013
1037
 
1014
1038
  /* Print include filestack */
1015
1039
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1016
 
          file_stack[0].file_name);
 
1040
          file_stack->file_name);
1017
1041
  fprintf(stderr, "Detected in file %s at line %d\n",
1018
1042
          err_file->file_name, err_file->lineno);
1019
 
  while (err_file != file_stack.data())
 
1043
  while (err_file != file_stack)
1020
1044
  {
1021
1045
    err_file--;
1022
1046
    fprintf(stderr, "included from %s at line %d\n",
1047
1071
 
1048
1072
  va_start(args, fmt);
1049
1073
  fprintf(stderr, "drizzletest: ");
1050
 
  if (cur_file && cur_file != file_stack.data())
 
1074
  if (cur_file && cur_file != file_stack)
1051
1075
    fprintf(stderr, "In included file \"%s\": ",
1052
1076
            cur_file->file_name);
1053
1077
  if (start_lineno != 0)
1055
1079
  vfprintf(stderr, fmt, args);
1056
1080
  fprintf(stderr, "\n");
1057
1081
  va_end(args);
 
1082
 
 
1083
  return;
1058
1084
}
1059
1085
 
1060
1086
 
1070
1096
  if (start_lineno != 0)
1071
1097
  {
1072
1098
    ds_warning_messages.append("Warning detected ");
1073
 
    if (cur_file && cur_file != file_stack.data())
 
1099
    if (cur_file && cur_file != file_stack)
1074
1100
    {
1075
1101
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1076
1102
                    cur_file->file_name);
1603
1629
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1604
1630
              int val_len)
1605
1631
{
 
1632
  int val_alloc_len;
 
1633
  VAR *tmp_var;
1606
1634
  if (!name_len && name)
1607
1635
    name_len = strlen(name);
1608
1636
  if (!val_len && val)
1609
1637
    val_len = strlen(val) ;
1610
 
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
 
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");
1611
1642
 
1612
 
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
 
1643
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1613
1644
  tmp_var->alloced = (v == 0);
1614
1645
 
1615
 
  int val_alloc_len = val_len + 16; /* room to grow */
1616
 
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
 
1646
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1647
    die("Out of memory");
1617
1648
 
1618
1649
  memcpy(tmp_var->name, name, name_len);
1619
1650
  if (val)
1624
1655
  tmp_var->name_len = name_len;
1625
1656
  tmp_var->str_val_len = val_len;
1626
1657
  tmp_var->alloced_len = val_alloc_len;
1627
 
  tmp_var->int_val = val ? atoi(val) : 0;
1628
 
  tmp_var->int_dirty = false;
 
1658
  tmp_var->int_val = (val) ? atoi(val) : 0;
 
1659
  tmp_var->int_dirty = 0;
1629
1660
  tmp_var->env_s = 0;
1630
1661
  return tmp_var;
1631
1662
}
1632
1663
 
 
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
 
1633
1674
VAR* var_from_env(const char *name, const char *def_val)
1634
1675
{
1635
 
  const char *tmp= getenv(name);
1636
 
  if (!tmp)
 
1676
  const char *tmp;
 
1677
  VAR *v;
 
1678
  if (!(tmp = getenv(name)))
1637
1679
    tmp = def_val;
1638
 
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
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;
1639
1685
}
1640
1686
 
 
1687
 
1641
1688
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1642
1689
             bool ignore_not_existing)
1643
1690
{
1644
1691
  int digit;
1645
1692
  VAR *v;
 
1693
 
1646
1694
  if (*var_name != '$')
1647
1695
    goto err;
1648
1696
  digit = *++var_name - '0';
1664
1712
      die("Too long variable name: %s", save_var_name);
1665
1713
 
1666
1714
    string save_var_name_str(save_var_name, length);
1667
 
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
 
1715
    boost::unordered_map<string, VAR*>::iterator iter=
 
1716
      var_hash.find(save_var_name_str);
1668
1717
    if (iter == var_hash.end())
1669
1718
    {
1670
1719
      char buff[MAX_VAR_NAME_LENGTH+1];
1674
1723
    }
1675
1724
    else
1676
1725
    {
1677
 
      v= iter->second;
 
1726
      v= (*iter).second;
1678
1727
    }
1679
1728
    var_name--;  /* Point at last character */
1680
1729
  }
1681
1730
  else
1682
 
    v = &var_reg[digit];
 
1731
    v = var_reg + digit;
1683
1732
 
1684
1733
  if (!raw && v->int_dirty)
1685
1734
  {
1701
1750
static VAR *var_obtain(const char *name, int len)
1702
1751
{
1703
1752
  string var_name(name, len);
1704
 
  var_hash_t::iterator iter= var_hash.find(var_name);
 
1753
  boost::unordered_map<string, VAR*>::iterator iter=
 
1754
    var_hash.find(var_name);
1705
1755
  if (iter != var_hash.end())
1706
 
    return iter->second;
1707
 
  return var_hash[var_name] = var_init(0, name, len, "", 0);
 
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;
1708
1760
}
1709
1761
 
1710
1762
 
1731
1783
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1732
1784
  }
1733
1785
  else
1734
 
    v= &var_reg[digit];
 
1786
    v= var_reg + digit;
1735
1787
 
1736
1788
  eval_expr(v, var_val, (const char**) &var_val_end);
1737
1789
 
2015
2067
    eval_expr(var, value, 0);
2016
2068
  }
2017
2069
  drizzle_result_free(&res);
 
2070
 
 
2071
  return;
2018
2072
}
2019
2073
 
2020
2074
 
2045
2099
{
2046
2100
  if (*p == '$')
2047
2101
  {
2048
 
    VAR *vp= var_get(p, p_end, 0, 0);
2049
 
    if (vp)
 
2102
    VAR *vp;
 
2103
    if ((vp= var_get(p, p_end, 0, 0)))
2050
2104
      var_copy(v, vp);
2051
2105
    return;
2052
2106
  }
2107
2161
  }
2108
2162
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2109
2163
 
 
2164
  if (cur_file == file_stack_end)
 
2165
    die("Source directives are nesting too deep");
2110
2166
  cur_file++;
2111
 
  if (cur_file == &*file_stack.end())
2112
 
    die("Source directives are nesting too deep");
2113
2167
  if (!(cur_file->file= fopen(buff, "r")))
2114
2168
  {
2115
2169
    cur_file--;
2171
2225
}
2172
2226
 
2173
2227
 
2174
 
static void init_builtin_echo()
 
2228
static void init_builtin_echo(void)
2175
2229
{
2176
2230
  builtin_echo[0]= 0;
 
2231
  return;
2177
2232
}
2178
2233
 
2179
2234
 
2425
2480
 
2426
2481
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
2427
2482
  handle_command_error(command, error);
 
2483
  return;
2428
2484
}
2429
2485
 
2430
2486
 
2459
2515
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2460
2516
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2461
2517
  handle_command_error(command, error);
 
2518
  return;
2462
2519
}
2463
2520
 
2464
2521
 
2496
2553
    die("You must write a 4 digit octal number for mode");
2497
2554
 
2498
2555
  handle_command_error(command, chmod(ds_file.c_str(), mode));
 
2556
  return;
2499
2557
}
2500
2558
 
2501
2559
 
2525
2583
 
2526
2584
  error= (access(ds_filename.c_str(), F_OK) != 0);
2527
2585
  handle_command_error(command, error);
 
2586
  return;
2528
2587
}
2529
2588
 
2530
2589
 
2553
2612
 
2554
2613
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
2555
2614
  handle_command_error(command, error);
 
2615
  return;
2556
2616
}
2557
2617
 
2558
2618
/*
2580
2640
 
2581
2641
  error= rmdir(ds_dirname.c_str()) != 0;
2582
2642
  handle_command_error(command, error);
 
2643
  return;
2583
2644
}
2584
2645
 
2585
2646
 
2818
2879
  }
2819
2880
 
2820
2881
  handle_command_error(command, error);
 
2882
  return;
2821
2883
}
2822
2884
 
2823
2885
 
2867
2929
 
2868
2930
  if (drizzle_quit(&con->con,&result, &ret))
2869
2931
    drizzle_result_free(&result);
 
2932
 
 
2933
  return;
2870
2934
}
2871
2935
 
2872
2936
 
2963
3027
  internal::my_delete(temp_file_path, MYF(0));
2964
3028
 
2965
3029
  handle_command_error(command, WEXITSTATUS(error));
 
3030
  return;
2966
3031
}
2967
3032
 
2968
3033
 
3136
3201
  when ndb binlog is on, this call will wait until last updated epoch
3137
3202
  (locally in the drizzled) has been received into the binlog
3138
3203
*/
3139
 
static int do_save_master_pos()
 
3204
static int do_save_master_pos(void)
3140
3205
{
3141
3206
  drizzle_result_st res;
3142
3207
  drizzle_return_t ret;
3275
3340
    sleep_val= opt_sleep;
3276
3341
 
3277
3342
  if (sleep_val)
3278
 
    usleep(sleep_val * 1000000);
 
3343
    usleep((uint32_t) (sleep_val * 1000000L));
3279
3344
  command->last_argument= sleep_end;
3280
3345
  return 0;
3281
3346
}
3282
3347
 
3283
3348
 
3284
 
static void do_get_file_name(st_command *command, string &dest)
 
3349
static void do_get_file_name(struct st_command *command, string &dest)
3285
3350
{
3286
 
  char *p= command->first_argument;
 
3351
  char *p= command->first_argument, *name;
3287
3352
  if (!*p)
3288
3353
    die("Missing file name argument");
3289
 
  char *name= p;
 
3354
  name= p;
3290
3355
  while (*p && !my_isspace(charset_info,*p))
3291
3356
    p++;
3292
3357
  if (*p)
3361
3426
      and assign that string to the $variable
3362
3427
    */
3363
3428
    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
 
3364
3432
    try
3365
3433
    {
3366
 
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
 
3434
      global_error_names.insert(ErrorCodes::value_type(error_name,
 
3435
                                                       boost::lexical_cast<uint32_t>(error_code)));
3367
3436
    }
3368
3437
    catch (boost::bad_lexical_cast &ex)
3369
3438
    {
3383
3452
 
3384
3453
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3385
3454
  if (it != global_error_names.end())
3386
 
    return it->second;
 
3455
  {
 
3456
    return (*it).second;
 
3457
  }
3387
3458
 
3388
3459
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3389
3460
  return 0;
3454
3525
    {
3455
3526
      die("The error name definition must start with an uppercase E");
3456
3527
    }
3457
 
    else if (*p == 'H')
 
3528
    else
3458
3529
    {
3459
 
      /* Error name string */
3460
 
 
3461
 
      to->code.errnum= get_errcode_from_name(p, end);
 
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;
3462
3548
      to->type= ERR_ERRNO;
3463
3549
    }
3464
 
    else
3465
 
    {
3466
 
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3467
 
    }
3468
3550
    to++;
3469
3551
    count++;
3470
3552
 
4004
4086
{
4005
4087
  char *p= command->first_argument;
4006
4088
  const char *expr_start, *expr_end;
 
4089
  VAR v;
4007
4090
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4008
4091
  bool not_expr= false;
4009
4092
 
4046
4129
  if (*p && *p != '{')
4047
4130
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4048
4131
 
4049
 
  VAR v;
4050
4132
  var_init(&v,0,0,0,0);
4051
4133
  eval_expr(&v, expr_start, &expr_end);
4052
4134
 
4182
4264
      }
4183
4265
      free((unsigned char*) cur_file->file_name);
4184
4266
      cur_file->file_name= 0;
4185
 
      if (cur_file == file_stack.data())
 
4267
      if (cur_file == file_stack)
4186
4268
      {
4187
4269
        /* We're back at the first file, check if
4188
4270
           all { have matching }
4416
4498
        end++;
4417
4499
      save= *end;
4418
4500
      *end= 0;
4419
 
      type= command_typelib.find_type(start, 1+2);
 
4501
      type= find_type(start, &command_typelib, 1+2);
4420
4502
      if (type)
4421
4503
        warning_msg("Embedded drizzletest command '--%s' detected in "
4422
4504
                    "query '%s' was this intentional? ",
4622
4704
          log_file);
4623
4705
}
4624
4706
 
4625
 
void dump_progress()
 
4707
void dump_progress(void)
4626
4708
{
4627
4709
  char progress_file[FN_REFLEN];
4628
4710
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4632
4714
              ds_progress.c_str(), ds_progress.length());
4633
4715
}
4634
4716
 
4635
 
void dump_warning_messages()
 
4717
void dump_warning_messages(void)
4636
4718
{
4637
4719
  char warn_file[FN_REFLEN];
4638
4720
 
4697
4779
    for (i = 0; i < num_fields; i++)
4698
4780
    {
4699
4781
      column= drizzle_column_next(res);
4700
 
      if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
4701
 
      {
4702
 
        if (boost::lexical_cast<uint32_t>(row[i]))
4703
 
        {
4704
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4705
 
          {
4706
 
            append_field(ds, i, column, "YES", 3, false);
4707
 
          }
4708
 
          else
4709
 
          {
4710
 
            append_field(ds, i, column, "TRUE", 4, false);
4711
 
          }
4712
 
        }
4713
 
        else
4714
 
        {
4715
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4716
 
          {
4717
 
            append_field(ds, i, column, "NO", 2, false);
4718
 
          }
4719
 
          else
4720
 
          {
4721
 
            append_field(ds, i, column, "FALSE", 5, false);
4722
 
          }
4723
 
        }
4724
 
      }
4725
 
      else
4726
 
      {
4727
 
        append_field(ds, i, column,
4728
 
                     (const char*)row[i], lengths[i], !row[i]);
4729
 
      }
 
4782
      append_field(ds, i, column,
 
4783
                   (const char*)row[i], lengths[i], !row[i]);
4730
4784
    }
4731
4785
    if (!display_result_vertically)
4732
4786
      ds->append("\n");
4770
4824
    ds->append("\t", 1);
4771
4825
    replace_append_uint(ds, drizzle_column_size(column));
4772
4826
    ds->append("\t", 1);
4773
 
    if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
4774
 
    {
4775
 
      replace_append_uint(ds, 1);
4776
 
    }
4777
 
    else
4778
 
    {
4779
 
      replace_append_uint(ds, drizzle_column_max_size(column));
4780
 
    }
 
4827
    replace_append_uint(ds, drizzle_column_max_size(column));
4781
4828
    ds->append("\t", 1);
4782
4829
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4783
4830
    ds->append("\t", 1);
5274
5321
 
5275
5322
  save= command->query[command->first_word_len];
5276
5323
  command->query[command->first_word_len]= 0;
5277
 
  type= command_typelib.find_type(command->query, 1+2);
 
5324
  type= find_type(command->query, &command_typelib, 1+2);
5278
5325
  command->query[command->first_word_len]= save;
5279
5326
  if (type > 0)
5280
5327
  {
5318
5365
        */
5319
5366
        save= command->query[command->first_word_len-1];
5320
5367
        command->query[command->first_word_len-1]= 0;
5321
 
        if (command_typelib.find_type(command->query, 1+2) > 0)
 
5368
        if (find_type(command->query, &command_typelib, 1+2) > 0)
5322
5369
          die("Extra delimiter \";\" found");
5323
5370
        command->query[command->first_word_len-1]= save;
5324
5371
 
5492
5539
 
5493
5540
  if (user_config_dir.compare(0, 2, "~/") == 0)
5494
5541
  {
5495
 
    const char *homedir= getenv("HOME");
 
5542
    char *homedir;
 
5543
    homedir= getenv("HOME");
5496
5544
    if (homedir != NULL)
5497
5545
      user_config_dir.replace(0, 1, homedir);
5498
5546
  }
5539
5587
  next_con= connections + 1;
5540
5588
 
5541
5589
  /* Init file stack */
5542
 
  memset(file_stack.data(), 0, sizeof(file_stack));
5543
 
  cur_file= file_stack.data();
 
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;
5544
5594
 
5545
5595
  /* Init block stack */
5546
5596
  memset(block_stack, 0, sizeof(block_stack));
5579
5629
      tmp= buff;
5580
5630
    }
5581
5631
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5582
 
    assert(cur_file == file_stack.data() && cur_file->file == 0);
 
5632
    assert(cur_file == file_stack && cur_file->file == 0);
5583
5633
    if (!(cur_file->file= fopen(buff, "r")))
5584
5634
    {
5585
5635
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5684
5734
  }
5685
5735
 
5686
5736
  server_initialized= 1;
5687
 
  if (cur_file == file_stack.data() && cur_file->file == 0)
 
5737
  if (cur_file == file_stack && cur_file->file == 0)
5688
5738
  {
5689
5739
    cur_file->file= stdin;
5690
5740
    cur_file->file_name= strdup("<stdin>");
6109
6159
  the time between executing the two commands.
6110
6160
*/
6111
6161
 
6112
 
void timer_output()
 
6162
void timer_output(void)
6113
6163
{
6114
6164
  if (timer_file)
6115
6165
  {
6123
6173
}
6124
6174
 
6125
6175
 
6126
 
uint64_t timer_now()
 
6176
uint64_t timer_now(void)
6127
6177
{
6128
6178
#if defined(HAVE_GETHRTIME)
6129
6179
  return gethrtime()/1000/1000;
6163
6213
  start= buff= (char *)malloc(strlen(from)+1);
6164
6214
  while (*from)
6165
6215
  {
 
6216
    char *to;
6166
6217
    uint32_t column_number;
6167
6218
 
6168
 
    char *to= get_string(&buff, &from, command);
 
6219
    to= get_string(&buff, &from, command);
6169
6220
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6170
6221
      die("Wrong column number to replace_column in '%s'", command->query);
6171
6222
    if (!*from)
6184
6235
 
6185
6236
void free_replace_column()
6186
6237
{
6187
 
  for (uint32_t i= 0 ; i < max_replace_column; i++)
 
6238
  uint32_t i;
 
6239
  for (i=0 ; i < max_replace_column ; i++)
6188
6240
  {
6189
 
    free(replace_column[i]);
6190
 
    replace_column[i]= 0;
 
6241
    if (replace_column[i])
 
6242
    {
 
6243
      free(replace_column[i]);
 
6244
      replace_column[i]= 0;
 
6245
    }
6191
6246
  }
6192
6247
  max_replace_column= 0;
6193
6248
}
6208
6263
} POINTER_ARRAY;
6209
6264
 
6210
6265
struct st_replace;
6211
 
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6212
 
                                char *word_end_chars);
 
6266
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
6267
                                char * word_end_chars);
6213
6268
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6214
6269
void replace_strings_append(struct st_replace *rep, string* ds,
6215
6270
                            const char *from, int len);
 
6271
void free_pointer_array(POINTER_ARRAY *pa);
6216
6272
 
6217
 
st_replace *glob_replace= NULL;
6218
 
// boost::scoped_ptr<st_replace> glob_replace;
 
6273
struct st_replace *glob_replace= NULL;
6219
6274
 
6220
6275
/*
6221
6276
  Get arguments for replace. The syntax is:
6225
6280
  variable is replaced.
6226
6281
*/
6227
6282
 
6228
 
static void free_pointer_array(POINTER_ARRAY *pa)
6229
 
{
6230
 
  if (!pa->typelib.count)
6231
 
    return;
6232
 
  pa->typelib.count=0;
6233
 
  free((char*) pa->typelib.type_names);
6234
 
  pa->typelib.type_names=0;
6235
 
  free(pa->str);
6236
 
}
6237
 
 
6238
6283
void do_get_replace(struct st_command *command)
6239
6284
{
6240
6285
  uint32_t i;
6266
6311
    if (my_isspace(charset_info,i))
6267
6312
      *pos++= i;
6268
6313
  *pos=0;          /* End pointer */
6269
 
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
6270
 
                                   to_array.typelib.type_names,
6271
 
                                   from_array.typelib.count,
 
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,
6272
6317
                                   word_end_chars)))
6273
6318
    die("Can't initialize replace from '%s'", command->query);
6274
6319
  free_pointer_array(&from_array);
6281
6326
 
6282
6327
void free_replace()
6283
6328
{
6284
 
  free(glob_replace);
6285
 
  glob_replace=0;
 
6329
 
 
6330
  if (glob_replace)
 
6331
  {
 
6332
    free(glob_replace);
 
6333
    glob_replace=0;
 
6334
  }
 
6335
  return;
6286
6336
}
6287
6337
 
6288
6338
 
6302
6352
void replace_strings_append(REPLACE *rep, string* ds,
6303
6353
                            const char *str, int len)
6304
6354
{
6305
 
  REPLACE *rep_pos;
6306
 
  REPLACE_STRING *rep_str;
 
6355
  register REPLACE *rep_pos;
 
6356
  register REPLACE_STRING *rep_str;
6307
6357
  const char *start, *from;
6308
6358
 
6309
6359
 
6356
6406
                 i.e. repeat the matching until the end of the string */
6357
6407
};
6358
6408
 
6359
 
class st_replace_regex
 
6409
struct st_replace_regex
6360
6410
{
6361
 
public:
6362
 
  st_replace_regex(char* expr);
6363
 
  int multi_reg_replace(char* val);
 
6411
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
6364
6412
 
6365
6413
  /*
6366
6414
    Temporary storage areas for substitutions. To reduce unnessary copying
6369
6417
    st_regex substition. At the end of substitutions  buf points to the
6370
6418
    one containing the final result.
6371
6419
  */
6372
 
  typedef vector<st_regex> regex_arr_t;
6373
 
 
6374
 
  char* buf_;
 
6420
  char* buf;
6375
6421
  char* even_buf;
6376
6422
  char* odd_buf;
6377
6423
  int even_buf_len;
6378
6424
  int odd_buf_len;
6379
 
  boost::array<char, 8 << 10> buf0_;
6380
 
  boost::array<char, 8 << 10> buf1_;
6381
 
  regex_arr_t regex_arr;
6382
6425
};
6383
6426
 
6384
 
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
 
6427
struct st_replace_regex *glob_replace_regex= 0;
6385
6428
 
6386
6429
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6387
6430
                char *string, int icase, int global);
6423
6466
  Returns: st_replace_regex struct with pairs of substitutions
6424
6467
*/
6425
6468
 
6426
 
st_replace_regex::st_replace_regex(char* expr)
 
6469
static struct st_replace_regex* init_replace_regex(char* expr)
6427
6470
{
 
6471
  struct st_replace_regex* res;
 
6472
  char* buf,*expr_end;
 
6473
  char* p;
 
6474
  char* buf_p;
6428
6475
  uint32_t expr_len= strlen(expr);
6429
6476
  char last_c = 0;
6430
 
  st_regex reg;
6431
 
 
6432
 
  char* buf= new char[expr_len];
6433
 
  char* expr_end= expr + expr_len;
6434
 
  char* p= expr;
6435
 
  char* buf_p= buf;
 
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;
6436
6488
 
6437
6489
  /* for each regexp substitution statement */
6438
6490
  while (p < expr_end)
6448
6500
 
6449
6501
    if (p == expr_end || ++p == expr_end)
6450
6502
    {
6451
 
      if (!regex_arr.empty())
 
6503
      if (res->regex_arr.elements)
6452
6504
        break;
6453
6505
      else
6454
6506
        goto err;
6487
6539
      p++;
6488
6540
      reg.global= 1;
6489
6541
    }
6490
 
    regex_arr.push_back(reg);
 
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");
6491
6546
  }
6492
 
  odd_buf_len= even_buf_len= buf0_.size();
6493
 
  even_buf= buf0_.data();
6494
 
  odd_buf= buf1_.data();
6495
 
  buf_= even_buf;
 
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;
6496
6551
 
6497
 
  return;
 
6552
  return res;
6498
6553
 
6499
6554
err:
 
6555
  free(res);
6500
6556
  die("Error parsing replace_regex \"%s\"", expr);
 
6557
  return 0;
6501
6558
}
6502
6559
 
6503
6560
/*
6519
6576
  in one pass
6520
6577
*/
6521
6578
 
6522
 
int st_replace_regex::multi_reg_replace(char* val)
 
6579
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6523
6580
{
6524
 
  char* in_buf= val;
6525
 
  char* out_buf= even_buf;
6526
 
  int* buf_len_p= &even_buf_len;
6527
 
  buf_= 0;
 
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;
6528
6589
 
6529
6590
  /* For each substitution, do the replace */
6530
 
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
 
6591
  for (i= 0; i < r->regex_arr.elements; i++)
6531
6592
  {
 
6593
    struct st_regex re;
6532
6594
    char* save_out_buf= out_buf;
6533
 
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6534
 
                     in_buf, i.icase, i.global))
 
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))
6535
6600
    {
6536
6601
      /* if the buffer has been reallocated, make adjustements */
6537
6602
      if (save_out_buf != out_buf)
6538
6603
      {
6539
 
        if (save_out_buf == even_buf)
6540
 
          even_buf= out_buf;
 
6604
        if (save_out_buf == r->even_buf)
 
6605
          r->even_buf= out_buf;
6541
6606
        else
6542
 
          odd_buf= out_buf;
 
6607
          r->odd_buf= out_buf;
6543
6608
      }
6544
 
      buf_= out_buf;
 
6609
 
 
6610
      r->buf= out_buf;
6545
6611
      if (in_buf == val)
6546
 
        in_buf= odd_buf;
6547
 
      std::swap(in_buf, out_buf);
6548
 
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
 
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;
6549
6618
    }
6550
6619
  }
6551
 
  return buf_ == 0;
 
6620
 
 
6621
  return (r->buf == 0);
6552
6622
}
6553
6623
 
6554
6624
/*
6563
6633
void do_get_replace_regex(struct st_command *command)
6564
6634
{
6565
6635
  char *expr= command->first_argument;
6566
 
  glob_replace_regex.reset(new st_replace_regex(expr));
 
6636
  free_replace_regex();
 
6637
  if (!(glob_replace_regex=init_replace_regex(expr)))
 
6638
    die("Could not init replace_regex");
6567
6639
  command->last_argument= command->end;
6568
6640
}
6569
6641
 
 
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
 
6570
6656
/*
6571
6657
  Performs a regex substitution
6572
6658
 
6673
6759
#define SET_MALLOC_HUNC 64
6674
6760
#define LAST_CHAR_CODE 259
6675
6761
 
6676
 
class REP_SET
6677
 
{
6678
 
public:
6679
 
  void internal_set_bit(uint32_t bit);
6680
 
  void internal_clear_bit(uint32_t bit);
6681
 
  void or_bits(const REP_SET *from);
6682
 
  void copy_bits(const REP_SET *from);
6683
 
  int cmp_bits(const REP_SET *set2) const;
6684
 
  int get_next_bit(uint32_t lastpos) const;
6685
 
 
 
6762
typedef struct st_rep_set {
6686
6763
  uint32_t  *bits;        /* Pointer to used sets */
6687
6764
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6688
6765
  uint32_t  found_len;      /* Best match to date */
6689
6766
  int  found_offset;
6690
6767
  uint32_t  table_offset;
6691
6768
  uint32_t  size_of_bits;      /* For convinience */
6692
 
};
6693
 
 
6694
 
class REP_SETS
6695
 
{
6696
 
public:
6697
 
  int find_set(const REP_SET *find);
6698
 
  void free_last_set();
6699
 
  void free_sets();
6700
 
  void make_sets_invisible();
6701
 
 
 
6769
} REP_SET;
 
6770
 
 
6771
typedef struct st_rep_sets {
6702
6772
  uint32_t    count;      /* Number of sets */
6703
6773
  uint32_t    extra;      /* Extra sets in buffer */
6704
 
  uint32_t    invisible;    /* Sets not shown */
 
6774
  uint32_t    invisible;    /* Sets not chown */
6705
6775
  uint32_t    size_of_bits;
6706
6776
  REP_SET  *set,*set_buffer;
6707
6777
  uint32_t    *bit_buffer;
6708
 
};
 
6778
} REP_SETS;
6709
6779
 
6710
 
struct FOUND_SET 
6711
 
{
 
6780
typedef struct st_found_set {
6712
6781
  uint32_t table_offset;
6713
6782
  int found_offset;
6714
 
};
 
6783
} FOUND_SET;
6715
6784
 
6716
 
struct FOLLOWS
6717
 
{
 
6785
typedef struct st_follow {
6718
6786
  int chr;
6719
6787
  uint32_t table_offset;
6720
6788
  uint32_t len;
6721
 
};
6722
 
 
6723
 
int init_sets(REP_SETS *sets, uint32_t states);
 
6789
} FOLLOWS;
 
6790
 
 
6791
 
 
6792
int init_sets(REP_SETS *sets,uint32_t states);
6724
6793
REP_SET *make_new_set(REP_SETS *sets);
6725
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6726
 
 
6727
 
static uint32_t found_sets= 0;
6728
 
 
6729
 
static uint32_t replace_len(const char *str)
 
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)
6730
6813
{
6731
6814
  uint32_t len=0;
6732
6815
  while (*str)
6739
6822
  return len;
6740
6823
}
6741
6824
 
6742
 
/* Return 1 if regexp starts with \b or ends with \b*/
6743
 
 
6744
 
static bool start_at_word(const char *pos)
6745
 
{
6746
 
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6747
 
}
6748
 
 
6749
 
static bool end_of_word(const char *pos)
6750
 
{
6751
 
  const char *end= strchr(pos, '\0');
6752
 
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6753
 
}
6754
 
 
6755
6825
/* Init a replace structure for further calls */
6756
6826
 
6757
 
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
 
6827
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6828
                      char * word_end_chars)
6758
6829
{
6759
 
  const int SPACE_CHAR= 256;
6760
 
  const int START_OF_LINE= 257;
6761
 
  const int END_OF_LINE= 258;
 
6830
  static const int SPACE_CHAR= 256;
 
6831
  static const int START_OF_LINE= 257;
 
6832
  static const int END_OF_LINE= 258;
6762
6833
 
6763
6834
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6764
6835
  int used_sets,chr,default_state;
6765
6836
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6766
 
  char *to_pos, **to_array;
 
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
 
6767
6845
 
6768
6846
  /* Count number of states */
6769
6847
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6783
6861
  for (i=0 ; word_end_chars[i] ; i++)
6784
6862
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6785
6863
 
6786
 
  REP_SETS sets;
6787
 
  REP_SET *set,*start_states,*word_states,*new_set;
6788
 
  REPLACE_STRING *rep_str;
6789
 
  if (init_sets(&sets, states))
6790
 
    return 0;
 
6864
  if (init_sets(&sets,states))
 
6865
    return(0);
6791
6866
  found_sets=0;
6792
 
  vector<FOUND_SET> found_set(max_length * count);
 
6867
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
 
6868
                                
 
6869
  {
 
6870
    free_sets(&sets);
 
6871
    return(0);
 
6872
  }
6793
6873
  make_new_set(&sets);      /* Set starting set */
6794
 
  sets.make_sets_invisible();      /* Hide previus sets */
 
6874
  make_sets_invisible(&sets);      /* Hide previus sets */
6795
6875
  used_sets=-1;
6796
6876
  word_states=make_new_set(&sets);    /* Start of new word */
6797
6877
  start_states=make_new_set(&sets);    /* This is first state */
6798
 
  vector<FOLLOWS> follow(states + 2);
6799
 
  FOLLOWS *follow_ptr= &follow[1];
 
6878
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6879
  {
 
6880
    free_sets(&sets);
 
6881
    free(found_set);
 
6882
    return(0);
 
6883
  }
 
6884
 
6800
6885
  /* Init follow_ptr[] */
6801
 
  for (i=0, states=1; i < count; i++)
 
6886
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6802
6887
  {
6803
6888
    if (from[i][0] == '\\' && from[i][1] == '^')
6804
6889
    {
6805
 
      start_states->internal_set_bit(states + 1);
 
6890
      internal_set_bit(start_states,states+1);
6806
6891
      if (!from[i][2])
6807
6892
      {
6808
6893
        start_states->table_offset=i;
6811
6896
    }
6812
6897
    else if (from[i][0] == '\\' && from[i][1] == '$')
6813
6898
    {
6814
 
      start_states->internal_set_bit(states);
6815
 
      word_states->internal_set_bit(states);
 
6899
      internal_set_bit(start_states,states);
 
6900
      internal_set_bit(word_states,states);
6816
6901
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6817
6902
      {
6818
6903
        start_states->table_offset=i;
6821
6906
    }
6822
6907
    else
6823
6908
    {
6824
 
      word_states->internal_set_bit(states);
 
6909
      internal_set_bit(word_states,states);
6825
6910
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6826
 
        start_states->internal_set_bit(states + 1);
 
6911
        internal_set_bit(start_states,states+1);
6827
6912
      else
6828
 
        start_states->internal_set_bit(states);
 
6913
        internal_set_bit(start_states,states);
6829
6914
    }
6830
 
    const char *pos;
6831
 
    for (pos= from[i], len=0; *pos ; pos++)
 
6915
    for (pos=from[i], len=0; *pos ; pos++)
6832
6916
    {
6833
6917
      if (*pos == '\\' && *(pos+1))
6834
6918
      {
6871
6955
  }
6872
6956
 
6873
6957
 
6874
 
  for (set_nr=0; set_nr < sets.count ; set_nr++)
 
6958
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6875
6959
  {
6876
6960
    set=sets.set+set_nr;
6877
6961
    default_state= 0;        /* Start from beginning */
6878
6962
 
6879
6963
    /* If end of found-string not found or start-set with current set */
6880
6964
 
6881
 
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
 
6965
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6882
6966
    {
6883
 
      if (!follow[i].chr && !default_state)
6884
 
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
 
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
      }
6885
6973
    }
6886
 
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
 
6974
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6887
6975
    if (!default_state)
6888
 
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
 
6976
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
6889
6977
 
6890
6978
    /* Find all chars that follows current sets */
6891
6979
    memset(used_chars, 0, sizeof(used_chars));
6892
 
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
 
6980
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6893
6981
    {
6894
6982
      used_chars[follow[i].chr]=1;
6895
6983
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6899
6987
 
6900
6988
    /* Mark word_chars used if \b is in state */
6901
6989
    if (used_chars[SPACE_CHAR])
6902
 
      for (const char *pos= word_end_chars ; *pos ; pos++)
 
6990
      for (pos= word_end_chars ; *pos ; pos++)
6903
6991
        used_chars[(int) (unsigned char) *pos] = 1;
6904
6992
 
6905
6993
    /* Handle other used characters */
6916
7004
        new_set->found_offset=set->found_offset+1;
6917
7005
        found_end=0;
6918
7006
 
6919
 
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
 
7007
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6920
7008
        {
6921
7009
          if (!follow[i].chr || follow[i].chr == chr ||
6922
7010
              (follow[i].chr == SPACE_CHAR &&
6928
7016
                follow[i].len > found_end)
6929
7017
              found_end=follow[i].len;
6930
7018
            if (chr && follow[i].chr)
6931
 
              new_set->internal_set_bit(i + 1);    /* To next set */
 
7019
              internal_set_bit(new_set,i+1);    /* To next set */
6932
7020
            else
6933
 
              new_set->internal_set_bit(i);
 
7021
              internal_set_bit(new_set,i);
6934
7022
          }
6935
7023
        }
6936
7024
        if (found_end)
6937
7025
        {
6938
7026
          new_set->found_len=0;      /* Set for testing if first */
6939
7027
          bits_set=0;
6940
 
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
 
7028
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6941
7029
          {
6942
7030
            if ((follow[i].chr == SPACE_CHAR ||
6943
7031
                 follow[i].chr == END_OF_LINE) && ! chr)
6947
7035
            if (follow[bit_nr-1].len < found_end ||
6948
7036
                (new_set->found_len &&
6949
7037
                 (chr == 0 || !follow[bit_nr].chr)))
6950
 
              new_set->internal_clear_bit(i);
 
7038
              internal_clear_bit(new_set,i);
6951
7039
            else
6952
7040
            {
6953
7041
              if (chr == 0 || !follow[bit_nr].chr)
6963
7051
          }
6964
7052
          if (bits_set == 1)
6965
7053
          {
6966
 
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6967
 
            sets.free_last_set();
 
7054
            set->next[chr] = find_found(found_set,
 
7055
                                        new_set->table_offset,
 
7056
                                        new_set->found_offset);
 
7057
            free_last_set(&sets);
6968
7058
          }
6969
7059
          else
6970
 
            set->next[chr] = sets.find_set(new_set);
 
7060
            set->next[chr] = find_set(&sets,new_set);
6971
7061
        }
6972
7062
        else
6973
 
          set->next[chr] = sets.find_set(new_set);
 
7063
          set->next[chr] = find_set(&sets,new_set);
6974
7064
      }
6975
7065
    }
6976
7066
  }
6977
7067
 
6978
7068
  /* Alloc replace structure for the replace-state-machine */
6979
7069
 
6980
 
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6981
 
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
6982
 
  if (replace)
 
7070
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
 
7071
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
 
7072
                                 sizeof(char *)*count+result_len)))
6983
7073
  {
6984
7074
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6985
7075
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6996
7086
    rep_str[0].replace_string=0;
6997
7087
    for (i=1 ; i <= found_sets ; i++)
6998
7088
    {
6999
 
      const char *pos= from[found_set[i-1].table_offset];
 
7089
      pos=from[found_set[i-1].table_offset];
7000
7090
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7001
 
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
7002
 
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
7003
 
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
 
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);
7004
7095
    }
7005
7096
    for (i=0 ; i < sets.count ; i++)
7006
7097
    {
7011
7102
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7012
7103
    }
7013
7104
  }
7014
 
  sets.free_sets();
7015
 
  return replace;
 
7105
  free(follow);
 
7106
  free_sets(&sets);
 
7107
  free(found_set);
 
7108
  return(replace);
7016
7109
}
7017
7110
 
7018
7111
 
7033
7126
 
7034
7127
/* Make help sets invisible for nicer codeing */
7035
7128
 
7036
 
void REP_SETS::make_sets_invisible()
 
7129
void make_sets_invisible(REP_SETS *sets)
7037
7130
{
7038
 
  invisible= count;
7039
 
  set += count;
7040
 
  count= 0;
 
7131
  sets->invisible=sets->count;
 
7132
  sets->set+=sets->count;
 
7133
  sets->count=0;
7041
7134
}
7042
7135
 
7043
7136
REP_SET *make_new_set(REP_SETS *sets)
7075
7168
  return make_new_set(sets);
7076
7169
}
7077
7170
 
7078
 
void REP_SETS::free_last_set()
7079
 
{
7080
 
  count--;
7081
 
  extra++;
7082
 
}
7083
 
 
7084
 
void REP_SETS::free_sets()
7085
 
{
7086
 
  free(set_buffer);
7087
 
  free(bit_buffer);
7088
 
}
7089
 
 
7090
 
void REP_SET::internal_set_bit(uint32_t bit)
7091
 
{
7092
 
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7093
 
}
7094
 
 
7095
 
void REP_SET::internal_clear_bit(uint32_t bit)
7096
 
{
7097
 
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7098
 
}
7099
 
 
7100
 
 
7101
 
void REP_SET::or_bits(const REP_SET *from)
7102
 
{
7103
 
  for (uint32_t i= 0 ; i < size_of_bits; i++)
7104
 
    bits[i]|=from->bits[i];
7105
 
}
7106
 
 
7107
 
void REP_SET::copy_bits(const REP_SET *from)
7108
 
{
7109
 
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
7110
 
}
7111
 
 
7112
 
int REP_SET::cmp_bits(const REP_SET *set2) const
7113
 
{
7114
 
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
7115
 
}
 
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
 
7116
7217
 
7117
7218
/* Get next set bit from set. */
7118
7219
 
7119
 
int REP_SET::get_next_bit(uint32_t lastpos) const
 
7220
int get_next_bit(REP_SET *set,uint32_t lastpos)
7120
7221
{
7121
 
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
7122
 
  uint32_t *end= bits + size_of_bits;
7123
 
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7124
 
 
7125
 
  while (!bits0 && ++start < end)
7126
 
    bits0= start[0];
7127
 
  if (!bits0)
 
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)
7128
7231
    return 0;
7129
 
  uint32_t pos= (start - bits) * WORD_BIT;
7130
 
  while (!(bits0 & 1))
 
7232
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
7233
  while (! (bits & 1))
7131
7234
  {
7132
 
    bits0 >>=1;
 
7235
    bits>>=1;
7133
7236
    pos++;
7134
7237
  }
7135
7238
  return pos;
7139
7242
   free given set, else put in given set in sets and return its
7140
7243
   position */
7141
7244
 
7142
 
int REP_SETS::find_set(const REP_SET *find)
 
7245
int find_set(REP_SETS *sets,REP_SET *find)
7143
7246
{
7144
 
  uint32_t i= 0;
7145
 
  for (; i < count - 1; i++)
 
7247
  uint32_t i;
 
7248
  for (i=0 ; i < sets->count-1 ; i++)
7146
7249
  {
7147
 
    if (!set[i].cmp_bits(find))
 
7250
    if (!cmp_bits(sets->set+i,find))
7148
7251
    {
7149
 
      free_last_set();
 
7252
      free_last_set(sets);
7150
7253
      return i;
7151
7254
    }
7152
7255
  }
7160
7263
   set->next[] == -1 is reserved for end without replaces.
7161
7264
*/
7162
7265
 
7163
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
 
7266
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7164
7267
{
7165
 
  uint32_t i= 0;
7166
 
  for (; i < found_sets; i++)
7167
 
  {
 
7268
  int i;
 
7269
  for (i=0 ; (uint32_t) i < found_sets ; i++)
7168
7270
    if (found_set[i].table_offset == table_offset &&
7169
7271
        found_set[i].found_offset == found_offset)
7170
 
      return - i - 2;
7171
 
  }
7172
 
  found_set[i].table_offset= table_offset;
7173
 
  found_set[i].found_offset= found_offset;
 
7272
      return -i-2;
 
7273
  found_set[i].table_offset=table_offset;
 
7274
  found_set[i].found_offset=found_offset;
7174
7275
  found_sets++;
7175
 
  return - i - 2; // return new postion
 
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;
7176
7292
}
7177
7293
 
7178
7294
/****************************************************************************
7251
7367
} /* insert_pointer_name */
7252
7368
 
7253
7369
 
 
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
 
7254
7384
/* Functions that uses replace and replace_regex */
7255
7385
 
7256
7386
/* Append the string to ds, with optional replace */
7257
 
void replace_append_mem(string *ds, const char *val, int len)
 
7387
void replace_append_mem(string *ds,
 
7388
                        const char *val, int len)
7258
7389
{
7259
7390
  char *v= strdup(val);
7260
7391
 
7261
 
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
 
7392
  if (glob_replace_regex)
7262
7393
  {
7263
 
    v= glob_replace_regex->buf_;
7264
 
    len= strlen(v);
 
7394
    /* Regex replace */
 
7395
    if (!multi_reg_replace(glob_replace_regex, v))
 
7396
    {
 
7397
      v= glob_replace_regex->buf;
 
7398
      len= strlen(v);
 
7399
    }
7265
7400
  }
 
7401
 
7266
7402
  if (glob_replace)
7267
7403
  {
7268
7404
    /* Normal replace */
7269
7405
    replace_strings_append(glob_replace, ds, v, len);
7270
7406
  }
7271
7407
  else
 
7408
  {
7272
7409
    ds->append(v, len);
 
7410
  }
7273
7411
}
7274
7412
 
7275
7413
 
7338
7476
 
7339
7477
  return;
7340
7478
}
7341
 
 
7342
 
static void free_all_replace()
7343
 
{
7344
 
  free_replace();
7345
 
  glob_replace_regex.reset();
7346
 
  free_replace_column();
7347
 
}