~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
#include <sys/stat.h>
57
57
#include <sys/types.h>
58
58
#include <fcntl.h>
59
 
#include <boost/array.hpp>
60
 
#include <boost/foreach.hpp>
61
59
#include <boost/program_options.hpp>
62
 
#include <boost/smart_ptr.hpp>
63
60
 
64
61
#include PCRE_HEADER
65
62
 
67
64
#include <boost/unordered_map.hpp>
68
65
 
69
66
/* Added this for string translation. */
70
 
#include <drizzled/gettext.h>
71
 
#include <drizzled/type/time.h>
72
 
#include <drizzled/charset.h>
73
 
#include <drizzled/typelib.h>
 
67
#include "drizzled/gettext.h"
 
68
#include "drizzled/type/time.h"
 
69
#include "drizzled/charset.h"
 
70
#include "drizzled/typelib.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
121
116
static bool is_windows= false;
122
117
static bool use_drizzle_protocol= false;
123
118
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
124
 
static void free_all_replace();
125
119
 
126
120
std::string opt_basedir,
127
121
  opt_charsets_dir,
171
165
  uint32_t lineno; /* Current line in file */
172
166
};
173
167
 
174
 
static boost::array<st_test_file, 16> file_stack;
175
 
static st_test_file* cur_file;
 
168
static struct st_test_file file_stack[16];
 
169
static struct st_test_file* cur_file;
 
170
static struct st_test_file* file_stack_end;
 
171
 
176
172
 
177
173
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
178
174
 
182
178
*/
183
179
static char *timer_file = NULL;
184
180
static uint64_t timer_start;
185
 
static void timer_output();
186
 
static uint64_t timer_now();
 
181
static void timer_output(void);
 
182
static uint64_t timer_now(void);
187
183
 
188
184
static uint64_t progress_start= 0;
189
185
 
204
200
 
205
201
/* if set, all results are concated and compared against this file */
206
202
 
207
 
class VAR
 
203
typedef struct st_var
208
204
{
209
 
public:
210
205
  char *name;
211
206
  int name_len;
212
207
  char *str_val;
216
211
  int int_dirty; /* do not update string if int is updated until first read */
217
212
  int alloced;
218
213
  char *env_s;
219
 
};
 
214
} VAR;
220
215
 
221
216
/*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;
 
217
VAR var_reg[10];
 
218
 
 
219
 
 
220
boost::unordered_map<string, VAR *> var_hash;
226
221
 
227
222
struct st_connection
228
223
{
395
390
  struct st_match_err err[10];
396
391
  uint32_t count;
397
392
};
398
 
 
399
 
static st_expected_errors saved_expected_errors;
400
 
 
401
 
class st_command
 
393
static struct st_expected_errors saved_expected_errors;
 
394
 
 
395
struct st_command
402
396
{
403
 
public:
404
397
  char *query, *query_buf,*first_argument,*last_argument,*end;
405
398
  int first_word_len, query_len;
406
399
  bool abort_on_error;
407
400
  st_expected_errors expected_errors;
408
401
  string require_file;
409
 
  enum_commands type;
 
402
  enum enum_commands type;
410
403
 
411
404
  st_command()
412
405
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
418
411
 
419
412
  ~st_command()
420
413
  {
421
 
    free(query_buf);
 
414
    if (query_buf != NULL)
 
415
    {
 
416
      free(query_buf);
 
417
    }
422
418
  }
423
419
};
424
420
 
443
439
VAR* var_from_env(const char *, const char *);
444
440
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
445
441
              int val_len);
 
442
void var_free(pair<string, VAR*> v);
446
443
VAR* var_get(const char *var_name, const char** var_name_end,
447
444
             bool raw, bool ignore_not_existing);
448
445
void eval_expr(VAR* v, const char *p, const char** p_end);
449
446
bool match_delimiter(int c, const char *delim, uint32_t length);
450
447
void dump_result_to_reject_file(char *buf, int size);
451
448
void dump_result_to_log_file(const char *buf, int size);
452
 
void dump_warning_messages();
453
 
void dump_progress();
 
449
void dump_warning_messages(void);
 
450
void dump_progress(void);
454
451
 
455
452
void do_eval(string *query_eval, const char *query,
456
453
             const char *query_end, bool pass_through_escape_chars);
461
458
static char *replace_column[MAX_COLUMNS];
462
459
static uint32_t max_replace_column= 0;
463
460
void do_get_replace_column(struct st_command*);
464
 
void free_replace_column();
 
461
void free_replace_column(void);
465
462
 
466
463
/* For replace */
467
464
void do_get_replace(struct st_command *command);
468
 
void free_replace();
 
465
void free_replace(void);
469
466
 
470
467
/* For replace_regex */
471
468
void do_get_replace_regex(struct st_command *command);
 
469
void free_replace_regex(void);
 
470
 
 
471
 
 
472
void free_all_replace(void);
 
473
 
 
474
 
 
475
void free_all_replace(void){
 
476
  free_replace();
 
477
  free_replace_regex();
 
478
  free_replace_column();
 
479
}
472
480
 
473
481
void replace_append_mem(string *ds, const char *val,
474
482
                        int len);
485
493
void do_eval(string *query_eval, const char *query,
486
494
             const char *query_end, bool pass_through_escape_chars)
487
495
{
488
 
  char c, next_c;
489
 
  int escaped = 0;
 
496
  const char *p;
 
497
  register char c, next_c;
 
498
  register int escaped = 0;
490
499
  VAR *v;
491
500
 
492
 
  for (const char *p= query; (c= *p) && p < query_end; ++p)
 
501
 
 
502
  for (p= query; (c= *p) && p < query_end; ++p)
493
503
  {
494
504
    switch(c) {
495
505
    case '$':
863
873
}
864
874
 
865
875
 
866
 
static void close_connections()
 
876
static void close_connections(void)
867
877
{
868
878
  for (--next_con; next_con >= connections; --next_con)
869
879
  {
874
884
    }
875
885
    free(next_con->name);
876
886
  }
 
887
  return;
877
888
}
878
889
 
879
890
 
880
 
static void close_files()
 
891
static void close_files(void)
881
892
{
882
 
  for (; cur_file >= file_stack.data(); cur_file--)
 
893
 
 
894
  for (; cur_file >= file_stack; cur_file--)
883
895
  {
884
896
    if (cur_file->file && cur_file->file != stdin)
 
897
    {
885
898
      fclose(cur_file->file);
886
 
    free(const_cast<char*>(cur_file->file_name));
 
899
    }
 
900
    free((unsigned char*) cur_file->file_name);
887
901
    cur_file->file_name= 0;
888
902
  }
 
903
  return;
889
904
}
890
905
 
891
 
static void free_used_memory()
 
906
 
 
907
static void free_used_memory(void)
892
908
{
 
909
  uint32_t i;
 
910
 
 
911
 
893
912
  close_connections();
894
913
  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
 
  }
 
914
  for_each(var_hash.begin(), var_hash.end(), var_free);
902
915
  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++)
 
