~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: LinuxJedi
  • Date: 2010-08-12 23:56:35 UTC
  • mto: (1723.1.4 build)
  • mto: This revision was merged to the branch mainline in revision 1724.
  • Revision ID: linuxjedi@linuxjedi-laptop-20100812235635-0dd1nuryjb43k9nj
Migrate the rest of strerror to strerror_r

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 * 
4
 
 *  Copyright (C) 2010 Vijay Samuel
 
3
 *
5
4
 *  Copyright (C) 2008 MySQL
6
5
 *
7
6
 *  This program is free software; you can redistribute it and/or modify
56
55
#include <sys/stat.h>
57
56
#include <sys/types.h>
58
57
#include <fcntl.h>
59
 
#include <boost/array.hpp>
60
 
#include <boost/foreach.hpp>
61
58
#include <boost/program_options.hpp>
62
 
#include <boost/smart_ptr.hpp>
63
59
 
64
60
#include PCRE_HEADER
65
61
 
66
62
#include <stdarg.h>
67
63
#include <boost/unordered_map.hpp>
68
64
 
 
65
#include "errname.h"
 
66
 
69
67
/* Added this for string translation. */
70
 
#include <drizzled/gettext.h>
71
 
#include <drizzled/type/time.h>
72
 
#include <drizzled/charset.h>
73
 
#include <drizzled/typelib.h>
 
68
#include "drizzled/gettext.h"
 
69
#include "drizzled/drizzle_time.h"
 
70
#include "drizzled/charset.h"
74
71
#include <drizzled/configmake.h>
75
72
 
76
 
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
77
 
 
78
73
#ifndef DRIZZLE_RETURN_SERVER_GONE
79
74
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
80
75
#endif
94
89
#define QUERY_SEND_FLAG  1
95
90
#define QUERY_REAP_FLAG  2
96
91
 
97
 
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
98
92
ErrorCodes global_error_names;
99
93
 
100
94
enum {
119
113
static bool abort_on_error= true;
120
114
static bool server_initialized= false;
121
115
static bool is_windows= false;
122
 
static bool use_drizzle_protocol= false;
 
116
static bool opt_mysql= false;
123
117
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
124
 
static void free_all_replace();
125
118
 
126
119
std::string opt_basedir,
127
120
  opt_charsets_dir,
133
126
  password,
134
127
  opt_password,
135
128
  result_file_name,
136
 
  opt_user,
137
 
  opt_protocol;
 
129
  opt_user;
138
130
 
139
131
static uint32_t start_lineno= 0; /* Start line of current command */
140
132
 
171
163
  uint32_t lineno; /* Current line in file */
172
164
};
173
165
 
174
 
static boost::array<st_test_file, 16> file_stack;
175
 
static st_test_file* cur_file;
 
166
static struct st_test_file file_stack[16];
 
167
static struct st_test_file* cur_file;
 
168
static struct st_test_file* file_stack_end;
 
169
 
176
170
 
177
171
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
178
172
 
182
176
*/
183
177
static char *timer_file = NULL;
184
178
static uint64_t timer_start;
185
 
static void timer_output();
186
 
static uint64_t timer_now();
 
179
static void timer_output(void);
 
180
static uint64_t timer_now(void);
187
181
 
188
182
static uint64_t progress_start= 0;
189
183
 
204
198
 
205
199
/* if set, all results are concated and compared against this file */
206
200
 
207
 
class VAR
 
201
typedef struct st_var
208
202
{
209
 
public:
210
203
  char *name;
211
204
  int name_len;
212
205
  char *str_val;
216
209
  int int_dirty; /* do not update string if int is updated until first read */
217
210
  int alloced;
218
211
  char *env_s;
219
 
};
 
212
} VAR;
220
213
 
221
214
/*Perl/shell-like variable registers */
222
 
boost::array<VAR, 10> var_reg;
223
 
 
224
 
typedef boost::unordered_map<string, VAR *> var_hash_t;
225
 
var_hash_t var_hash;
 
215
VAR var_reg[10];
 
216
 
 
217
 
 
218
boost::unordered_map<string, VAR *> var_hash;
226
219
 
227
220
struct st_connection
228
221
{
395
388
  struct st_match_err err[10];
396
389
  uint32_t count;
397
390
};
398
 
 
399
 
static st_expected_errors saved_expected_errors;
400
 
 
401
 
class st_command
 
391
static struct st_expected_errors saved_expected_errors;
 
392
 
 
393
struct st_command
402
394
{
403
 
public:
404
395
  char *query, *query_buf,*first_argument,*last_argument,*end;
405
396
  int first_word_len, query_len;
406
397
  bool abort_on_error;
407
398
  st_expected_errors expected_errors;
408
399
  string require_file;
409
 
  enum_commands type;
 
400
  enum enum_commands type;
410
401
 
411
402
  st_command()
412
403
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
418
409
 
419
410
  ~st_command()
420
411
  {
421
 
    free(query_buf);
 
412
    if (query_buf != NULL)
 
413
    {
 
414
      free(query_buf);
 
415
    }
422
416
  }
423
417
};
424
418
 
443
437
VAR* var_from_env(const char *, const char *);
444
438
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
445
439
              int val_len);
 
440
void var_free(pair<string, VAR*> v);
446
441
VAR* var_get(const char *var_name, const char** var_name_end,
447
442
             bool raw, bool ignore_not_existing);
448
443
void eval_expr(VAR* v, const char *p, const char** p_end);
449
444
bool match_delimiter(int c, const char *delim, uint32_t length);
450
445
void dump_result_to_reject_file(char *buf, int size);
451
446
void dump_result_to_log_file(const char *buf, int size);
452
 
void dump_warning_messages();
453
 
void dump_progress();
 
447
void dump_warning_messages(void);
 
448
void dump_progress(void);
454
449
 
455
450
void do_eval(string *query_eval, const char *query,
456
451
             const char *query_end, bool pass_through_escape_chars);
461
456
static char *replace_column[MAX_COLUMNS];
462
457
static uint32_t max_replace_column= 0;
463
458
void do_get_replace_column(struct st_command*);
464
 
void free_replace_column();
 
459
void free_replace_column(void);
465
460
 
466
461
/* For replace */
467
462
void do_get_replace(struct st_command *command);
468
 
void free_replace();
 
463
void free_replace(void);
469
464
 
470
465
/* For replace_regex */
471
466
void do_get_replace_regex(struct st_command *command);
 
467
void free_replace_regex(void);
 
468
 
 
469
 
 
470
void free_all_replace(void);
 
471
 
 
472
 
 
473
void free_all_replace(void){
 
474
  free_replace();
 
475
  free_replace_regex();
 
476
  free_replace_column();
 
477
}
472
478
 
473
479
void replace_append_mem(string *ds, const char *val,
474
480
                        int len);
485
491
void do_eval(string *query_eval, const char *query,
486
492
             const char *query_end, bool pass_through_escape_chars)
487
493
{
488
 
  char c, next_c;
489
 
  int escaped = 0;
 
494
  const char *p;
 
495
  register char c, next_c;
 
496
  register int escaped = 0;
490
497
  VAR *v;
491
498
 
492
 
  for (const char *p= query; (c= *p) && p < query_end; ++p)
 
499
 
 
500
  for (p= query; (c= *p) && p < query_end; ++p)
493
501
  {
494
502
    switch(c) {
495
503
    case '$':
773
781
    const struct command_arg *arg= &args[i];
774
782
    arg->ds->clear();
775
783
 
776
 
    bool known_arg_type= true;
777
784
    switch (arg->type) {
778
785
      /* A string */
779
786
    case ARG_STRING:
808
815
      break;
809
816
 
810
817
    default:
811
 
      known_arg_type= false;
 
818
      assert("Unknown argument type");
812
819
      break;
813
820
    }
814
 
    assert(known_arg_type);
815
821
 
816
822
    /* Check required arg */
817
823
    if (arg->ds->length() == 0 && arg->required)
834
840
 
835
841
static void handle_command_error(struct st_command *command, uint32_t error)
836
842
{
 
843
 
837
844
  if (error != 0)
838
845
  {
839
846
    uint32_t i;
860
867
        command->first_word_len, command->query,
861
868
        command->expected_errors.err[0].code.errnum);
862
869
  }
 
870
  return;
863
871
}
864
872
 
865
873
 
866
 
static void close_connections()
 
874
static void close_connections(void)
867
875
{
868
876
  for (--next_con; next_con >= connections; --next_con)
869
877
  {
874
882
    }
875
883
    free(next_con->name);
876
884
  }
 
885
  return;
877
886
}
878
887
 
879
888
 
880
 
static void close_files()
 
889
static void close_files(void)
881
890
{
882
 
  for (; cur_file >= file_stack.data(); cur_file--)
 
891
 
 
892
  for (; cur_file >= file_stack; cur_file--)
883
893
  {
884
894
    if (cur_file->file && cur_file->file != stdin)
 
895
    {
885
896
      fclose(cur_file->file);
886
 
    free(const_cast<char*>(cur_file->file_name));
 
897
    }
 
898
    free((unsigned char*) cur_file->file_name);
887
899
    cur_file->file_name= 0;
888
900
  }
 
901
  return;
889
902
}
890
903
 
891
 
static void free_used_memory()
 
904
 
 
905
static void free_used_memory(void)
892
906
{
 
907
  uint32_t i;
 
908
 
 
909
 
893
910
  close_connections();
894
911
  close_files();
895
 
  BOOST_FOREACH(var_hash_t::reference i, var_hash)
896
 
  {
897
 
    free(i.second->str_val);
898
 
    free(i.second->env_s);
899
 
    if (i.second->alloced)
900
 
      free(i.second);
901
 
  }
 
912
  for_each(var_hash.begin(), var_hash.end(), var_free);
902
913
  var_hash.clear();
903
 
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
904
 
    delete i;
905
 
  for (size_t i= 0; i < var_reg.size(); i++)
 
914
 
 
915
  vector<st_command *>::iterator iter;
 
916
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
917
  {
 
918
    struct st_command * q_line= *iter;
 
919
    delete q_line;
 
920
  }
 
921
 
 
922
  for (i= 0; i < 10; i++)
906
923
  {
907
924
    if (var_reg[i].alloced_len)
908
925
      free(var_reg[i].str_val);
909
926
  }
 
927
 
910
928
  free_all_replace();
911
929
  free(opt_pass);
 
930
 
 
931
  return;
912
932
}
913
933
 
914
934
 
933
953
      assert(0);
934
954
    }
