List:Commits« Previous MessageNext Message »
From:Sasha Pachev Date:January 2 2006 10:08pm
Subject:bk commit into 5.0 tree (sasha:1.2009)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of sasha. When sasha does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2009 06/01/02 15:07:48 sasha@stripped +1 -0
  replace_regex in mysqltest

  client/mysqltest.c
    1.181 06/01/02 15:07:21 sasha@stripped +321 -1
    added replace_regex

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	sasha
# Host:	mysql.sashanet.com
# Root:	/reiser-data/mysql-dev/mysql-5.0-mysqltest

--- 1.180/client/mysqltest.c	2005-12-22 12:05:35 -07:00
+++ 1.181/client/mysqltest.c	2006-01-02 15:07:21 -07:00
@@ -57,6 +57,7 @@
 #include <hash.h>
 #include <my_getopt.h>
 #include <stdarg.h>
+#include <ctype.h>
 #include <sys/stat.h>
 #include <violite.h>
 #include "my_regex.h"                     /* Our own version of lib */
@@ -326,6 +327,7 @@
 Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
 Q_IF,
 Q_DISABLE_PARSING, Q_ENABLE_PARSING,
+Q_REPLACE_REGEX,
 
 Q_UNKNOWN,			       /* Unknown command.   */
 Q_COMMENT,			       /* Comments, ignored. */
@@ -419,6 +421,7 @@
   "if",
   "disable_parsing",
   "enable_parsing",
+  "replace_regex",
   0
 };
 
@@ -460,6 +463,7 @@
 uint replace_strings(struct st_replace *rep, my_string *start,
 		     uint *max_length, const char *from);
 void free_replace();
+static void free_replace_regex();
 static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
 void free_pointer_array(POINTER_ARRAY *pa);
 static int initialize_replace_buffer(void);
@@ -468,7 +472,15 @@
 void str_to_file(const char *fname, char *str, int size);
 int do_server_op(struct st_query *q,const char *op);
 
-struct st_replace *glob_replace;
+struct st_replace_regex
+{
+  char* pattern;
+  char* replace;
+  int icase;
+};
+
+struct st_replace *glob_replace= 0;
+struct st_replace_regex *glob_replace_regex= 0;
 static char *out_buff;
 static uint out_length;
 static int eval_result = 0;