916
 
 
917
  vector<st_command *>::iterator iter;
 
918
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
 
919
  {
 
920
    struct st_command * q_line= *iter;
 
921
    delete q_line;
 
922
  }
 
923
 
 
924
  for (i= 0; i < 10; i++)
906
925
  {
907
926
    if (var_reg[i].alloced_len)
908
927
      free(var_reg[i].str_val);
909
928
  }
 
929
 
910
930
  free_all_replace();
911
931
  free(opt_pass);
 
932
 
 
933
  return;
912
934
}
913
935
 
914
936
 
933
955
      assert(0);
934
956
    }
935
957
  }
 
958
 
936
959
  exit(exit_code);
937
960
}
938
961
 
952
975
 
953
976
  /* Print the error message */
954
977
  fprintf(stderr, "drizzletest: ");
955
 
  if (cur_file && cur_file != file_stack.data())
 
978
  if (cur_file && cur_file != file_stack)
956
979
    fprintf(stderr, "In included file \"%s\": ",
957
980
            cur_file->file_name);
958
981
  if (start_lineno > 0)
1013
1036
 
1014
1037
  /* Print include filestack */
1015
1038
  fprintf(stderr, "The test '%s' is not supported by this installation\n",
1016
 
          file_stack[0].file_name);
 
1039
          file_stack->file_name);
1017
1040
  fprintf(stderr, "Detected in file %s at line %d\n",
1018
1041
          err_file->file_name, err_file->lineno);
1019
 
  while (err_file != file_stack.data())
 
1042
  while (err_file != file_stack)
1020
1043
  {
1021
1044
    err_file--;
1022
1045
    fprintf(stderr, "included from %s at line %d\n",
1047
1070
 
1048
1071
  va_start(args, fmt);
1049
1072
  fprintf(stderr, "drizzletest: ");
1050
 
  if (cur_file && cur_file != file_stack.data())
 
1073
  if (cur_file && cur_file != file_stack)
1051
1074
    fprintf(stderr, "In included file \"%s\": ",
1052
1075
            cur_file->file_name);
1053
1076
  if (start_lineno != 0)
1055
1078
  vfprintf(stderr, fmt, args);
1056
1079
  fprintf(stderr, "\n");
1057
1080
  va_end(args);
 
1081
 
 
1082
  return;
1058
1083
}
1059
1084
 
1060
1085
 
1070
1095
  if (start_lineno != 0)
1071
1096
  {
1072
1097
    ds_warning_messages.append("Warning detected ");
1073
 
    if (cur_file && cur_file != file_stack.data())
 
1098
    if (cur_file && cur_file != file_stack)
1074
1099
    {
1075
1100
      len= snprintf(buff, sizeof(buff), "in included file %s ",
1076
1101
                    cur_file->file_name);
1603
1628
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1604
1629
              int val_len)
1605
1630
{
 
1631
  int val_alloc_len;
 
1632
  VAR *tmp_var;
1606
1633
  if (!name_len && name)
1607
1634
    name_len = strlen(name);
1608
1635
  if (!val_len && val)
1609
1636
    val_len = strlen(val) ;
1610
 
  VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
 
1637
  val_alloc_len = val_len + 16; /* room to grow */
 
1638
  if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
 
1639
                                               + name_len+1)))
 
1640
    die("Out of memory");
1611
1641
 
1612
 
  tmp_var->name = name ? (char*)&tmp_var[1] : 0;
 
1642
  tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1613
1643
  tmp_var->alloced = (v == 0);
1614
1644
 
1615
 
  int val_alloc_len = val_len + 16; /* room to grow */
1616
 
  tmp_var->str_val = (char*)malloc(val_alloc_len+1);
 
1645
  if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
 
1646
    die("Out of memory");
1617
1647
 
1618
1648
  memcpy(tmp_var->name, name, name_len);
1619
1649
  if (val)
1624
1654
  tmp_var->name_len = name_len;
1625
1655
  tmp_var->str_val_len = val_len;
1626
1656
  tmp_var->alloced_len = val_alloc_len;
1627
 
  tmp_var->int_val = val ? atoi(val) : 0;
1628
 
  tmp_var->int_dirty = false;
 
1657
  tmp_var->int_val = (val) ? atoi(val) : 0;
 
1658
  tmp_var->int_dirty = 0;
1629
1659
  tmp_var->env_s = 0;
1630
1660
  return tmp_var;
1631
1661
}
1632
1662
 
 
1663
 
 
1664
void var_free(pair<string, VAR *> v)
 
1665
{
 
1666
  free(v.second->str_val);
 
1667
  free(v.second->env_s);
 
1668
  if (v.second->alloced)
 
1669
    free(v.second);
 
1670
}
 
1671
 
 
1672
 
1633
1673
VAR* var_from_env(const char *name, const char *def_val)
1634
1674
{
1635
 
  const char *tmp= getenv(name);
1636
 
  if (!tmp)
 
1675
  const char *tmp;
 
1676
  VAR *v;
 
1677
  if (!(tmp = getenv(name)))
1637
1678
    tmp = def_val;
1638
 
  return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1679
 
 
1680
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
 
1681
  string var_name(name);
 
1682
  var_hash.insert(make_pair(var_name, v));
 
1683
  return v;
1639
1684
}
1640
1685
 
 
1686
 
1641
1687
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1642
1688
             bool ignore_not_existing)
1643
1689
{
1644
1690
  int digit;
1645
1691
  VAR *v;
 
1692
 
1646
1693
  if (*var_name != '$')
1647
1694
    goto err;
1648
1695
  digit = *++var_name - '0';
1664
1711
      die("Too long variable name: %s", save_var_name);
1665
1712
 
1666
1713
    string save_var_name_str(save_var_name, length);
1667
 
    var_hash_t::iterator iter= var_hash.find(save_var_name_str);
 
1714
    boost::unordered_map<string, VAR*>::iterator iter=
 
1715
      var_hash.find(save_var_name_str);
1668
1716
    if (iter == var_hash.end())
1669
1717
    {
1670
1718
      char buff[MAX_VAR_NAME_LENGTH+1];
1674
1722
    }
1675
1723
    else
1676
1724
    {
1677
 
      v= iter->second;
 
1725
      v= (*iter).second;
1678
1726
    }
1679
1727
    var_name--;  /* Point at last character */
1680
1728
  }