935
955
  }
 
956
 
936
957
  exit(exit_code);
937
958
}
938
959
 
952
973
 
953
974
  /* Print the error message */
954
975
  fprintf(stderr, "drizzletest: ");
955
 
  if (cur_file && cur_file != file_stack.data())
 
976
  if (cur_file && cur_file != file_stack)
956
977
    fprintf(stderr, "In included file \"%s\": ",
957
978
            cur_file->file_name);
958
979
  if (start_lineno > 0)
1013
1034
 
1014
1035
  /* Print include filestack */
1015
1036
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1016
 
          file_stack[0].file_name);
 
1037
          file_stack->file_name);
1017
1038
  fprintf(stderr, "Detected in file %s at line %d\n",
1018
1039
          err_file->file_name, err_file->lineno);
1019
 
  while (err_file != file_stack.data())
 
1040
  while (err_file != file_stack)
1020
1041
  {
1021
1042
    err_file--;
1022
1043
    fprintf(stderr, "included from %s at line %d\n",
1047
1068
 
1048
1069
  va_start(args, fmt);
1049
1070
  fprintf(stderr, "drizzletest: ");
1050
 
  if (cur_file && cur_file != file_stack.data())
 
1071
  if (cur_file && cur_file != file_stack)
1051
1072
    fprintf(stderr, "In included file \"%s\": ",
1052
1073
            cur_file->file_name);
1053
1074
  if (start_lineno != 0)
1055
1076
  vfprintf(stderr, fmt, args);
1056
1077
  fprintf(stderr, "\n");
1057
1078
  va_end(args);
 
1079
 
 
1080
  return;
1058
1081
}
1059
1082
 
1060
1083
 
1070
1093
  if (start_lineno != 0)
1071
1094
  {
1072
1095
    ds_warning_messages.append("Warning detected ");
1073
 
    if (cur_file && cur_file != file_stack.data())
 
1096
    if (cur_file && cur_file != file_stack)
1074
1097
    {
1075
1098
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1076
1099
                    cur_file->file_name);
1435
1458
  int fd;
1436
1459
  char temp_file_path[FN_REFLEN];
1437
1460
 
1438
 
  if ((fd= internal::create_temp_file(temp_file_path, TMPDIR,
 
1461
  if ((fd= internal::create_temp_file(temp_file_path, NULL,
1439
1462
                            "tmp", MYF(MY_WME))) < 0)
1440
1463
    die("Failed to create temporary file for ds");
1441
1464
 
1603
1626
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1604
1627
              int val_len)
1605
1628
{
 
1629
  int val_alloc_len;
 
1630
  VAR *tmp_var;
1606
1631
  if (!name_len && name)
1607
1632
    name_len = strlen(name);
1608
1633
  if (!val_len && val)
1609
1634
    val_len = strlen(val) ;
1610
 
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
 
1635
  val_alloc_len = val_len + 16; /* room to grow */
 
1636
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
 
1637
                                               + name_len+1)))
 
1638
    die("Out of memory");
1611
1639
 
1612
 
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
 
1640
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1613
1641
  tmp_var->alloced = (v == 0);
1614
1642
 
1615
 
  int val_alloc_len = val_len + 16; /* room to grow */
1616
 
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
 
1643
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1644
    die("Out of memory");
1617
1645
 
1618
1646
  memcpy(tmp_var->name, name, name_len);
1619
1647
  if (val)
1624
1652
  tmp_var->name_len = name_len;
1625
1653
  tmp_var->str_val_len = val_len;
1626
1654
  tmp_var->alloced_len = val_alloc_len;
1627
 
  tmp_var->int_val = val ? atoi(val) : 0;
1628
 
  tmp_var->int_dirty = false;
 
1655
  tmp_var->int_val = (val) ? atoi(val) : 0;
 
1656
  tmp_var->int_dirty = 0;
1629
1657
  tmp_var->env_s = 0;
1630
1658
  return tmp_var;
1631
1659
}
1632
1660
 
 
1661
 
 
1662
void var_free(pair<string, VAR *> v)
 
1663
{
 
1664
  free(v.second->str_val);
 
1665
  free(v.second->env_s);
 
1666
  if (v.second->alloced)
 
1667
    free(v.second);
 
1668
}
 
1669
 
 
1670
 
1633
1671
VAR* var_from_env(const char *name, const char *def_val)
1634
1672
{
1635
 
  const char *tmp= getenv(name);
1636
 
  if (!tmp)
 
1673
  const char *tmp;
 
1674
  VAR *v;
 
1675
  if (!(tmp = getenv(name)))
1637
1676
    tmp = def_val;
1638
 
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1677
 
 
1678
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1679
  string var_name(name);
 
1680
  var_hash.insert(make_pair(var_name, v));
 
1681
  return v;
1639
1682
}
1640
1683
 
 
1684
 
1641
1685
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1642
1686
             bool ignore_not_existing)
1643
1687
{
1644
1688
  int digit;
1645
1689
  VAR *v;
 
1690
 
1646
1691
  if (*var_name != '$')
1647
1692
    goto err;
1648
1693
  digit = *++var_name - '0';
1664
1709
      die("Too long variable name: %s", save_var_name);
1665
1710
 
1666
1711
    string save_var_name_str(save_var_name, length);
1667
 
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
 
1712
    boost::unordered_map<string, VAR*>::iterator iter=
 
1713
      var_hash.find(save_var_name_str);
1668
1714
    if (iter == var_hash.end())
1669
1715
    {
1670
1716
      char buff[MAX_VAR_NAME_LENGTH+1];
1674
1720
    }
1675
1721
    else
1676
1722
    {
1677
 
      v= iter->second;
 
1723
      v= (*iter).second;
1678
1724
    }
1679
1725
    var_name--;  /* Point at last character */
1680
1726
  }
1681
1727
  else
1682
 
    v = &var_reg[digit];
 
1728
    v = var_reg + digit;
1683
1729
 
1684
1730
  if (!raw && v->int_dirty)
1685
1731
  {
1701
1747
static VAR *var_obtain(const char *name, int len)
1702
1748
{
1703
1749
  string var_name(name, len);
1704
 
  var_hash_t::iterator iter= var_hash.find(var_name);
 
1750
  boost::unordered_map<string, VAR*>::iterator iter=
 
1751
    var_hash.find(var_name);
1705
1752
  if (iter != var_hash.end())
1706
 
    return iter->second;
1707
 
  return var_hash[var_name] = var_init(0, name, len, "", 0);
 
1753
    return (*iter).second;
 
1754
  VAR *v = var_init(0, name, len, "", 0);
 
1755
  var_hash.insert(make_pair(var_name, v));
 
1756
  return v;
1708
1757
}
1709
1758
 
1710
1759
 
1731
1780
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1732
1781
  }
1733
1782
  else
1734
 
    v= &var_reg[digit];
 
1783
    v= var_reg + digit;
1735
1784
 
1736
1785
  eval_expr(v, var_val, (const char**) &var_val_end);
1737
1786
 
2015
2064
    eval_expr(var, value, 0);
2016
2065
  }
2017
2066
  drizzle_result_free(&res);
 
2067
 
 
2068
  return;
2018
2069
}
2019
2070
 
2020
2071
 
