~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Olaf van der Spek
  • Date: 2011-04-20 09:27:49 UTC
  • mto: This revision was merged to the branch mainline in revision 2285.
  • Revision ID: olafvdspek@gmail.com-20110420092749-hw1q9rfj1pumc2no
Session Cache

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
 
 
72
#include <drizzled/definitions.h>
 
73
#include <drizzled/charset_info.h>
 
74
#include <drizzled/internal/my_sys.h>
 
75
#include <drizzled/type/time.h>
 
76
#include <drizzled/charset.h>
 
77
#include <drizzled/typelib.h>
70
78
#include <drizzled/configmake.h>
 
79
#include <drizzled/util/find_ptr.h>
 
80
 
 
81
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
71
82
 
72
83
#ifndef DRIZZLE_RETURN_SERVER_GONE
73
84
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
76
87
using namespace std;
77
88
using namespace drizzled;
78
89
 
79
 
extern "C"
80
90
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
81
91
 
82
92
int get_one_option(int optid, const struct option *, char *argument);
115
125
static bool is_windows= false;
116
126
static bool use_drizzle_protocol= false;
117
127
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
 
128
static void free_all_replace();
118
129
 
119
130
std::string opt_basedir,
120
131
  opt_charsets_dir,
164
175
  uint32_t lineno; /* Current line in file */
165
176
};
166
177
 
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
 
 
171
 
 
172
 
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
 
178
static boost::array<st_test_file, 16> file_stack;
 
179
static st_test_file* cur_file;
 
180
 
 
181
static const charset_info_st *charset_info= &my_charset_utf8_general_ci; /* Default charset */
173
182
 
174
183
/*
175
184
  Timer related variables
177
186
*/
178
187
static char *timer_file = NULL;
179
188
static uint64_t timer_start;
180
 
static void timer_output(void);
181
 
static uint64_t timer_now(void);
 
189
static void timer_output();
 
190
static uint64_t timer_now();
182
191
 
183
192
static uint64_t progress_start= 0;
184
193
 
199
208
 
200
209
/* if set, all results are concated and compared against this file */
201
210
 
202
 
typedef struct st_var
 
211
class VAR
203
212
{
 
213
public:
204
214
  char *name;
205
215
  int name_len;
206
216
  char *str_val;
210
220
  int int_dirty; /* do not update string if int is updated until first read */
211
221
  int alloced;
212
222
  char *env_s;
213
 
} VAR;
 
223
};
214
224
 
215
225
/*Perl/shell-like variable registers */
216
 
VAR var_reg[10];
217
 
 
218
 
 
219
 
boost::unordered_map<string, VAR *> var_hash;
 
226
boost::array<VAR, 10> var_reg;
 
227
 
 
228
typedef boost::unordered_map<string, VAR *> var_hash_t;
 
229
var_hash_t var_hash;
220
230
 
221
231
struct st_connection
222
232
{
389
399
  struct st_match_err err[10];
390
400
  uint32_t count;
391
401
};
392
 
static struct st_expected_errors saved_expected_errors;
393
 
 
394
 
struct st_command
 
402
 
 
403
static st_expected_errors saved_expected_errors;
 
404
 
 
405
class st_command
395
406
{
 
407
public:
396
408
  char *query, *query_buf,*first_argument,*last_argument,*end;
397
409
  int first_word_len, query_len;
398
410
  bool abort_on_error;
399
411
  st_expected_errors expected_errors;
400
412
  string require_file;
401
 
  enum enum_commands type;
 
413
  enum_commands type;
402
414
 
403
415
  st_command()
404
416
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
410
422
 
411
423
  ~st_command()
412
424
  {
413
 
    if (query_buf != NULL)
414
 
    {
415
 
      free(query_buf);
416
 
    }
 
425
    free(query_buf);
417
426
  }
418
427
};
419
428
 
438
447
VAR* var_from_env(const char *, const char *);
439
448
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
440
449
              int val_len);
441
 
void var_free(pair<string, VAR*> v);
442
450
VAR* var_get(const char *var_name, const char** var_name_end,
443
451
             bool raw, bool ignore_not_existing);
444
452
void eval_expr(VAR* v, const char *p, const char** p_end);
445
453
bool match_delimiter(int c, const char *delim, uint32_t length);
446
454
void dump_result_to_reject_file(char *buf, int size);
447
455
void dump_result_to_log_file(const char *buf, int size);
448
 
void dump_warning_messages(void);
449
 
void dump_progress(void);
 
456
void dump_warning_messages();
 
457
void dump_progress();
450
458
 
451
459
void do_eval(string *query_eval, const char *query,
452
460
             const char *query_end, bool pass_through_escape_chars);
457
465
static char *replace_column[MAX_COLUMNS];
458
466
static uint32_t max_replace_column= 0;
459
467
void do_get_replace_column(struct st_command*);
460
 
void free_replace_column(void);
 
468
void free_replace_column();
461
469
 
462
470
/* For replace */
463
471
void do_get_replace(struct st_command *command);
464
 
void free_replace(void);
 
472
void free_replace();
465
473
 
466
474
/* For replace_regex */
467
475
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
476
 
480
477
void replace_append_mem(string *ds, const char *val,
481
478
                        int len);
492
489
void do_eval(string *query_eval, const char *query,
493
490
             const char *query_end, bool pass_through_escape_chars)
494
491
{
495
 
  const char *p;
496
 
  register char c, next_c;
497
 
  register int escaped = 0;
 
492
  char c, next_c;
 
493
  int escaped = 0;
498
494
  VAR *v;
499
495
 
500
 
 
501
 
  for (p= query; (c= *p) && p < query_end; ++p)
 
496
  for (const char *p= query; (c= *p) && p < query_end; ++p)
502
497
  {
503
498
    switch(c) {
504
499
    case '$':
843
838
 
844
839
static void handle_command_error(struct st_command *command, uint32_t error)
845
840
{
846
 
 
847
841
  if (error != 0)
848
842
  {
849
843
    uint32_t i;
870
864
        command->first_word_len, command->query,
871
865
        command->expected_errors.err[0].code.errnum);
872
866
  }
873
 
  return;
874
867
}
875
868
 
876
869
 
877
 
static void close_connections(void)
 
870
static void close_connections()
878
871
{
879
872
  for (--next_con; next_con >= connections; --next_con)
880
873
  {
885
878
    }
886
879
    free(next_con->name);
887
880
  }
888
 
  return;
889
881
}
890
882
 
891
883
 
892
 
static void close_files(void)
 
884
static void close_files()
893
885
{
894
 
 
895
 
  for (; cur_file >= file_stack; cur_file--)
 
886
  for (; cur_file >= file_stack.data(); cur_file--)
896
887
  {
897
888
    if (cur_file->file && cur_file->file != stdin)
898
 
    {
899
889
      fclose(cur_file->file);
900
 
    }
901
 
    free((unsigned char*) cur_file->file_name);
 
890
    free(const_cast<char*>(cur_file->file_name));
902
891
    cur_file->file_name= 0;
903
892
  }
904
 
  return;
905
893
}
906
894
 
907
 
 
908
 
static void free_used_memory(void)
 
895
static void free_used_memory()
909
896
{
910
 
  uint32_t i;
911
 
 
912
 
 
913
897
  close_connections();
914
898
  close_files();
915
 
  for_each(var_hash.begin(), var_hash.end(), var_free);
 
899
  BOOST_FOREACH(var_hash_t::reference i, var_hash)
 
900
  {
 
901
    free(i.second->str_val);
 
902
    free(i.second->env_s);
 
903
    if (i.second->alloced)
 
904
      free(i.second);
 
905
  }
916
906
  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++)
 
907
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
 
908
    delete i;
 
909
  for (size_t i= 0; i < var_reg.size(); i++)
926
910
  {
927
911
    if (var_reg[i].alloced_len)
928
912
      free(var_reg[i].str_val);
929
913
  }
930
 
 
931
914
  free_all_replace();
932
915
  free(opt_pass);
933
 
 
934
 
  return;
935
916
}
936
917
 