@@ -1121,6 +1133,9 @@
   {
     if (glob_replace)
       free_replace();
+      
+    if (glob_replace_regex)
+      free_replace_regex();  
 
     if (record)
     {
@@ -1772,6 +1787,91 @@
   DBUG_RETURN(start);
 }
 
+#define PARSE_REGEX_ARG \
+  while (p < expr_end) \
+  {\
+    char c= *p;\
+    if (c == '/')\
+    {\
+      if (last_c == '\\')\
+      {\
+        buf_p[-1]= '/';\
+      }\
+      else\
+      {\
+        *buf_p++ = 0;\
+        break;\
+      }  \
+    }  \
+    else\
+      *buf_p++ = c;\
+       \
+    last_c= c;\
+    p++;\
+  }  \
+
+static struct st_replace_regex* init_replace_regex(char* expr)
+{
+  struct st_replace_regex* res;
+  char* buf,*expr_end;
+  char* p;
+  char* buf_p;
+  uint expr_len= strlen(expr);
+  char last_c = 0;
+  
+  if (!(res=(struct st_replace_regex*)my_malloc(
+              sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME))))
+    return 0;
+  res->icase= 0;
+    
+  buf= (char*)res + sizeof(*res);
+  expr_end= buf + expr_len;
+  p= expr;
+  while (p < expr_end)
+  {
+    if (*p == '/')
+      break;
+    p++;  
+  }  
+  
+  if (p == expr_end || ++p == expr_end)
+    goto err;
+  
+  buf_p= buf;  
+  res->pattern= buf_p;
+  
+  PARSE_REGEX_ARG
+  
+  if (p == expr_end || ++p == expr_end)
+    goto err;
+
+  res->replace= buf_p;  
+  
+  PARSE_REGEX_ARG
+  
+  if (p == expr_end)
+    goto err;
+  
+    
+  p++;
+  
+  if (p < expr_end && *p == 'i')
+    res->icase= 1;    
+        
+  return res;  
+err:
+  my_free((gptr)res,0);
+  return 0;    
+}
+
+static void get_replace_regex(struct st_query *q)
+{
+  char *expr= q->first_argument;
+  free_replace_regex();
+  if (!(glob_replace_regex=init_replace_regex(expr)))
+    die("Could not init replace_regex");
+  q->last_argument= q->end;  
+}
 
 /*
   Get arguments for replace. The syntax is:
@@ -1824,6 +1924,15 @@
   DBUG_VOID_RETURN;
 }
 
+static void free_replace_regex()
+{
+  if (glob_replace_regex)
+  {
+    my_free((char*) glob_replace_regex,MYF(0));
+    glob_replace_regex=0;
+  }
+}
+
 void free_replace()
 {
   DBUG_ENTER("free_replace");
@@ -2138,6 +2247,7 @@
 
 err:
   free_replace();
+  free_replace_regex();
   if (ds == &ds_tmp)
     dynstr_free(&ds_tmp);
   return error;
@@ -2986,6 +3096,198 @@
   str_to_file(fn_format(reject_file, record_file,"",".reject",2), buf, size);
 }
 
+/* Sasha Pachev: these functions are needed for replace_regex */
+
+/* start of replace_regex support functions */
+
+static void check_regerr(my_regex_t* r, int err)
+{
+  char err_buf[1024];
+
+  if (err)
+  {
+    my_regerror(err,r,err_buf,sizeof(err_buf));
+    fprintf(stderr, "Regex error: %s\n", err_buf);
+    exit(1);
+  }  
+}
+
+static char* safe_malloc(uint size)
+{
+  return (char*)my_malloc(size,MYF(MY_FAE+MY_WME));
+}
+
+static char* safe_calloc(uint msize, uint count)
+{
+  uint size= msize * count;
+  char* res;
+  res= (char*)my_malloc(size,MYF(MY_FAE+MY_WME));
+  bzero(res,size);
+  return res;
+}
+
+
+static void safe_free(char* ptr)
+{
+  my_free(ptr,0);
+}
+
+/* 
+   This function has been taken and adapted from standard/ext/reg.c in 
+   the PHP 4.3.10 source. At some point we may want to move it to 
+   libregex.
+*/   
+
+static char *reg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended)
+{
+	my_regex_t re;
+	my_regmatch_t *subs;
+
+	char *buf,	/* buf is where we build the replaced string */
+	     *nbuf,	/* nbuf is used when we grow the buffer */
+		 *walkbuf; /* used to walk buf when replacing backrefs */
+	const char *walk; /* used to walk replacement string for backrefs */
+	int buf_len;
+	int pos, tmp, string_len, new_l;
+	int err, copts = 0;
+
+	string_len = strlen(string);
+  
+	if (icase) {
+		copts = REG_ICASE;
+	}
+	if (extended) {
+		copts |= REG_EXTENDED;
+	}
+
+	err = my_regcomp(&re, pattern, copts,&my_charset_latin1);
+	if (err) {
+		check_regerr(&re,err);
+		return ((char *) -1);
+	}
+
+
+	/* allocate storage for (sub-)expression-matches */
+	subs = (my_regmatch_t *)safe_calloc(sizeof(my_regmatch_t), re.re_nsub+1);
+  
+
+	/* start with a buffer that is twice the size of the stringo
+	   we're doing replacements in */
+	buf_len = 2 * string_len + 1;
+	buf = safe_malloc(buf_len);
+
+	err = pos = 0;
+	buf[0] = '\0';
+	while (!err) {
+		err = my_regexec(&re, &string[pos], re.re_nsub+1, subs, 
+       (pos ? REG_NOTBOL : 0));
+
+		if (err && err != REG_NOMATCH) {
+			check_regerr(&re,err);
+		  safe_free((char*)subs);
+			safe_free(buf);
+			my_regfree(&re);
+			return ((char *) -1);
+		}
+
+		if (!err) {
+			/* backref replacement is done in two passes:
+			   1) find out how long the string will be, and allocate buf
+			   2) copy the part before match, replacement and backrefs to buf
+
+			   */
+
+			new_l = strlen(buf) + subs[0].rm_so; /* part before the match */
+			walk = replace;
+			while (*walk) {
+				if ('\\' == *walk && isdigit((unsigned char)walk[1]) && ((unsigned char)walk[1]) - '0' <= (int)re.re_nsub) {
+					if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1) {
+						new_l += subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
+					}    
+					walk += 2;
+				} else {
+					new_l++;
+					walk++;
+				}
+			}
+			if (new_l + 1 > buf_len) {
+				buf_len = 1 + buf_len + 2 * new_l;
+				nbuf = safe_malloc(buf_len);
+				strcpy(nbuf, buf);
+				safe_free(buf);
+				buf = nbuf;
+			}
+			tmp = strlen(buf);
+			/* copy the part of the string before the match */
+			strncat(buf, &string[pos], subs[0].rm_so);
+
+			/* copy replacement and backrefs */
+			walkbuf = &buf[tmp + subs[0].rm_so];
+			walk = replace;
+			while (*walk) {
+				if ('\\' == *walk && isdigit(walk[1]) && walk[1] - '0' 
+            <= (int)re.re_nsub) {
+					if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1
+						/* this next case shouldn't happen. it does. */
+						&& subs[walk[1] - '0'].rm_so <= subs[walk[1] - '0'].rm_eo) {
+						
+						tmp = subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
+						memcpy (walkbuf, &string[pos + subs[walk[1] - '0'].rm_so], tmp);
+						walkbuf += tmp;
+					}
+					walk += 2;
+				} else {
+					*walkbuf++ = *walk++;
+				}
+			}
+			*walkbuf = '\0';
+
+			/* and get ready to keep looking for replacements */
+			if (subs[0].rm_so == subs[0].rm_eo) {
+				if (subs[0].rm_so + pos >= string_len) {
+					break;
+				}
+				new_l = strlen (buf) + 1;
+				if (new_l + 1 > buf_len) {
+					buf_len = 1 + buf_len + 2 * new_l;
+					nbuf = safe_malloc(buf_len);
+					strcpy(nbuf, buf);
+					safe_free(buf);
+					buf = nbuf;
+				}
+				pos += subs[0].rm_eo + 1;
+				buf [new_l-1] = string [pos-1];
+				buf [new_l] = '\0';
+			} else {
+				pos += subs[0].rm_eo;
+			}
+		} else { /* REG_NOMATCH */
+			new_l = strlen(buf) + strlen(&string[pos]);
+			if (new_l + 1 > buf_len) {
+				buf_len = new_l + 1; /* now we know exactly how long it is */
+				nbuf = safe_malloc(buf_len);
+				strcpy(nbuf, buf);
+				safe_free(buf);
+				buf = nbuf;
+			}
+			/* stick that last bit of string on our output */
+			strcat(buf, &string[pos]);
+		}
+	}
+
+	/* don't want to leak memory .. */
+	safe_free((char*)subs);
+	my_regfree(&re);
+
+	/* whew. */
+	return (buf);
+}
+
+
+/* end of replace_regex support functions */
+
+
 
 /* Append the string to ds, with optional replace */
 