2045
2096
{
2046
2097
  if (*p == '$')
2047
2098
  {
2048
 
    VAR *vp= var_get(p, p_end, 0, 0);
2049
 
    if (vp)
 
2099
    VAR *vp;
 
2100
    if ((vp= var_get(p, p_end, 0, 0)))
2050
2101
      var_copy(v, vp);
2051
2102
    return;
2052
2103
  }
2107
2158
  }
2108
2159
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2109
2160
 
 
2161
  if (cur_file == file_stack_end)
 
2162
    die("Source directives are nesting too deep");
2110
2163
  cur_file++;
2111
 
  if (cur_file == &*file_stack.end())
2112
 
    die("Source directives are nesting too deep");
2113
2164
  if (!(cur_file->file= fopen(buff, "r")))
2114
2165
  {
2115
2166
    cur_file--;
2171
2222
}
2172
2223
 
2173
2224
 
2174
 
static void init_builtin_echo()
 
2225
static void init_builtin_echo(void)
2175
2226
{
2176
2227
  builtin_echo[0]= 0;
 
2228
  return;
2177
2229
}
2178
2230
 
2179
2231
 
2425
2477
 
2426
2478
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
2427
2479
  handle_command_error(command, error);
 
2480
  return;
2428
2481
}
2429
2482
 
2430
2483
 
2459
2512
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2460
2513
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2461
2514
  handle_command_error(command, error);
 
2515
  return;
2462
2516
}
2463
2517
 
2464
2518
 
2496
2550
    die("You must write a 4 digit octal number for mode");
2497
2551
 
2498
2552
  handle_command_error(command, chmod(ds_file.c_str(), mode));
 
2553
  return;
2499
2554
}
2500
2555
 
2501
2556
 
2525
2580
 
2526
2581
  error= (access(ds_filename.c_str(), F_OK) != 0);
2527
2582
  handle_command_error(command, error);
 
2583
  return;
2528
2584
}
2529
2585
 
2530
2586
 
2553
2609
 
2554
2610
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
2555
2611
  handle_command_error(command, error);
 
2612
  return;
2556
2613
}
2557
2614
 
2558
2615
/*
2580
2637
 
2581
2638
  error= rmdir(ds_dirname.c_str()) != 0;
2582
2639
  handle_command_error(command, error);
 
2640
  return;
2583
2641
}
2584
2642
 
2585
2643
 
2818
2876
  }
2819
2877
 
2820
2878
  handle_command_error(command, error);
 
2879
  return;
2821
2880
}
2822
2881
 
2823
2882
 
2867
2926
 
2868
2927
  if (drizzle_quit(&con->con,&result, &ret))
2869
2928
    drizzle_result_free(&result);
 
2929
 
 
2930
  return;
2870
2931
}
2871
2932
 
2872
2933
 
2963
3024
  internal::my_delete(temp_file_path, MYF(0));
2964
3025
 
2965
3026
  handle_command_error(command, WEXITSTATUS(error));
 
3027
  return;
2966
3028
}
2967
3029
 
2968
3030
 
3136
3198
  when ndb binlog is on, this call will wait until last updated epoch
3137
3199
  (locally in the drizzled) has been received into the binlog
3138
3200
*/
3139
 
static int do_save_master_pos()
 
3201
static int do_save_master_pos(void)
3140
3202
{
3141
3203
  drizzle_result_st res;
3142
3204
  drizzle_return_t ret;
3252
3314
  bool error= false;
3253
3315
  char *p= command->first_argument;
3254
3316
  char *sleep_start, *sleep_end= command->end;
3255
 
  double sleep_val= 0;
 
3317
  double sleep_val;
3256
3318
 
3257
3319
  while (my_isspace(charset_info, *p))
3258
3320
    p++;
3275
3337
    sleep_val= opt_sleep;
3276
3338
 
3277
3339
  if (sleep_val)
3278
 
    usleep(sleep_val * 1000000);
 
3340
    usleep((uint32_t) (sleep_val * 1000000L));
3279
3341
  command->last_argument= sleep_end;
3280
3342
  return 0;
3281
3343
}
3282
3344
 
3283
3345
 
3284
 
static void do_get_file_name(st_command *command, string &dest)
 
3346
static void do_get_file_name(struct st_command *command, string &dest)
3285
3347
{
3286
 
  char *p= command->first_argument;
 
3348
  char *p= command->first_argument, *name;
3287
3349
  if (!*p)
3288
3350
    die("Missing file name argument");
3289
 
  char *name= p;
 
3351
  name= p;
3290
3352
  while (*p && !my_isspace(charset_info,*p))
3291
3353
    p++;
3292
3354
  if (*p)
3321
3383
    abort_not_supported_test("Test requires charset '%s'", charset_name);
3322
3384
}
3323
3385
 
3324
 
static void fill_global_error_names()
3325
 
{
3326
 
  drizzle_result_st res;
3327
 
  drizzle_return_t ret;
3328
 
  drizzle_row_t row;
3329
 
  drizzle_con_st *con= &cur_con->con;
3330
 
 
3331
 
  global_error_names.clear();
3332
 
 
3333
 
  const std::string ds_query("select error_name, error_code "
3334
 
                             "from data_dictionary.errors");
3335
 
  if (drizzle_query_str(con, &res, ds_query.c_str(), &ret) == NULL ||
3336
 
      ret != DRIZZLE_RETURN_OK)
3337
 
  {
3338
 
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
3339
 
    {
3340
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
3341
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
3342
 
      drizzle_result_free(&res);
3343
 
    }
3344
 
    else
3345
 
    {
3346
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
3347
 
          drizzle_con_error(con));
3348
 
    }
3349
 
  }
3350
 
  if (drizzle_result_column_count(&res) == 0 ||
3351
 
      drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3352
 
  {
3353
 
    drizzle_result_free(&res);
3354
 
    die("Query '%s' didn't return a result set", ds_query.c_str());
3355
 
  }
3356
 
 
3357
 
  while ((row= drizzle_row_next(&res)) && row[0])
3358
 
  {
3359
 
    /*
3360
 
      Concatenate all fields in the first row with tab in between
3361
 
      and assign that string to the $variable
3362
 
    */
3363
 
    size_t *lengths= drizzle_row_field_sizes(&res);
3364
 
    try
3365
 
    {
3366
 
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3367
 
    }
3368
 
    catch (boost::bad_lexical_cast &ex)
3369
 
    {
3370
 
      drizzle_result_free(&res);
3371
 
      die("Invalid error_code from Drizzle: %s", ex.what());
3372
 
    }
3373
 
 
3374
 
  }
3375
 
 
3376
 
  drizzle_result_free(&res);
3377
 
}
3378
 
 
3379
3386
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3380
3387
{
3381
3388
  size_t err_name_len= error_end - error_name;
3382
3389
  string error_name_s(error_name, err_name_len);
3383
3390
 
3384
 
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3385
 
  if (it != global_error_names.end())
3386
 
    return it->second;
3387
 
 
3388
 
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3389
 
  return 0;
 
3391
  uint32_t code= global_error_names.getErrorCode(error_name_s);
 
3392
 
 
3393
  if (!code)
 
3394
    die("Unknown SQL error name '%s'", error_name_s.c_str());
 
3395
 
 
3396
  return(code);
3390
3397
}
3391
3398
 
3392
3399
static void do_get_errcodes(struct st_command *command)
3454
3461
    {
3455
3462
      die("The error name definition must start with an uppercase E");
3456
3463
    }
3457
 
    else if (*p == 'H')
 
3464
    else
3458
3465
    {
3459
 
      /* Error name string */
3460
 
 
3461
 
      to->code.errnum= get_errcode_from_name(p, end);
 
3466
      long val;
 
3467
      char *start= p;
 
3468
      /* Check that the string passed to str2int only contain digits */
 
3469
      while (*p && p != end)
 
3470
      {
 
3471
        if (!my_isdigit(charset_info, *p))
 
3472
          die("Invalid argument to error: '%s' - "              \
 
3473
              "the errno may only consist of digits[0-9]",
 
3474
              command->first_argument);
 
3475
        p++;
 
3476
      }
 
3477
 
 
3478
      /* Convert the sting to int */
 
3479
      istringstream buff(start);
 
3480
      if ((buff >> val).fail())
 
3481
        die("Invalid argument to error: '%s'", command->first_argument);
 
3482
 
 
3483
      to->code.errnum= (uint32_t) val;
3462
3484
      to->type= ERR_ERRNO;
3463
3485
    }
3464
 
    else
3465
 
    {
3466
 
      die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3467
 
    }
3468
3486
    to++;
3469
3487
    count++;
3470
3488
 