937
918
 
956
937
      assert(0);
957
938
    }
958
939
  }
959
 
 
960
940
  exit(exit_code);
961
941
}
962
942
 
976
956
 
977
957
  /* Print the error message */
978
958
  fprintf(stderr, "drizzletest: ");
979
 
  if (cur_file && cur_file != file_stack)
 
959
  if (cur_file && cur_file != file_stack.data())
980
960
    fprintf(stderr, "In included file \"%s\": ",
981
961
            cur_file->file_name);
982
962
  if (start_lineno > 0)
1037
1017
 
1038
1018
  /* Print include filestack */
1039
1019
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1040
 
          file_stack->file_name);
 
1020
          file_stack[0].file_name);
1041
1021
  fprintf(stderr, "Detected in file %s at line %d\n",
1042
1022
          err_file->file_name, err_file->lineno);
1043
 
  while (err_file != file_stack)
 
1023
  while (err_file != file_stack.data())
1044
1024
  {
1045
1025
    err_file--;
1046
1026
    fprintf(stderr, "included from %s at line %d\n",
1071
1051
 
1072
1052
  va_start(args, fmt);
1073
1053
  fprintf(stderr, "drizzletest: ");
1074
 
  if (cur_file && cur_file != file_stack)
 
1054
  if (cur_file && cur_file != file_stack.data())
1075
1055
    fprintf(stderr, "In included file \"%s\": ",
1076
1056
            cur_file->file_name);
1077
1057
  if (start_lineno != 0)
1079
1059
  vfprintf(stderr, fmt, args);
1080
1060
  fprintf(stderr, "\n");
1081
1061
  va_end(args);
1082
 
 
1083
 
  return;
1084
1062
}
1085
1063
 
1086
1064
 
1096
1074
  if (start_lineno != 0)
1097
1075
  {
1098
1076
    ds_warning_messages.append("Warning detected ");
1099
 
    if (cur_file && cur_file != file_stack)
 
1077
    if (cur_file && cur_file != file_stack.data())
1100
1078
    {
1101
1079
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1102
1080
                    cur_file->file_name);
1429
1407
 
1430
1408
static int compare_files(const char* filename1, const char* filename2)
1431
1409
{
1432
 
  int fd;
1433
 
  int error;
1434
 
 
1435
 
  if ((fd= internal::my_open(filename1, O_RDONLY, MYF(0))) < 0)
 
1410
  int fd= internal::my_open(filename1, O_RDONLY, MYF(0));
 
1411
  if (fd < 0)
1436
1412
    die("Failed to open first file: '%s'", filename1);
1437
 
 
1438
 
  error= compare_files2(fd, filename2);
1439
 
 
 
1413
  int error= compare_files2(fd, filename2);
1440
1414
  internal::my_close(fd, MYF(0));
1441
 
 
1442
1415
  return error;
1443
1416
}
1444
1417
 
1629
1602
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1630
1603
              int val_len)
1631
1604
{
1632
 
  int val_alloc_len;
1633
 
  VAR *tmp_var;
1634
1605
  if (!name_len && name)
1635
1606
    name_len = strlen(name);
1636
1607
  if (!val_len && val)
1637
1608
    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");
 
1609
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
1642
1610
 
1643
 
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
 
1611
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
1644
1612
  tmp_var->alloced = (v == 0);
1645
1613
 
1646
 
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
1647
 
    die("Out of memory");
 
1614
  int val_alloc_len = val_len + 16; /* room to grow */
 
1615
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
1648
1616
 
1649
1617
  memcpy(tmp_var->name, name, name_len);
1650
1618
  if (val)
1655
1623
  tmp_var->name_len = name_len;
1656
1624
  tmp_var->str_val_len = val_len;
1657
1625
  tmp_var->alloced_len = val_alloc_len;
1658
 
  tmp_var->int_val = (val) ? atoi(val) : 0;
1659
 
  tmp_var->int_dirty = 0;
 
1626
  tmp_var->int_val = val ? atoi(val) : 0;
 
1627
  tmp_var->int_dirty = false;
1660
1628
  tmp_var->env_s = 0;
1661
1629
  return tmp_var;
1662
1630
}
1663
1631
 
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
1632
VAR* var_from_env(const char *name, const char *def_val)
1675
1633
{
1676
 
  const char *tmp;
1677
 
  VAR *v;
1678
 
  if (!(tmp = getenv(name)))
 
1634
  const char *tmp= getenv(name);
 
1635
  if (!tmp)
1679
1636
    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;
 
1637
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
1685
1638
}
1686
1639
 
1687
 
 
1688
1640
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1689
1641
             bool ignore_not_existing)
1690
1642
{
1691
1643
  int digit;
1692
1644
  VAR *v;
1693
 
 
1694
1645
  if (*var_name != '$')
1695
1646
    goto err;
1696
1647
  digit = *++var_name - '0';
1712
1663
      die("Too long variable name: %s", save_var_name);
1713
1664
 
1714
1665
    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);
1717
 
    if (iter == var_hash.end())
 
1666
    if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, save_var_name_str))
 
1667
      v= *ptr;
 
1668
    else
1718
1669
    {
1719
1670
      char buff[MAX_VAR_NAME_LENGTH+1];
1720
1671
      strncpy(buff, save_var_name, length);
1721
1672
      buff[length]= '\0';
1722
1673
      v= var_from_env(buff, "");
1723
1674
    }
1724
 
    else
1725
 
    {
1726
 
      v= (*iter).second;
1727
 
    }
1728
1675
    var_name--;  /* Point at last character */
1729
1676
  }
1730
1677
  else
1731
 
    v = var_reg + digit;
 
1678
    v = &var_reg[digit];
1732
1679
 
1733
1680
  if (!raw && v->int_dirty)
1734
1681
  {
1750
1697
static VAR *var_obtain(const char *name, int len)
1751
1698
{
1752
1699
  string var_name(name, len);
1753
 
  boost::unordered_map<string, VAR*>::iterator iter=
1754
 
    var_hash.find(var_name);
1755
 
  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;
 
1700
  if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, var_name))
 
1701
    return *ptr;
 
1702
  return var_hash[var_name] = var_init(0, name, len, "", 0);
1760
1703
}
1761
1704
 
1762
1705
 
1783
1726
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1784
1727
  }
