~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

  • Committer: Brian Aker
  • Date: 2010-04-05 23:46:43 UTC
  • Revision ID: brian@gaz-20100405234643-0he3xnj902rc70r8
Fixing tests to work with PBXT.

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
#ifdef HAVE_SYS_WAIT_H
51
51
#include <sys/wait.h>
52
52
#endif
 
53
#include <cassert>
 
54
#include <sys/stat.h>
 
55
#include <sys/types.h>
 
56
#include <fcntl.h>
53
57
 
54
58
#include PCRE_HEADER
55
59
 
56
 
#include <mysys/hash.h>
57
60
#include <stdarg.h>
58
61
 
59
62
#include "errname.h"
60
63
 
61
64
/* Added this for string translation. */
62
 
#include <drizzled/gettext.h>
 
65
#include "drizzled/gettext.h"
 
66
#include "drizzled/hash.h"
 
67
#include "drizzled/drizzle_time.h"
 
68
#include "drizzled/charset.h"
63
69
 
64
70
#ifndef DRIZZLE_RETURN_SERVER_GONE
65
71
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
66
72
#endif
67
73
 
68
74
using namespace std;
 
75
using namespace drizzled;
69
76
 
70
77
extern "C"
71
 
{
72
 
  unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
73
 
  bool get_one_option(int optid, const struct my_option *, char *argument);
74
 
}
 
78
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
 
79
 
 
80
int get_one_option(int optid, const struct option *, char *argument);
75
81
 
76
82
#define MAX_VAR_NAME_LENGTH    256
77
83
#define MAX_COLUMNS            256
78
 
#define MAX_EMBEDDED_SERVER_ARGS 64
79
84
#define MAX_DELIMITER_LENGTH 16
80
85
/* Flags controlling send and reap */
81
86
#define QUERY_SEND_FLAG  1
98
103
const char *opt_testdir= NULL;
99
104
static uint32_t opt_port= 0;
100
105
static int opt_max_connect_retries;
101
 
static bool opt_compress= false, silent= false, verbose= false;
102
 
static bool debug_info_flag= false, debug_check_flag= false;
 
106
static bool silent= false, verbose= false;
103
107
static bool tty_password= false;
104
108
static bool opt_mark_progress= false;
105
109
static bool parsing_disabled= false;
111
115
static bool abort_on_error= true;
112
116
static bool server_initialized= false;
113
117
static bool is_windows= false;
 
118
static bool opt_mysql= false;
114
119
static char **default_argv;
115
120
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
116
121
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
117
122
 
118
123
static uint32_t start_lineno= 0; /* Start line of current command */
119
 
static uint32_t my_end_arg= 0;
120
124
 
121
125
/* Number of lines of the result to include in failure report */
122
126
static uint32_t opt_tail_lines= 0;
158
162
 
159
163
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci; /* Default charset */
160
164
 
161
 
static int embedded_server_arg_count=0;
162
 
static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
163
 
 
164
165
/*
165
166
  Timer related variables
166
167
  See the timer_output() definition for details
206
207
/*Perl/shell-like variable registers */
207
208
VAR var_reg[10];
208
209
 
209
 
HASH var_hash;
 
210
 
 
211
drizzled::hash_map<string, VAR *> var_hash;
210
212
 
211
213
struct st_connection
212
214
{
386
388
  char *query, *query_buf,*first_argument,*last_argument,*end;
387
389
  int first_word_len, query_len;
388
390
  bool abort_on_error;
389
 
  struct st_expected_errors expected_errors;
390
 
  char require_file[FN_REFLEN];
 
391
  st_expected_errors expected_errors;
 
392
  string require_file;
391
393
  enum enum_commands type;
 
394
 
 
395
  st_command()
 
396
    : query(NULL), query_buf(NULL), first_argument(NULL), last_argument(NULL),
 
397
      end(NULL), first_word_len(0), query_len(0), abort_on_error(false),
 
398
      require_file(""), type(Q_CONNECTION)
 
399
  {
 
400
    memset(&expected_errors, 0, sizeof(st_expected_errors));
 
401
  }
 
402
 
 
403
  ~st_command()
 
404
  {
 
405
    if (query_buf != NULL)
 
406
    {
 
407
      free(query_buf);
 
408
    }
 
409
  }
392
410
};
393
411
 
394
412
TYPELIB command_typelib= {array_elements(command_names),"",
412
430
VAR* var_from_env(const char *, const char *);
413
431
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
414
432
              int val_len);
415
 
extern "C" void var_free(void* v);
 
433
void var_free(pair<string, VAR*> v);
416
434
VAR* var_get(const char *var_name, const char** var_name_end,
417
435
             bool raw, bool ignore_not_existing);
418
436
void eval_expr(VAR* v, const char *p, const char** p_end);
884
902
 
885
903
  close_connections();
886
904
  close_files();
887
 
  hash_free(&var_hash);
 
905
  for_each(var_hash.begin(), var_hash.end(), var_free);
 
906
  var_hash.clear();
888
907
 
889
 
  vector<struct st_command *>::iterator iter;
 
908
  vector<st_command *>::iterator iter;
890
909
  for (iter= q_lines.begin() ; iter < q_lines.end() ; iter++)
891
910
  {
892
911
    struct st_command * q_line= *iter;
893
 
    if (q_line->query_buf != NULL)
894
 
    {
895
 
      free(q_line->query_buf);
896
 
    }
897
 
    free(q_line);
 
912
    delete q_line;
898
913
  }
899
914
 
900
915
  for (i= 0; i < 10; i++)
902
917
    if (var_reg[i].alloced_len)
903
918
      free(var_reg[i].str_val);
904
919
  }
905
 
  while (embedded_server_arg_count > 1)
906
 
    free(embedded_server_args[--embedded_server_arg_count]);
907
920
 
908
921
  free_all_replace();
909
922
  free(opt_pass);
910
 
  free_defaults(default_argv);
 