3826
3844
{
3827
3845
  uint32_t con_port= opt_port;
3828
3846
  const char *con_options;
3829
 
  bool con_ssl= 0;
 
3847
  bool con_ssl= 0, con_compress= 0;
3830
3848
  struct st_connection* con_slot;
3831
3849
 
3832
3850
  string ds_connection_name;
3892
3910
      end++;
3893
3911
    if (!strncmp(con_options, "SSL", 3))
3894
3912
      con_ssl= 1;
 
3913
    else if (!strncmp(con_options, "COMPRESS", 8))
 
3914
      con_compress= 1;
3895
3915
    else
3896
3916
      die("Illegal option to connect: %.*s",
3897
3917
          (int) (end - con_options), con_options);
3917
3937
    die("Failed on drizzle_create()");
3918
3938
  if (!drizzle_con_create(con_slot->drizzle, &con_slot->con))
3919
3939
    die("Failed on drizzle_con_create()");
3920
 
  drizzle_con_add_options(&con_slot->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
3940
  if (opt_mysql)
 
3941
    drizzle_con_add_options(&con_slot->con, DRIZZLE_CON_MYSQL);
3921
3942
 
3922
3943
  /* Use default db name */
3923
3944
  if (ds_database.length() == 0)
4004
4025
{
4005
4026
  char *p= command->first_argument;
4006
4027
  const char *expr_start, *expr_end;
 
4028
  VAR v;
4007
4029
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4008
4030
  bool not_expr= false;
4009
4031
 
4046
4068
  if (*p && *p != '{')
4047
4069
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4048
4070
 
4049
 
  VAR v;
4050
4071
  var_init(&v,0,0,0,0);
4051
4072
  eval_expr(&v, expr_start, &expr_end);
4052
4073
 
4182
4203
      }
4183
4204
      free((unsigned char*) cur_file->file_name);
4184
4205
      cur_file->file_name= 0;
4185
 
      if (cur_file == file_stack.data())
 
4206
      if (cur_file == file_stack)
4186
4207
      {
4187
4208
        /* We're back at the first file, check if
4188
4209
           all { have matching }
4416
4437
        end++;
4417
4438
      save= *end;
4418
4439
      *end= 0;
4419
 
      type= command_typelib.find_type(start, 1+2);
 
4440
      type= find_type(start, &command_typelib, 1+2);
4420
4441
      if (type)
4421
4442
        warning_msg("Embedded drizzletest command '--%s' detected in "
4422
4443
                    "query '%s' was this intentional? ",
4622
4643
          log_file);
4623
4644
}
4624
4645
 
4625
 
void dump_progress()
 
4646
void dump_progress(void)
4626
4647
{
4627
4648
  char progress_file[FN_REFLEN];
4628
4649
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4632
4653
              ds_progress.c_str(), ds_progress.length());
4633
4654
}
4634
4655
 
4635
 
void dump_warning_messages()
 
4656
void dump_warning_messages(void)
4636
4657
{
4637
4658
  char warn_file[FN_REFLEN];
4638
4659
 
4697
4718
    for (i = 0; i < num_fields; i++)
4698
4719
    {
4699
4720
      column= drizzle_column_next(res);
4700
 
      if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
4701
 
      {
4702
 
        if (boost::lexical_cast<uint32_t>(row[i]))
4703
 
        {
4704
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4705
 
          {
4706
 
            append_field(ds, i, column, "YES", 3, false);
4707
 
          }
4708
 
          else
4709
 
          {
4710
 
            append_field(ds, i, column, "TRUE", 4, false);
4711
 
          }
4712
 
        }
4713
 
        else
4714
 
        {
4715
 
          if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4716
 
          {
4717
 
            append_field(ds, i, column, "NO", 2, false);
4718
 
          }
4719
 
          else
4720
 
          {
4721
 
            append_field(ds, i, column, "FALSE", 5, false);
4722
 
          }
4723
 
        }
4724
 
      }
4725
 
      else
4726
 
      {
4727
 
        append_field(ds, i, column,
4728
 
                     (const char*)row[i], lengths[i], !row[i]);
4729
 
      }
 
4721
      append_field(ds, i, column,
 
4722
                   (const char*)row[i], lengths[i], !row[i]);
4730
4723
    }
4731
4724
    if (!display_result_vertically)
4732
4725
      ds->append("\n");
4770
4763
    ds->append("\t", 1);
4771
4764
    replace_append_uint(ds, drizzle_column_size(column));
4772
4765
    ds->append("\t", 1);
4773
 
    if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
4774
 
    {
4775
 
      replace_append_uint(ds, 1);
4776
 
    }
4777
 
    else
4778
 
    {
4779
 
      replace_append_uint(ds, drizzle_column_max_size(column));
4780
 
    }
 
4766
    replace_append_uint(ds, drizzle_column_max_size(column));
4781
4767
    ds->append("\t", 1);
4782
4768
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4783
4769
    ds->append("\t", 1);
5274
5260
 
5275
5261
  save= command->query[command->first_word_len];
5276
5262
  command->query[command->first_word_len]= 0;
5277
 
  type= command_typelib.find_type(command->query, 1+2);
 
5263
  type= find_type(command->query, &command_typelib, 1+2);
5278
5264
  command->query[command->first_word_len]= save;
5279
5265
  if (type > 0)
5280
5266
  {
5318
5304
        */
5319
5305
        save= command->query[command->first_word_len-1];
5320
5306
        command->query[command->first_word_len-1]= 0;
5321
 
        if (command_typelib.find_type(command->query, 1+2) > 0)
 
5307
        if (find_type(command->query, &command_typelib, 1+2) > 0)
5322
5308
          die("Extra delimiter \";\" found");
5323
5309
        command->query[command->first_word_len-1]= save;
5324
5310
 
5374
5360
{
5375
5361
  if (in_opt_max_connect_retries > 10000 || opt_max_connect_retries<1)
5376
5362
  {
5377
 
    cout << N_("Error: Invalid Value for opt_max_connect_retries"); 
 
5363
    cout<<N_("Error: Invalid Value for opt_max_connect_retries"); 
5378
5364
    exit(-1);
5379
5365
  }
5380
5366
  opt_max_connect_retries= in_opt_max_connect_retries;
5384
5370
{
5385
5371
  if (in_opt_tail_lines > 10000)
5386
5372
  {
5387
 
    cout << N_("Error: Invalid Value for opt_tail_lines"); 
 
5373
    cout<<N_("Error: Invalid Value for opt_tail_lines"); 
5388
5374
    exit(-1);
5389
5375
  }
5390
5376
  opt_tail_lines= in_opt_tail_lines;
5450
5436
  "Directory for log files")
5451
5437
  ("max-connect-retries", po::value<uint32_t>(&opt_max_connect_retries)->default_value(500)->notifier(&check_retries),
5452
5438
  "Max number of connection attempts when connecting to server")
5453
 
  ("quiet,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
 
5439
  ("quiet,s", po::value<bool>(&silent)->default_value(0)->zero_tokens(),
5454
5440
  "Suppress all normal output.")
5455
5441
  ("record,r", "Record output of test_file into result file.")
5456
5442
  ("result-file,R", po::value<string>(&result_file_name)->default_value(""),
5466
5452
 
5467
5453
  ("host,h", po::value<string>(&opt_host)->default_value("localhost"),
5468
5454
  "Connect to host.")
 
5455
  ("mysql,m", po::value<bool>(&opt_mysql)->default_value(true)->zero_tokens(),
 
5456
  N_("Use MySQL Protocol."))
5469
5457
  ("password,P", po::value<string>(&password)->default_value("PASSWORD_SENTINEL"),
5470
5458
  "Password to use when connecting to server.")
5471
5459
  ("port,p", po::value<uint32_t>(&opt_port)->default_value(0),
5472
5460
  "Port number to use for connection or 0 for default")
5473
 
  ("protocol", po::value<string>(&opt_protocol),
5474
 
  "The protocol of connection (mysql or drizzle).")
 
5461
  ("protocol", po::value<string>(),
 
5462
  "The protocol of connection (tcp,socket,pipe,memory).")
5475
5463
  ("user,u", po::value<string>(&opt_user)->default_value(""),
5476
5464
  "User for login.")
5477
5465
  ;
5490
5478
 
5491
5479
  std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5492
5480
 
5493
 
  if (user_config_dir.compare(0, 2, "~/") == 0)
5494
 
  {
5495
 
    const char *homedir= getenv("HOME");
5496
 
    if (homedir != NULL)
5497
 
      user_config_dir.replace(0, 1, homedir);
5498
 
  }
5499
 
 
5500
5481
  po::variables_map vm;
5501
5482
 
5502
 
  // Disable allow_guessing
5503
 
  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
5504
 
 
5505
5483
  po::store(po::command_line_parser(argc, argv).options(long_options).
5506
 
            style(style).positional(p).extra_parser(parse_password_arg).run(),
5507
 
            vm);
 
5484
            positional(p).extra_parser(parse_password_arg).run(), vm);
5508
5485
 
5509
5486
  if (! vm["no-defaults"].as<bool>())
5510
5487
  {
5539
5516
  next_con= connections + 1;
5540
5517
 
5541
5518
  /* Init file stack */
5542
 
  memset(file_stack.data(), 0, sizeof(file_stack));
5543
 
  cur_file= file_stack.data();
 
5519
  memset(file_stack, 0, sizeof(file_stack));
 
5520
  file_stack_end=
 
5521
    file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
 
5522
  cur_file= file_stack;
5544
5523
 
5545
5524
  /* Init block stack */
5546
5525
  memset(block_stack, 0, sizeof(block_stack));
5579
5558
      tmp= buff;
5580
5559
    }
5581
5560
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5582
 
    assert(cur_file == file_stack.data() && cur_file->file == 0);
 
5561
    assert(cur_file == file_stack && cur_file->file == 0);
5583
5562
    if (!(cur_file->file= fopen(buff, "r")))
5584
5563
    {
5585
5564
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5607
5586
    unlink(timer_file);       /* Ignore error, may not exist */
5608
5587
  }
5609
5588
 
5610
 
  if (vm.count("protocol"))
5611
 
  {
5612
 
    std::transform(opt_protocol.begin(), opt_protocol.end(),
5613
 
      opt_protocol.begin(), ::tolower);
5614
 
 
5615
 
    if (not opt_protocol.compare("mysql"))
5616
 
      use_drizzle_protocol=false;
5617
 
    else if (not opt_protocol.compare("drizzle"))
5618
 
      use_drizzle_protocol=true;
5619
 
    else
5620
 
    {
5621
 
      cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
5622
 
      exit(-1);
5623
 
    }
5624
 
  }
5625
 
 
5626
5589
  if (vm.count("port"))
5627
5590
  {
5628
5591
    /* If the port number is > 65535 it is not a valid port
5684
5647
  }
5685
5648
 
5686
5649
  server_initialized= 1;
5687
 
  if (cur_file == file_stack.data() && cur_file->file == 0)
 
5650
  if (cur_file == file_stack && cur_file->file == 0)
5688
5651
  {
5689
5652
    cur_file->file= stdin;
5690
5653
    cur_file->file_name= strdup("<stdin>");
5697
5660
    die("Failed in drizzle_create()");
5698
5661
  if (!( drizzle_con_create(cur_con->drizzle, &cur_con->con)))
5699
5662
    die("Failed in drizzle_con_create()");
5700
 
  drizzle_con_add_options(&cur_con->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
 
5663
  if (opt_mysql)
 
5664
    drizzle_con_add_options(&cur_con->con, DRIZZLE_CON_MYSQL);
5701
5665
 
5702
5666
  if (!(cur_con->name = strdup("default")))
5703
5667
    die("Out of memory");
5704
5668
  safe_connect(&cur_con->con, cur_con->name, opt_host, opt_user, opt_pass,
5705
5669
               opt_db, opt_port);
5706
5670
 
5707
 
  fill_global_error_names();
5708
 
 
5709
5671
  /* Use all time until exit if no explicit 'start_timer' */
5710
5672
  timer_start= timer_now();
5711
5673
 
6109
6071
  the time between executing the two commands.
6110
6072
*/
6111
6073
 
6112
 
void timer_output()
 
6074
void timer_output(void)
6113
6075
{
6114
6076
  if (timer_file)
6115
6077
  {
6123
6085
}
6124
6086
 
6125
6087
 
6126
 
uint64_t timer_now()
 
6088
uint64_t timer_now(void)
6127
6089
{
6128
6090
#if defined(HAVE_GETHRTIME)
6129
6091
  return gethrtime()/1000/1000;
6163
6125
  start= buff= (char *)malloc(strlen(from)+1);
6164
6126
  while (*from)
6165
6127
  {
 
6128
    char *to;
6166
6129
    uint32_t column_number;
6167
6130
 
6168
 
    char *to= get_string(&buff, &from, command);
 
6131
    to= get_string(&buff, &from, command);
6169
6132
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6170
6133
      die("Wrong column number to replace_column in '%s'", command->query);
6171
6134
    if (!*from)
6184
6147
 
6185
6148
void free_replace_column()
6186
6149
{
6187
 
  for (uint32_t i= 0 ; i < max_replace_column; i++)
 
6150
  uint32_t i;
 
6151
  for (i=0 ; i < max_replace_column ; i++)
6188
6152
  {
6189
 
    free(replace_column[i]);
6190
 
    replace_column[i]= 0;
 
6153
    if (replace_column[i])
 
6154
    {
 
6155
      free(replace_column[i]);
 
6156
      replace_column[i]= 0;
 
6157
    }
6191
6158
  }
6192
6159
  max_replace_column= 0;
6193
6160
}
6208
6175
} POINTER_ARRAY;
6209
6176
 
6210
6177
struct st_replace;
6211
 
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6212
 
                                char *word_end_chars);
 
6178
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
6179
                                char * word_end_chars);
6213
6180
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6214
6181
void replace_strings_append(struct st_replace *rep, string* ds,
6215
6182
                            const char *from, int len);
 
6183
void free_pointer_array(POINTER_ARRAY *pa);
6216
6184
 
6217
 
st_replace *glob_replace= NULL;
6218
 
// boost::scoped_ptr<st_replace> glob_replace;
 
6185
struct st_replace *glob_replace= NULL;
6219
6186
 
6220
6187
/*
6221
6188
  Get arguments for replace. The syntax is:
6225
6192
  variable is replaced.
6226
6193
*/
6227
6194
 
6228
 
static void free_pointer_array(POINTER_ARRAY *pa)
6229
 
{
6230
 
  if (!pa->typelib.count)
6231
 
    return;
6232
 
  pa->typelib.count=0;
6233
 
  free((char*) pa->typelib.type_names);
6234
 
  pa->typelib.type_names=0;
6235
 
  free(pa->str);
6236
 
}
6237
 
 
6238
6195
void do_get_replace(struct st_command *command)
6239
6196
{
6240
6197
  uint32_t i;
6266
6223
    if (my_isspace(charset_info,i))
6267
6224
      *pos++= i;
6268
6225
  *pos=0;          /* End pointer */
6269
 
  if (!(glob_replace= init_replace(from_array.typelib.type_names,
6270
 
                                   to_array.typelib.type_names,
6271
 
                                   from_array.typelib.count,
 
6226
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
 
6227
                                   (char**) to_array.typelib.type_names,
 
6228
                                   (uint32_t) from_array.typelib.count,
6272
6229
                                   word_end_chars)))
6273
6230
    die("Can't initialize replace from '%s'", command->query);
6274
6231
  free_pointer_array(&from_array);
6281
6238
 
6282
6239
void free_replace()
6283
6240
{
6284
 
  free(glob_replace);
6285
 
  glob_replace=0;
 
6241
 
 
6242
  if (glob_replace)
 
6243
  {
 
6244
    free(glob_replace);
 
6245
    glob_replace=0;
 
6246
  }
 
6247
  return;
6286
6248
}
6287
6249
 
6288
6250
 
6302
6264
void replace_strings_append(REPLACE *rep, string* ds,
6303
6265
                            const char *str, int len)
6304
6266
{
6305
 
  REPLACE *rep_pos;
6306
 
  REPLACE_STRING *rep_str;
 
6267
  register REPLACE *rep_pos;
 
6268
  register REPLACE_STRING *rep_str;
6307
6269
  const char *start, *from;
6308
6270
 
6309
6271
 
6356
6318
                 i.e. repeat the matching until the end of the string */
6357
6319
};
6358
6320
 
6359
 
class st_replace_regex
 
6321
struct st_replace_regex
6360
6322
{
6361
 
public:
6362
 
  st_replace_regex(char* expr);
6363
 
  int multi_reg_replace(char* val);
 
6323
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
6364
6324
 
6365
6325
  /*
6366
6326
    Temporary storage areas for substitutions. To reduce unnessary copying
6369
6329
    st_regex substition. At the end of substitutions  buf points to the
6370
6330
    one containing the final result.
6371
6331
  */
6372
 
  typedef vector<st_regex> regex_arr_t;
6373
 
 
6374
 
  char* buf_;
 
6332
  char* buf;
6375
6333
  char* even_buf;
6376
6334
  char* odd_buf;
6377
6335
  int even_buf_len;
6378
6336
  int odd_buf_len;
6379
 
  boost::array<char, 8 << 10> buf0_;
6380
 
  boost::array<char, 8 << 10> buf1_;
6381
 
  regex_arr_t regex_arr;
6382
6337
};
6383
6338
 
6384
 
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
 
6339
struct st_replace_regex *glob_replace_regex= 0;
6385
6340
 
6386
6341
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6387
6342
                char *string, int icase, int global);
6423
6378
  Returns: st_replace_regex struct with pairs of substitutions
6424
6379
*/
6425
6380
 
6426
 
st_replace_regex::st_replace_regex(char* expr)
 
6381
static struct st_replace_regex* init_replace_regex(char* expr)
6427
6382
{
 
6383
  struct st_replace_regex* res;
 
6384
  char* buf,*expr_end;
 
6385
  char* p;
 
6386
  char* buf_p;
6428
6387
  uint32_t expr_len= strlen(expr);
6429
6388
  char last_c = 0;
6430
 
  st_regex reg;
6431
 
 
6432
 
  char* buf= new char[expr_len];
6433
 
  char* expr_end= expr + expr_len;
6434
 
  char* p= expr;
6435
 
  char* buf_p= buf;
 
6389
  struct st_regex reg;
 
6390
 
 
6391
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
 
6392
  if (!res)
 
6393
    return NULL;
 
6394
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
 
6395
 
 
6396
  buf= (char*)res + sizeof(*res);
 
6397
  expr_end= expr + expr_len;
 
6398
  p= expr;
 
6399
  buf_p= buf;
6436
6400
 
6437
6401
  /* for each regexp substitution statement */
6438
6402
  while (p < expr_end)
6448
6412
 
6449
6413
    if (p == expr_end || ++p == expr_end)
6450
6414
    {
6451
 
      if (!regex_arr.empty())
 
6415
      if (res->regex_arr.elements)
6452
6416
        break;
6453
6417
      else
6454
6418
        goto err;
6487
6451
      p++;
6488
6452
      reg.global= 1;
6489
6453
    }
6490
 
    regex_arr.push_back(reg);
 
6454
 
 
6455
    /* done parsing the statement, now place it in regex_arr */
 
6456
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6457
      die("Out of memory");
6491
6458
  }
6492
 
  odd_buf_len= even_buf_len= buf0_.size();
6493
 
  even_buf= buf0_.data();
6494
 
  odd_buf= buf1_.data();
6495
 
  buf_= even_buf;
 
6459
  res->odd_buf_len= res->even_buf_len= 8192;
 
6460
  res->even_buf= (char*)malloc(res->even_buf_len);
 
6461
  res->odd_buf= (char*)malloc(res->odd_buf_len);
 
6462
  res->buf= res->even_buf;
6496
6463
 
6497
 
  return;
 
6464
  return res;
6498
6465
 
6499
6466
err:
 
6467
  free(res);
6500
6468
  die("Error parsing replace_regex \"%s\"", expr);
 
6469
  return 0;
6501
6470
}
6502
6471
 
6503
6472
/*
6519
6488
  in one pass
6520
6489
*/
6521
6490
 
6522
 
int st_replace_regex::multi_reg_replace(char* val)
 
6491
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6523
6492
{
6524
 
  char* in_buf= val;
6525
 
  char* out_buf= even_buf;
6526
 
  int* buf_len_p= &even_buf_len;
6527
 
  buf_= 0;
 
6493
  uint32_t i;
 
6494
  char* in_buf, *out_buf;
 
6495
  int* buf_len_p;
 
6496
 
 
6497
  in_buf= val;
 
6498
  out_buf= r->even_buf;
 
6499
  buf_len_p= &r->even_buf_len;
 
6500
  r->buf= 0;
6528
6501
 
6529
6502
  /* For each substitution, do the replace */
6530
 
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
 
6503
  for (i= 0; i < r->regex_arr.elements; i++)
6531
6504
  {
 
6505
    struct st_regex re;
6532
6506
    char* save_out_buf= out_buf;
6533
 
    if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6534
 
                     in_buf, i.icase, i.global))
 
6507
 
 
6508
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6509
 
 
6510
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
 
6511
                     in_buf, re.icase, re.global))
6535
6512
    {
6536
6513
      /* if the buffer has been reallocated, make adjustements */
6537
6514
      if (save_out_buf != out_buf)
6538
6515
      {
6539
 
        if (save_out_buf == even_buf)
6540
 
          even_buf= out_buf;
 
6516
        if (save_out_buf == r->even_buf)
 
6517
          r->even_buf= out_buf;
6541
6518
        else
6542
 
          odd_buf= out_buf;
 
6519
          r->odd_buf= out_buf;
6543
6520
      }
6544
 
      buf_= out_buf;
 
6521
 
 
6522
      r->buf= out_buf;
6545
6523
      if (in_buf == val)
6546
 
        in_buf= odd_buf;
6547
 
      std::swap(in_buf, out_buf);
6548
 
      buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
 
6524
        in_buf= r->odd_buf;
 
6525
 
 
6526
      std::swap(in_buf,out_buf);
 
6527
 
 
6528
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
 
6529
        &r->odd_buf_len;
6549
6530
    }
6550
6531
  }
6551
 
  return buf_ == 0;
 
6532
 
 
6533
  return (r->buf == 0);
6552
6534
}
6553
6535
 
6554
6536
/*
6563
6545
void do_get_replace_regex(struct st_command *command)
6564
6546
{
6565
6547
  char *expr= command->first_argument;
6566
 
  glob_replace_regex.reset(new st_replace_regex(expr));
 
6548
  free_replace_regex();
 
6549
  if (!(glob_replace_regex=init_replace_regex(expr)))
 
6550
    die("Could not init replace_regex");
6567
6551
  command->last_argument= command->end;
6568
6552
}
6569
6553
 
 
6554
void free_replace_regex()
 
6555
{
 
6556
  if (glob_replace_regex)
 
6557
  {
 
6558
    delete_dynamic(&glob_replace_regex->regex_arr);
 
6559
    free(glob_replace_regex->even_buf);
 
6560
    free(glob_replace_regex->odd_buf);
 
6561
    free(glob_replace_regex);
 
6562
    glob_replace_regex=0;
 
6563
  }
 
6564
}
 
6565
 
 
6566
 
 
6567
 
6570
6568
/*
6571
6569
  Performs a regex substitution
6572
6570
 
6630
6628
    /* Repeatedly replace the string with the matched regex */
6631
6629
    string subject(in_string);
6632
6630
    size_t replace_length= strlen(replace);
6633
 
    size_t length_of_replacement= strlen(replace);
6634
6631
    size_t current_position= 0;
6635
6632
    int rc= 0;
6636
 
 
6637
 
    while (true) 
 
6633
    while(0 >= (rc= pcre_exec(re, NULL, subject.c_str() + current_position, subject.length() - current_position,
 
6634
                      0, 0, ovector, 3)))
6638
6635
    {
6639
 
      rc= pcre_exec(re, NULL, subject.c_str(), subject.length(), 
6640
 
                    current_position, 0, ovector, 3);
6641
 
      if (rc < 0)
6642
 
      {
6643
 
        break;
6644
 
      }
6645
 
 
6646
6636
      current_position= static_cast<size_t>(ovector[0]);
6647
6637
      replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
6648
 
      subject.replace(current_position, replace_length, replace, length_of_replacement);
6649
 
      current_position= current_position + length_of_replacement;
 
6638
      subject.replace(current_position, replace_length, replace, replace_length);
6650
6639
    }
6651
6640
 
6652
6641
    char *new_buf = (char *) malloc(subject.length() + 1);
6673
6662
#define SET_MALLOC_HUNC 64
6674
6663
#define LAST_CHAR_CODE 259
6675
6664
 
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
 
 
 
6665
typedef struct st_rep_set {
6686
6666
  uint32_t  *bits;        /* Pointer to used sets */
6687
6667
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6688
6668
  uint32_t  found_len;      /* Best match to date */
6689
6669
  int  found_offset;
6690
6670
  uint32_t  table_offset;
6691
6671
  uint32_t  size_of_bits;      /* For convinience */
6692
 
};
6693
 
 
6694
 
class REP_SETS
6695
 
{
6696
 
public:
6697
 
  int find_set(const REP_SET *find);
6698
 
  void free_last_set();
6699
 
  void free_sets();
6700
 
  void make_sets_invisible();
6701
 
 
 
6672
} REP_SET;
 
6673
 
 
6674
typedef struct st_rep_sets {
6702
6675
  uint32_t    count;      /* Number of sets */
6703
6676
  uint32_t    extra;      /* Extra sets in buffer */
6704
 
  uint32_t    invisible;    /* Sets not shown */
 
6677
  uint32_t    invisible;    /* Sets not chown */
6705
6678
  uint32_t    size_of_bits;
6706
6679
  REP_SET  *set,*set_buffer;
6707
6680
  uint32_t    *bit_buffer;
6708
 
};
 
6681
} REP_SETS;
6709
6682
 