1785
1728
  else
1786
 
    v= var_reg + digit;
 
1729
    v= &var_reg[digit];
1787
1730
 
1788
1731
  eval_expr(v, var_val, (const char**) &var_val_end);
1789
1732
 
2067
2010
    eval_expr(var, value, 0);
2068
2011
  }
2069
2012
  drizzle_result_free(&res);
2070
 
 
2071
 
  return;
2072
2013
}
2073
2014
 
2074
2015
 
2099
2040
{
2100
2041
  if (*p == '$')
2101
2042
  {
2102
 
    VAR *vp;
2103
 
    if ((vp= var_get(p, p_end, 0, 0)))
 
2043
    VAR *vp= var_get(p, p_end, 0, 0);
 
2044
    if (vp)
2104
2045
      var_copy(v, vp);
2105
2046
    return;
2106
2047
  }
2161
2102
  }
2162
2103
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2163
2104
 
2164
 
  if (cur_file == file_stack_end)
 
2105
  cur_file++;
 
2106
  if (cur_file == &*file_stack.end())
2165
2107
    die("Source directives are nesting too deep");
2166
 
  cur_file++;
2167
2108
  if (!(cur_file->file= fopen(buff, "r")))
2168
2109
  {
2169
2110
    cur_file--;
2225
2166
}
2226
2167
 
2227
2168
 
2228
 
static void init_builtin_echo(void)
 
2169
static void init_builtin_echo()
2229
2170
{
2230
2171
  builtin_echo[0]= 0;
2231
 
  return;
2232
2172
}
2233
2173
 
2234
2174
 
2480
2420
 
2481
2421
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
2482
2422
  handle_command_error(command, error);
2483
 
  return;
2484
2423
}
2485
2424
 
2486
2425
 
2515
2454
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2516
2455
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2517
2456
  handle_command_error(command, error);
2518
 
  return;
2519
2457
}
2520
2458
 
2521
2459
 
2553
2491
    die("You must write a 4 digit octal number for mode");
2554
2492
 
2555
2493
  handle_command_error(command, chmod(ds_file.c_str(), mode));
2556
 
  return;
2557
2494
}
2558
2495
 
2559
2496
 
2583
2520
 
2584
2521
  error= (access(ds_filename.c_str(), F_OK) != 0);
2585
2522
  handle_command_error(command, error);
2586
 
  return;
2587
2523
}
2588
2524
 
2589
2525
 
2612
2548
 
2613
2549
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
2614
2550
  handle_command_error(command, error);
2615
 
  return;
2616
2551
}
2617
2552
 
2618
2553
/*
2640
2575
 
2641
2576
  error= rmdir(ds_dirname.c_str()) != 0;
2642
2577
  handle_command_error(command, error);
2643
 
  return;
2644
2578
}
2645
2579
 
2646
2580
 
2879
2813
  }
2880
2814
 
2881
2815
  handle_command_error(command, error);
2882
 
  return;
2883
2816
}
2884
2817
 
2885
2818
 
2929
2862
 
2930
2863
  if (drizzle_quit(&con->con,&result, &ret))
2931
2864
    drizzle_result_free(&result);
2932
 
 
2933
 
  return;
2934
2865
}
2935
2866
 
2936
2867
 
3027
2958
  internal::my_delete(temp_file_path, MYF(0));
3028
2959
 
3029
2960
  handle_command_error(command, WEXITSTATUS(error));
3030
 
  return;
3031
2961
}
3032
2962
 
3033
2963
 
3201
3131
  when ndb binlog is on, this call will wait until last updated epoch
3202
3132
  (locally in the drizzled) has been received into the binlog
3203
3133
*/
3204
 
static int do_save_master_pos(void)
 
3134
static int do_save_master_pos()
3205
3135
{
3206
3136
  drizzle_result_st res;
3207
3137
  drizzle_return_t ret;
3340
3270
    sleep_val= opt_sleep;
3341
3271
 
3342
3272
  if (sleep_val)
3343
 
    usleep((uint32_t) (sleep_val * 1000000L));
 
3273
    usleep(sleep_val * 1000000);
3344
3274
  command->last_argument= sleep_end;
3345
3275
  return 0;
3346
3276
}
3347
3277
 
3348
3278
 
3349
 
static void do_get_file_name(struct st_command *command, string &dest)
 