1681
1729
  else
1682
 
    v = &var_reg[digit];
 
1730
    v = var_reg + digit;
1683
1731
 
1684
1732
  if (!raw && v->int_dirty)
1685
1733
  {
1701
1749
static VAR *var_obtain(const char *name, int len)
1702
1750
{
1703
1751
  string var_name(name, len);
1704
 
  var_hash_t::iterator iter= var_hash.find(var_name);
 
1752
  boost::unordered_map<string, VAR*>::iterator iter=
 
1753
    var_hash.find(var_name);
1705
1754
  if (iter != var_hash.end())
1706
 
    return iter->second;
1707
 
  return var_hash[var_name] = var_init(0, name, len, "", 0);
 
1755
    return (*iter).second;
 
1756
  VAR *v = var_init(0, name, len, "", 0);
 
1757
  var_hash.insert(make_pair(var_name, v));
 
1758
  return v;
1708
1759
}
1709
1760
 
1710
1761
 
1731
1782
    v= var_obtain(var_name, (uint32_t) (var_name_end - var_name));
1732
1783
  }
1733
1784
  else
1734
 
    v= &var_reg[digit];
 
1785
    v= var_reg + digit;
1735
1786
 
1736
1787
  eval_expr(v, var_val, (const char**) &var_val_end);
1737
1788
 
2015
2066
    eval_expr(var, value, 0);
2016
2067
  }
2017
2068
  drizzle_result_free(&res);
 
2069
 
 
2070
  return;
2018
2071
}
2019
2072
 
2020
2073
 
2045
2098
{
2046
2099
  if (*p == '$')
2047
2100
  {
2048
 
    VAR *vp= var_get(p, p_end, 0, 0);
2049
 
    if (vp)
 
2101
    VAR *vp;
 
2102
    if ((vp= var_get(p, p_end, 0, 0)))
2050
2103
      var_copy(v, vp);
2051
2104
    return;
2052
2105
  }
2107
2160
  }
2108
2161
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2109
2162
 
 
2163
  if (cur_file == file_stack_end)
 
2164
    die("Source directives are nesting too deep");
2110
2165
  cur_file++;
2111
 
  if (cur_file == &*file_stack.end())
2112
 
    die("Source directives are nesting too deep");
2113
2166
  if (!(cur_file->file= fopen(buff, "r")))
2114
2167
  {
2115
2168
    cur_file--;
2171
2224
}
2172
2225
 
2173
2226
 
2174
 
static void init_builtin_echo()
 
2227
static void init_builtin_echo(void)
2175
2228
{
2176
2229
  builtin_echo[0]= 0;
 
2230
  return;
2177
2231
}
2178
2232
 
2179
2233
 
3136
3190
  when ndb binlog is on, this call will wait until last updated epoch
3137
3191
  (locally in the drizzled) has been received into the binlog
3138
3192
*/
3139
 
static int do_save_master_pos()
 
3193
static int do_save_master_pos(void)
3140
3194
{
3141
3195
  drizzle_result_st res;
3142
3196
  drizzle_return_t ret;
3275
3329
    sleep_val= opt_sleep;
3276
3330
 
3277
3331
  if (sleep_val)
3278
 
    usleep(sleep_val * 1000000);
 
3332
    usleep((uint32_t) (sleep_val * 1000000L));
3279
3333
  command->last_argument= sleep_end;
3280
3334
  return 0;
3281
3335
}
3282
3336
 
3283
3337
 
3284
 
static void do_get_file_name(st_command *command, string &dest)
 