923
  internal::free_defaults(default_argv);
911
924
 
912
925
  return;
913
926
}
916
929
static void cleanup_and_exit(int exit_code)
917
930
{
918
931
  free_used_memory();
919
 
  my_end(my_end_arg);
 
932
  internal::my_end();
920
933
 
921
934
  if (!silent) {
922
935
    switch (exit_code) {
1129
1142
  uint32_t len;
1130
1143
  char buff[512];
1131
1144
 
1132
 
  if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
 
1145
  if ((fd= internal::my_open(filename, O_RDONLY, MYF(0))) < 0)
1133
1146
    die("Failed to open file '%s'", filename);
1134
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1147
  while((len= internal::my_read(fd, (unsigned char*)&buff,
1135
1148
                      sizeof(buff), MYF(0))) > 0)
1136
1149
  {
1137
1150
    char *p= buff, *start= buff;
1153
1166
    /* Output any chars that might be left */
1154
1167
    ds->append(start, p-start);
1155
1168
  }
1156
 
  my_close(fd, MYF(0));
 
1169
  internal::my_close(fd, MYF(0));
1157
1170
}
1158
1171
 
1159
1172
 
1329
1342
 
1330
1343
*/
1331
1344
 
1332
 
static int compare_files2(File fd, const char* filename2)
 
1345
static int compare_files2(int fd, const char* filename2)
1333
1346
{
1334
1347
  int error= RESULT_OK;
1335
 
  File fd2;
 
1348
  int fd2;
1336
1349
  uint32_t len, len2;
1337
1350
  char buff[512], buff2[512];
1338
1351
  const char *fname= filename2;
1339
1352
  string tmpfile;
1340
1353
 
1341
 
  if ((fd2= my_open(fname, O_RDONLY, MYF(0))) < 0)
 
1354
  if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
1342
1355
  {
1343
 
    my_close(fd, MYF(0));
 
1356
    internal::my_close(fd, MYF(0));
1344
1357
    if (opt_testdir != NULL)
1345
1358
    {
1346
1359
      tmpfile= opt_testdir;
1349
1362
      tmpfile.append(filename2);
1350
1363
      fname= tmpfile.c_str();
1351
1364
    }
1352
 
    if ((fd2= my_open(fname, O_RDONLY, MYF(0))) < 0)
 
1365
    if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
1353
1366
    {
1354
 
      my_close(fd, MYF(0));
 
1367
      internal::my_close(fd, MYF(0));
1355
1368
    
1356
1369
      die("Failed to open second file: '%s'", fname);
1357
1370
    }
1358
1371
  }
1359
 
  while((len= my_read(fd, (unsigned char*)&buff,
 
1372
  while((len= internal::my_read(fd, (unsigned char*)&buff,
1360
1373
                      sizeof(buff), MYF(0))) > 0)
1361
1374
  {
1362
 
    if ((len2= my_read(fd2, (unsigned char*)&buff2,
 
1375
    if ((len2= internal::my_read(fd2, (unsigned char*)&buff2,
1363
1376
                       sizeof(buff2), MYF(0))) < len)
1364
1377
    {
1365
1378
      /* File 2 was smaller */
1379
1392
      break;
1380
1393
    }
1381
1394
  }
1382
 
  if (!error && my_read(fd2, (unsigned char*)&buff2,
 
1395
  if (!error && internal::my_read(fd2, (unsigned char*)&buff2,
1383
1396
                        sizeof(buff2), MYF(0)) > 0)
1384
1397
  {
1385
1398
    /* File 1 was smaller */
1386
1399
    error= RESULT_LENGTH_MISMATCH;
1387
1400
  }
1388
1401
 
1389
 
  my_close(fd2, MYF(0));
 
1402
  internal::my_close(fd2, MYF(0));
1390
1403
 
1391
1404
  return error;
1392
1405
}
1407
1420
 
1408
1421
static int compare_files(const char* filename1, const char* filename2)
1409
1422
{
1410
 
  File fd;
 
1423
  int fd;
1411
1424
  int error;
1412
1425
 
1413
 
  if ((fd= my_open(filename1, O_RDONLY, MYF(0))) < 0)
 
1426
  if ((fd= internal::my_open(filename1, O_RDONLY, MYF(0))) < 0)
1414
1427
    die("Failed to open first file: '%s'", filename1);
1415
1428
 
1416
1429
  error= compare_files2(fd, filename2);
1417
1430
 
1418
 
  my_close(fd, MYF(0));
 
1431
  internal::my_close(fd, MYF(0));
1419
1432
 
1420
1433
  return error;
1421
1434
}
1436
1449
static int string_cmp(string* ds, const char *fname)
1437
1450
{
1438
1451
  int error;
1439
 
  File fd;
 
1452
  int fd;
1440
1453
  char temp_file_path[FN_REFLEN];
1441
1454
 
1442
 
  if ((fd= create_temp_file(temp_file_path, NULL,
 
1455
  if ((fd= internal::create_temp_file(temp_file_path, NULL,
1443
1456
                            "tmp", MYF(MY_WME))) < 0)
1444
1457
    die("Failed to create temporary file for ds");
1445
1458
 
1446
1459
  /* Write ds to temporary file and set file pos to beginning*/
1447
 
  if (my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
 
1460
  if (internal::my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
1448
1461
               MYF(MY_FNABP | MY_WME)) ||
1449
1462
      lseek(fd, 0, SEEK_SET) == MY_FILEPOS_ERROR)
1450
1463
  {
1451
 
    my_close(fd, MYF(0));
 
1464
    internal::my_close(fd, MYF(0));
1452
1465
    /* Remove the temporary file */
1453
 
    my_delete(temp_file_path, MYF(0));
 
1466
    internal::my_delete(temp_file_path, MYF(0));
1454
1467
    die("Failed to write file '%s'", temp_file_path);
1455
1468
  }
1456
1469
 
1457
1470
  error= compare_files2(fd, fname);
1458
1471
 
1459
 
  my_close(fd, MYF(0));
 
1472
  internal::my_close(fd, MYF(0));
1460
1473
  /* Remove the temporary file */
1461
 
  my_delete(temp_file_path, MYF(0));
 
1474
  internal::my_delete(temp_file_path, MYF(0));
1462
1475
 
1463
1476
  return(error);
1464
1477
}
1500
1513
    */
1501
1514
    char reject_file[FN_REFLEN];
1502
1515
    size_t reject_length;
1503
 
    dirname_part(reject_file, result_file_name, &reject_length);
 
1516
    internal::dirname_part(reject_file, result_file_name, &reject_length);
1504
1517
 
1505
1518
    if (access(reject_file, W_OK) == 0)
1506
1519
    {
1507
1520
      /* Result file directory is writable, save reject file there */
1508
 
      fn_format(reject_file, result_file_name, NULL,
 
1521
      internal::fn_format(reject_file, result_file_name, NULL,
1509
1522
                ".reject", MY_REPLACE_EXT);
1510
1523
    }
1511
1524
    else
1512
1525
    {
1513
1526
      /* Put reject file in opt_logdir */
1514
 
      fn_format(reject_file, result_file_name, opt_logdir,
 
1527
      internal::fn_format(reject_file, result_file_name, opt_logdir,
1515
1528
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1516
1529
    }
1517
1530
    str_to_file(reject_file, ds->c_str(), ds->length());
1545
1558
 
1546
1559
*/
1547
1560
 
1548
 
static void check_require(string* ds, const char *fname)
 
1561
static void check_require(string* ds, const string &fname)
1549
1562
{
1550
1563
 
1551
1564
 
1552
 
  if (string_cmp(ds, fname))
 
1565
  if (string_cmp(ds, fname.c_str()))
1553
1566
  {
1554
1567
    char reason[FN_REFLEN];
1555
 
    fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
 
1568
    internal::fn_format(reason, fname.c_str(), "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1556
1569
    abort_not_supported_test("Test requires: '%s'", reason);
1557
1570
  }
1558
1571
  return;
1603
1616
}
1604
1617
 
1605
1618
 
1606
 
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool)
1607
 
{
1608
 
  register char* key;
1609
 
  key = ((VAR*)var)->name;
1610
 
  *len = ((VAR*)var)->name_len;
1611
 
  return (unsigned char*)key;
1612
 
}
1613
 
 
1614
1619
 
1615
1620
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
1616
1621
              int val_len)
1648
1653
}
1649
1654
 
1650
1655
 
1651
 
void var_free(void *v)
 
1656
void var_free(pair<string, VAR *> v)
1652
1657
{
1653
 
  free(((VAR*) v)->str_val);
1654
 
  free(((VAR*) v)->env_s);
1655
 
  if (((VAR*)v)->alloced)
1656
 
    free(v);
 
1658
  free(v.second->str_val);
 
1659
  free(v.second->env_s);
 
1660
  if (v.second->alloced)
 
1661
    free(v.second);
1657
1662
}
1658
1663
 
1659
1664
 
1665
1670
    tmp = def_val;
1666
1671
 
1667
1672
  v = var_init(0, name, strlen(name), tmp, strlen(tmp));
1668
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1673
  string var_name(name);
 
1674
  var_hash.insert(make_pair(var_name, v));
1669
1675
  return v;
1670
1676
}
1671
1677
 
1696
1702
    if (length >= MAX_VAR_NAME_LENGTH)
1697
1703
      die("Too long variable name: %s", save_var_name);
1698
1704
 
1699
 
    if (!(v = (VAR*) hash_search(&var_hash, (const unsigned char*) save_var_name,
1700
 
                                 length)))
 
1705
    string save_var_name_str(save_var_name, length);
 
1706
    drizzled::hash_map<string, VAR*>::iterator iter=
 
1707
      var_hash.find(save_var_name_str);
 
1708
    if (iter == var_hash.end())
1701
1709
    {
1702
1710
      char buff[MAX_VAR_NAME_LENGTH+1];
1703
1711
      strncpy(buff, save_var_name, length);
1704
1712
      buff[length]= '\0';
1705
1713
      v= var_from_env(buff, "");
1706
1714
    }
 
1715
    else
 
1716
    {
 
1717
      v= (*iter).second;
 
1718
    }
1707
1719
    var_name--;  /* Point at last character */
1708
1720
  }
1709
1721
  else
1728
1740
 
1729
1741
static VAR *var_obtain(const char *name, int len)
1730
1742
{
1731
 
  VAR* v;
1732
 
  if ((v = (VAR*)hash_search(&var_hash, (const unsigned char *) name, len)))
1733
 
    return v;
1734
 
  v = var_init(0, name, len, "", 0);
1735
 
  my_hash_insert(&var_hash, (unsigned char*)v);
 
1743
  string var_name(name, len);
 
1744
  drizzled::hash_map<string, VAR*>::iterator iter=
 
1745
    var_hash.find(var_name);
 
1746
  if (iter != var_hash.end())
 
1747
    return (*iter).second;
 
1748
  VAR *v = var_init(0, name, len, "", 0);
 
1749
  var_hash.insert(make_pair(var_name, v));
1736
1750
  return v;
1737
1751
}
1738
1752
 
2094
2108
    const size_t len= strlen(get_value_str);
2095
2109
    if (strncmp(p, get_value_str, len)==0)
2096
2110
    {
2097
 
      struct st_command command;
2098
 
      memset(&command, 0, sizeof(command));
 
2111
      st_command command;
2099
2112
      command.query= (char*)p;
2100
2113
      command.first_word_len= len;
2101
2114
      command.first_argument= command.query + len;
2132
2145
{
2133
2146
  char buff[FN_REFLEN];
2134
2147
 
2135
 
  if (!test_if_hard_path(name))
 
2148
  if (!internal::test_if_hard_path(name))
2136
2149
  {
2137
 
    sprintf(buff,"%s%s",opt_basedir,name);
 
2150
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir,name);
2138
2151
    name=buff;
2139
2152
  }
2140
 
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
 
2153
  internal::fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
2141
2154
 
2142
2155
  if (cur_file == file_stack_end)
2143
2156
    die("Source directives are nesting too deep");
2456
2469
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2457
2470
                     ' ');
2458
2471
 
2459
 
  error= my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2472
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
2460
2473
  handle_command_error(command, error);
2461
2474
  return;
2462
2475
}
2490
2503
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2491
2504
                     ' ');
2492
2505
 
2493
 
  error= (my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2506
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2494
2507
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2495
2508
  handle_command_error(command, error);
2496
2509
  return;
2588
2601
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2589
2602
                     ' ');
2590
2603
 
2591
 
  error= mkdir(ds_dirname.c_str(), (0777 & my_umask_dir)) != 0;
 
2604
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
2592
2605
  handle_command_error(command, error);
2593
2606
  return;
2594
2607
}
2955
2968
static void do_perl(struct st_command *command)
2956
2969
{
2957
2970
  int error;
2958
 
  File fd;
 
2971
  int fd;
2959
2972
  FILE *res_file;
2960
2973
  char buf[FN_REFLEN];
2961
2974
  char temp_file_path[FN_REFLEN];
2979
2992
  read_until_delimiter(&ds_script, &ds_delimiter);
2980
2993
 
2981
2994
  /* Create temporary file name */
2982
 
  if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
 
2995
  if ((fd= internal::create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
2983
2996
                            "tmp", MYF(MY_WME))) < 0)
2984
2997
    die("Failed to create temporary file for perl command");
2985
 
  my_close(fd, MYF(0));
 
2998
  internal::my_close(fd, MYF(0));
2986
2999
 
2987
3000
  str_to_file(temp_file_path, ds_script.c_str(), ds_script.length());
2988
3001
 
3002
3015
  error= pclose(res_file);
3003
3016
 
3004
3017
  /* Remove the temporary file */
3005
 
  my_delete(temp_file_path, MYF(0));
 
3018
  internal::my_delete(temp_file_path, MYF(0));
3006
3019
 
3007
3020
  handle_command_error(command, WEXITSTATUS(error));
3008
3021
  return;
3108
3121
  if (!master_pos.file[0])
3109
3122
    die("Calling 'sync_with_master' without calling 'save_master_pos'");
3110
3123
 
3111
 
  sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
 
3124
  snprintf(query_buf, sizeof(query_buf), "select master_pos_wait('%s', %ld)", master_pos.file,
3112
3125
          master_pos.pos + offset);
3113
3126
 
3114
3127
wait_for_position:
3302
3315
  if (!*p)
3303
3316
    die("Missing argument to %.*s", command->first_word_len, command->query);
3304
3317
  sleep_start= p;
3305
 
  /* Check that arg starts with a digit, not handled by my_strtod */
 
3318
  /* Check that arg starts with a digit, not handled by internal::my_strtod */
3306
3319
  if (!my_isdigit(charset_info, *sleep_start))
3307
3320
    die("Invalid argument to %.*s \"%s\"", command->first_word_len,
3308
3321
        command->query,command->first_argument);
3324
3337
}
3325
3338
 
3326
3339
 
3327
 
static void do_get_file_name(struct st_command *command,
3328
 
                             char* dest, uint32_t dest_max_len)
 
3340
static void do_get_file_name(struct st_command *command, string &dest)
3329
3341
{
3330
3342
  char *p= command->first_argument, *name;
3331
3343
  if (!*p)
3336
3348
  if (*p)
3337
3349
    *p++= 0;
3338
3350
  command->last_argument= p;
3339
 
  strncpy(dest, name, dest_max_len - 1);
 
3351
  if (opt_testdir != NULL)
 
3352
  {
 
3353
    dest= opt_testdir;
 
3354
    if (dest[dest.length()] != '/')
 
3355
      dest.append("/");
 
3356
  }
 
3357
  dest.append(name);
3340
3358
}
3341
3359
 
3342
3360
 
3866
3884
    if (*ds_sock.c_str() != FN_LIBCHAR)
3867
3885
    {
3868
3886
      char buff[FN_REFLEN];
3869
 
      fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
 
3887
      internal::fn_format(buff, ds_sock.c_str(), TMPDIR, "", 0);
3870
3888
      ds_sock.clear();
3871
3889
      ds_sock.append(buff);
3872
3890
    }
3913
3931
    die("Failed on drizzle_create()");
3914
3932
  if (!drizzle_con_create(con_slot->drizzle, &con_slot->con))
3915
3933
    die("Failed on drizzle_con_create()");
 
3934
  if (opt_mysql)
 
3935
    drizzle_con_add_options(&con_slot->con, DRIZZLE_CON_MYSQL);
3916
3936
 
3917
3937
  /* Use default db name */
3918
3938
  if (ds_database.length() == 0)
4132
4152
 
4133
4153
*/
4134
4154
 
 
4155
 
 
4156
static int my_strnncoll_simple(const CHARSET_INFO * const  cs, const unsigned char *s, size_t slen,
 
4157
                               const unsigned char *t, size_t tlen,
 
4158
                               bool t_is_prefix)
 
4159
{
 
4160
  size_t len = ( slen > tlen ) ? tlen : slen;
 
4161
  unsigned char *map= cs->sort_order;
 
4162
  if (t_is_prefix && slen > tlen)
 
4163
    slen=tlen;
 
4164
  while (len--)
 
4165
  {
 
4166
    if (map[*s++] != map[*t++])
 
4167
      return ((int) map[s[-1]] - (int) map[t[-1]]);
 
4168
  }
 
4169
  /*
 
4170
    We can't use (slen - tlen) here as the result may be outside of the
 
4171
    precision of a signed int
 
4172
  */
 
4173
  return slen > tlen ? 1 : slen < tlen ? -1 : 0 ;
 
4174
}
 
4175
 
4135
4176
static int read_line(char *buf, int size)
4136
4177
{
4137
4178
  char c, last_quote= 0;
4488
4529
    *command_ptr= q_lines[parser.current_line];
4489
4530
    return(0);
4490
4531
  }
4491
 
  if (!(*command_ptr= command=
4492
 
        (struct st_command*) malloc(sizeof(*command))))
4493
 
    die("command malloc failed");
4494
 
  memset(command, 0, sizeof(*command));
 
4532
  if (!(*command_ptr= command= new st_command))
 
4533
    die("command construction failed");
4495
4534
  q_lines.push_back(command);
4496
4535
  command->type= Q_UNKNOWN;
4497
4536
 
4539
4578
}
4540
4579
 
4541
4580
 
4542
 
static struct my_option my_long_options[] =
 
4581
static struct option my_long_options[] =
4543
4582
{
4544
4583
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
4545
4584
   0, 0, 0, 0, 0, 0},
4548
4587
  {"character-sets-dir", OPT_CHARSETS_DIR,
4549
4588
   "Directory where character sets are.", (char**) &opt_charsets_dir,
4550
4589
   (char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4551
 
  {"compress", 'C', "Use the compressed server/client protocol.",
4552
 
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
4553
 
   0, 0, 0},
4554
4590
  {"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
4555
4591
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4556
 
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
4557
 
   (char**) &debug_check_flag, (char**) &debug_check_flag, 0,
4558
 
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4559
 
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
4560
 
   (char**) &debug_info_flag, (char**) &debug_info_flag,
4561
 
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4562
4592
  {"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
4563
4593
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4564
4594
  {"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
4576
4606
   "Max number of connection attempts when connecting to server",
4577
4607
   (char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
4578
4608
   GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
 
4609
  {"mysql", 'm', N_("Use MySQL Protocol."),
 
4610
   (char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
 
4611
   0, 0, 0},
4579
4612
  {"password", 'P', "Password to use when connecting to server.",
4580
4613
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4581
4614
  {"port", 'p', "Port number to use for connection or 0 for default to, in "
4589
4622
  {"result-file", 'R', "Read/Store result from/in this file.",
4590
4623
   (char**) &result_file_name, (char**) &result_file_name, 0,
4591
4624
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4592
 
  {"server-arg", 'A', "Send option value to embedded server as a parameter.",
4593
 
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4594
 
  {"server-file", 'F', "Read embedded server arguments from file.",
4595
 
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4596
4625
  {"silent", 's', "Suppress all normal output. Synonym for --quiet.",
4597
4626
   (char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4598
4627
  {"sleep", 'T', "Sleep always this many seconds on sleep commands.",
4620
4649
 
4621
4650
static void print_version(void)
4622
4651
{
4623
 
  printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",my_progname,MTEST_VERSION,
 
4652
  printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
4624
4653
         drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
4625
4654
}
4626
4655
 
4628
4657
{
4629
4658
  print_version();
4630
4659
  printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
 
4660
  printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
4631
4661
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4632
4662
  printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4633
 
  printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
 
4663
  printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
4634
4664
  my_print_help(my_long_options);
4635
4665
  printf("  --no-defaults       Don't read default options from any options file.\n");
4636
4666
  my_print_variables(my_long_options);
4637
4667
}
4638
4668
 
4639
 
/*
4640
 
  Read arguments for embedded server and put them into
4641
 
  embedded_server_args[]
4642
 
*/
4643
 
 
4644
 
static void read_embedded_server_arguments(const char *name)
4645
 
{
4646
 
  char argument[1024],buff[FN_REFLEN], *str=0;
4647
 
  FILE *file;
4648
 
 
4649
 
  if (!test_if_hard_path(name))
4650
 
  {
4651
 
    sprintf(buff,"%s%s",opt_basedir,name);
4652
 
    name=buff;
4653
 
  }
4654
 
  fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
4655
 
 
4656
 
  if (!embedded_server_arg_count)
4657
 
  {
4658
 
    embedded_server_arg_count=1;
4659
 
    embedded_server_args[0]= (char*) "";    /* Progname */
4660
 
  }
4661
 
  if (!(file= fopen(buff, "r")))
4662
 
    die("Failed to open file '%s'", buff);
4663
 
 
4664
 
  while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4665
 
         (str=fgets(argument,sizeof(argument), file)))
4666
 
  {
4667
 
    *(strchr(str, '\0')-1)=0;        /* Remove end newline */
4668
 
    if (!(embedded_server_args[embedded_server_arg_count]=
4669
 
          (char*) strdup(str)))
4670
 
    {
4671
 
      fclose(file);
4672
 
      die("Out of memory");
4673
 
 
4674
 
    }
4675
 
    embedded_server_arg_count++;
4676
 
  }
4677
 
  fclose(file);
4678
 
  if (str)
4679
 
    die("Too many arguments in option file: %s",name);
4680
 
 
4681
 
  return;
4682
 
}
4683
 
 
4684
 
 
4685
 
bool get_one_option(int optid, const struct my_option *, char *argument)
 
4669
int get_one_option(int optid, const struct option *, char *argument)
4686
4670
{
4687
4671
  char *endchar= NULL;
4688
4672
  uint64_t temp_drizzle_port= 0;
4694
4678
  case 'x':
4695
4679
  {
4696
4680
    char buff[FN_REFLEN];
4697
 
    if (!test_if_hard_path(argument))
 
4681
    if (!internal::test_if_hard_path(argument))
4698
4682
    {
4699
 
      sprintf(buff,"%s%s",opt_basedir,argument);
 
4683
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir,argument);
4700
4684
      argument= buff;
4701
4685
    }
4702
 
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4686
    internal::fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4703
4687
    assert(cur_file == file_stack && cur_file->file == 0);
4704
4688
    if (!(cur_file->file= fopen(buff, "r")))
4705
 
      die("Could not open '%s' for reading: errno = %d", buff, errno);
 
4689
    {
 
4690
      fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
 
4691
      return EXIT_ARGUMENT_INVALID;
 
4692
    }
4706
4693
    if (!(cur_file->file_name= strdup(buff)))
4707
 
      die("Out of memory");
 
4694
    {
 
4695
      fprintf(stderr, _("Out of memory"));
 
4696
      return EXIT_OUT_OF_MEMORY;
 
4697
    }
4708
4698
    cur_file->lineno= 1;
4709
4699
    break;
4710
4700
  }
4711
4701
  case 'm':
4712
4702
  {
4713
4703
    static char buff[FN_REFLEN];
4714
 
    if (!test_if_hard_path(argument))
 
4704
    if (!internal::test_if_hard_path(argument))
4715
4705
    {
4716
 
      sprintf(buff,"%s%s",opt_basedir,argument);
 
4706
      snprintf(buff, sizeof(buff), "%s%s",opt_basedir,argument);
4717
4707
      argument= buff;
4718
4708
    }
4719
 
    fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
 
4709
    internal::fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4720
4710
    timer_file= buff;
4721
4711
    unlink(timer_file);       /* Ignore error, may not exist */
4722
4712
    break;
4727
4717
    if (strlen(endchar) != 0)
4728
4718
    {
4729
4719
      fprintf(stderr, _("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead.\n"));
4730
 
      exit(1);
 
4720
      return EXIT_ARGUMENT_INVALID;
4731
4721
    }
4732
4722
    /* If the port number is > 65535 it is not a valid port
4733
4723
       This also helps with potential data loss casting unsigned long to a
4735
4725
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
4736
4726
    {
4737
4727
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
4738
 
      exit(1);
 
4728
      return EXIT_ARGUMENT_INVALID;
4739
4729
    }
4740
4730
    else
4741
4731
    {
4749
4739
        free(opt_pass);
4750
4740
      opt_pass = strdup(argument);
4751
4741
      if (opt_pass == NULL)
4752
 
        die("Out of memory");
 
4742
      {
 
4743
        fprintf(stderr, _("Out of memory"));
 
4744
        return EXIT_OUT_OF_MEMORY;
 
4745
      }
4753
4746
      while (*argument)
4754
4747
      {
4755
4748
        /* Overwriting password with 'x' */
4763
4756
  case 't':
4764
4757
    strncpy(TMPDIR, argument, sizeof(TMPDIR));
4765
4758
    break;
4766
 
  case 'A':
4767
 
    if (!embedded_server_arg_count)
4768
 
    {
4769
 
      embedded_server_arg_count=1;
4770
 
      embedded_server_args[0]= (char*) "";
4771
 
    }
4772
 
    if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
4773
 
        !(embedded_server_args[embedded_server_arg_count++]=
4774
 
          strdup(argument)))
4775
 
    {
4776
 
      die("Can't use server argument");
4777
 
    }
4778
 
    break;
4779
 
  case 'F':
4780
 
    read_embedded_server_arguments(argument);
4781
 
    break;
4782
4759
  case 'V':
4783
4760
    print_version();
4784
4761
    exit(0);
4792
4769
 
4793
4770
static int parse_args(int argc, char **argv)
4794
4771
{
4795
 
  load_defaults("drizzle",load_default_groups,&argc,&argv);
 
4772
  internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
4796
4773
  default_argv= argv;
4797
4774
 
4798
4775
  if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
4807
4784
    opt_db= *argv;
4808
4785
  if (tty_password)
4809
4786
    opt_pass= client_get_tty_password(NULL);          /* purify tested */
4810
 
  if (debug_info_flag)
4811
 
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
4812
 
  if (debug_check_flag)
4813
 
    my_end_arg= MY_CHECK_ERROR;
4814
4787
 
4815
4788
  return 0;
4816
4789
}
4831
4804
  int fd;
4832
4805
  char buff[FN_REFLEN];
4833
4806
  int flags= O_WRONLY | O_CREAT;
4834
 
  if (!test_if_hard_path(fname))
 
4807
  if (!internal::test_if_hard_path(fname))
4835
4808
  {
4836
 
    sprintf(buff,"%s%s",opt_basedir,fname);
 
4809
    snprintf(buff, sizeof(buff), "%s%s",opt_basedir,fname);
4837
4810
    fname= buff;
4838
4811
  }
4839
 
  fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
 
4812
  internal::fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
4840
4813
 
4841
4814
  if (!append)
4842
4815
    flags|= O_TRUNC;
4843
 
  if ((fd= my_open(buff, flags,
 
4816
  if ((fd= internal::my_open(buff, flags,
4844
4817
                   MYF(MY_WME | MY_FFNF))) < 0)
4845
4818
    die("Could not open '%s' for writing: errno = %d", buff, errno);
4846
4819
  if (append && lseek(fd, 0, SEEK_END) == MY_FILEPOS_ERROR)
4847
4820
    die("Could not find end of file '%s': errno = %d", buff, errno);
4848
 
  if (my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
 
4821
  if (internal::my_write(fd, (unsigned char*)str, size, MYF(MY_WME|MY_FNABP)))
4849
4822
    die("write failed");
4850
 
  my_close(fd, MYF(0));
 
4823
  internal::my_close(fd, MYF(0));
4851
4824
}
4852
4825
 
4853
4826
/*
4869
4842
void dump_result_to_log_file(const char *buf, int size)
4870
4843
{
4871
4844
  char log_file[FN_REFLEN];
4872
 
  str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
 
4845
  str_to_file(internal::fn_format(log_file, result_file_name, opt_logdir, ".log",
4873
4846
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4874
4847
                        MY_REPLACE_EXT),
4875
4848
              buf, size);
4880
4853
void dump_progress(void)
4881
4854
{
4882
4855
  char progress_file[FN_REFLEN];
4883
 
  str_to_file(fn_format(progress_file, result_file_name,
 
4856
  str_to_file(internal::fn_format(progress_file, result_file_name,
4884
4857
                        opt_logdir, ".progress",
4885
4858
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4886
4859
                        MY_REPLACE_EXT),
4891
4864
{
4892
4865
  char warn_file[FN_REFLEN];
4893
4866
 
4894
 
  str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
 
4867
  str_to_file(internal::fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
4895
4868
                        *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
4896
4869
                        MY_REPLACE_EXT),
4897
4870
              ds_warning_messages.c_str(), ds_warning_messages.length());
5196
5169
      }
5197
5170
 
5198
5171
      /*
5199
 
        Need to call drizzleclient_affected_rows() before the "new"
 
5172
        Need to call drizzle_result_affected_rows() before the "new"
5200
5173
        query to find the warnings
5201
5174
      */
5202
5175
      if (!disable_info)
5263
5236
  uint32_t i;
5264
5237
 
5265
5238
 
5266
 
  if (command->require_file[0])
 
5239
  if (! command->require_file.empty())
5267
5240
  {
5268
5241
    /*
5269
5242
      The query after a "--require" failed. This is fine as long the server
5422
5395
    Create a temporary dynamic string to contain the output from
5423
5396
    this query.
5424
5397
  */
5425
 
  if (command->require_file[0])
 
5398
  if (! command->require_file.empty())
5426
5399
  {
5427
5400
    ds= &ds_result;
5428
5401
  }
5465
5438
    ds= save_ds;
5466
5439
  }
5467
5440
 
5468
 
  if (command->require_file[0])
 
5441
  if (! command->require_file.empty())
5469
5442
  {
5470
5443
    /* A result file was specified for _this_ query
5471
5444
       and the output should be checked against an already
5596
5569
  struct st_command *command;
5597
5570
  bool q_send_flag= 0, abort_flag= 0;
5598
5571
  uint32_t command_executed= 0, last_command_executed= 0;
5599
 
  char save_file[FN_REFLEN];
 
5572
  string save_file("");
5600
5573
  struct stat res_info;
5601
5574
  MY_INIT(argv[0]);
5602
5575
 
5603
 
  save_file[0]= 0;
5604
5576
  TMPDIR[0]= 0;
5605
5577
 
5606
5578
  /* Init expected errors */
5626
5598
  cur_block->ok= true; /* Outer block should always be executed */
5627
5599
  cur_block->cmd= cmd_none;
5628
5600
 
5629
 
  if (hash_init(&var_hash, charset_info,
5630
 
                1024, 0, 0, get_var_key, var_free, MYF(0)))
5631
 
    die("Variable hash initialization failed");
5632
 
 
5633
5601
  var_set_string("$DRIZZLE_SERVER_VERSION", drizzle_version());
5634
5602
 
5635
5603
  memset(&master_pos, 0, sizeof(master_pos));
5659
5627
    die("Failed in drizzle_create()");
5660
5628
  if (!( drizzle_con_create(cur_con->drizzle, &cur_con->con)))
5661
5629
    die("Failed in drizzle_con_create()");
 
5630
  if (opt_mysql)
 
5631
    drizzle_con_add_options(&cur_con->con, DRIZZLE_CON_MYSQL);
5662
5632
 
5663
5633
  if (!(cur_con->name = strdup("default")))
5664
5634
    die("Out of memory");
5795
5765
        /* Check for special property for this query */
5796
5766
        display_result_vertically|= (command->type == Q_QUERY_VERTICAL);
5797
5767
 
5798
 
        if (save_file[0])
 
5768
        if (! save_file.empty())
5799
5769
        {
5800
 
          strncpy(command->require_file, save_file, sizeof(save_file) - 1);
5801
 
          save_file[0]= 0;
 
5770
          command->require_file= save_file;
 
5771
          save_file.clear();
5802
5772
        }
5803
5773
        run_query(cur_con, command, flags);
5804
5774
        command_executed++;
5835
5805
        command->last_argument= command->end;
5836
5806
        break;
5837
5807
      case Q_REQUIRE:
5838
 
        do_get_file_name(command, save_file, sizeof(save_file));
 
5808
        do_get_file_name(command, save_file);
5839
5809
        break;
5840
5810
      case Q_ERROR:
5841
5811
        do_get_errcodes(command);
6078
6048
 
6079
6049
uint64_t timer_now(void)
6080
6050
{
6081
 
  return my_micro_time() / 1000;
 
6051
#if defined(HAVE_GETHRTIME)
 
6052
  return gethrtime()/1000/1000;
 
6053
#else
 
6054
  uint64_t newtime;
 
6055
  struct timeval t;
 
6056
  /*
 
6057
    The following loop is here because gettimeofday may fail on some systems
 
6058
  */
 
6059
  while (gettimeofday(&t, NULL) != 0)
 
6060
  {}
 
6061
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
 
6062
  return newtime/1000;
 
6063
#endif  /* defined(HAVE_GETHRTIME) */
6082
6064
}
6083
6065
 
6084
6066
 
6293
6275
  char* pattern; /* Pattern to be replaced */
6294
6276
  char* replace; /* String or expression to replace the pattern with */
6295
6277
  int icase; /* true if the match is case insensitive */
 
6278
  int global; /* true if the match should be global -- 
 
6279
                 i.e. repeat the matching until the end of the string */
6296
6280
};
6297
6281
 
6298
6282
struct st_replace_regex
6316
6300
struct st_replace_regex *glob_replace_regex= 0;
6317
6301
 
6318
6302
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
6319
 
                char *string, int icase);
 
6303
                char *string, int icase, int global);
6320
6304
 
6321
6305
 
6322
6306
 
6417
6401
 
6418
6402
    /* Check if we should do matching case insensitive */
6419
6403
    if (p < expr_end && *p == 'i')
 
6404
    {
 
6405
      p++;
6420
6406
      reg.icase= 1;
 
6407
    }
 
6408
 
 
6409
    /* Check if we should do matching globally */
 
6410
    if (p < expr_end && *p == 'g')
 
6411
    {
 
6412
      p++;
 
6413
      reg.global= 1;
 
6414
    }
6421
6415
 
6422
6416
    /* done parsing the statement, now place it in regex_arr */
6423
6417
    if (insert_dynamic(&res->regex_arr,(unsigned char*) &reg))
6475
6469
    get_dynamic(&r->regex_arr,(unsigned char*)&re,i);
6476
6470
 
6477
6471
    if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
6478
 
                     in_buf, re.icase))
 
6472
                     in_buf, re.icase, re.global))
6479
6473
    {
6480
6474
      /* if the buffer has been reallocated, make adjustements */
6481
6475
      if (save_out_buf != out_buf)
6545
6539
  icase - flag, if set to 1 the match is case insensitive
6546
6540
*/
6547
6541
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
6548
 
                char *replace, char *in_string, int icase)
 
6542
                char *replace, char *in_string, int icase, int global)
6549
6543
{
6550
 
  string string_to_match(in_string);
6551
6544
  const char *error= NULL;
6552
6545
  int erroffset;
6553
6546
  int ovector[3];
6554
6547
  pcre *re= pcre_compile(pattern,
6555
 
                         icase ? PCRE_CASELESS : 0,
 
6548
                         icase ? PCRE_CASELESS | PCRE_MULTILINE : PCRE_MULTILINE,
6556
6549
                         &error, &erroffset, NULL);
6557
6550
  if (re == NULL)
6558
6551
    return 1;
6559
6552
 
6560
 
  int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6561
 
                    0, 0, ovector, 3);
6562
 
  if (rc < 0)
6563
 
  {
6564
 
    pcre_free(re);
6565
 
    return 1;
6566
 
  }
6567
 
 
6568
 
  char *substring_to_replace= in_string + ovector[0];
6569
 
  int substring_length= ovector[1] - ovector[0];
6570
 
  *buf_len_p= strlen(in_string) - substring_length + strlen(replace);
6571
 
  char * new_buf = (char *)malloc(*buf_len_p+1);
6572
 
  if (new_buf == NULL)
6573
 
  {
6574
 
    pcre_free(re);
6575
 
    return 1;
6576
 
  }
6577
 
 
6578
 
  memset(new_buf, 0, *buf_len_p+1);
6579
 
  strncpy(new_buf, in_string, substring_to_replace-in_string);
6580
 
  strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6581
 
  strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6582
 
          substring_to_replace + substring_length,
6583
 
          strlen(in_string)
6584
 
            - substring_length
6585
 
            - (substring_to_replace-in_string));
6586
 
  *buf_p= new_buf;
6587
 
 
6588
 
  pcre_free(re);
6589
 
  return 0;
 
6553
  if (! global)
 
6554
  {
 
6555
 
 
6556
    int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
 
6557
                      0, 0, ovector, 3);
 
6558
    if (rc < 0)
 
6559
    {
 
6560
      pcre_free(re);
 
6561
      return 1;
 
6562
    }
 
6563
 
 
6564
    char *substring_to_replace= in_string + ovector[0];
 
6565
    int substring_length= ovector[1] - ovector[0];
 
6566
    *buf_len_p= strlen(in_string) - substring_length + strlen(replace);
 
6567
    char * new_buf = (char *)malloc(*buf_len_p+1);
 
6568
    if (new_buf == NULL)
 
6569
    {
 
6570
      pcre_free(re);
 
6571
      return 1;
 
6572
    }
 
6573
 
 
6574
    memset(new_buf, 0, *buf_len_p+1);
 
6575
    strncpy(new_buf, in_string, substring_to_replace-in_string);
 
6576
    strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
 
6577
    strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
 
6578
            substring_to_replace + substring_length,
 
6579
            strlen(in_string)
 
6580
              - substring_length
 
6581
              - (substring_to_replace-in_string));
 
6582
    *buf_p= new_buf;
 
6583
 
 
6584
    pcre_free(re);
 
6585
    return 0;
 
6586
  }
 
6587
  else
 
6588
  {
 
6589
    /* Repeatedly replace the string with the matched regex */
 
6590
    string subject(in_string);
 
6591
    size_t replace_length= strlen(replace);
 
6592
    size_t current_position= 0;
 
6593
    int rc= 0;
 
6594
    while(0 >= (rc= pcre_exec(re, NULL, subject.c_str() + current_position, subject.length() - current_position,
 
6595
                      0, 0, ovector, 3)))
 
6596
    {
 
6597
      current_position= static_cast<size_t>(ovector[0]);
 
6598
      replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
 
6599
      subject.replace(current_position, replace_length, replace, replace_length);
 
6600
    }
 
6601
 
 
6602
    char *new_buf = (char *) malloc(subject.length() + 1);
 
6603
    if (new_buf == NULL)
 
6604
    {
 
6605
      pcre_free(re);
 
6606
      return 1;
 
6607
    }
 
6608
    memset(new_buf, 0, subject.length() + 1);
 
6609
    strncpy(new_buf, subject.c_str(), subject.length());
 
6610
    *buf_len_p= subject.length() + 1;
 
6611
    *buf_p= new_buf;
 
6612
          
 
6613
    pcre_free(re);
 
6614
    return 0;
 
6615
  }
6590
6616
}
6591
6617
 
6592
6618
 
7170
7196
      return(1);
7171
7197
    if (new_pos != pa->str)
7172
7198
    {
7173
 
      my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
 
7199
      ptrdiff_t diff= PTR_BYTE_DIFF(new_pos,pa->str);
7174
7200
      for (i=0 ; i < pa->typelib.count ; i++)
7175
7201
        pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
7176
7202
                                              char*);