3279
static void do_get_file_name(st_command *command, string &dest)
3350
3280
{
3351
 
  char *p= command->first_argument, *name;
 
3281
  char *p= command->first_argument;
3352
3282
  if (!*p)
3353
3283
    die("Missing file name argument");
3354
 
  name= p;
 
3284
  char *name= p;
3355
3285
  while (*p && !my_isspace(charset_info,*p))
3356
3286
    p++;
3357
3287
  if (*p)
3426
3356
      and assign that string to the $variable
3427
3357
    */
3428
3358
    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
3359
    try
3433
3360
    {
3434
 
      global_error_names.insert(ErrorCodes::value_type(error_name,
3435
 
                                                       boost::lexical_cast<uint32_t>(error_code)));
 
3361
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3436
3362
    }
3437
3363
    catch (boost::bad_lexical_cast &ex)
3438
3364
    {
3445
3371
  drizzle_result_free(&res);
3446
3372
}
3447
3373
 
3448
 
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
 
3374
static uint32_t get_errcode_from_name(const char *error_name, const char *error_end)
3449
3375
{
3450
 
  size_t err_name_len= error_end - error_name;
3451
 
  string error_name_s(error_name, err_name_len);
 
3376
  string error_name_s(error_name, error_end);
3452
3377
 
3453
 
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3454
 
  if (it != global_error_names.end())
3455
 
  {
3456
 
    return (*it).second;
3457
 
  }
 
3378
  if (ErrorCodes::mapped_type* ptr= find_ptr(global_error_names, error_name_s))
 
3379
    return *ptr;
3458
3380
 
3459
3381
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3460
3382
  return 0;
3525
3447
    {
3526
3448
      die("The error name definition must start with an uppercase E");
3527
3449
    }
 
3450
    else if (*p == 'H')
 
3451
    {
 
3452
      /* Error name string */
 
3453
 
 
3454
      to->code.errnum= get_errcode_from_name(p, end);
 
3455
      to->type= ERR_ERRNO;
 
3456
    }
3528
3457
    else
3529
3458
    {
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;
 
3459
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3549
3460
    }
3550
3461
    to++;
3551
3462
    count++;
3908
3819
{
3909
3820
  uint32_t con_port= opt_port;
3910
3821
  const char *con_options;
3911
 
  bool con_ssl= 0;
3912
3822
  struct st_connection* con_slot;
3913
3823
 
3914
3824
  string ds_connection_name;
3972
3882
    end= con_options;
3973
3883
    while (*end && !my_isspace(charset_info, *end))
3974
3884
      end++;
3975
 
    if (!strncmp(con_options, "SSL", 3))
3976
 
      con_ssl= 1;
3977
 
    else
3978
 
      die("Illegal option to connect: %.*s",
3979
 
          (int) (end - con_options), con_options);
 
3885
    die("Illegal option to connect: %.*s",
 
3886
        (int) (end - con_options), con_options);
3980
3887
    /* Process next option */
3981
3888
    con_options= end;
3982
3889
  }
4086
3993
{
4087
3994
  char *p= command->first_argument;
4088
3995
  const char *expr_start, *expr_end;
4089
 
  VAR v;
4090
3996
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4091
3997
  bool not_expr= false;
4092
3998
 
4129
4035
  if (*p && *p != '{')
4130
4036
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4131
4037
 
 
4038
  VAR v;
4132
4039
  var_init(&v,0,0,0,0);
4133
4040
  eval_expr(&v, expr_start, &expr_end);
4134
4041
 
4220
4127
*/
4221
4128
 
4222
4129
 
4223
 
static int my_strnncoll_simple(const CHARSET_INFO * const  cs, const unsigned char *s, size_t slen,
 
4130
static int my_strnncoll_simple(const charset_info_st * const  cs, const unsigned char *s, size_t slen,
4224
4131
                               const unsigned char *t, size_t tlen,
4225
4132
                               bool t_is_prefix)
4226
4133
{
4264
4171
      }
4265
4172
      free((unsigned char*) cur_file->file_name);
4266
4173
      cur_file->file_name= 0;
4267
 
      if (cur_file == file_stack)
 
4174
      if (cur_file == file_stack.data())
4268
4175
      {
4269
4176
        /* We're back at the first file, check if
4270
4177
           all { have matching }
4498
4405
        end++;
4499
4406
      save= *end;
4500
4407
      *end= 0;
4501
 
      type= find_type(start, &command_typelib, 1+2);
 
4408
      type= command_typelib.find_type(start, TYPELIB::e_default);
4502
4409
      if (type)
4503
4410
        warning_msg("Embedded drizzletest command '--%s' detected in "
4504
4411
                    "query '%s' was this intentional? ",
4704
4611
          log_file);
4705
4612
}
4706
4613
 
4707
 
void dump_progress(void)
 
4614
void dump_progress()
4708
4615
{
4709
4616
  char progress_file[FN_REFLEN];
4710
4617
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4714
4621
              ds_progress.c_str(), ds_progress.length());
4715
4622
}
4716
4623
 
4717
 
void dump_warning_messages(void)
 
4624
void dump_warning_messages()
4718
4625
{
4719
4626
  char warn_file[FN_REFLEN];
4720
4627
 
4779
4686
    for (i = 0; i < num_fields; i++)
4780
4687
    {
4781
4688
      column= drizzle_column_next(res);
4782
 
      append_field(ds, i, column,
4783
 
                   (const char*)row[i], lengths[i], !row[i]);
 
4689
      if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
 
4690
      {
 
4691
        if (boost::lexical_cast<uint32_t>(row[i]))
 
4692
        {
 
4693
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
 
4694
          {
 
4695
            append_field(ds, i, column, "YES", 3, false);
 
4696
          }
 
4697
          else
 
4698
          {
 
4699
            append_field(ds, i, column, "TRUE", 4, false);
 
4700
          }
 
4701
        }
 
4702
        else
 
4703
        {
 
4704
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
 
4705
          {
 
4706
            append_field(ds, i, column, "NO", 2, false);
 
4707
          }
 
4708
          else
 
4709
          {
 
4710
            append_field(ds, i, column, "FALSE", 5, false);
 
4711
          }
 
4712
        }
 
4713
      }
 
4714
      else
 
4715
      {
 
4716
        append_field(ds, i, column,
 
4717
                     (const char*)row[i], lengths[i], !row[i]);
 
4718
      }
4784
4719
    }
4785
4720
    if (!display_result_vertically)
4786
4721
      ds->append("\n");
4824
4759
    ds->append("\t", 1);
4825
4760
    replace_append_uint(ds, drizzle_column_size(column));
4826
4761
    ds->append("\t", 1);
4827
 
    replace_append_uint(ds, drizzle_column_max_size(column));
 
4762
    if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
 
4763
    {
 
4764
      replace_append_uint(ds, 1);
 
4765
    }
 
4766
    else
 
4767
    {
 
4768
      replace_append_uint(ds, drizzle_column_max_size(column));
 
4769
    }
4828
4770
    ds->append("\t", 1);
4829
4771
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4830
4772
    ds->append("\t", 1);
5321
5263
 
5322
5264
  save= command->query[command->first_word_len];
5323
5265
  command->query[command->first_word_len]= 0;
5324
 
  type= find_type(command->query, &command_typelib, 1+2);
 
5266
  type= command_typelib.find_type(command->query, TYPELIB::e_default);
5325
5267
  command->query[command->first_word_len]= save;
5326
5268
  if (type > 0)
5327
5269
  {
5365
5307
        */
5366
5308
        save= command->query[command->first_word_len-1];
5367
5309
        command->query[command->first_word_len-1]= 0;
5368
 
        if (find_type(command->query, &command_typelib, 1+2) > 0)
 
5310
        if (command_typelib.find_type(command->query, TYPELIB::e_default) > 0)
5369
5311
          die("Extra delimiter \";\" found");
5370
5312
        command->query[command->first_word_len-1]= save;
5371
5313
 
5539
5481
 
5540
5482
  if (user_config_dir.compare(0, 2, "~/") == 0)
5541
5483
  {
5542
 
    char *homedir;
5543
 
    homedir= getenv("HOME");
 
5484
    const char *homedir= getenv("HOME");
5544
5485
    if (homedir != NULL)
5545
5486
      user_config_dir.replace(0, 1, homedir);
5546
5487
  }
5587
5528
  next_con= connections + 1;
5588
5529
 
5589
5530
  /* 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;
 
5531
  memset(file_stack.data(), 0, sizeof(file_stack));
 
5532
  cur_file= file_stack.data();
5594
5533
 
5595
5534
  /* Init block stack */
5596
5535
  memset(block_stack, 0, sizeof(block_stack));
5629
5568
      tmp= buff;
5630
5569
    }
5631
5570
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5632
 
    assert(cur_file == file_stack && cur_file->file == 0);
 
5571
    assert(cur_file == file_stack.data() && cur_file->file == 0);
5633
5572
    if (!(cur_file->file= fopen(buff, "r")))
5634
5573
    {
5635
5574
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5734
5673
  }
5735
5674
 
5736
5675
  server_initialized= 1;
5737
 
  if (cur_file == file_stack && cur_file->file == 0)
 
5676
  if (cur_file == file_stack.data() && cur_file->file == 0)
5738
5677
  {
5739
5678
    cur_file->file= stdin;
5740
5679
    cur_file->file_name= strdup("<stdin>");
6159
6098
  the time between executing the two commands.
6160
6099
*/
6161
6100
 
6162
 
void timer_output(void)
 
6101
void timer_output()
6163
6102
{
6164
6103
  if (timer_file)
6165
6104
  {
6173
6112
}
6174
6113
 
6175
6114
 
6176
 
uint64_t timer_now(void)
 
6115
uint64_t timer_now()
6177
6116
{
6178
6117
#if defined(HAVE_GETHRTIME)
6179
6118
  return gethrtime()/1000/1000;
6213
6152
  start= buff= (char *)malloc(strlen(from)+1);
6214
6153
  while (*from)
6215
6154
  {
6216
 
    char *to;
6217
6155
    uint32_t column_number;
6218
6156
 
6219
 
    to= get_string(&buff, &from, command);
 
6157
    char *to= get_string(&buff, &from, command);
6220
6158
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6221
6159
      die("Wrong column number to replace_column in '%s'", command->query);
6222
6160
    if (!*from)
6235
6173
 
6236
6174
void free_replace_column()
6237
6175
{
6238
 
  uint32_t i;
6239
 
  for (i=0 ; i < max_replace_column ; i++)
 
6176
  for (uint32_t i= 0 ; i < max_replace_column; i++)
6240
6177
  {
6241
 
    if (replace_column[i])
6242
 
    {
6243
 
      free(replace_column[i]);
6244
 
      replace_column[i]= 0;
6245
 
    }
 
6178
    free(replace_column[i]);
 
6179
    replace_column[i]= 0;
6246
6180
  }
6247
6181
  max_replace_column= 0;
6248
6182
}
6255
6189
 
6256
6190
/* Definitions for replace result */
6257
6191
 
6258
 
typedef struct st_pointer_array {    /* when using array-strings */
 
6192
class POINTER_ARRAY
 
6193
{    /* when using array-strings */
 
6194
public:
 
6195
  ~POINTER_ARRAY();
 
6196
  int insert(char* name);
 
6197
 
 
6198
  POINTER_ARRAY()
 
6199
  {
 
6200
    memset(this, 0, sizeof(*this));
 
6201
  }
 
6202
 
6259
6203
  TYPELIB typelib;        /* Pointer to strings */
6260
 
  unsigned char  *str;          /* Strings is here */
6261
 
  uint8_t *flag;          /* Flag about each var. */
6262
 
  uint32_t  array_allocs,max_count,length,max_length;
6263
 
} POINTER_ARRAY;
 
6204
  unsigned char *str;          /* Strings is here */
 
6205
  uint8_t* flag;          /* Flag about each var. */
 
6206
  uint32_t array_allocs;
 
6207
  uint32_t max_count;
 
6208
  uint32_t length;
 
6209
  uint32_t max_length;
 
6210
};
6264
6211
 
6265
6212
struct st_replace;
6266
 
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
6267
 
                                char * word_end_chars);
6268
 
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
 
6213
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
 
6214
                                char *word_end_chars);
 
6215
 
6269
6216
void replace_strings_append(struct st_replace *rep, string* ds,
6270
6217
                            const char *from, int len);
6271
 
void free_pointer_array(POINTER_ARRAY *pa);
6272
6218
 
6273
 
struct st_replace *glob_replace= NULL;
 
6219
st_replace *glob_replace= NULL;
 
6220
// boost::scoped_ptr<st_replace> glob_replace;
6274
6221
 
6275
6222
/*
6276
6223
  Get arguments for replace. The syntax is:
6280
6227
  variable is replaced.
6281
6228
*/
6282
6229
 
6283
 
void do_get_replace(struct st_command *command)
6284
 
{
6285
 
  uint32_t i;
 
6230
POINTER_ARRAY::~POINTER_ARRAY()
 
6231
{
 
6232
  if (!typelib.count)
 
6233
    return;
 
6234
  typelib.count= 0;
 
6235
  free((char*) typelib.type_names);
 
6236
  typelib.type_names=0;
 
6237
  free(str);
 
6238
}
 
6239
 
 
6240
void do_get_replace(st_command *command)
 
6241
{
6286
6242
  char *from= command->first_argument;
6287
 
  char *buff, *start;
6288
 
  char word_end_chars[256], *pos;
 
6243
  if (!*from)
 
6244
    die("Missing argument in %s", command->query);
 
6245
  free_replace();
6289
6246
  POINTER_ARRAY to_array, from_array;
6290
 
 
6291
 
 
6292
 
  free_replace();
6293
 
 
6294
 
  memset(&to_array, 0, sizeof(to_array));
6295
 
  memset(&from_array, 0, sizeof(from_array));
6296
 
  if (!*from)
6297
 
    die("Missing argument in %s", command->query);
6298
 
  start= buff= (char *)malloc(strlen(from)+1);
 
6247
  char* start= (char*)malloc(strlen(from) + 1);
 
6248
  char* buff= start;
6299
6249
  while (*from)
6300
6250
  {
6301
 
    char *to= buff;
6302
 
    to= get_string(&buff, &from, command);
 
6251
    char *to= get_string(&buff, &from, command);
6303
6252
    if (!*from)
6304
 
      die("Wrong number of arguments to replace_result in '%s'",
6305
 
          command->query);
6306
 
    insert_pointer_name(&from_array,to);
 
6253
      die("Wrong number of arguments to replace_result in '%s'", command->query);
 
6254
    from_array.insert(to);
6307
6255
    to= get_string(&buff, &from, command);
6308
 
    insert_pointer_name(&to_array,to);
 
6256
    to_array.insert(to);
6309
6257
  }
6310
 
  for (i= 1,pos= word_end_chars ; i < 256 ; i++)
6311
 
    if (my_isspace(charset_info,i))
 
6258
  char word_end_chars[256];
 
6259
  char* pos= word_end_chars;
 
6260
  for (int i= 1; i < 256; i++)
 
6261
  {
 
6262
    if (my_isspace(charset_info, i))
6312
6263
      *pos++= i;
 
6264
  }
6313
6265
  *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,
 
6266
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
 
6267
                                   to_array.typelib.type_names,
 
6268
                                   from_array.typelib.count,
6317
6269
                                   word_end_chars)))
6318
6270
    die("Can't initialize replace from '%s'", command->query);
6319
 
  free_pointer_array(&from_array);
6320
 
  free_pointer_array(&to_array);
6321
6271
  free(start);
6322
6272
  command->last_argument= command->end;
6323
6273
  return;
6326
6276
 
6327
6277
void free_replace()
6328
6278
{
6329
 
 
6330
 
  if (glob_replace)
6331
 
  {
6332
 
    free(glob_replace);
6333
 
    glob_replace=0;
6334
 
  }
6335
 
  return;
 
6279
  free(glob_replace);
 
6280
  glob_replace=0;
6336
6281
}
6337
6282
 
6338
6283
 
6352
6297
void replace_strings_append(REPLACE *rep, string* ds,
6353
6298
                            const char *str, int len)
6354
6299
{
6355
 
  register REPLACE *rep_pos;
6356
 
  register REPLACE_STRING *rep_str;
 
6300
  REPLACE *rep_pos;
 
6301
  REPLACE_STRING *rep_str;
6357
6302
  const char *start, *from;
6358
6303
 
6359
6304
 
6406
6351
                 i.e. repeat the matching until the end of the string */
6407
6352
};
6408
6353
 
6409
 
struct st_replace_regex
 
6354
class st_replace_regex
6410
6355
{
6411
 
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
 
6356
public:
 
6357
  st_replace_regex(char* expr);
 
6358
  int multi_reg_replace(char* val);
6412
6359
 
6413
6360
  /*
6414
6361
    Temporary storage areas for substitutions. To reduce unnessary copying
6417
6364
    st_regex substition. At the end of substitutions  buf points to the
6418
6365
    one containing the final result.
6419
6366
  */
6420
 
  char* buf;
 
6367
  typedef vector<st_regex> regex_arr_t;
 
6368
 
 
6369
  char* buf_;
6421
6370
  char* even_buf;
6422
6371
  char* odd_buf;
6423
6372
  int even_buf_len;
6424
6373
  int odd_buf_len;
 
6374
  boost::array<char, 8 << 10> buf0_;
 
6375
  boost::array<char, 8 << 10> buf1_;
 
6376
  regex_arr_t regex_arr;
6425
6377
};
6426
6378
 
6427
 
struct st_replace_regex *glob_replace_regex= 0;
 
6379
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
6428
6380
 
6429
6381
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6430
6382
                char *string, int icase, int global);
6466
6418
  Returns: st_replace_regex struct with pairs of substitutions
6467
6419
*/
6468
6420
 
6469
 
static struct st_replace_regex* init_replace_regex(char* expr)
 
6421
st_replace_regex::st_replace_regex(char* expr)
6470
6422
{
6471
 
  struct st_replace_regex* res;
6472
 
  char* buf,*expr_end;
6473
 
  char* p;
6474
 
  char* buf_p;
6475
6423
  uint32_t expr_len= strlen(expr);
6476
6424
  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;
 
6425
  st_regex reg;
 
6426
 
 
6427
  char* buf= new char[expr_len];
 
6428
  char* expr_end= expr + expr_len;
 
6429
  char* p= expr;
 
6430
  char* buf_p= buf;
6488
6431
 
6489
6432
  /* for each regexp substitution statement */
6490
6433
  while (p < expr_end)
6500
6443
 
6501
6444
    if (p == expr_end || ++p == expr_end)
6502
6445
    {
6503
 
      if (res->regex_arr.elements)
 
6446
      if (!regex_arr.empty())
6504
6447
        break;
6505
6448
      else
6506
6449
        goto err;
6539
6482
      p++;
6540
6483
      reg.global= 1;
6541
6484
    }
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");
 
6485
    regex_arr.push_back(reg);
6546
6486
  }
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;
 
6487
  odd_buf_len= even_buf_len= buf0_.size();
 
6488
  even_buf= buf0_.data();
 
6489
  odd_buf= buf1_.data();
 
6490
  buf_= even_buf;
6551
6491
 
6552
 
  return res;
 
6492
  return;
6553
6493
 
6554
6494
err:
6555
 
  free(res);
6556
6495
  die("Error parsing replace_regex \"%s\"", expr);
6557
 
  return 0;
6558
6496
}
6559
6497
 
6560
6498
/*
6576
6514
  in one pass
6577
6515
*/
6578
6516
 
6579
 
static int multi_reg_replace(struct st_replace_regex* r,char* val)
 
6517
int st_replace_regex::multi_reg_replace(char* val)
6580
6518
{
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;
 
6519
  char* in_buf= val;
 
6520
  char* out_buf= even_buf;
 
6521
  int* buf_len_p= &even_buf_len;
 
6522
  buf_= 0;
6589
6523
 
6590
6524
  /* For each substitution, do the replace */
6591
 
  for (i= 0; i < r->regex_arr.elements; i++)
 
6525
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
6592
6526
  {
6593
 
    struct st_regex re;
6594
6527
    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))
 
6528
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
 
6529
                     in_buf, i.icase, i.global))
6600
6530
    {
6601
6531
      /* if the buffer has been reallocated, make adjustements */
6602
6532
      if (save_out_buf != out_buf)
6603
6533
      {
6604
 
        if (save_out_buf == r->even_buf)
6605
 
          r->even_buf= out_buf;
 
6534
        if (save_out_buf == even_buf)
 
6535
          even_buf= out_buf;
6606
6536
        else
6607
 
          r->odd_buf= out_buf;
 
6537
          odd_buf= out_buf;
6608
6538
      }
6609
 
 
6610
 
      r->buf= out_buf;
 
6539
      buf_= out_buf;
6611
6540
      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;
 
6541
        in_buf= odd_buf;
 
6542
      std::swap(in_buf, out_buf);
 
6543
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
6618
6544
    }
6619
6545
  }
