165
169
uint32_t lineno; /* Current line in 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;
172
static boost::array<st_test_file, 16> file_stack;
173
static st_test_file* cur_file;
173
175
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
179
181
static char *timer_file = NULL;
180
182
static uint64_t timer_start;
181
static void timer_output(void);
182
static uint64_t timer_now(void);
183
static void timer_output();
184
static uint64_t timer_now();
184
186
static uint64_t progress_start= 0;
390
393
struct st_match_err err[10];
393
static struct st_expected_errors saved_expected_errors;
397
static st_expected_errors saved_expected_errors;
397
402
char *query, *query_buf,*first_argument,*last_argument,*end;
398
403
int first_word_len, query_len;
399
404
bool abort_on_error;
400
405
st_expected_errors expected_errors;
401
406
string require_file;
402
enum enum_commands type;
405
410
: query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
439
441
VAR* var_from_env(const char *, const char *);
440
442
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
442
void var_free(pair<string, VAR*> v);
443
444
VAR* var_get(const char *var_name, const char** var_name_end,
444
445
bool raw, bool ignore_not_existing);
445
446
void eval_expr(VAR* v, const char *p, const char** p_end);
446
447
bool match_delimiter(int c, const char *delim, uint32_t length);
447
448
void dump_result_to_reject_file(char *buf, int size);
448
449
void dump_result_to_log_file(const char *buf, int size);
449
void dump_warning_messages(void);
450
void dump_progress(void);
450
void dump_warning_messages();
451
void dump_progress();
452
453
void do_eval(string *query_eval, const char *query,
453
454
const char *query_end, bool pass_through_escape_chars);
458
459
static char *replace_column[MAX_COLUMNS];
459
460
static uint32_t max_replace_column= 0;
460
461
void do_get_replace_column(struct st_command*);
461
void free_replace_column(void);
462
void free_replace_column();
463
464
/* For replace */
464
465
void do_get_replace(struct st_command *command);
465
void free_replace(void);
467
468
/* For replace_regex */
468
469
void do_get_replace_regex(struct st_command *command);
469
void free_replace_regex(void);
472
void free_all_replace(void);
475
void free_all_replace(void){
477
free_replace_regex();
478
free_replace_column();
481
471
void replace_append_mem(string *ds, const char *val,
885
873
free(next_con->name);
891
static void close_files(void)
878
static void close_files()
894
for (; cur_file >= file_stack; cur_file--)
880
for (; cur_file >= file_stack.data(); cur_file--)
896
882
if (cur_file->file && cur_file->file != stdin)
898
883
fclose(cur_file->file);
900
free((unsigned char*) cur_file->file_name);
884
free(const_cast<char*>(cur_file->file_name));
901
885
cur_file->file_name= 0;
907
static void free_used_memory(void)
889
static void free_used_memory()
912
891
close_connections();
914
for_each(var_hash.begin(), var_hash.end(), var_free);
893
BOOST_FOREACH(var_hash_t::reference i, var_hash)
895
free(i.second->str_val);
896
free(i.second->env_s);
897
if (i.second->alloced)
915
900
var_hash.clear();
917
vector<st_command *>::iterator iter;
918
for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
920
struct st_command * q_line= *iter;
924
for (i= 0; i < 10; i++)
901
BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
903
for (size_t i= 0; i < var_reg.size(); i++)
926
905
if (var_reg[i].alloced_len)
927
906
free(var_reg[i].str_val);
930
908
free_all_replace();
1037
1012
/* Print include filestack */
1038
1013
fprintf(stderr, "The test '%s' is not supported by this installation\n",
1039
file_stack->file_name);
1014
file_stack[0].file_name);
1040
1015
fprintf(stderr, "Detected in file %s at line %d\n",
1041
1016
err_file->file_name, err_file->lineno);
1042
while (err_file != file_stack)
1017
while (err_file != file_stack.data())
1045
1020
fprintf(stderr, "included from %s at line %d\n",
1628
1601
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1633
1604
if (!name_len && name)
1634
1605
name_len = strlen(name);
1635
1606
if (!val_len && val)
1636
1607
val_len = strlen(val) ;
1637
val_alloc_len = val_len + 16; /* room to grow */
1638
if (!(tmp_var=v) && !(tmp_var = (VAR*)malloc(sizeof(*tmp_var)
1640
die("Out of memory");
1608
VAR *tmp_var = v ? v : (VAR*)malloc(sizeof(*tmp_var) + name_len+1);
1642
tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
1610
tmp_var->name = name ? (char*)&tmp_var[1] : 0;
1643
1611
tmp_var->alloced = (v == 0);
1645
if (!(tmp_var->str_val = (char *)malloc(val_alloc_len+1)))
1646
die("Out of memory");
1613
int val_alloc_len = val_len + 16; /* room to grow */
1614
tmp_var->str_val = (char*)malloc(val_alloc_len+1);
1648
1616
memcpy(tmp_var->name, name, name_len);
1654
1622
tmp_var->name_len = name_len;
1655
1623
tmp_var->str_val_len = val_len;
1656
1624
tmp_var->alloced_len = val_alloc_len;
1657
tmp_var->int_val = (val) ? atoi(val) : 0;
1658
tmp_var->int_dirty = 0;
1625
tmp_var->int_val = val ? atoi(val) : 0;
1626
tmp_var->int_dirty = false;
1659
1627
tmp_var->env_s = 0;
1660
1628
return tmp_var;
1664
void var_free(pair<string, VAR *> v)
1666
free(v.second->str_val);
1667
free(v.second->env_s);
1668
if (v.second->alloced)
1673
1631
VAR* var_from_env(const char *name, const char *def_val)
1677
if (!(tmp = getenv(name)))
1633
const char *tmp= getenv(name);
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));
1636
return var_hash[name] = var_init(0, name, strlen(name), tmp, strlen(tmp));
1687
1639
VAR* var_get(const char *var_name, const char **var_name_end, bool raw,
1688
1640
bool ignore_not_existing)
1693
1644
if (*var_name != '$')
1695
1646
digit = *++var_name - '0';
1711
1662
die("Too long variable name: %s", save_var_name);
1713
1664
string save_var_name_str(save_var_name, length);
1714
boost::unordered_map<string, VAR*>::iterator iter=
1715
var_hash.find(save_var_name_str);
1665
var_hash_t::iterator iter= var_hash.find(save_var_name_str);
1716
1666
if (iter == var_hash.end())
1718
1668
char buff[MAX_VAR_NAME_LENGTH+1];
1749
1699
static VAR *var_obtain(const char *name, int len)
1751
1701
string var_name(name, len);
1752
boost::unordered_map<string, VAR*>::iterator iter=
1753
var_hash.find(var_name);
1702
var_hash_t::iterator iter= var_hash.find(var_name);
1754
1703
if (iter != var_hash.end())
1755
return (*iter).second;
1756
VAR *v = var_init(0, name, len, "", 0);
1757
var_hash.insert(make_pair(var_name, v));
1704
return iter->second;
1705
return var_hash[var_name] = var_init(0, name, len, "", 0);
2161
2106
internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2163
if (cur_file == file_stack_end)
2109
if (cur_file == &*file_stack.end())
2164
2110
die("Source directives are nesting too deep");
2166
2111
if (!(cur_file->file= fopen(buff, "r")))
3329
3273
sleep_val= opt_sleep;
3332
usleep((uint32_t) (sleep_val * 1000000L));
3276
usleep(sleep_val * 1000000);
3333
3277
command->last_argument= sleep_end;
3338
static void do_get_file_name(struct st_command *command, string &dest)
3282
static void do_get_file_name(st_command *command, string &dest)
3340
char *p= command->first_argument, *name;
3284
char *p= command->first_argument;
3342
3286
die("Missing file name argument");
3344
3288
while (*p && !my_isspace(charset_info,*p))
3415
3359
and assign that string to the $variable
3417
3361
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]);
3423
global_error_names.insert(ErrorCodes::value_type(error_name,
3424
boost::lexical_cast<uint32_t>(error_code)));
3364
global_error_names[string(row[0], lengths[0])] = boost::lexical_cast<uint32_t>(string(row[1], lengths[1]));
3426
3366
catch (boost::bad_lexical_cast &ex)
5565
5502
next_con= connections + 1;
5567
5504
/* Init file stack */
5568
memset(file_stack, 0, sizeof(file_stack));
5570
file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
5571
cur_file= file_stack;
5505
memset(file_stack.data(), 0, sizeof(file_stack));
5506
cur_file= file_stack.data();
5573
5508
/* Init block stack */
5574
5509
memset(block_stack, 0, sizeof(block_stack));
5609
5544
internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5610
assert(cur_file == file_stack && cur_file->file == 0);
5545
assert(cur_file == file_stack.data() && cur_file->file == 0);
5611
5546
if (!(cur_file->file= fopen(buff, "r")))
5613
5548
fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
6191
6126
start= buff= (char *)malloc(strlen(from)+1);
6195
6129
uint32_t column_number;
6197
to= get_string(&buff, &from, command);
6131
char *to= get_string(&buff, &from, command);
6198
6132
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
6199
6133
die("Wrong column number to replace_column in '%s'", command->query);
6241
6171
} POINTER_ARRAY;
6243
6173
struct st_replace;
6244
struct st_replace *init_replace(char * *from, char * *to, uint32_t count,
6245
char * word_end_chars);
6174
struct st_replace *init_replace(const char **from, const char **to, uint32_t count,
6175
char *word_end_chars);
6246
6176
int insert_pointer_name(POINTER_ARRAY *pa,char * name);
6247
6177
void replace_strings_append(struct st_replace *rep, string* ds,
6248
6178
const char *from, int len);
6249
void free_pointer_array(POINTER_ARRAY *pa);
6251
struct st_replace *glob_replace= NULL;
6180
st_replace *glob_replace= NULL;
6181
// boost::scoped_ptr<st_replace> glob_replace;
6254
6184
Get arguments for replace. The syntax is:
6289
6229
if (my_isspace(charset_info,i))
6291
6231
*pos=0; /* End pointer */
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,
6232
if (!(glob_replace= init_replace(from_array.typelib.type_names,
6233
to_array.typelib.type_names,
6234
from_array.typelib.count,
6295
6235
word_end_chars)))
6296
6236
die("Can't initialize replace from '%s'", command->query);
6297
6237
free_pointer_array(&from_array);
6395
6332
st_regex substition. At the end of substitutions buf points to the
6396
6333
one containing the final result.
6335
typedef vector<st_regex> regex_arr_t;
6399
6338
char* even_buf;
6401
6340
int even_buf_len;
6402
6341
int odd_buf_len;
6342
boost::array<char, 8 << 10> buf0_;
6343
boost::array<char, 8 << 10> buf1_;
6344
regex_arr_t regex_arr;
6405
struct st_replace_regex *glob_replace_regex= 0;
6347
boost::scoped_ptr<st_replace_regex> glob_replace_regex;
6407
6349
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6408
6350
char *string, int icase, int global);
6444
6386
Returns: st_replace_regex struct with pairs of substitutions
6447
static struct st_replace_regex* init_replace_regex(char* expr)
6389
st_replace_regex::st_replace_regex(char* expr)
6449
struct st_replace_regex* res;
6450
char* buf,*expr_end;
6453
6391
uint32_t expr_len= strlen(expr);
6454
6392
char last_c = 0;
6455
struct st_regex reg;
6457
res=(st_replace_regex*)malloc(sizeof(*res)+expr_len);
6460
my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
6462
buf= (char*)res + sizeof(*res);
6463
expr_end= expr + expr_len;
6395
char* buf= new char[expr_len];
6396
char* expr_end= expr + expr_len;
6467
6400
/* for each regexp substitution statement */
6468
6401
while (p < expr_end)
6521
/* done parsing the statement, now place it in regex_arr */
6522
if (insert_dynamic(&res->regex_arr,(unsigned char*) ®))
6523
die("Out of memory");
6453
regex_arr.push_back(reg);
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;
6455
odd_buf_len= even_buf_len= buf0_.size();
6456
even_buf= buf0_.data();
6457
odd_buf= buf1_.data();
6534
6463
die("Error parsing replace_regex \"%s\"", expr);
6557
static int multi_reg_replace(struct st_replace_regex* r,char* val)
6485
int st_replace_regex::multi_reg_replace(char* val)
6560
char* in_buf, *out_buf;
6564
out_buf= r->even_buf;
6565
buf_len_p= &r->even_buf_len;
6488
char* out_buf= even_buf;
6489
int* buf_len_p= &even_buf_len;
6568
6492
/* For each substitution, do the replace */
6569
for (i= 0; i < r->regex_arr.elements; i++)
6493
BOOST_FOREACH(regex_arr_t::const_reference i, regex_arr)
6572
6495
char* save_out_buf= out_buf;
6574
get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
6576
if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6577
in_buf, re.icase, re.global))
6496
if (!reg_replace(&out_buf, buf_len_p, i.pattern, i.replace,
6497
in_buf, i.icase, i.global))
6579
6499
/* if the buffer has been reallocated, make adjustements */
6580
6500
if (save_out_buf != out_buf)
6582
if (save_out_buf == r->even_buf)
6583
r->even_buf= out_buf;
6502
if (save_out_buf == even_buf)
6585
r->odd_buf= out_buf;
6589
6508
if (in_buf == val)
6592
std::swap(in_buf,out_buf);
6594
buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
6510
std::swap(in_buf, out_buf);
6511
buf_len_p= (out_buf == even_buf) ? &even_buf_len : &odd_buf_len;
6599
return (r->buf == 0);
6611
6526
void do_get_replace_regex(struct st_command *command)
6613
6528
char *expr= command->first_argument;
6614
free_replace_regex();
6615
if (!(glob_replace_regex=init_replace_regex(expr)))
6616
die("Could not init replace_regex");
6529
glob_replace_regex.reset(new st_replace_regex(expr));
6617
6530
command->last_argument= command->end;
6620
void free_replace_regex()
6622
if (glob_replace_regex)
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;
6635
6534
Performs a regex substitution
6737
6636
#define SET_MALLOC_HUNC 64
6738
6637
#define LAST_CHAR_CODE 259
6740
typedef struct st_rep_set {
6642
void internal_set_bit(uint32_t bit);
6643
void internal_clear_bit(uint32_t bit);
6644
void or_bits(const REP_SET *from);
6645
void copy_bits(const REP_SET *from);
6646
int cmp_bits(const REP_SET *set2) const;
6647
int get_next_bit(uint32_t lastpos) const;
6741
6649
uint32_t *bits; /* Pointer to used sets */
6742
6650
short next[LAST_CHAR_CODE]; /* Pointer to next sets */
6743
6651
uint32_t found_len; /* Best match to date */
6744
6652
int found_offset;
6745
6653
uint32_t table_offset;
6746
6654
uint32_t size_of_bits; /* For convinience */
6749
typedef struct st_rep_sets {
6660
int find_set(const REP_SET *find);
6661
void free_last_set();
6663
void make_sets_invisible();
6750
6665
uint32_t count; /* Number of sets */
6751
6666
uint32_t extra; /* Extra sets in buffer */
6752
uint32_t invisible; /* Sets not chown */
6667
uint32_t invisible; /* Sets not shown */
6753
6668
uint32_t size_of_bits;
6754
6669
REP_SET *set,*set_buffer;
6755
6670
uint32_t *bit_buffer;
6758
typedef struct st_found_set {
6759
6675
uint32_t table_offset;
6760
6676
int found_offset;
6763
typedef struct st_follow {
6765
6682
uint32_t table_offset;
6770
int init_sets(REP_SETS *sets,uint32_t states);
6686
int init_sets(REP_SETS *sets, uint32_t states);
6771
6687
REP_SET *make_new_set(REP_SETS *sets);
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,
6784
uint32_t start_at_word(char * pos);
6785
uint32_t end_of_word(char * pos);
6787
static uint32_t found_sets=0;
6790
static uint32_t replace_len(char * str)
6688
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset);
6690
static uint32_t found_sets= 0;
6692
static uint32_t replace_len(const char *str)
6792
6694
uint32_t len=0;
6705
/* Return 1 if regexp starts with \b or ends with \b*/
6707
static bool start_at_word(const char *pos)
6709
return ((!memcmp(pos, "\\b",2) && pos[2]) || !memcmp(pos, "\\^", 2));
6712
static bool end_of_word(const char *pos)
6714
const char *end= strchr(pos, '\0');
6715
return (end > pos+2 && !memcmp(end-2, "\\b", 2)) || (end >= pos+2 && !memcmp(end-2, "\\$",2));
6803
6718
/* Init a replace structure for further calls */
6805
REPLACE *init_replace(char * *from, char * *to,uint32_t count,
6806
char * word_end_chars)
6720
REPLACE *init_replace(const char **from, const char **to, uint32_t count, char *word_end_chars)
6808
static const int SPACE_CHAR= 256;
6809
static const int START_OF_LINE= 257;
6810
static const int END_OF_LINE= 258;
6722
const int SPACE_CHAR= 256;
6723
const int START_OF_LINE= 257;
6724
const int END_OF_LINE= 258;
6812
6726
uint32_t i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
6813
6727
int used_sets,chr,default_state;
6814
6728
char used_chars[LAST_CHAR_CODE],is_word_end[256];
6815
char * pos, *to_pos, **to_array;
6817
REP_SET *set,*start_states,*word_states,*new_set;
6818
FOLLOWS *follow,*follow_ptr;
6820
FOUND_SET *found_set;
6821
REPLACE_STRING *rep_str;
6729
char *to_pos, **to_array;
6824
6731
/* Count number of states */
6825
6732
for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
6839
6746
for (i=0 ; word_end_chars[i] ; i++)
6840
6747
is_word_end[(unsigned char) word_end_chars[i]]=1;
6842
if (init_sets(&sets,states))
6750
REP_SET *set,*start_states,*word_states,*new_set;
6751
REPLACE_STRING *rep_str;
6752
if (init_sets(&sets, states))
6845
if (!(found_set= (FOUND_SET*) malloc(sizeof(FOUND_SET)*max_length*count)))
6755
vector<FOUND_SET> found_set(max_length * count);
6851
6756
make_new_set(&sets); /* Set starting set */
6852
make_sets_invisible(&sets); /* Hide previus sets */
6757
sets.make_sets_invisible(); /* Hide previus sets */
6854
6759
word_states=make_new_set(&sets); /* Start of new word */
6855
6760
start_states=make_new_set(&sets); /* This is first state */
6856
if (!(follow=(FOLLOWS*) malloc((states+2)*sizeof(FOLLOWS))))
6761
vector<FOLLOWS> follow(states + 2);
6762
FOLLOWS *follow_ptr= &follow[1];
6863
6763
/* Init follow_ptr[] */
6864
for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
6764
for (i=0, states=1; i < count; i++)
6866
6766
if (from[i][0] == '\\' && from[i][1] == '^')
6868
internal_set_bit(start_states,states+1);
6768
start_states->internal_set_bit(states + 1);
6869
6769
if (!from[i][2])
6871
6771
start_states->table_offset=i;
6875
6775
else if (from[i][0] == '\\' && from[i][1] == '$')
6877
internal_set_bit(start_states,states);
6878
internal_set_bit(word_states,states);
6777
start_states->internal_set_bit(states);
6778
word_states->internal_set_bit(states);
6879
6779
if (!from[i][2] && start_states->table_offset == UINT32_MAX)
6881
6781
start_states->table_offset=i;
6887
internal_set_bit(word_states,states);
6787
word_states->internal_set_bit(states);
6888
6788
if (from[i][0] == '\\' && (from[i][1] == 'b' && from[i][2]))
6889
internal_set_bit(start_states,states+1);
6789
start_states->internal_set_bit(states + 1);
6891
internal_set_bit(start_states,states);
6791
start_states->internal_set_bit(states);
6893
for (pos=from[i], len=0; *pos ; pos++)
6794
for (pos= from[i], len=0; *pos ; pos++)
6895
6796
if (*pos == '\\' && *(pos+1))
6936
for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
6837
for (set_nr=0; set_nr < sets.count ; set_nr++)
6938
6839
set=sets.set+set_nr;
6939
6840
default_state= 0; /* Start from beginning */
6941
6842
/* If end of found-string not found or start-set with current set */
6943
for (i= UINT32_MAX; (i=get_next_bit(set,i)) ;)
6844
for (i= UINT32_MAX; (i= set->get_next_bit(i)) ;)
6947
if (! default_state)
6948
default_state= find_found(found_set,set->table_offset,
6949
set->found_offset+1);
6846
if (!follow[i].chr && !default_state)
6847
default_state= find_found(&found_set.front(), set->table_offset, set->found_offset+1);
6952
copy_bits(sets.set+used_sets,set); /* Save set for changes */
6849
sets.set[used_sets].copy_bits(set); /* Save set for changes */
6953
6850
if (!default_state)
6954
or_bits(sets.set+used_sets,sets.set); /* Can restart from start */
6851
sets.set[used_sets].or_bits(sets.set); /* Can restart from start */
6956
6853
/* Find all chars that follows current sets */
6957
6854
memset(used_chars, 0, sizeof(used_chars));
6958
for (i= UINT32_MAX; (i=get_next_bit(sets.set+used_sets,i)) ;)
6855
for (i= UINT32_MAX; (i= sets.set[used_sets].get_next_bit(i)) ;)
6960
6857
used_chars[follow[i].chr]=1;
6961
6858
if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
6994
6891
follow[i].len > found_end)
6995
6892
found_end=follow[i].len;
6996
6893
if (chr && follow[i].chr)
6997
internal_set_bit(new_set,i+1); /* To next set */
6894
new_set->internal_set_bit(i + 1); /* To next set */
6999
internal_set_bit(new_set,i);
6896
new_set->internal_set_bit(i);
7004
6901
new_set->found_len=0; /* Set for testing if first */
7006
for (i= UINT32_MAX; (i=get_next_bit(new_set,i)) ;)
6903
for (i= UINT32_MAX; (i= new_set->get_next_bit(i)) ;)
7008
6905
if ((follow[i].chr == SPACE_CHAR ||
7009
6906
follow[i].chr == END_OF_LINE) && ! chr)
7030
6927
if (bits_set == 1)
7032
set->next[chr] = find_found(found_set,
7033
new_set->table_offset,
7034
new_set->found_offset);
7035
free_last_set(&sets);
6929
set->next[chr] = find_found(&found_set.front(), new_set->table_offset, new_set->found_offset);
6930
sets.free_last_set();
7038
set->next[chr] = find_set(&sets,new_set);
6933
set->next[chr] = sets.find_set(new_set);
7041
set->next[chr] = find_set(&sets,new_set);
6936
set->next[chr] = sets.find_set(new_set);
7046
6941
/* Alloc replace structure for the replace-state-machine */
7048
if ((replace=(REPLACE*) malloc(sizeof(REPLACE)*(sets.count)+
7049
sizeof(REPLACE_STRING)*(found_sets+1)+
7050
sizeof(char *)*count+result_len)))
6943
REPLACE *replace= (REPLACE*)malloc(sizeof(REPLACE) * (sets.count)
6944
+ sizeof(REPLACE_STRING) * (found_sets + 1) + sizeof(char*) * count + result_len);
7052
6947
memset(replace, 0, sizeof(REPLACE)*(sets.count)+
7053
6948
sizeof(REPLACE_STRING)*(found_sets+1)+
7064
6959
rep_str[0].replace_string=0;
7065
6960
for (i=1 ; i <= found_sets ; i++)
7067
pos=from[found_set[i-1].table_offset];
6962
const char *pos= from[found_set[i-1].table_offset];
7068
6963
rep_str[i].found= !memcmp(pos, "\\^", 3) ? 2 : 1;
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)+
6964
rep_str[i].replace_string= to_array[found_set[i-1].table_offset];
6965
rep_str[i].to_offset= found_set[i-1].found_offset-start_at_word(pos);
6966
rep_str[i].from_offset= found_set[i-1].found_offset-replace_len(pos) + end_of_word(pos);
7074
6968
for (i=0 ; i < sets.count ; i++)
7146
7038
return make_new_set(sets);
7149
void free_last_set(REP_SETS *sets)
7156
void free_sets(REP_SETS *sets)
7158
free(sets->set_buffer);
7159
free(sets->bit_buffer);
7163
void internal_set_bit(REP_SET *set, uint32_t bit)
7165
set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7169
void internal_clear_bit(REP_SET *set, uint32_t bit)
7171
set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7176
void or_bits(REP_SET *to,REP_SET *from)
7178
register uint32_t i;
7179
for (i=0 ; i < to->size_of_bits ; i++)
7180
to->bits[i]|=from->bits[i];
7184
void copy_bits(REP_SET *to,REP_SET *from)
7186
memcpy(to->bits,from->bits,
7187
(size_t) (sizeof(uint32_t) * to->size_of_bits));
7190
int cmp_bits(REP_SET *set1,REP_SET *set2)
7192
return memcmp(set1->bits,set2->bits, sizeof(uint32_t) * set1->size_of_bits);
7041
void REP_SETS::free_last_set()
7047
void REP_SETS::free_sets()
7053
void REP_SET::internal_set_bit(uint32_t bit)
7055
bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
7058
void REP_SET::internal_clear_bit(uint32_t bit)
7060
bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
7064
void REP_SET::or_bits(const REP_SET *from)
7066
for (uint32_t i= 0 ; i < size_of_bits; i++)
7067
bits[i]|=from->bits[i];
7070
void REP_SET::copy_bits(const REP_SET *from)
7072
memcpy(bits, from->bits, sizeof(uint32_t) * size_of_bits);
7075
int REP_SET::cmp_bits(const REP_SET *set2) const
7077
return memcmp(bits, set2->bits, sizeof(uint32_t) * size_of_bits);
7196
7080
/* Get next set bit from set. */
7198
int get_next_bit(REP_SET *set,uint32_t lastpos)
7082
int REP_SET::get_next_bit(uint32_t lastpos) const
7200
uint32_t pos,*start,*end,bits;
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);
7206
while (! bits && ++start < end)
7084
uint32_t *start= bits + ((lastpos+1) / WORD_BIT);
7085
uint32_t *end= bits + size_of_bits;
7086
uint32_t bits0= start[0] & ~((1 << ((lastpos+1) % WORD_BIT)) -1);
7088
while (!bits0 && ++start < end)
7210
pos=(uint32_t) (start-set->bits)*WORD_BIT;
7211
while (! (bits & 1))
7092
uint32_t pos= (start - bits) * WORD_BIT;
7093
while (!(bits0 & 1))
7220
7102
free given set, else put in given set in sets and return its
7223
int find_set(REP_SETS *sets,REP_SET *find)
7105
int REP_SETS::find_set(const REP_SET *find)
7226
for (i=0 ; i < sets->count-1 ; i++)
7108
for (; i < count - 1; i++)
7228
if (!cmp_bits(sets->set+i,find))
7110
if (!set[i].cmp_bits(find))
7230
free_last_set(sets);
7241
7123
set->next[] == -1 is reserved for end without replaces.
7244
int find_found(FOUND_SET *found_set,uint32_t table_offset, int found_offset)
7126
int find_found(FOUND_SET *found_set, uint32_t table_offset, int found_offset)
7247
for (i=0 ; (uint32_t) i < found_sets ; i++)
7129
for (; i < found_sets; i++)
7248
7131
if (found_set[i].table_offset == table_offset &&
7249
7132
found_set[i].found_offset == found_offset)
7251
found_set[i].table_offset=table_offset;
7252
found_set[i].found_offset=found_offset;
7135
found_set[i].table_offset= table_offset;
7136
found_set[i].found_offset= found_offset;
7254
return -i-2; /* return new postion */
7257
/* Return 1 if regexp starts with \b or ends with \b*/
7259
uint32_t start_at_word(char * pos)
7261
return (((!memcmp(pos, "\\b",2) && pos[2]) ||
7262
!memcmp(pos, "\\^", 2)) ? 1 : 0);
7265
uint32_t end_of_word(char * pos)
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;
7138
return - i - 2; // return new postion
7272
7141
/****************************************************************************
7345
7214
} /* insert_pointer_name */
7348
/* free pointer array */
7350
void free_pointer_array(POINTER_ARRAY *pa)
7352
if (pa->typelib.count)
7354
pa->typelib.count=0;
7355
free((char*) pa->typelib.type_names);
7356
pa->typelib.type_names=0;
7359
} /* free_pointer_array */
7362
7217
/* Functions that uses replace and replace_regex */
7364
7219
/* Append the string to ds, with optional replace */
7365
void replace_append_mem(string *ds,
7366
const char *val, int len)
7220
void replace_append_mem(string *ds, const char *val, int len)
7368
7222
char *v= strdup(val);
7370
if (glob_replace_regex)
7224
if (glob_replace_regex && !glob_replace_regex->multi_reg_replace(v))
7373
if (!multi_reg_replace(glob_replace_regex, v))
7375
v= glob_replace_regex->buf;
7226
v= glob_replace_regex->buf_;
7380
7229
if (glob_replace)
7382
7231
/* Normal replace */
7383
7232
replace_strings_append(glob_replace, ds, v, len);
7387
7235
ds->append(v, len);