3338
static void do_get_file_name(struct st_command *command, string &dest)
3285
3339
{
3286
 
  char *p= command->first_argument;
 
3340
  char *p= command->first_argument, *name;
3287
3341
  if (!*p)
3288
3342
    die("Missing file name argument");
3289
 
  char *name= p;
 
3343
  name= p;
3290
3344
  while (*p && !my_isspace(charset_info,*p))
3291
3345
    p++;
3292
3346
  if (*p)
3361
3415
      and assign that string to the $variable
3362
3416
    */
3363
3417
    size_t *lengths= drizzle_row_field_sizes(&res);
 
3418
    const std::string error_name(row[0], lengths[0]);
 
3419
    const std::string error_code(row[1], lengths[1]);
 
3420
 
3364
3421
    try
3365
3422
    {
3366
 
      global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
 
3423
      global_error_names.insert(ErrorCodes::value_type(error_name,
 
3424
                                                       boost::lexical_cast<uint32_t>(error_code)));
3367
3425
    }
3368
3426
    catch (boost::bad_lexical_cast &ex)
3369
3427
    {
3383
3441
 
3384
3442
  ErrorCodes::iterator it= global_error_names.find(error_name_s);
3385
3443
  if (it != global_error_names.end())
3386
 
    return it->second;
 
3444
  {
 
3445
    return (*it).second;
 
3446
  }
3387
3447
 
3388
3448
  die("Unknown SQL error name '%s'", error_name_s.c_str());
3389
3449
  return 0;
4004
4064
{
4005
4065
  char *p= command->first_argument;
4006
4066
  const char *expr_start, *expr_end;
 
4067
  VAR v;
4007
4068
  const char *cmd_name= (cmd == cmd_while ? "while" : "if");
4008
4069
  bool not_expr= false;
4009
4070
 
4046
4107
  if (*p && *p != '{')
4047
4108
    die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
4048
4109
 
4049
 
  VAR v;
4050
4110
  var_init(&v,0,0,0,0);
4051
4111
  eval_expr(&v, expr_start, &expr_end);
4052
4112
 
4182
4242
      }
4183
4243
      free((unsigned char*) cur_file->file_name);
4184
4244
      cur_file->file_name= 0;
4185
 
      if (cur_file == file_stack.data())
 
4245
      if (cur_file == file_stack)
4186
4246
      {
4187
4247
        /* We're back at the first file, check if
4188
4248
           all { have matching }
4622
4682
          log_file);
4623
4683
}
4624
4684
 
4625
 
void dump_progress()
 
4685
void dump_progress(void)
4626
4686
{
4627
4687
  char progress_file[FN_REFLEN];
4628
4688
  str_to_file(internal::fn_format(progress_file, result_file_name.c_str(),
4632
4692
              ds_progress.c_str(), ds_progress.length());
4633
4693
}
4634
4694
 
4635
 
void dump_warning_messages()
 
4695
void dump_warning_messages(void)
4636
4696
{
4637
4697
  char warn_file[FN_REFLEN];
4638
4698
 
4697
4757
    for (i = 0; i < num_fields; i++)
4698
4758
    {
4699
4759
      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
 
      }
 
4760
      append_field(ds, i, column,
 
4761
                   (const char*)row[i], lengths[i], !row[i]);
4730
4762
    }
4731
4763
    if (!display_result_vertically)
4732
4764
      ds->append("\n");
4770
4802
    ds->append("\t", 1);
4771
4803
    replace_append_uint(ds, drizzle_column_size(column));
4772
4804
    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
 
    }
 
4805
    replace_append_uint(ds, drizzle_column_max_size(column));
4781
4806
    ds->append("\t", 1);
4782
4807
    ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4783
4808
    ds->append("\t", 1);
5492
5517
 
5493
5518
  if (user_config_dir.compare(0, 2, "~/") == 0)
5494
5519
  {
5495
 
    const char *homedir= getenv("HOME");
 
5520
    char *homedir;
 
5521
    homedir= getenv("HOME");
5496
5522
    if (homedir != NULL)
5497
5523
      user_config_dir.replace(0, 1, homedir);
5498
5524
  }
5539
5565
  next_con= connections + 1;
5540
5566
 
5541
5567
  /* Init file stack */
5542
 
  memset(file_stack.data(), 0, sizeof(file_stack));
5543
 
  cur_file= file_stack.data();
 
5568
  memset(file_stack, 0, sizeof(file_stack));
 
5569
  file_stack_end=
 
5570
    file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
 
5571
  cur_file= file_stack;
5544
5572
 
5545
5573
  /* Init block stack */
5546
5574
  memset(block_stack, 0, sizeof(block_stack));
5579
5607
      tmp= buff;
5580
5608
    }
5581
5609
    internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5582
 
    assert(cur_file == file_stack.data() && cur_file->file == 0);
 
5610
    assert(cur_file == file_stack && cur_file->file == 0);
5583
5611
    if (!(cur_file->file= fopen(buff, "r")))
5584
5612
    {
5585
5613
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5684
5712
  }
5685
5713
 
5686
5714
  server_initialized= 1;
5687
 
  if (cur_file == file_stack.data() && cur_file->file == 0)
 
5715
  if (cur_file == file_stack && cur_file->file == 0)
5688
5716
  {
5689
5717
    cur_file->file= stdin;
5690
5718
    cur_file->file_name= strdup("<stdin>");
6109
6137
  the time between executing the two commands.
6110
6138
*/
6111
6139
 
6112
 
void timer_output()
 
6140
void timer_output(void)
6113
6141
{
6114
6142
  if (timer_file)
6115
6143
  {
6123
6151
}
6124
6152
 
6125
6153
 
6126
 
uint64_t timer_now()
 
6154
uint64_t timer_now(void)
6127
6155
{
6128
6156
#if defined(HAVE_GETHRTIME)
6129
6157
  return gethrtime()/1000/1000;
6163
6191
  start= buff= (char *)malloc(strlen(from)+1);
6164
6192
  while (*from)
6165
6193
  {
 
6194
    char *to;
6166
6195
    uint32_t column_number;
6167
6196
 
6168
 
    char *to= get_string(&buff, &from, command);
 
6197
    to= get_string(&buff, &from, command);
6169
6198
    if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6170
6199
      die("Wrong column number to replace_column in '%s'", command->query);
6171
6200
    if (!*from)
6184
6213
 
6185
6214
void free_replace_column()
6186
6215
{
6187
 
  for (uint32_t i= 0 ; i < max_replace_column; i++)
 
6216
  uint32_t i;
 
6217
  for (i=0 ; i < max_replace_column ; i++)
6188
6218
  {
6189
 
    free(replace_column[i]);
6190
 
    replace_column[i]= 0;
 
6219
    if (replace_column[i])
 
6220
    {
 
6221
      free(replace_column[i]);
 
6222
      replace_column[i]= 0;
 
6223
    }
6191
6224
  }
6192
6225
  max_replace_column= 0;
6193
6226
}
6208
6241
} POINTER_ARRAY;
6209
6242
 
6210
6243
struct st_replace;
6211
 
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6212
 
                                char *word_end_chars);
 
6244
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
 
6245
                                char * word_end_chars);
6213
6246
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6214
6247
void replace_strings_append(struct st_replace *rep, string* ds,
6215
6248
                            const char *from, int len);
 
6249
void free_pointer_array(POINTER_ARRAY *pa);
6216
6250
 
6217
 
st_replace *glob_replace= NULL;
6218
 
// boost::scoped_ptr<st_replace> glob_replace;
 
6251
struct st_replace *glob_replace= NULL;
6219
6252
 
6220
6253
/*
6221
6254
  Get arguments for replace. The syntax is:
6225
6258
  variable is replaced.
6226
6259
*/
6227
6260
 
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
6261
void do_get_replace(struct st_command *command)
6239
6262
{
6240
6263
  uint32_t i;
6266
6289
    if (my_isspace(charset_info,i))
6267
6290
      *pos++= i;
6268
6291
  *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,
 
6292
  if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
 
6293
                                   (char**) to_array.typelib.type_names,
 
6294
                                   (uint32_t) from_array.typelib.count,
6272
6295
                                   word_end_chars)))
6273
6296
    die("Can't initialize replace from '%s'", command->query);
6274
6297
  free_pointer_array(&from_array);
6281
6304
 
6282
6305
void free_replace()
6283
6306
{
6284
 
  free(glob_replace);
6285
 
  glob_replace=0;
 
6307
 
 
6308
  if (glob_replace)
 
6309
  {
 
6310
    free(glob_replace);
 
6311
    glob_replace=0;
 
6312
  }
 
6313
  return;
6286
6314
}
6287
6315
 
6288
6316
 
6302
6330
void replace_strings_append(REPLACE *rep, string* ds,
6303
6331
                            const char *str, int len)
6304
6332
{
6305
 
  REPLACE *rep_pos;
6306
 
  REPLACE_STRING *rep_str;
 
6333
  register REPLACE *rep_pos;
 
6334
  register REPLACE_STRING *rep_str;
6307
6335
  const char *start, *from;
6308
6336
 
6309
6337
 
6356
6384
                 i.e. repeat the matching until the end of the string */
6357
6385
};
6358
6386
 
6359
 
class st_replace_regex
 
6387
struct st_replace_regex
6360
6388
{
6361
 
public:
6362
 
  st_replace_regex(char* expr);
6363
 
  int multi_reg_replace(char* val);
 
6389
  DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
6364
6390
 
6365
6391
  /*
6366
6392
    Temporary storage areas for substitutions. To reduce unnessary copying
6369
6395
    st_regex substition. At the end of substitutions  buf points to the
6370
6396
    one containing the final result.
6371
6397
  */
6372
 
  typedef vector<st_regex> regex_arr_t;
6373
 
 
6374
 
  char* buf_;
 
6398
  char* buf;
6375
6399
  char* even_buf;
6376
6400
  char* odd_buf;
6377
6401
  int even_buf_len;
6378
6402
  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
6403
};
6383
6404
 
6384
 
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
 
6405
struct st_replace_regex *glob_replace_regex= 0;
6385
6406
 
6386
6407
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6387
6408
                char *string, int icase, int global);