6620
 
 
6621
 
  return (r->buf == 0);
 
6546
  return buf_ == 0;
6622
6547
}
6623
6548
 
6624
6549
/*
6633
6558
void do_get_replace_regex(struct st_command *command)
6634
6559
{
6635
6560
  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");
 
6561
  glob_replace_regex.reset(new st_replace_regex(expr));
6639
6562
  command->last_argument= command->end;
6640
6563
}
6641
6564
 
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
6565
/*
6657
6566
  Performs a regex substitution
6658
6567
 
6759
6668
#define SET_MALLOC_HUNC 64
6760
6669
#define LAST_CHAR_CODE 259
6761
6670
 
6762
 
typedef struct st_rep_set {
 
6671
class REP_SET
 
6672
{
 
6673
public:
 
6674
  void internal_set_bit(uint32_t bit);
 
6675
  void internal_clear_bit(uint32_t bit);
 
6676
  void or_bits(const REP_SET *from);
 
6677
  void copy_bits(const REP_SET *from);
 
6678
  int cmp_bits(const REP_SET *set2) const;
 
6679
  int get_next_bit(uint32_t lastpos) const;
 
6680
 
6763
6681
  uint32_t  *bits;        /* Pointer to used sets */
6764
6682
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6765
6683
  uint32_t  found_len;      /* Best match to date */
