64
67
#include <boost/unordered_map.hpp>
66
69
/* Added this for string translation. */
67
#include "drizzled/gettext.h"
68
#include "drizzled/drizzle_time.h"
69
#include "drizzled/charset.h"
70
#include <drizzled/gettext.h>
72
#include <drizzled/definitions.h>
73
#include <drizzled/charset_info.h>
74
#include <drizzled/internal/my_sys.h>
75
#include <drizzled/type/time.h>
76
#include <drizzled/charset.h>
77
#include <drizzled/typelib.h>
70
78
#include <drizzled/configmake.h>
79
#include <drizzled/util/find_ptr.h>
81
#define PTR_BYTE_DIFF(A,B) (ptrdiff_t) (reinterpret_cast<const unsigned char*>(A) - reinterpret_cast<const unsigned char*>(B))
72
83
#ifndef DRIZZLE_RETURN_SERVER_GONE
73
84
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
164
175
uint32_t lineno; /* Current line in file */
167
static struct st_test_file file_stack[16];
168
static struct st_test_file* cur_file;
169
static struct st_test_file* file_stack_end;
172
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
178
static boost::array<st_test_file, 16> file_stack;
179
static st_test_file* cur_file;
181
static const charset_info_st *charset_info= &my_charset_utf8_general_ci; /* Default charset */
175
184
Timer related variables
178
187
static char *timer_file = NULL;
179
188
static uint64_t timer_start;
180
static void timer_output(void);
181
static uint64_t timer_now(void);
189
static void timer_output();
190
static uint64_t timer_now();
183
192
static uint64_t progress_start= 0;
389
399
struct st_match_err err[10];
392
static struct st_expected_errors saved_expected_errors;
403
static st_expected_errors saved_expected_errors;
396
408
char *query, *query_buf,*first_argument,*last_argument,*end;
397
409
int first_word_len, query_len;
398
410
bool abort_on_error;
399
411
st_expected_errors expected_errors;
400
412
string require_file;
401
enum enum_commands type;
404
416
: query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
438
447
VAR* var_from_env(const char *, const char *);
439
448
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
441
void var_free(pair<string, VAR*> v);
442
450
VAR* var_get(const char *var_name, const char** var_name_end,
443
451
bool raw, bool ignore_not_existing);
444
452
void eval_expr(VAR* v, const char *p, const char** p_end);
445
453
bool match_delimiter(int c, const char *delim, uint32_t length);
446
454
void dump_result_to_reject_file(char *buf, int size);
447
455
void dump_result_to_log_file(const char *buf, int size);
448
void dump_warning_messages(void);
449
void dump_progress(void);
456
void dump_warning_messages();
457
void dump_progress();
451
459
void do_eval(string *query_eval, const char *query,
452
460
const char *query_end, bool pass_through_escape_chars);
457
465
static char *replace_column[MAX_COLUMNS];
458
466
static uint32_t max_replace_column= 0;
459
467
void do_get_replace_column(struct st_command*);
460
void free_replace_column(void);
468
void free_replace_column();
462
470
/* For replace */
463
471
void do_get_replace(struct st_command *command);
464
void free_replace(void);
466
474
/* For replace_regex */
467
475
void do_get_replace_regex(struct st_command *command);
468
void free_replace_regex(void);
471
void free_all_replace(void);
474
void free_all_replace(void){
476
free_replace_regex();
477
free_replace_column();
480
477
void replace_append_mem(string *ds, const char *val,
886
879
free(next_con->name);
892
static void close_files(void)
884
static void close_files()
895
for (; cur_file >= file_stack; cur_file--)
886
for (; cur_file >= file_stack.data(); cur_file--)
897
888
if (cur_file->file && cur_file->file != stdin)
899
889
fclose(cur_file->file);
901
free((unsigned char*) cur_file->file_name);
890
free(const_cast<char*>(cur_file->file_name));
902
891
cur_file->file_name= 0;
908
static void free_used_memory(void)
895
static void free_used_memory()
913
897
close_connections();
915
for_each(var_hash.begin(), var_hash.end(), var_free);
899
BOOST_FOREACH(var_hash_t::reference i, var_hash)
901
free(i.second->str_val);
902
free(i.second->env_s);
903
if (i.second->alloced)
916
906
var_hash.clear();
918
vector<st_command *>::iterator iter;
919
for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
921
struct st_command * q_line= *iter;
925
for (i= 0; i < 10; i++)
907
BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
909
for (size_t i= 0; i < var_reg.size(); i++)
927
911
if (var_reg[i].alloced_len)
928
912
free(var_reg[i].str_val);
931
914
free_all_replace();
1038
1018
/* Print include filestack */
1039
1019
fprintf(stderr, "The test '%s' is not supported by this installation\n",
1040
file_stack->file_name);
1020
file_stack[0].file_name);
1041
1021
fprintf(stderr, "Detected in file %s at line %d\n",
1042
1022
err_file->file_name, err_file->lineno);
1043
while (err_file != file_stack)
1023
while (err_file != file_stack.data())
1046
1026
fprintf(stderr, "included from %s at line %d\n",
1430
1408
static int compare_files(const char* filename1, const char* filename2)
1435
if ((fd= internal::my_open(filename1, O_RDONLY, MYF(0))) < 0)
1410
int fd= internal::my_open(filename1, O_RDONLY, MYF(0));
1436
1412
die("Failed to open first file: '%s'", filename1);
1438
error= compare_files2(fd, filename2);
1413
int error= compare_files2(fd, filename2);
1440
1414
internal::my_close(fd, MYF(0));
1629
1602
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1634
1605
if (!name_len && name)
1635
1606
name_len = strlen(name);
1636
1607
if (!val_len && val)
1637
1608
val_len = strlen(val) ;
1638
val_alloc_len = val_len + 16; /* room to grow */
1639
if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
1641
die("Out of memory");
1609
VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
1643
tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1611
tmp_var->name = name ? (char*)&tmp_var[1] : 0;
1644
1612
tmp_var->alloced = (v == 0);
1646
if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
1647
die("Out of memory");
1614
int val_alloc_len = val_len + 16; /* room to grow */
1615
tmp_var->str_val = (char*)malloc(val_alloc_len+1);
1649
1617
memcpy(tmp_var->name, name, name_len);
1655
1623
tmp_var->name_len = name_len;
1656
1624
tmp_var->str_val_len = val_len;
1657
1625
tmp_var->alloced_len = val_alloc_len;
1658
tmp_var->int_val = (val) ? atoi(val) : 0;
1659
tmp_var->int_dirty = 0;
1626
tmp_var->int_val = val ? atoi(val) : 0;
1627
tmp_var->int_dirty = false;
1660
1628
tmp_var->env_s = 0;
1661
1629
return tmp_var;
1665
void var_free(pair<string, VAR *> v)
1667
free(v.second->str_val);
1668
free(v.second->env_s);
1669
if (v.second->alloced)
1674
1632
VAR* var_from_env(const char *name, const char *def_val)
1678
if (!(tmp = getenv(name)))
1634
const char *tmp= getenv(name);
1681
v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1682
string var_name(name);
1683
var_hash.insert(make_pair(var_name, v));
1637
return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
1688
1640
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1689
1641
bool ignore_not_existing)
1694
1645
if (*var_name != '$')
1696
1647
digit = *++var_name - '0';
1712
1663
die("Too long variable name: %s", save_var_name);
1714
1665
string save_var_name_str(save_var_name, length);
1715
boost::unordered_map<string, VAR*>::iterator iter=
1716
var_hash.find(save_var_name_str);
1717
if (iter == var_hash.end())
1666
if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, save_var_name_str))
1719
1670
char buff[MAX_VAR_NAME_LENGTH+1];
1720
1671
strncpy(buff, save_var_name, length);
1721
1672
buff[length]= '\0';
1722
1673
v= var_from_env(buff, "");
1728
1675
var_name--; /* Point at last character */
1731
v = var_reg + digit;
1678
v = &var_reg[digit];
1733
1680
if (!raw && v->int_dirty)
1750
1697
static VAR *var_obtain(const char *name, int len)
1752
1699
string var_name(name, len);
1753
boost::unordered_map<string, VAR*>::iterator iter=
1754
var_hash.find(var_name);
1755
if (iter != var_hash.end())
1756
return (*iter).second;
1757
VAR *v = var_init(0, name, len, "", 0);
1758
var_hash.insert(make_pair(var_name, v));
1700
if (var_hash_t::mapped_type* ptr= find_ptr(var_hash, var_name))
1702
return var_hash[var_name] = var_init(0, name, len, "", 0);
2162
2103
internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2164
if (cur_file == file_stack_end)
2106
if (cur_file == &*file_stack.end())
2165
2107
die("Source directives are nesting too deep");
2167
2108
if (!(cur_file->file= fopen(buff, "r")))
3340
3270
sleep_val= opt_sleep;
3343
usleep((uint32_t) (sleep_val * 1000000L));
3273
usleep(sleep_val * 1000000);
3344
3274
command->last_argument= sleep_end;
3349
static void do_get_file_name(struct st_command *command, string &dest)
3279
static void do_get_file_name(st_command *command, string &dest)
3351
char *p= command->first_argument, *name;
3281
char *p= command->first_argument;
3353
3283
die("Missing file name argument");
3355
3285
while (*p && !my_isspace(charset_info,*p))
3426
3356
and assign that string to the $variable
3428
3358
size_t *lengths= drizzle_row_field_sizes(&res);
3429
const std::string error_name(row[0], lengths[0]);
3430
const std::string error_code(row[1], lengths[1]);
3434
global_error_names.insert(ErrorCodes::value_type(error_name,
3435
boost::lexical_cast<uint32_t>(error_code)));
3361
global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3437
3363
catch (boost::bad_lexical_cast &ex)
3445
3371
drizzle_result_free(&res);
3448
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3374
static uint32_t get_errcode_from_name(const char *error_name, const char *error_end)
3450
size_t err_name_len= error_end - error_name;
3451
string error_name_s(error_name, err_name_len);
3376
string error_name_s(error_name, error_end);
3453
ErrorCodes::iterator it= global_error_names.find(error_name_s);
3454
if (it != global_error_names.end())
3456
return (*it).second;
3378
if (ErrorCodes::mapped_type* ptr= find_ptr(global_error_names, error_name_s))
3459
3381
die("Unknown SQL error name '%s'", error_name_s.c_str());
3526
3448
die("The error name definition must start with an uppercase E");
3452
/* Error name string */
3454
to->code.errnum= get_errcode_from_name(p, end);
3455
to->type= ERR_ERRNO;
3532
/* Check that the string passed to str2int only contain digits */
3533
while (*p && p != end)
3535
if (!my_isdigit(charset_info, *p))
3536
die("Invalid argument to error: '%s' - " \
3537
"the errno may only consist of digits[0-9]",
3538
command->first_argument);
3542
/* Convert the sting to int */
3543
istringstream buff(start);
3544
if ((buff >> val).fail())
3545
die("Invalid argument to error: '%s'", command->first_argument);
3547
to->code.errnum= (uint32_t) val;
3548
to->type= ERR_ERRNO;
3459
die ("You must either use the SQLSTATE or built in drizzle error label, numbers are not accepted");
3972
3882
end= con_options;
3973
3883
while (*end && !my_isspace(charset_info, *end))
3975
if (!strncmp(con_options, "SSL", 3))
3978
die("Illegal option to connect: %.*s",
3979
(int) (end - con_options), con_options);
3885
die("Illegal option to connect: %.*s",
3886
(int) (end - con_options), con_options);
3980
3887
/* Process next option */
3981
3888
con_options= end;
4223
static int my_strnncoll_simple(const CHARSET_INFO * const cs, const unsigned char *s, size_t slen,
4130
static int my_strnncoll_simple(const charset_info_st * const cs, const unsigned char *s, size_t slen,
4224
4131
const unsigned char *t, size_t tlen,
4225
4132
bool t_is_prefix)
4779
4686
for (i = 0; i < num_fields; i++)
4781
4688
column= drizzle_column_next(res);
4782
append_field(ds, i, column,
4783
(const char*)row[i], lengths[i], !row[i]);
4689
if (row[i] && (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY))
4691
if (boost::lexical_cast<uint32_t>(row[i]))
4693
if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4695
append_field(ds, i, column, "YES", 3, false);
4699
append_field(ds, i, column, "TRUE", 4, false);
4704
if ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
4706
append_field(ds, i, column, "NO", 2, false);
4710
append_field(ds, i, column, "FALSE", 5, false);
4716
append_field(ds, i, column,
4717
(const char*)row[i], lengths[i], !row[i]);
4785
4720
if (!display_result_vertically)
4786
4721
ds->append("\n");
4824
4759
ds->append("\t", 1);
4825
4760
replace_append_uint(ds, drizzle_column_size(column));
4826
4761
ds->append("\t", 1);
4827
replace_append_uint(ds, drizzle_column_max_size(column));
4762
if (drizzle_column_type(column) == DRIZZLE_COLUMN_TYPE_TINY)
4764
replace_append_uint(ds, 1);
4768
replace_append_uint(ds, drizzle_column_max_size(column));
4828
4770
ds->append("\t", 1);
4829
4771
ds->append((char*) ((drizzle_column_flags(column) & DRIZZLE_COLUMN_FLAGS_NOT_NULL) ? "N" : "Y"), 1);
4830
4772
ds->append("\t", 1);
5366
5308
save= command->query[command->first_word_len-1];
5367
5309
command->query[command->first_word_len-1]= 0;
5368
if (find_type(command->query, &command_typelib, 1+2) > 0)
5310
if (command_typelib.find_type(command->query, TYPELIB::e_default) > 0)
5369
5311
die("Extra delimiter \";\" found");
5370
5312
command->query[command->first_word_len-1]= save;
5587
5528
next_con= connections + 1;
5589
5530
/* Init file stack */
5590
memset(file_stack, 0, sizeof(file_stack));
5592
file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
5593
cur_file= file_stack;
5531
memset(file_stack.data(), 0, sizeof(file_stack));
5532
cur_file= file_stack.data();
5595
5534
/* Init block stack */
5596
5535
memset(block_stack, 0, sizeof(block_stack));
5631
5570
internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5632
assert(cur_file == file_stack && cur_file->file == 0);
5571
assert(cur_file == file_stack.data() && cur_file->file == 0);
5633
5572
if (!(cur_file->file= fopen(buff, "r")))
5635
5574
fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
6213
6152
start= buff= (char *)malloc(strlen(from)+1);
6217
6155
uint32_t column_number;
6219
to= get_string(&buff, &from, command);
6157
char *to= get_string(&buff, &from, command);
6220
6158
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6221
6159
die("Wrong column number to replace_column in '%s'", command->query);
6256
6190
/* Definitions for replace result */
6258
typedef struct st_pointer_array { /* when using array-strings */
6193
{ /* when using array-strings */
6196
int insert(char* name);
6200
memset(this, 0, sizeof(*this));
6259
6203
TYPELIB typelib; /* Pointer to strings */
6260
unsigned char *str; /* Strings is here */
6261
uint8_t *flag; /* Flag about each var. */
6262
uint32_t array_allocs,max_count,length,max_length;
6204
unsigned char *str; /* Strings is here */
6205
uint8_t* flag; /* Flag about each var. */
6206
uint32_t array_allocs;
6209
uint32_t max_length;
6265
6212
struct st_replace;
6266
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
6267
char * word_end_chars);
6268
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6213
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6214
char *word_end_chars);
6269
6216
void replace_strings_append(struct st_replace *rep, string* ds,
6270
6217
const char *from, int len);
6271
void free_pointer_array(POINTER_ARRAY *pa);
6273
struct st_replace *glob_replace= NULL;
6219
st_replace *glob_replace= NULL;
6220
// boost::scoped_ptr<st_replace> glob_replace;
6276
6223
Get arguments for replace. The syntax is:
6280
6227
variable is replaced.
6283
void do_get_replace(struct st_command *command)
6230
POINTER_ARRAY::~POINTER_ARRAY()
6235
free((char*) typelib.type_names);
6236
typelib.type_names=0;
6240
void do_get_replace(st_command *command)
6286
6242
char *from= command->first_argument;
6288
char word_end_chars[256], *pos;
6244
die("Missing argument in %s", command->query);
6289
6246
POINTER_ARRAY to_array, from_array;
6294
memset(&to_array, 0, sizeof(to_array));
6295
memset(&from_array, 0, sizeof(from_array));
6297
die("Missing argument in %s", command->query);
6298
start= buff= (char *)malloc(strlen(from)+1);
6247
char* start= (char*)malloc(strlen(from) + 1);
6302
to= get_string(&buff, &from, command);
6251
char *to= get_string(&buff, &from, command);
6304
die("Wrong number of arguments to replace_result in '%s'",
6306
insert_pointer_name(&from_array,to);
6253
die("Wrong number of arguments to replace_result in '%s'", command->query);
6254
from_array.insert(to);
6307
6255
to= get_string(&buff, &from, command);
6308
insert_pointer_name(&to_array,to);
6256
to_array.insert(to);
6310
for (i= 1,pos= word_end_chars ; i < 256 ; i++)
6311
if (my_isspace(charset_info,i))
6258
char word_end_chars[256];
6259
char* pos= word_end_chars;
6260
for (int i= 1; i < 256; i++)
6262
if (my_isspace(charset_info, i))
6313
6265
*pos=0; /* End pointer */
6314
if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
6315
(char**) to_array.typelib.type_names,
6316
(uint32_t) from_array.typelib.count,
6266
if (!(glob_replace= init_replace(from_array.typelib.type_names,
6267
to_array.typelib.type_names,
6268
from_array.typelib.count,
6317
6269
word_end_chars)))
6318
6270
die("Can't initialize replace from '%s'", command->query);
6319
free_pointer_array(&from_array);
6320
free_pointer_array(&to_array);
6322
6272
command->last_argument= command->end;
6417
6364
st_regex substition. At the end of substitutions buf points to the
6418
6365
one containing the final result.
6367
typedef vector<st_regex> regex_arr_t;
6421
6370
char* even_buf;
6423
6372
int even_buf_len;
6424
6373
int odd_buf_len;
6374
boost::array<char, 8 << 10> buf0_;
6375
boost::array<char, 8 << 10> buf1_;
6376
regex_arr_t regex_arr;
6427
struct st_replace_regex *glob_replace_regex= 0;
6379
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
6429
6381
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6430
6382
char *string, int icase, int global);
6466
6418
Returns: st_replace_regex struct with pairs of substitutions
6469
static struct st_replace_regex* init_replace_regex(char* expr)
6421
st_replace_regex::st_replace_regex(char* expr)
6471
struct st_replace_regex* res;
6472
char* buf,*expr_end;
6475
6423
uint32_t expr_len= strlen(expr);
6476
6424
char last_c = 0;
6477
struct st_regex reg;
6479
res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
6482
my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
6484
buf= (char*)res + sizeof(*res);
6485
expr_end= expr + expr_len;
6427
char* buf= new char[expr_len];
6428
char* expr_end= expr + expr_len;
6489
6432
/* for each regexp substitution statement */
6490
6433
while (p < expr_end)
6543
/* done parsing the statement, now place it in regex_arr */
6544
if (insert_dynamic(&res->regex_arr,(unsigned char*) ®))
6545
die("Out of memory");
6485
regex_arr.push_back(reg);
6547
res->odd_buf_len= res->even_buf_len= 8192;
6548
res->even_buf= (char*)malloc(res->even_buf_len);
6549
res->odd_buf= (char*)malloc(res->odd_buf_len);
6550
res->buf= res->even_buf;
6487
odd_buf_len= even_buf_len= buf0_.size();
6488
even_buf= buf0_.data();
6489
odd_buf= buf1_.data();
6556
6495
die("Error parsing replace_regex \"%s\"", expr);
6579
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6517
int st_replace_regex::multi_reg_replace(char* val)
6582
char* in_buf, *out_buf;
6586
out_buf= r->even_buf;
6587
buf_len_p= &r->even_buf_len;
6520
char* out_buf= even_buf;
6521
int* buf_len_p= &even_buf_len;
6590
6524
/* For each substitution, do the replace */
6591
for (i= 0; i < r->regex_arr.elements; i++)
6525
BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
6594
6527
char* save_out_buf= out_buf;
6596
get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
6598
if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6599
in_buf, re.icase, re.global))
6528
if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6529
in_buf, i.icase, i.global))
6601
6531
/* if the buffer has been reallocated, make adjustements */
6602
6532
if (save_out_buf != out_buf)
6604
if (save_out_buf == r->even_buf)
6605
r->even_buf= out_buf;
6534
if (save_out_buf == even_buf)
6607
r->odd_buf= out_buf;
6611
6540
if (in_buf == val)
6614
std::swap(in_buf,out_buf);
6616
buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6542
std::swap(in_buf, out_buf);
6543
buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
6621
return (r->buf == 0);
6633
6558
void do_get_replace_regex(struct st_command *command)
6635
6560
char *expr= command->first_argument;
6636
free_replace_regex();
6637
if (!(glob_replace_regex=init_replace_regex(expr)))
6638
die("Could not init replace_regex");
6561
glob_replace_regex.reset(new st_replace_regex(expr));
6639
6562
command->last_argument= command->end;
6642
void free_replace_regex()
6644
if (glob_replace_regex)
6646
delete_dynamic(&glob_replace_regex->regex_arr);
6647
free(glob_replace_regex->even_buf);
6648
free(glob_replace_regex->odd_buf);
6649
free(glob_replace_regex);
6650
glob_replace_regex=0;
6657
6566
Performs a regex substitution
6759
6668
#define SET_MALLOC_HUNC 64
6760
6669
#define LAST_CHAR_CODE 259
6762
typedef struct st_rep_set {
6674
void internal_set_bit(uint32_t bit);
6675
void internal_clear_bit(uint32_t bit);
6676
void or_bits(const REP_SET *from);
6677
void copy_bits(const REP_SET *from);
6678
int cmp_bits(const REP_SET *set2) const;
6679
int get_next_bit(uint32_t lastpos) const;
6763
6681
uint32_t *bits; /* Pointer to used sets */
6764
6682
short next[LAST_CHAR_CODE]; /* Pointer to next sets */
6765
6683
uint32_t found_len; /* Best match to date */
6766
6684
int found_offset;
6767
6685
uint32_t table_offset;
6768
6686
uint32_t size_of_bits; /* For convinience */
6771
typedef struct st_rep_sets {
6692
int find_set(const REP_SET *find);
6693
void free_last_set();
6695
void make_sets_invisible();
6772
6697
uint32_t count; /* Number of sets */
6773
6698
uint32_t extra; /* Extra sets in buffer */
6774
uint32_t invisible; /* Sets not chown */
6699
uint32_t invisible; /* Sets not shown */
6775
6700
uint32_t size_of_bits;
6776
6701
REP_SET *set,*set_buffer;
6777
6702
uint32_t *bit_buffer;
6780
typedef struct st_found_set {
6781
6707
uint32_t table_offset;
6782
6708
int found_offset;
6785
typedef struct st_follow {
6787
6714
uint32_t table_offset;
6792
int init_sets(REP_SETS *sets,uint32_t states);
6718
int init_sets(REP_SETS *sets, uint32_t states);
6793
6719
REP_SET *make_new_set(REP_SETS *sets);
6794
void make_sets_invisible(REP_SETS *sets);
6795
void free_last_set(REP_SETS *sets);
6796
void free_sets(REP_SETS *sets);
6797
void internal_set_bit(REP_SET *set, uint32_t bit);
6798
void internal_clear_bit(REP_SET *set, uint32_t bit);
6799
void or_bits(REP_SET *to,REP_SET *from);
6800
void copy_bits(REP_SET *to,REP_SET *from);
6801
int cmp_bits(REP_SET *set1,REP_SET *set2);
6802
int get_next_bit(REP_SET *set,uint32_t lastpos);
6803
int find_set(REP_SETS *sets,REP_SET *find);
6804
int find_found(FOUND_SET *found_set,uint32_t table_offset,
6806
uint32_t start_at_word(char * pos);
6807
uint32_t end_of_word(char * pos);
6809
static uint32_t found_sets=0;
6812
static uint32_t replace_len(char * str)
6720
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6722
static uint32_t found_sets= 0;
6724
static uint32_t replace_len(const char *str)
6814
6726
uint32_t len=0;
6737
/* Return 1 if regexp starts with \b or ends with \b*/
6739
static bool start_at_word(const char *pos)
6741
return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6744
static bool end_of_word(const char *pos)
6746
const char *end= strchr(pos, '\0');
6747
return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6825
6750
/* Init a replace structure for further calls */
6827
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
6828
char * word_end_chars)
6752
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
6830
static const int SPACE_CHAR= 256;
6831
static const int START_OF_LINE= 257;
6832
static const int END_OF_LINE= 258;
6754
const int SPACE_CHAR= 256;
6755
const int START_OF_LINE= 257;
6756
const int END_OF_LINE= 258;
6834
6758
uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6835
6759
int used_sets,chr,default_state;
6836
6760
char used_chars[LAST_CHAR_CODE],is_word_end[256];
6837
char * pos, *to_pos, **to_array;
6839
REP_SET *set,*start_states,*word_states,*new_set;
6840
FOLLOWS *follow,*follow_ptr;
6842
FOUND_SET *found_set;
6843
REPLACE_STRING *rep_str;
6761
char *to_pos, **to_array;
6846
6763
/* Count number of states */
6847
6764
for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6861
6778
for (i=0 ; word_end_chars[i] ; i++)
6862
6779
is_word_end[(unsigned char) word_end_chars[i]]=1;
6864
if (init_sets(&sets,states))
6782
REP_SET *set,*start_states,*word_states,*new_set;
6783
REPLACE_STRING *rep_str;
6784
if (init_sets(&sets, states))
6867
if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
6787
vector<FOUND_SET> found_set(max_length * count);
6873
6788
make_new_set(&sets); /* Set starting set */
6874
make_sets_invisible(&sets); /* Hide previus sets */
6789
sets.make_sets_invisible(); /* Hide previus sets */
6876
6791
word_states=make_new_set(&sets); /* Start of new word */
6877
6792
start_states=make_new_set(&sets); /* This is first state */
6878
if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
6793
vector<FOLLOWS> follow(states + 2);
6794
FOLLOWS *follow_ptr= &follow[1];
6885
6795
/* Init follow_ptr[] */
6886
for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6796
for (i=0, states=1; i < count; i++)
6888
6798
if (from[i][0] == '\\' && from[i][1] == '^')
6890
internal_set_bit(start_states,states+1);
6800
start_states->internal_set_bit(states + 1);
6891
6801
if (!from[i][2])
6893
6803
start_states->table_offset=i;
6897
6807
else if (from[i][0] == '\\' && from[i][1] == '$')
6899
internal_set_bit(start_states,states);
6900
internal_set_bit(word_states,states);
6809
start_states->internal_set_bit(states);
6810
word_states->internal_set_bit(states);
6901
6811
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6903
6813
start_states->table_offset=i;
6909
internal_set_bit(word_states,states);
6819
word_states->internal_set_bit(states);
6910
6820
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6911
internal_set_bit(start_states,states+1);
6821
start_states->internal_set_bit(states + 1);
6913
internal_set_bit(start_states,states);
6823
start_states->internal_set_bit(states);
6915
for (pos=from[i], len=0; *pos ; pos++)
6826
for (pos= from[i], len=0; *pos ; pos++)
6917
6828
if (*pos == '\\' && *(pos+1))
6958
for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6869
for (set_nr=0; set_nr < sets.count ; set_nr++)
6960
6871
set=sets.set+set_nr;
6961
6872
default_state= 0; /* Start from beginning */
6963
6874
/* If end of found-string not found or start-set with current set */
6965
for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6876
for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
6969
if (! default_state)
6970
default_state= find_found(found_set,set->table_offset,
6971
set->found_offset+1);
6878
if (!follow[i].chr && !default_state)
6879
default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
6974
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6881
sets.set[used_sets].copy_bits(set); /* Save set for changes */
6975
6882
if (!default_state)
6976
or_bits(sets.set+used_sets,sets.set); /* Can restart from start */
6883
sets.set[used_sets].or_bits(sets.set); /* Can restart from start */
6978
6885
/* Find all chars that follows current sets */
6979
6886
memset(used_chars, 0, sizeof(used_chars));
6980
for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6887
for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
6982
6889
used_chars[follow[i].chr]=1;
6983
6890
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
7016
6923
follow[i].len > found_end)
7017
6924
found_end=follow[i].len;
7018
6925
if (chr && follow[i].chr)
7019
internal_set_bit(new_set,i+1); /* To next set */
6926
new_set->internal_set_bit(i + 1); /* To next set */
7021
internal_set_bit(new_set,i);
6928
new_set->internal_set_bit(i);
7026
6933
new_set->found_len=0; /* Set for testing if first */
7028
for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6935
for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
7030
6937
if ((follow[i].chr == SPACE_CHAR ||
7031
6938
follow[i].chr == END_OF_LINE) && ! chr)
7052
6959
if (bits_set == 1)
7054
set->next[chr] = find_found(found_set,
7055
new_set->table_offset,
7056
new_set->found_offset);
7057
free_last_set(&sets);
6961
set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6962
sets.free_last_set();
7060
set->next[chr] = find_set(&sets,new_set);
6965
set->next[chr] = sets.find_set(new_set);
7063
set->next[chr] = find_set(&sets,new_set);
6968
set->next[chr] = sets.find_set(new_set);
7068
6973
/* Alloc replace structure for the replace-state-machine */
7070
if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
7071
sizeof(REPLACE_STRING)*(found_sets+1)+
7072
sizeof(char *)*count+result_len)))
6975
REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6976
+ sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
7074
6979
memset(replace, 0, sizeof(REPLACE)*(sets.count)+
7075
6980
sizeof(REPLACE_STRING)*(found_sets+1)+
7086
6991
rep_str[0].replace_string=0;
7087
6992
for (i=1 ; i <= found_sets ; i++)
7089
pos=from[found_set[i-1].table_offset];
6994
const char *pos= from[found_set[i-1].table_offset];
7090
6995
rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
7091
rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
7092
rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
7093
rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
6996
rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
6997
rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
6998
rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
7096
7000
for (i=0 ; i < sets.count ; i++)
7168
7070
return make_new_set(sets);
7171
void free_last_set(REP_SETS *sets)
7178
void free_sets(REP_SETS *sets)
7180
free(sets->set_buffer);
7181
free(sets->bit_buffer);
7185
void internal_set_bit(REP_SET *set, uint32_t bit)
7187
set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7191
void internal_clear_bit(REP_SET *set, uint32_t bit)
7193
set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7198
void or_bits(REP_SET *to,REP_SET *from)
7200
register uint32_t i;
7201
for (i=0 ; i < to->size_of_bits ; i++)
7202
to->bits[i]|=from->bits[i];
7206
void copy_bits(REP_SET *to,REP_SET *from)
7208
memcpy(to->bits,from->bits,
7209
(size_t) (sizeof(uint32_t) * to->size_of_bits));
7212
int cmp_bits(REP_SET *set1,REP_SET *set2)
7214
return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
7073
void REP_SETS::free_last_set()
7079
void REP_SETS::free_sets()
7085
void REP_SET::internal_set_bit(uint32_t bit)
7087
bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7090
void REP_SET::internal_clear_bit(uint32_t bit)
7092
bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7096
void REP_SET::or_bits(const REP_SET *from)
7098
for (uint32_t i= 0 ; i < size_of_bits; i++)
7099
bits[i]|=from->bits[i];
7102
void REP_SET::copy_bits(const REP_SET *from)
7104
memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
7107
int REP_SET::cmp_bits(const REP_SET *set2) const
7109
return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
7218
7112
/* Get next set bit from set. */
7220
int get_next_bit(REP_SET *set,uint32_t lastpos)
7114
int REP_SET::get_next_bit(uint32_t lastpos) const
7222
uint32_t pos,*start,*end,bits;
7224
start=set->bits+ ((lastpos+1) / WORD_BIT);
7225
end=set->bits + set->size_of_bits;
7226
bits=start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7228
while (! bits && ++start < end)
7116
uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
7117
uint32_t *end= bits + size_of_bits;
7118
uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7120
while (!bits0 && ++start < end)
7232
pos=(uint32_t) (start-set->bits)*WORD_BIT;
7233
while (! (bits & 1))
7124
uint32_t pos= (start - bits) * WORD_BIT;
7125
while (!(bits0 & 1))
7242
7134
free given set, else put in given set in sets and return its
7245
int find_set(REP_SETS *sets,REP_SET *find)
7137
int REP_SETS::find_set(const REP_SET *find)
7248
for (i=0 ; i < sets->count-1 ; i++)
7140
for (; i < count - 1; i++)
7250
if (!cmp_bits(sets->set+i,find))
7142
if (!set[i].cmp_bits(find))
7252
free_last_set(sets);
7263
7155
set->next[] == -1 is reserved for end without replaces.
7266
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7158
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
7269
for (i=0 ; (uint32_t) i < found_sets ; i++)
7161
for (; i < found_sets; i++)
7270
7163
if (found_set[i].table_offset == table_offset &&
7271
7164
found_set[i].found_offset == found_offset)
7273
found_set[i].table_offset=table_offset;
7274
found_set[i].found_offset=found_offset;
7167
found_set[i].table_offset= table_offset;
7168
found_set[i].found_offset= found_offset;
7276
return -i-2; /* return new postion */
7279
/* Return 1 if regexp starts with \b or ends with \b*/
7281
uint32_t start_at_word(char * pos)
7283
return (((!memcmp(pos, "\\b",2) && pos[2]) ||
7284
!memcmp(pos, "\\^", 2)) ? 1 : 0);
7287
uint32_t end_of_word(char * pos)
7289
char * end= strchr(pos, '\0');
7290
return ((end > pos+2 && !memcmp(end-2, "\\b", 2)) ||
7291
(end >= pos+2 && !memcmp(end-2, "\\$",2))) ? 1 : 0;
7170
return - i - 2; // return new postion
7294
7173
/****************************************************************************
7298
7177
#define PC_MALLOC 256 /* Bytes for pointers */
7299
7178
#define PS_MALLOC 512 /* Bytes for data */
7301
int insert_pointer_name(POINTER_ARRAY *pa,char * name)
7180
static int insert_pointer_name(POINTER_ARRAY* pa, char* name)
7303
7182
uint32_t i,length,old_count;
7304
7183
unsigned char *new_pos;
7367
7246
} /* insert_pointer_name */
7370
/* free pointer array */
7372
void free_pointer_array(POINTER_ARRAY *pa)
7248
int POINTER_ARRAY::insert(char* name)
7374
if (pa->typelib.count)
7376
pa->typelib.count=0;
7377
free((char*) pa->typelib.type_names);
7378
pa->typelib.type_names=0;
7381
} /* free_pointer_array */
7250
return insert_pointer_name(this, name);
7384
7254
/* Functions that uses replace and replace_regex */
7386
7256
/* Append the string to ds, with optional replace */
7387
void replace_append_mem(string *ds,
7388
const char *val, int len)
7257
void replace_append_mem(string *ds, const char *val, int len)
7390
7259
char *v= strdup(val);
7392
if (glob_replace_regex)
7261
if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
7395
if (!multi_reg_replace(glob_replace_regex, v))
7397
v= glob_replace_regex->buf;
7263
v= glob_replace_regex->buf_;
7402
7266
if (glob_replace)
7404
7268
/* Normal replace */
7405
7269
replace_strings_append(glob_replace, ds, v, len);
7409
7272
ds->append(v, len);