6423
6444
  Returns: st_replace_regex struct with pairs of substitutions
6424
6445
*/
6425
6446
 
6426
 
st_replace_regex::st_replace_regex(char* expr)
 
6447
static struct st_replace_regex* init_replace_regex(char* expr)
6427
6448
{
 
6449
  struct st_replace_regex* res;
 
6450
  char* buf,*expr_end;
 
6451
  char* p;
 
6452
  char* buf_p;
6428
6453
  uint32_t expr_len= strlen(expr);
6429
6454
  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;
 
6455
  struct st_regex reg;
 
6456
 
 
6457
  res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
 
6458
  if (!res)
 
6459
    return NULL;
 
6460
  my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
 
6461
 
 
6462
  buf= (char*)res + sizeof(*res);
 
6463
  expr_end= expr + expr_len;
 
6464
  p= expr;
 
6465
  buf_p= buf;
6436
6466
 
6437
6467
  /* for each regexp substitution statement */
6438
6468
  while (p < expr_end)
6448
6478
 
6449
6479
    if (p == expr_end || ++p == expr_end)
6450
6480
    {
6451
 
      if (!regex_arr.empty())
 
6481
      if (res->regex_arr.elements)
6452
6482
        break;
6453
6483
      else
6454
6484
        goto err;
6487
6517
      p++;
6488
6518
      reg.global= 1;
6489
6519
    }
6490
 
    regex_arr.push_back(reg);
 
6520
 
 
6521
    /* done parsing the statement, now place it in regex_arr */
 
6522
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
 
6523
      die("Out of memory");
6491
6524
  }
6492
 
  odd_buf_len= even_buf_len= buf0_.size();
6493
 
  even_buf= buf0_.data();
6494
 
  odd_buf= buf1_.data();
6495
 
  buf_= even_buf;
 
6525
  res->odd_buf_len= res->even_buf_len= 8192;
 
6526
  res->even_buf= (char*)malloc(res->even_buf_len);
 
6527
  res->odd_buf= (char*)malloc(res->odd_buf_len);
 
6528
  res->buf= res->even_buf;
6496
6529
 
6497
 
  return;
 
6530
  return res;
6498
6531
 
6499
6532
err:
 
6533
  free(res);
6500
6534
  die("Error parsing replace_regex \"%s\"", expr);
 
6535
  return 0;
6501
6536
}
6502
6537
 
6503
6538
/*
6519
6554
  in one pass
6520
6555
*/
6521
6556
 
6522
 
int st_replace_regex::multi_reg_replace(char* val)
 
6557
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6523
6558
{
6524
 
  char* in_buf= val;
6525
 
  char* out_buf= even_buf;
6526
 
  int* buf_len_p= &even_buf_len;
6527
 
  buf_= 0;
 
6559
  uint32_t i;
 
6560
  char* in_buf, *out_buf;
 
6561
  int* buf_len_p;
 
6562
 
 
6563
  in_buf= val;
 
6564
  out_buf= r->even_buf;
 
6565
  buf_len_p= &r->even_buf_len;
 
6566
  r->buf= 0;
6528
6567
 
6529
6568
  /* For each substitution, do the replace */
6530
 
  BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
 
6569
  for (i= 0; i < r->regex_arr.elements; i++)
6531
6570
  {
 
6571
    struct st_regex re;
6532
6572
    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))
 
6573
 
 
6574
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
 
6575
 
 
6576
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
 
6577
                     in_buf, re.icase, re.global))
6535
6578
    {
6536
6579
      /* if the buffer has been reallocated, make adjustements */
6537
6580
      if (save_out_buf != out_buf)
6538
6581
      {
6539
 
        if (save_out_buf == even_buf)
6540
 
          even_buf= out_buf;
 
6582
        if (save_out_buf == r->even_buf)
 
6583
          r->even_buf= out_buf;
6541
6584
        else
6542
 
          odd_buf= out_buf;
 
6585
          r->odd_buf= out_buf;
6543
6586
      }
6544
 
      buf_= out_buf;
 
6587
 
 
6588
      r->buf= out_buf;
6545
6589
      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;
 
6590
        in_buf= r->odd_buf;
 
6591
 
 
6592
      std::swap(in_buf,out_buf);
 
6593
 
 
6594
      buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
 
6595
        &r->odd_buf_len;
6549
6596
    }
6550
6597
  }
6551
 
  return buf_ == 0;
 
6598
 
 
6599
  return (r->buf == 0);
6552
6600
}
6553
6601
 
6554
6602
/*
6563
6611
void do_get_replace_regex(struct st_command *command)
6564
6612
{
6565
6613
  char *expr= command->first_argument;
6566
 
  glob_replace_regex.reset(new st_replace_regex(expr));
 
6614
  free_replace_regex();
 
6615
  if (!(glob_replace_regex=init_replace_regex(expr)))
 
6616
    die("Could not init replace_regex");
6567
6617
  command->last_argument= command->end;
6568
6618
}
6569
6619
 
 
6620
void free_replace_regex()
 
6621
{
 
6622
  if (glob_replace_regex)
 
6623
  {
 
6624
    delete_dynamic(&glob_replace_regex->regex_arr);
 
6625
    free(glob_replace_regex->even_buf);
 
6626
    free(glob_replace_regex->odd_buf);
 
6627
    free(glob_replace_regex);
 
6628
    glob_replace_regex=0;
 
6629
  }
 
6630
}
 
6631
 
 
6632
 
 
6633
 
6570
6634
/*
6571
6635
  Performs a regex substitution
6572
6636
 
6673
6737
#define SET_MALLOC_HUNC 64
6674
6738
#define LAST_CHAR_CODE 259
6675
6739
 
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
 
 
 
6740
typedef struct st_rep_set {
6686
6741
  uint32_t  *bits;        /* Pointer to used sets */
6687
6742
  short next[LAST_CHAR_CODE];    /* Pointer to next sets */
6688
6743
  uint32_t  found_len;      /* Best match to date */
6689
6744
  int  found_offset;
6690
6745
  uint32_t  table_offset;
6691
6746
  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
 
 
 
6747
} REP_SET;
 