6766
6684
  int  found_offset;
6767
6685
  uint32_t  table_offset;
6768
6686
  uint32_t  size_of_bits;      /* For convinience */
6769
 
} REP_SET;
6770
 
 
6771
 
typedef struct st_rep_sets {
 
6687
};
 
6688
 
 
6689
class REP_SETS
 
6690
{
 
6691
public:
 
6692
  int find_set(const REP_SET *find);
 
6693
  void free_last_set();
 
6694
  void free_sets();
 
6695
  void make_sets_invisible();
 
6696
 
6772
6697
  uint32_t    count;      /* Number of sets */
6773
6698
  uint32_t    extra;      /* Extra sets in buffer */
6774
 
  uint32_t    invisible;    /* Sets not chown */
 
6699
  uint32_t    invisible;    /* Sets not shown */
6775
6700
  uint32_t    size_of_bits;
6776
6701
  REP_SET  *set,*set_buffer;
6777
6702
  uint32_t    *bit_buffer;
6778
 
} REP_SETS;
 
6703
};
6779
6704
 
6780
 
typedef struct st_found_set {
 
6705
struct FOUND_SET 
 
6706
{
6781
6707
  uint32_t table_offset;
6782
6708
  int found_offset;
6783
 
} FOUND_SET;
 
6709
};
6784
6710
 
6785
 
typedef struct st_follow {
 
6711
struct FOLLOWS
 
6712
{
6786
6713
  int chr;
6787
6714
  uint32_t table_offset;
6788
6715
  uint32_t len;
6789
 
} FOLLOWS;
6790
 
 
6791
 
 
6792
 
int init_sets(REP_SETS *sets,uint32_t states);
 
6716
};
 