6710
 
struct FOUND_SET 
6711
 
{
 
6683
typedef struct st_found_set {
6712
6684
  uint32_t table_offset;
6713
6685
  int found_offset;
6714
 
};
 
6686
} FOUND_SET;
6715
6687
 
6716
 
struct FOLLOWS
6717
 
{
 
6688
typedef struct st_follow {
6718
6689
  int chr;
6719
6690
  uint32_t table_offset;
6720
6691
  uint32_t len;
6721
 
};
6722
 
 
6723
 
int init_sets(REP_SETS *sets, uint32_t states);
 
6692
} FOLLOWS;
 
6693
 
 
6694
 
 
6695
int init_sets(REP_SETS *sets,uint32_t states);
6724
6696
REP_SET *make_new_set(REP_SETS *sets);
6725
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6726
 
 
6727
 
static uint32_t found_sets= 0;
6728
 
 
6729
 
static uint32_t replace_len(const char *str)
 
6697
void make_sets_invisible(REP_SETS *sets);
 
6698
void free_last_set(REP_SETS *sets);
 
6699
void free_sets(REP_SETS *sets);
 
6700
void internal_set_bit(REP_SET *set, uint32_t bit);
 
6701
void internal_clear_bit(REP_SET *set, uint32_t bit);
 
6702
void or_bits(REP_SET *to,REP_SET *from);
 