@@ -2999,6 +3301,19 @@
       die("Out of memory in replace");
     val=out_buff;
   }
+  
+  if (glob_replace_regex)
+  {
+    char* buf;
+    buf = reg_replace(glob_replace_regex->pattern, 
+             glob_replace_regex->replace, val,
+             glob_replace_regex->icase,1);
+    if (buf == ((char*)-1))
+      die("Error in replace_regex");
+    val=buf;           
+    len= strlen(buf);
+  }
+  
   dynstr_append_mem(ds, val, len);
 }
 
@@ -3261,6 +3576,7 @@
 
 end:
   free_replace();
+  free_replace_regex();
   last_result=0;
   if (ds == &ds_tmp)
     dynstr_free(&ds_tmp);
@@ -3717,6 +4033,7 @@
 
 end:
   free_replace();
+  free_replace_regex();
   last_result=0;
   if (ds == &ds_tmp)
     dynstr_free(&ds_tmp);
@@ -4261,6 +4578,9 @@
       case Q_REPLACE:
 	get_replace(q);
 	break;
+      case Q_REPLACE_REGEX:
+        get_replace_regex(q);
+        break;
       case Q_REPLACE_COLUMN:
 	get_replace_column(q);
 	break;
Thread
bk commit into 5.0 tree (sasha:1.2009)Sasha Pachev2 Jan