6717
 
 
6718
int init_sets(REP_SETS *sets, uint32_t states);
6793
6719
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)
 
6720
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
 
6721
 
 
6722
static uint32_t found_sets= 0;
 
6723
 
 
6724
static uint32_t replace_len(const char *str)
6813
6725
{
6814
6726
  uint32_t len=0;
6815
6727
  while (*str)
6822
6734
  return len;
6823
6735
}
6824
6736
 
 
6737
/* Return 1 if regexp starts with \b or ends with \b*/
 
6738
 
 
6739
static bool start_at_word(const char *pos)
 
6740
{
 
6741
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
 
6742
}
 
6743
 
 
6744
static bool end_of_word(const char *pos)
 
6745
{
 
6746
  const char *end= strchr(pos, '\0');
 
6747
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
 
6748
}
 
6749
 
6825
6750
/* Init a replace structure for further calls */
6826
6751
 
6827
 
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
6828
 
                      char * word_end_chars)
 
6752
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
6829
6753
{
6830
 
  static const int SPACE_CHAR= 256;
6831
 
  static const int START_OF_LINE= 257;
6832
 
  static const int END_OF_LINE= 258;
 
6754
  const int SPACE_CHAR= 256;
 
6755
  const int START_OF_LINE= 257;
 
6756
  const int END_OF_LINE= 258;
6833
6757
 
6834
6758
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6835
6759
  int used_sets,chr,default_state;
6836
6760
  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
 
 
 
6761
  char *to_pos, **to_array;
6845
6762
 
6846
6763
  /* Count number of states */
6847
6764
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6861
6778
  for (i=0 ; word_end_chars[i] ; i++)
6862
6779
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6863
6780
 
6864
 
  if (init_sets(&sets,states))
6865
 
    return(0);
 
6781
  REP_SETS sets;
 
6782
  REP_SET *set,*start_states,*word_states,*new_set;
 
6783
  REPLACE_STRING *rep_str;
 
6784
  if (init_sets(&sets, states))
 
6785
    return 0;
6866
6786
  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
 
  }
 
6787
  vector<FOUND_SET> found_set(max_length * count);
6873
6788
  make_new_set(&sets);      /* Set starting set */
6874
 
  make_sets_invisible(&sets);      /* Hide previus sets */
 
6789
  sets.make_sets_invisible();      /* Hide previus sets */
6875
6790
  used_sets=-1;
6876
6791
  word_states=make_new_set(&sets);    /* Start of new word */
6877
6792
  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
 
 
 
6793
  vector<FOLLOWS> follow(states + 2);
 
6794
  FOLLOWS *follow_ptr= &follow[1];
6885
6795
  /* Init follow_ptr[] */
6886
 
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
 
6796
  for (i=0, states=1; i < count; i++)
6887
6797
  {
6888
6798
    if (from[i][0] == '\\' && from[i][1] == '^')
6889
6799
    {
6890
 
      internal_set_bit(start_states,states+1);
 
6800
      start_states->internal_set_bit(states + 1);
6891
6801
      if (!from[i][2])
6892
6802
      {
6893
6803
        start_states->table_offset=i;
6896
6806
    }
6897
6807
    else if (from[i][0] == '\\' && from[i][1] == '$')
6898
6808
    {
6899
 
      internal_set_bit(start_states,states);
6900
 
      internal_set_bit(word_states,states);
 
6809
      start_states->internal_set_bit(states);
 
6810
      word_states->internal_set_bit(states);
6901
6811
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6902
6812
      {
6903
6813
        start_states->table_offset=i;
6906
6816
    }
6907
6817
    else
6908
6818
    {
6909
 
      internal_set_bit(word_states,states);
 
6819
      word_states->internal_set_bit(states);
6910
6820
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6911
 
        internal_set_bit(start_states,states+1);
 
6821
        start_states->internal_set_bit(states + 1);
6912
6822
      else
6913
 
        internal_set_bit(start_states,states);
 
6823
        start_states->internal_set_bit(states);
6914
6824
    }
6915
 
    for (pos=from[i], len=0; *pos ; pos++)
 
6825
    const char *pos;
 
6826
    for (pos= from[i], len=0; *pos ; pos++)
6916
6827
    {
6917
6828
      if (*pos == '\\' && *(pos+1))
6918
6829
      {
6955
6866
  }
6956
6867
 
6957
6868
 
6958
 
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
 
6869
  for (set_nr=0; set_nr < sets.count ; set_nr++)
6959
6870
  {
6960
6871
    set=sets.set+set_nr;
6961
6872
    default_state= 0;        /* Start from beginning */
6962
6873
 
6963
6874
    /* If end of found-string not found or start-set with current set */
6964
6875
 
6965
 
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
 
6876
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
6966
6877
    {
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
 
      }
 
6878
      if (!follow[i].chr && !default_state)
 
6879
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
6973
6880
    }
6974
 
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
 
6881
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
6975
6882
    if (!default_state)
6976
 
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
 
6883
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
6977
6884
 
6978
6885
    /* Find all chars that follows current sets */
6979
6886
    memset(used_chars, 0, sizeof(used_chars));
6980
 
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
 
6887
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
6981
6888
    {
6982
6889
      used_chars[follow[i].chr]=1;
6983
6890
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6987
6894
 
6988
6895
    /* Mark word_chars used if \b is in state */
6989
6896
    if (used_chars[SPACE_CHAR])
6990
 
      for (pos= word_end_chars ; *pos ; pos++)
 
6897
      for (const char *pos= word_end_chars ; *pos ; pos++)
6991
6898
        used_chars[(int) (unsigned char) *pos] = 1;
6992
6899
 
6993
6900
    /* Handle other used characters */
7004
6911
        new_set->found_offset=set->found_offset+1;
7005
6912
        found_end=0;
7006
6913
 
7007
 
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
 
6914
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
7008
6915
        {
7009
6916
          if (!follow[i].chr || follow[i].chr == chr ||
7010
6917
              (follow[i].chr == SPACE_CHAR &&
7016
6923
                follow[i].len > found_end)
7017
6924
              found_end=follow[i].len;
7018
6925
            if (chr && follow[i].chr)
7019
 
              internal_set_bit(new_set,i+1);    /* To next set */
 
6926
              new_set->internal_set_bit(i + 1);    /* To next set */
7020
6927
            else
7021
 
              internal_set_bit(new_set,i);
 
6928
              new_set->internal_set_bit(i);
7022
6929
          }
7023
6930
        }
7024
6931
        if (found_end)
7025
6932
        {
7026
6933
          new_set->found_len=0;      /* Set for testing if first */
7027
6934
          bits_set=0;
7028
 
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
 
6935
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
7029
6936
          {
7030
6937
            if ((follow[i].chr == SPACE_CHAR ||
7031
6938
                 follow[i].chr == END_OF_LINE) && ! chr)
7035
6942
            if (follow[bit_nr-1].len < found_end ||
7036
6943
                (new_set->found_len &&
7037
6944
                 (chr == 0 || !follow[bit_nr].chr)))
7038
 
              internal_clear_bit(new_set,i);
 
6945
              new_set->internal_clear_bit(i);
7039
6946
            else
7040
6947
            {
7041
6948
              if (chr == 0 || !follow[bit_nr].chr)
7051
6958
          }
7052
6959
          if (bits_set == 1)
7053
6960
          {
7054
 
            set->next[chr] = find_found(found_set,
7055
 
                                        new_set->table_offset,
7056
 
                                        new_set->found_offset);
7057
 
            free_last_set(&sets);
 
6961
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
 
6962
            sets.free_last_set();
7058
6963
          }
7059
6964
          else
7060
 
            set->next[chr] = find_set(&sets,new_set);
 
6965
            set->next[chr] = sets.find_set(new_set);
7061
6966
        }
7062
6967
        else
7063
 
          set->next[chr] = find_set(&sets,new_set);
 
6968
          set->next[chr] = sets.find_set(new_set);
7064
6969
      }
7065
6970
    }
7066
6971
  }
7067
6972
 
7068
6973
  /* Alloc replace structure for the replace-state-machine */
7069
6974
 
7070
 
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
7071
 
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
7072
 
                                 sizeof(char *)*count+result_len)))
 