6703
void copy_bits(REP_SET *to,REP_SET *from);
 
6704
int cmp_bits(REP_SET *set1,REP_SET *set2);
 
6705
int get_next_bit(REP_SET *set,uint32_t lastpos);
 
6706
int find_set(REP_SETS *sets,REP_SET *find);
 
6707
int find_found(FOUND_SET *found_set,uint32_t table_offset,
 
6708
               int found_offset);
 
6709
uint32_t start_at_word(char * pos);
 
6710
uint32_t end_of_word(char * pos);
 
6711
 
 
6712
static uint32_t found_sets=0;
 
6713
 
 
6714
 
 
6715
static uint32_t replace_len(char * str)
6730
6716
{
6731
6717
  uint32_t len=0;
6732
6718
  while (*str)
6739
6725
  return len;
6740
6726
}
6741
6727
 
6742
 
/* Return 1 if regexp starts with \b or ends with \b*/
6743
 
 
6744
 
static bool start_at_word(const char *pos)
6745
 
{
6746
 
  return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6747
 
}
6748
 
 
6749
 
static bool end_of_word(const char *pos)
6750
 
{
6751
 
  const char *end= strchr(pos, '\0');
6752
 
  return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6753
 
}
6754
 
 
6755
6728
/* Init a replace structure for further calls */
6756
6729
 