6748
 
 
6749
typedef struct st_rep_sets {
6702
6750
  uint32_t    count;      /* Number of sets */
6703
6751
  uint32_t    extra;      /* Extra sets in buffer */
6704
 
  uint32_t    invisible;    /* Sets not shown */
 
6752
  uint32_t    invisible;    /* Sets not chown */
6705
6753
  uint32_t    size_of_bits;
6706
6754
  REP_SET  *set,*set_buffer;
6707
6755
  uint32_t    *bit_buffer;
6708
 
};
 
6756
} REP_SETS;
6709
6757
 
6710
 
struct FOUND_SET 
6711
 
{
 
6758
typedef struct st_found_set {
6712
6759
  uint32_t table_offset;
6713
6760
  int found_offset;
6714
 
};
 
6761
} FOUND_SET;
6715
6762
 
6716
 
struct FOLLOWS
6717
 
{
 
6763
typedef struct st_follow {
6718
6764
  int chr;
6719
6765
  uint32_t table_offset;
6720
6766
  uint32_t len;
6721
 
};
6722
 
 
6723
 
int init_sets(REP_SETS *sets, uint32_t states);
 
6767
} FOLLOWS;
 
6768
 
 
6769
 
 
6770
int init_sets(REP_SETS *sets,uint32_t states);
6724
6771
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)
 
6772
void make_sets_invisible(REP_SETS *sets);
 
6773
void free_last_set(REP_SETS *sets);
 
6774
void free_sets(REP_SETS *sets);
 
6775
void internal_set_bit(REP_SET *set, uint32_t bit);
 
6776
void internal_clear_bit(REP_SET *set, uint32_t bit);
 
6777
void or_bits(REP_SET *to,REP_SET *from);
 
6778
void copy_bits(REP_SET *to,REP_SET *from);
 
6779
int cmp_bits(REP_SET *set1,REP_SET *set2);
 
6780
int get_next_bit(REP_SET *set,uint32_t lastpos);
 
6781
int find_set(REP_SETS *sets,REP_SET *find);
 
6782
int find_found(FOUND_SET *found_set,uint32_t table_offset,
 
6783
               int found_offset);
 
6784
uint32_t start_at_word(char * pos);
 
6785
uint32_t end_of_word(char * pos);
 
6786
 
 
6787
static uint32_t found_sets=0;
 
6788
 
 
6789
 
 
6790
static uint32_t replace_len(char * str)
6730
6791
{
6731
6792
  uint32_t len=0;
6732
6793
  while (*str)
6739
6800
  return len;
6740
6801
}
6741
6802
 
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
6803
/* Init a replace structure for further calls */
6756
6804
 
6757
 
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
 
6805
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
 
6806
                      char * word_end_chars)