6975
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
 
6976
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
 
6977
  if (replace)
7073
6978
  {
7074
6979
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
7075
6980
                       sizeof(REPLACE_STRING)*(found_sets+1)+
7086
6991
    rep_str[0].replace_string=0;
7087
6992
    for (i=1 ; i <= found_sets ; i++)
7088
6993
    {
7089
 
      pos=from[found_set[i-1].table_offset];
 
6994
      const char *pos= from[found_set[i-1].table_offset];
7090
6995
      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);
 
6996
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
 
6997
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
 
6998
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
7095
6999
    }
7096
7000
    for (i=0 ; i < sets.count ; i++)
7097
7001
    {
7102
7006
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7103
7007
    }
7104
7008
  }
7105
 
  free(follow);
7106
 
  free_sets(&sets);
7107
 
  free(found_set);
7108
 
  return(replace);
 
7009
  sets.free_sets();
 
7010
  return replace;
7109
7011
}
7110
7012
 
7111
7013
 
7126
7028
 
7127
7029
/* Make help sets invisible for nicer codeing */
7128
7030
 
7129
 
void make_sets_invisible(REP_SETS *sets)
 
7031
void REP_SETS::make_sets_invisible()
7130
7032
{
7131
 
  sets->invisible=sets->count;
7132
 
  sets->set+=sets->count;
7133
 
  sets->count=0;
 
7033
  invisible= count;
 
7034
  set += count;
 
7035
  count= 0;
7134
7036
}
7135
7037
 
7136
7038
REP_SET *make_new_set(REP_SETS *sets)
7168
7070
  return make_new_set(sets);
7169
7071
}
7170
7072
 
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
 
 
 
7073
void REP_SETS::free_last_set()
 
7074
{
 
7075
  count--;
 
7076
  extra++;
 
7077
}
 
7078
 
 
7079
void REP_SETS::free_sets()
 
7080
{
 
7081
  free(set_buffer);
 
7082
  free(bit_buffer);
 
7083
}
 
7084
 
 
7085
void REP_SET::internal_set_bit(uint32_t bit)
 
7086
{
 
7087
  bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
7088
}
 
7089
 
 
7090
void REP_SET::internal_clear_bit(uint32_t bit)
 
7091
{
 
7092
  bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
7093
}
 
7094
 
 
7095
 
 
7096
void REP_SET::or_bits(const REP_SET *from)
 
7097
{
 
7098
  for (uint32_t i= 0 ; i < size_of_bits; i++)
 
7099
    bits[i]|=from->bits[i];
 
7100
}
 
7101
 
 
7102
void REP_SET::copy_bits(const REP_SET *from)
 
7103
{
 
7104
  memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
 
7105
}
 
7106
 
 
7107
int REP_SET::cmp_bits(const REP_SET *set2) const
 
7108
{
 
7109
  return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
 
7110
}
7217
7111
 
7218
7112
/* Get next set bit from set. */
7219
7113
 
7220
 
int get_next_bit(REP_SET *set,uint32_t lastpos)
 
7114
int REP_SET::get_next_bit(uint32_t lastpos) const
7221
7115
{
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)
 
7116
  uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
 
7117
  uint32_t *end= bits + size_of_bits;
 
7118
  uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
7119
 
 
7120
  while (!bits0 && ++start < end)
 
7121
    bits0= start[0];
 
7122
  if (!bits0)
7231
7123
    return 0;
7232
 
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
7233
 
  while (! (bits & 1))
 
7124
  uint32_t pos= (start - bits) * WORD_BIT;
 
7125
  while (!(bits0 & 1))
7234
7126
  {
7235
 
    bits>>=1;
 
7127
    bits0 >>=1;
7236
7128
    pos++;
7237
7129
  }
7238
7130
  return pos;
7242
7134
   free given set, else put in given set in sets and return its
7243
7135
   position */
7244
7136
 
7245
 
int find_set(REP_SETS *sets,REP_SET *find)
 
7137
int REP_SETS::find_set(const REP_SET *find)
7246
7138
{
7247
 
  uint32_t i;
7248
 
  for (i=0 ; i < sets->count-1 ; i++)
 
7139
  uint32_t i= 0;
 
7140
  for (; i < count - 1; i++)
7249
7141
  {
7250
 
    if (!cmp_bits(sets->set+i,find))
 
7142
    if (!set[i].cmp_bits(find))
7251
7143
    {
7252
 
      free_last_set(sets);
 
7144
      free_last_set();
7253
7145
      return i;
7254
7146
    }
7255
7147
  }
7263
7155
   set->next[] == -1 is reserved for end without replaces.
7264
7156
*/
7265
7157
 
7266
 
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
 
7158
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
7267
7159
{
7268
 
  int i;
7269
 
  for (i=0 ; (uint32_t) i < found_sets ; i++)
 
7160
  uint32_t i= 0;
 
7161
  for (; i < found_sets; i++)
 
7162
  {
7270
7163
    if (found_set[i].table_offset == table_offset &&
7271
7164
        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;
 
7165
      return - i - 2;
 
7166
  }
 
7167
  found_set[i].table_offset= table_offset;
 
7168
  found_set[i].found_offset= found_offset;
7275
7169
  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;
 
7170
  return - i - 2; // return new postion
7292
7171
}
7293
7172
 
7294
7173
/****************************************************************************
7298
7177
#define PC_MALLOC    256  /* Bytes for pointers */
7299
7178
#define PS_MALLOC    512  /* Bytes for data */
7300
7179
 
7301
 
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
 
7180
static int insert_pointer_name(POINTER_ARRAY* pa, char* name)
7302
7181
{
7303
7182
  uint32_t i,length,old_count;
7304
7183
  unsigned char *new_pos;
7366
7245
  return(0);
7367
7246
} /* insert_pointer_name */
7368
7247
 
7369
 
 
7370
 
/* free pointer array */
7371
 
 
7372
 
void free_pointer_array(POINTER_ARRAY *pa)
 
7248
int POINTER_ARRAY::insert(char* name)
7373
7249
{
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 */
 
7250
  return insert_pointer_name(this, name);
 
7251
}
7382
7252
 
7383
7253
 
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
}