~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Stewart Smith
  • Date: 2011-02-24 07:46:16 UTC
  • mto: (2200.1.2 drizzle-staging)
  • mto: This revision was merged to the branch mainline in revision 2201.
  • Revision ID: stewart@flamingspork.com-20110224074616-l2rmp406vf78x71q
add ER_NO_LOCK_HELD error code, and expect it in case of UNLOCK TABLES without any locks held.

Show diffs side-by-side

added added

removed removed

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