6758
6807
{
6759
 
  const int SPACE_CHAR= 256;
6760
 
  const int START_OF_LINE= 257;
6761
 
  const int END_OF_LINE= 258;
 
6808
  static const int SPACE_CHAR= 256;
 
6809
  static const int START_OF_LINE= 257;
 
6810
  static const int END_OF_LINE= 258;
6762
6811
 
6763
6812
  uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6764
6813
  int used_sets,chr,default_state;
6765
6814
  char used_chars[LAST_CHAR_CODE],is_word_end[256];
6766
 
  char *to_pos, **to_array;
 
6815
  char * pos, *to_pos, **to_array;
 
6816
  REP_SETS sets;
 
6817
  REP_SET *set,*start_states,*word_states,*new_set;
 
6818
  FOLLOWS *follow,*follow_ptr;
 
6819
  REPLACE *replace;
 
6820
  FOUND_SET *found_set;
 
6821
  REPLACE_STRING *rep_str;
 
6822
 
6767
6823
 
6768
6824
  /* Count number of states */
6769
6825
  for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6783
6839
  for (i=0 ; word_end_chars[i] ; i++)
6784
6840
    is_word_end[(unsigned char) word_end_chars[i]]=1;
6785
6841
 
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;
 
6842
  if (init_sets(&sets,states))
 
6843
    return(0);
6791
6844
  found_sets=0;
6792
 
  vector<FOUND_SET> found_set(max_length * count);
 
6845
  if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
 
6846
                                
 
6847
  {
 
6848
    free_sets(&sets);
 
6849
    return(0);
 
6850
  }
6793
6851
  make_new_set(&sets);      /* Set starting set */
6794
 
  sets.make_sets_invisible();      /* Hide previus sets */
 
6852
  make_sets_invisible(&sets);      /* Hide previus sets */
6795
6853
  used_sets=-1;
6796
6854
  word_states=make_new_set(&sets);    /* Start of new word */
6797
6855
  start_states=make_new_set(&sets);    /* This is first state */
6798
 
  vector<FOLLOWS> follow(states + 2);
6799
 
  FOLLOWS *follow_ptr= &follow[1];
 
6856
  if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
 
6857
  {
 
6858
    free_sets(&sets);
 
6859
    free(found_set);
 
6860
    return(0);
 
6861
  }
 
6862
 
6800
6863
  /* Init follow_ptr[] */
6801
 
  for (i=0, states=1; i < count; i++)
 
6864
  for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6802
6865
  {
6803
6866
    if (from[i][0] == '\\' && from[i][1] == '^')
6804
6867
    {
6805
 
      start_states->internal_set_bit(states + 1);
 
6868
      internal_set_bit(start_states,states+1);
6806
6869
      if (!from[i][2])
6807
6870
      {
6808
6871
        start_states->table_offset=i;
6811
6874
    }
6812
6875
    else if (from[i][0] == '\\' && from[i][1] == '$')
6813
6876
    {
6814
 
      start_states->internal_set_bit(states);
6815
 
      word_states->internal_set_bit(states);
 
6877
      internal_set_bit(start_states,states);
 
6878
      internal_set_bit(word_states,states);
6816
6879
      if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6817
6880
      {
6818
6881
        start_states->table_offset=i;
6821
6884
    }
6822
6885
    else
6823
6886
    {
6824
 
      word_states->internal_set_bit(states);
 
6887
      internal_set_bit(word_states,states);
6825
6888
      if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6826
 
        start_states->internal_set_bit(states + 1);
 
6889
        internal_set_bit(start_states,states+1);
6827
6890
      else
6828
 
        start_states->internal_set_bit(states);
 
6891
        internal_set_bit(start_states,states);
6829
6892
    }
6830
 
    const char *pos;
6831
 
    for (pos= from[i], len=0; *pos ; pos++)
 
6893
    for (pos=from[i], len=0; *pos ; pos++)
6832
6894
    {
6833
6895
      if (*pos == '\\' && *(pos+1))
6834
6896
      {
6871
6933
  }
6872
6934
 
6873
6935
 
6874
 
  for (set_nr=0; set_nr < sets.count ; set_nr++)
 
6936
  for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6875
6937
  {
6876
6938
    set=sets.set+set_nr;
6877
6939
    default_state= 0;        /* Start from beginning */
6878
6940
 
6879
6941
    /* If end of found-string not found or start-set with current set */
6880
6942
 
6881
 
    for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
 
6943
    for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6882
6944
    {
6883
 
      if (!follow[i].chr && !default_state)
6884
 
        default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
 
6945
      if (!follow[i].chr)
 
6946
      {
 
6947
        if (! default_state)
 
6948
          default_state= find_found(found_set,set->table_offset,
 
6949
                                    set->found_offset+1);
 
6950
      }
6885
6951
    }
6886
 
    sets.set[used_sets].copy_bits(set);    /* Save set for changes */
 
6952
    copy_bits(sets.set+used_sets,set);    /* Save set for changes */
6887
6953
    if (!default_state)
6888
 
      sets.set[used_sets].or_bits(sets.set);  /* Can restart from start */
 
6954
      or_bits(sets.set+used_sets,sets.set);  /* Can restart from start */
6889
6955
 
6890
6956
    /* Find all chars that follows current sets */
6891
6957
    memset(used_chars, 0, sizeof(used_chars));
6892
 
    for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
 
6958
    for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6893
6959
    {
6894
6960
      used_chars[follow[i].chr]=1;
6895
6961
      if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6899
6965
 
6900
6966
    /* Mark word_chars used if \b is in state */
6901
6967
    if (used_chars[SPACE_CHAR])
6902
 
      for (const char *pos= word_end_chars ; *pos ; pos++)
 
6968
      for (pos= word_end_chars ; *pos ; pos++)
6903
6969
        used_chars[(int) (unsigned char) *pos] = 1;
6904
6970
 
6905
6971
    /* Handle other used characters */
6916
6982
        new_set->found_offset=set->found_offset+1;
6917
6983
        found_end=0;
6918
6984
 
6919
 
        for (i= UINT32_MAX ; (i= sets.set[used_sets].get_next_bit(i)) ; )
 
6985
        for (i= UINT32_MAX ; (i=get_next_bit(sets.set+used_sets,i)) ; )
6920
6986
        {
6921
6987
          if (!follow[i].chr || follow[i].chr == chr ||
6922
6988
              (follow[i].chr == SPACE_CHAR &&
6928
6994
                follow[i].len > found_end)
6929
6995
              found_end=follow[i].len;
6930
6996
            if (chr && follow[i].chr)
6931
 
              new_set->internal_set_bit(i + 1);    /* To next set */
 
6997
              internal_set_bit(new_set,i+1);    /* To next set */
6932
6998
            else
6933
 
              new_set->internal_set_bit(i);
 
6999
              internal_set_bit(new_set,i);
6934
7000
          }
6935
7001
        }
6936
7002
        if (found_end)
6937
7003
        {
6938
7004
          new_set->found_len=0;      /* Set for testing if first */
6939
7005
          bits_set=0;
6940
 
          for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
 
7006
          for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6941
7007
          {
6942
7008
            if ((follow[i].chr == SPACE_CHAR ||
6943
7009
                 follow[i].chr == END_OF_LINE) && ! chr)
6947
7013
            if (follow[bit_nr-1].len < found_end ||
6948
7014
                (new_set->found_len &&
6949
7015
                 (chr == 0 || !follow[bit_nr].chr)))
6950
 
              new_set->internal_clear_bit(i);
 
7016
              internal_clear_bit(new_set,i);
6951
7017
            else
6952
7018
            {
6953
7019
              if (chr == 0 || !follow[bit_nr].chr)
6963
7029
          }
6964
7030
          if (bits_set == 1)
6965
7031
          {
6966
 
            set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6967
 
            sets.free_last_set();
 
7032
            set->next[chr] = find_found(found_set,
 
7033
                                        new_set->table_offset,
 
7034
                                        new_set->found_offset);
 
7035
            free_last_set(&sets);
6968
7036
          }
6969
7037
          else
6970
 
            set->next[chr] = sets.find_set(new_set);
 
7038
            set->next[chr] = find_set(&sets,new_set);
6971
7039
        }
6972
7040
        else
6973
 
          set->next[chr] = sets.find_set(new_set);
 
7041
          set->next[chr] = find_set(&sets,new_set);
6974
7042
      }
6975
7043
    }
6976
7044
  }
6977
7045
 
6978
7046
  /* Alloc replace structure for the replace-state-machine */
6979
7047
 
6980
 
  REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6981
 
    + sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
6982
 
  if (replace)
 
7048
  if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
 
7049
                                 sizeof(REPLACE_STRING)*(found_sets+1)+
 
7050
                                 sizeof(char *)*count+result_len)))
6983
7051
  {
6984
7052
    memset(replace, 0, sizeof(REPLACE)*(sets.count)+
6985
7053
                       sizeof(REPLACE_STRING)*(found_sets+1)+
6996
7064
    rep_str[0].replace_string=0;
6997
7065
    for (i=1 ; i <= found_sets ; i++)
6998
7066
    {
6999
 
      const char *pos= from[found_set[i-1].table_offset];
 
7067
      pos=from[found_set[i-1].table_offset];
7000
7068
      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);
 
7069
      rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
 
7070
      rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
 
7071
      rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
 
7072
        end_of_word(pos);
7004
7073
    }
7005
7074
    for (i=0 ; i < sets.count ; i++)
7006
7075
    {
7011
7080
          replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
7012
7081
    }
7013
7082
  }
7014
 
  sets.free_sets();
7015
 
  return replace;
 
7083
  free(follow);
 
7084
  free_sets(&sets);
 
7085
  free(found_set);
 
7086
  return(replace);
7016
7087
}
7017
7088
 
7018
7089
 
7033
7104
 
7034
7105
/* Make help sets invisible for nicer codeing */
7035
7106
 
7036
 
void REP_SETS::make_sets_invisible()
 
7107
void make_sets_invisible(REP_SETS *sets)
7037
7108
{
7038
 
  invisible= count;
7039
 
  set += count;
7040
 
  count= 0;
 
7109
  sets->invisible=sets->count;
 
7110
  sets->set+=sets->count;
 
7111
  sets->count=0;
7041
7112
}
7042
7113
 
7043
7114
REP_SET *make_new_set(REP_SETS *sets)
7075
7146
  return make_new_set(sets);
7076
7147
}
7077
7148
 
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
 
}
 
7149
void free_last_set(REP_SETS *sets)
 
7150
{
 
7151
  sets->count--;
 
7152
  sets->extra++;
 
7153
  return;
 
7154
}
 