6757
 
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
 
6730
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6731
                      char * word_end_chars)
6758
6732
{
6759
 
  const int SPACE_CHAR= 256;
6760
 
  const int START_OF_LINE= 257;
6761
 
  const int END_OF_LINE= 258;
 
6733
  static const int SPACE_CHAR= 256;
 
6734
  static const int START_OF_LINE= 257;
 
6735
  static const int END_OF_LINE= 258;
6762
6736
 
6763
6737
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6764
6738
  int used_sets,chr,default_state;
6765
6739
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6766
 
  char *to_pos, **to_array;
 
6740
  char * pos, *to_pos, **to_array;
 
6741
  REP_SETS sets;
 
6742
  REP_SET *set,*start_states,*word_states,*new_set;
 
6743
  FOLLOWS *follow,*follow_ptr;
 
6744
  REPLACE *replace;
 
6745
  FOUND_SET *found_set;
 
6746
  REPLACE_STRING *rep_str;
 
6747
 
6767
6748
 
6768
6749
  /* Count number of states */
6769
6750
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6783
6764
  for (i=0 ; word_end_chars[i] ; i++)
6784
6765
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6785
6766
 
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;
 
6767
  if (init_sets(&sets,states))
 
6768
    return(0);
6791
6769
  found_sets=0;
6792
 
  vector<FOUND_SET> found_set(max_length * count);
 
6770
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
 
6771
                                
 
6772
  {
 
6773
    free_sets(&sets);
 
6774
    return(0);
 
6775
  }
6793
6776
  make_new_set(&sets);      /* Set starting set */
6794
 
  sets.make_sets_invisible();      /* Hide previus sets */
 
6777
  make_sets_invisible(&sets);      /* Hide previus sets */
6795
6778
  used_sets=-1;
6796
6779
  word_states=make_new_set(&sets);    /* Start of new word */
6797
6780
  start_states=make_new_set(&sets);    /* This is first state */
6798
 
  vector<FOLLOWS> follow(states + 2);
6799
 
  FOLLOWS *follow_ptr= &follow[1];
 
6781
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6782
  {
 
6783
    free_sets(&sets);
 
6784
    free(found_set);
 
6785
    return(0);
 
6786
  }
 
6787
 
6800
6788
  /* Init follow_ptr[] */
6801
 
  for (i=0, states=1; i < count; i++)
 
6789
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6802
6790
  {
6803
6791
    if (from[i][0] == '\\' && from[i][1] == '^')
6804
6792
    {
6805
 
      start_states->internal_set_bit(states + 1);
 
6793
      internal_set_bit(start_states,states+1);
6806
6794
      if (!from[i][2])
6807
6795
      {
6808
6796
        start_states->table_offset=i;
6811
6799
    }
6812
6800
    else if (from[i][0] == '\\' && from[i][1] == '$')
6813
6801
    {
6814
 
      start_states->internal_set_bit(states);
6815
 
      word_states->internal_set_bit(states);
 
6802
      internal_set_bit(start_states,states);
 
6803
      internal_set_bit(word_states,states);
6816
6804
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6817
6805
      {
6818
6806
        start_states->table_offset=i;
6821
6809
    }
6822
6810
    else
6823
6811
    {
6824
 
      word_states->internal_set_bit(states);
 
6812
      internal_set_bit(word_states,states);
6825
6813
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6826
 
        start_states->internal_set_bit(states + 1);
 
6814
        internal_set_bit(start_states,states+1);
6827
6815
      else
6828
 
        start_states->internal_set_bit(states);
 
6816
        internal_set_bit(start_states,states);
6829
6817
    }
6830
 
    const char *pos;
6831
 
    for (pos= from[i], len=0; *pos ; pos++)
 
6818
    for (pos=from[i], len=0; *pos ; pos++)
6832
6819
    {
6833
6820
      if (*pos == '\\' && *(pos+1))
6834
6821
      {
6871
6858
  }
6872
6859
 
6873
6860
 
6874
 
  for (set_nr=0; set_nr < sets.count ; set_nr++)
 
6861
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6875
6862
  {
6876
6863
    set=sets.set+set_nr;
6877
6864
    default_state= 0;        /* Start from beginning */
6878
6865
 
6879
6866
    /* If end of found-string not found or start-set with current set */
6880
6867
 
6881
 
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
 
6868
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6882
6869
    {
6883
 
      if (!follow[i].chr && !default_state)
6884
 
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
 
6870
      if (!follow[i].chr)
 
6871
      {
 
6872
        if (! default_state)
 
6873
          default_state= find_found(found_set,set->table_offset,
 
6874
                                    set->found_offset+1);
 
6875
      }
6885
6876
    }
6886
 
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
 
6877
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6887
6878
    if (!default_state)
6888
 
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
 
6879
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
6889
6880
 
6890
6881
    /* Find all chars that follows current sets */
6891
6882
    memset(used_chars, 0, sizeof(used_chars));
6892
 
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
 
6883
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6893
6884
    {
6894
6885
      used_chars[follow[i].chr]=1;
6895
6886
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6899
6890
 
6900
6891
    /* Mark word_chars used if \b is in state */
6901
6892
    if (used_chars[SPACE_CHAR])
6902
 
      for (const char *pos= word_end_chars ; *pos ; pos++)
 
6893
      for (pos= word_end_chars ; *pos ; pos++)
6903
6894
        used_chars[(int) (unsigned char) *pos] = 1;
6904
6895
 
6905
6896
    /* Handle other used characters */
6916
6907
        new_set->found_offset=set->found_offset+1;
6917
6908
        found_end=0;
6918
6909
 
6919
 
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
 
6910
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6920
6911
        {
6921
6912
          if (!follow[i].chr || follow[i].chr == chr ||
6922
6913
              (follow[i].chr == SPACE_CHAR &&
6928
6919
                follow[i].len > found_end)
6929
6920
              found_end=follow[i].len;
6930
6921
            if (chr && follow[i].chr)
6931
 
              new_set->internal_set_bit(i + 1);    /* To next set */
 
6922
              internal_set_bit(new_set,i+1);    /* To next set */
6932
6923
            else
6933
 
              new_set->internal_set_bit(i);
 
6924
              internal_set_bit(new_set,i);
6934
6925
          }
6935
6926
        }
6936
6927
        if (found_end)
6937
6928
        {
6938
6929
          new_set->found_len=0;      /* Set for testing if first */
6939
6930
          bits_set=0;
6940
 
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
 
6931
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6941
6932
          {
6942
6933
            if ((follow[i].chr == SPACE_CHAR ||
6943
6934
                 follow[i].chr == END_OF_LINE) && ! chr)
6947
6938
            if (follow[bit_nr-1].len < found_end ||
6948
6939
                (new_set->found_len &&
6949
6940
                 (chr == 0 || !follow[bit_nr].chr)))
6950
 
              new_set->internal_clear_bit(i);
 
6941
              internal_clear_bit(new_set,i);
6951
6942
            else
6952
6943
            {
6953
6944
              if (chr == 0 || !follow[bit_nr].chr)
6963
6954
          }
6964
6955
          if (bits_set == 1)
6965
6956
          {
6966
 
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6967
 
            sets.free_last_set();
 
6957
            set->next[chr] = find_found(found_set,
 
6958
                                        new_set->table_offset,
 
6959
                                        new_set->found_offset);
 
6960
            free_last_set(&sets);
6968
6961
          }
6969
6962
          else
6970
 
            set->next[chr] = sets.find_set(new_set);
 
6963
            set->next[chr] = find_set(&sets,new_set);
6971
6964
        }
6972
6965
        else
6973
 
          set->next[chr] = sets.find_set(new_set);
 
6966
          set->next[chr] = find_set(&sets,new_set);
6974
6967
      }
6975
6968
    }
6976
6969
  }
6977
6970
 
6978
6971
  /* Alloc replace structure for the replace-state-machine */
6979
6972
 
6980
 
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6981
 
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
6982
 
  if (replace)
 
6973
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
 
6974
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
 
6975
                                 sizeof(char *)*count+result_len)))
6983
6976
  {
6984
6977
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6985
6978
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6996
6989
    rep_str[0].replace_string=0;
6997
6990
    for (i=1 ; i <= found_sets ; i++)
6998
6991
    {
6999
 
      const char *pos= from[found_set[i-1].table_offset];
 
6992
      pos=from[found_set[i-1].table_offset];
7000
6993
      rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7001
 
      rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
7002
 
      rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
7003
 
      rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
 
6994
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
 
6995
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
 
6996
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
 
6997
        end_of_word(pos);
7004
6998
    }
7005
6999
    for (i=0 ; i < sets.count ; i++)
7006
7000
    {
7011
7005
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7012
7006
    }
7013
7007
  }
7014
 
  sets.free_sets();
7015
 
  return replace;
 
7008
  free(follow);
 
7009
  free_sets(&sets);
 
7010
  free(found_set);
 
7011
  return(replace);
7016
7012
}
7017
7013
 
7018
7014
 
7033
7029
 
7034
7030
/* Make help sets invisible for nicer codeing */
7035
7031
 
7036
 
void REP_SETS::make_sets_invisible()
 
7032
void make_sets_invisible(REP_SETS *sets)
7037
7033
{
7038
 
  invisible= count;
7039
 
  set += count;
7040
 
  count= 0;
 
7034
  sets->invisible=sets->count;
 
7035
  sets->set+=sets->count;
 
7036
  sets->count=0;
7041
7037
}
7042
7038
 
7043
7039
REP_SET *make_new_set(REP_SETS *sets)
7075
7071
  return make_new_set(sets);
7076
7072
}
7077
7073
 
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
 
}
 
7074
void free_last_set(REP_SETS *sets)
 
7075
{
 
7076
  sets->count--;
 
7077
  sets->extra++;
 
7078
  return;
 
7079
}
 
7080
 
 
7081
void free_sets(REP_SETS *sets)
 
7082
{
 
7083
  free(sets->set_buffer);
 
7084
  free(sets->bit_buffer);
 
7085
  return;
 
7086
}
 
7087
 
 
7088
void internal_set_bit(REP_SET *set, uint32_t bit)
 
7089
{
 
7090
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
7091
  return;
 
7092
}
 
7093
 
 
7094
void internal_clear_bit(REP_SET *set, uint32_t bit)
 
7095
{
 
7096
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
7097
  return;
 
7098
}
 
7099
 
 
7100
 
 
7101
void or_bits(REP_SET *to,REP_SET *from)
 
7102
{
 
7103
  register uint32_t i;
 
7104
  for (i=0 ; i < to->size_of_bits ; i++)
 
7105
    to->bits[i]|=from->bits[i];
 
7106
  return;
 
7107
}
 
7108
 
 
7109
void copy_bits(REP_SET *to,REP_SET *from)
 
7110
{
 
7111
  memcpy(to->bits,from->bits,
 
7112
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
 
7113
}
 
7114
 
 
7115
int cmp_bits(REP_SET *set1,REP_SET *set2)
 
7116
{
 
7117
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
 
7118
}
 
7119
 
7116
7120
 
7117
7121
/* Get next set bit from set. */
7118
7122
 
7119
 
int REP_SET::get_next_bit(uint32_t lastpos) const
 
7123
int get_next_bit(REP_SET *set,uint32_t lastpos)
7120
7124
{
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)
 
7125
  uint32_t pos,*start,*end,bits;
 
7126
 
 
7127
  start=set->bits+ ((lastpos+1) / WORD_BIT);
 
7128
  end=set->bits + set->size_of_bits;
 
7129
  bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
7130
 
 
7131
  while (! bits && ++start < end)
 
7132
    bits=start[0];
 
7133
  if (!bits)
7128
7134
    return 0;
7129
 
  uint32_t pos= (start - bits) * WORD_BIT;
7130
 
  while (!(bits0 & 1))
 
7135
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
7136
  while (! (bits & 1))
7131
7137
  {
7132
 
    bits0 >>=1;
 
7138
    bits>>=1;
7133
7139
    pos++;
7134
7140
  }
7135
7141
  return pos;
7139
7145
   free given set, else put in given set in sets and return its
7140
7146
   position */
7141
7147
 
7142
 
int REP_SETS::find_set(const REP_SET *find)
 
7148
int find_set(REP_SETS *sets,REP_SET *find)
7143
7149
{
7144
 
  uint32_t i= 0;
7145
 
  for (; i < count - 1; i++)
 
7150
  uint32_t i;
 
7151
  for (i=0 ; i < sets->count-1 ; i++)
7146
7152
  {
7147
 
    if (!set[i].cmp_bits(find))
 
7153
    if (!cmp_bits(sets->set+i,find))
7148
7154
    {
7149
 
      free_last_set();
 
7155
      free_last_set(sets);
7150
7156
      return i;
7151
7157
    }
7152
7158
  }
7160
7166
   set->next[] == -1 is reserved for end without replaces.
7161
7167
*/
7162
7168
 
7163
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
 
7169
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7164
7170
{
7165
 
  uint32_t i= 0;
7166
 
  for (; i < found_sets; i++)
7167
 
  {
 
7171
  int i;
 
7172
  for (i=0 ; (uint32_t) i < found_sets ; i++)
7168
7173
    if (found_set[i].table_offset == table_offset &&
7169
7174
        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;
 
7175
      return -i-2;
 
7176
  found_set[i].table_offset=table_offset;
 
7177
  found_set[i].found_offset=found_offset;
7174
7178
  found_sets++;
7175
 
  return - i - 2; // return new postion
 
7179
  return -i-2;        /* return new postion */
 
7180
}
 
7181
 
 
7182
/* Return 1 if regexp starts with \b or ends with \b*/
 
7183
 
 
7184
uint32_t start_at_word(char * pos)
 
7185
{
 
7186
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
 
7187
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
7188
}
 
7189
 
 
7190
uint32_t end_of_word(char * pos)
 
7191
{
 
7192
  char * end= strchr(pos, '\0');
 
7193
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
 
7194
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7176
7195
}
7177
7196
 
7178
7197
/****************************************************************************
7251
7270
} /* insert_pointer_name */
7252
7271
 
7253
7272
 
 
7273
/* free pointer array */
 
7274
 
 
7275
void free_pointer_array(POINTER_ARRAY *pa)
 
7276
{
 
7277
  if (pa->typelib.count)
 
7278
  {
 
7279
    pa->typelib.count=0;
 
7280
    free((char*) pa->typelib.type_names);
 
7281
    pa->typelib.type_names=0;
 
7282
    free(pa->str);
 
7283
  }
 
7284
} /* free_pointer_array */
 
7285
 
 
7286
 
7254
7287
/* Functions that uses replace and replace_regex */
7255
7288
 
7256
7289
/* Append the string to ds, with optional replace */
7257
 
void replace_append_mem(string *ds, const char *val, int len)
 
7290
void replace_append_mem(string *ds,
 
7291
                        const char *val, int len)
7258
7292
{
7259
7293
  char *v= strdup(val);
7260
7294
 
7261
 
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
 
7295
  if (glob_replace_regex)
7262
7296
  {
7263
 
    v= glob_replace_regex->buf_;
7264
 
    len= strlen(v);
 
7297
    /* Regex replace */
 
7298
    if (!multi_reg_replace(glob_replace_regex, v))
 
7299
    {
 
7300
      v= glob_replace_regex->buf;
 
7301
      len= strlen(v);
 
7302
    }
7265
7303
  }
 
7304
 
7266
7305
  if (glob_replace)
7267
7306
  {
7268
7307
    /* Normal replace */
7269
7308
    replace_strings_append(glob_replace, ds, v, len);
7270
7309
  }
7271
7310
  else
 
7311
  {
7272
7312
    ds->append(v, len);
 
7313
  }
7273
7314
}
7274
7315
 
7275
7316
 
7338
7379
 
7339
7380
  return;
7340
7381
}
7341
 
 
7342
 
static void free_all_replace()
7343
 
{
7344
 
  free_replace();
7345
 
  glob_replace_regex.reset();
7346
 
  free_replace_column();
7347
 
}