7155
 
 
7156
void free_sets(REP_SETS *sets)
 
7157
{
 
7158
  free(sets->set_buffer);
 
7159
  free(sets->bit_buffer);
 
7160
  return;
 
7161
}
 
7162
 
 
7163
void internal_set_bit(REP_SET *set, uint32_t bit)
 
7164
{
 
7165
  set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
 
7166
  return;
 
7167
}
 
7168
 
 
7169
void internal_clear_bit(REP_SET *set, uint32_t bit)
 
7170
{
 
7171
  set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
 
7172
  return;
 
7173
}
 
7174
 
 
7175
 
 
7176
void or_bits(REP_SET *to,REP_SET *from)
 
7177
{
 
7178
  register uint32_t i;
 
7179
  for (i=0 ; i < to->size_of_bits ; i++)
 
7180
    to->bits[i]|=from->bits[i];
 
7181
  return;
 
7182
}
 
7183
 
 
7184
void copy_bits(REP_SET *to,REP_SET *from)
 
7185
{
 
7186
  memcpy(to->bits,from->bits,
 
7187
         (size_t) (sizeof(uint32_t) * to->size_of_bits));
 
7188
}
 
7189
 
 
7190
int cmp_bits(REP_SET *set1,REP_SET *set2)
 
7191
{
 
7192
  return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
 
7193
}
 
7194
 
7116
7195
 
7117
7196
/* Get next set bit from set. */
7118
7197
 
7119
 
int REP_SET::get_next_bit(uint32_t lastpos) const
 
7198
int get_next_bit(REP_SET *set,uint32_t lastpos)
7120
7199
{
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)
 
7200
  uint32_t pos,*start,*end,bits;
 
7201
 
 
7202
  start=set->bits+ ((lastpos+1) / WORD_BIT);
 
7203
  end=set->bits + set->size_of_bits;
 
7204
  bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
 
7205
 
 
7206
  while (! bits && ++start < end)
 
7207
    bits=start[0];
 
7208
  if (!bits)
7128
7209
    return 0;
7129
 
  uint32_t pos= (start - bits) * WORD_BIT;
7130
 
  while (!(bits0 & 1))
 
7210
  pos=(uint32_t) (start-set->bits)*WORD_BIT;
 
7211
  while (! (bits & 1))
7131
7212
  {
7132
 
    bits0 >>=1;
 
7213
    bits>>=1;
7133
7214
    pos++;
7134
7215
  }
7135
7216
  return pos;
7139
7220
   free given set, else put in given set in sets and return its
7140
7221
   position */
7141
7222
 
7142
 
int REP_SETS::find_set(const REP_SET *find)
 
7223
int find_set(REP_SETS *sets,REP_SET *find)
7143
7224
{
7144
 
  uint32_t i= 0;
7145
 
  for (; i < count - 1; i++)
 
7225
  uint32_t i;
 
7226
  for (i=0 ; i < sets->count-1 ; i++)
7146
7227
  {
7147
 
    if (!set[i].cmp_bits(find))
 
7228
    if (!cmp_bits(sets->set+i,find))
7148
7229
    {
7149
 
      free_last_set();
 
7230
      free_last_set(sets);
7150
7231
      return i;
7151
7232
    }
7152
7233
  }
7160
7241
   set->next[] == -1 is reserved for end without replaces.
7161
7242
*/
7162
7243
 
7163
 
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
 
7244
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7164
7245
{
7165
 
  uint32_t i= 0;
7166
 
  for (; i < found_sets; i++)
7167
 
  {
 
7246
  int i;
 
7247
  for (i=0 ; (uint32_t) i < found_sets ; i++)
7168
7248
    if (found_set[i].table_offset == table_offset &&
7169
7249
        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;
 
7250
      return -i-2;
 
7251
  found_set[i].table_offset=table_offset;
 
7252
  found_set[i].found_offset=found_offset;
7174
7253
  found_sets++;
7175
 
  return - i - 2; // return new postion
 
7254
  return -i-2;        /* return new postion */
 
7255
}
 
7256
 
 
7257
/* Return 1 if regexp starts with \b or ends with \b*/
 
7258
 
 
7259
uint32_t start_at_word(char * pos)
 
7260
{
 
7261
  return (((!memcmp(pos, "\\b",2) && pos[2]) ||
 
7262
           !memcmp(pos, "\\^", 2)) ? 1 : 0);
 
7263
}
 
7264
 
 
7265
uint32_t end_of_word(char * pos)
 
7266
{
 
7267
  char * end= strchr(pos, '\0');
 
7268
  return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
 
7269
          (end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7176
7270
}
7177
7271
 
7178
7272
/****************************************************************************
7251
7345
} /* insert_pointer_name */
7252
7346
 
7253
7347
 
 
7348
/* free pointer array */
 
7349
 
 
7350
void free_pointer_array(POINTER_ARRAY *pa)
 
7351
{
 
7352
  if (pa->typelib.count)
 
7353
  {
 
7354
    pa->typelib.count=0;
 
7355
    free((char*) pa->typelib.type_names);
 
7356
    pa->typelib.type_names=0;
 
7357
    free(pa->str);
 
7358
  }
 
7359
} /* free_pointer_array */
 
7360
 
 
7361
 
7254
7362
/* Functions that uses replace and replace_regex */
7255
7363
 
7256
7364
/* Append the string to ds, with optional replace */
7257
 
void replace_append_mem(string *ds, const char *val, int len)
 
7365
void replace_append_mem(string *ds,
 
7366
                        const char *val, int len)
7258
7367
{
7259
7368
  char *v= strdup(val);
7260
7369
 
7261
 
  if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
 
7370
  if (glob_replace_regex)
7262
7371
  {
7263
 
    v= glob_replace_regex->buf_;
7264
 
    len= strlen(v);
 
7372
    /* Regex replace */
 
7373
    if (!multi_reg_replace(glob_replace_regex, v))
 
7374
    {
 
7375
      v= glob_replace_regex->buf;
 
7376
      len= strlen(v);
 
7377
    }
7265
7378
  }
 
7379
 
7266
7380
  if (glob_replace)
7267
7381
  {
7268
7382
    /* Normal replace */
7269
7383
    replace_strings_append(glob_replace, ds, v, len);
7270
7384
  }
7271
7385
  else
 
7386
  {
7272
7387
    ds->append(v, len);
 
7388
  }
7273
7389
}
7274
7390
 
7275
7391
 
7338
7454
 
7339
7455
  return;
7340
7456
}
7341
 
 
7342
 
static void free_all_replace()
7343
 
{
7344
 
  free_replace();
7345
 
  glob_replace_regex.reset();
7346
 
  free_replace_column();
7347
 
}