rev 129 - in trunk: include/prothon modules/File modules/Re modules/String modules/Tuple pr src

SVN User <[email protected]>
Newsgroups gmane.comp.lang.prothon.cvs
Message-ID <[email protected]>
Author: mark
Date: 2004-03-25 23:27:31 -0500 (Thu, 25 Mar 2004)
New Revision: 129

Removed:
   trunk/include/prothon/prstring.h
Modified:
   trunk/include/prothon/prothon.h
   trunk/modules/File/File.c
   trunk/modules/Re/Re.c
   trunk/modules/String/String.c
   trunk/modules/Tuple/Tuple.c
   trunk/pr/re_test.pr
   trunk/src/builtins.c
   trunk/src/console.c
   trunk/src/interp.c
   trunk/src/lock.c
   trunk/src/lock.h
   trunk/src/memory_mgr.c
   trunk/src/object.c
   trunk/src/parser_routines.c
   trunk/src/symbol.c
   trunk/src/sys.c
Log:
fixed string object so it can hold binary data 
(embedded null chars), added unmutable bit to object
which disables all write locking and turns read locking
into no-ops for efficiency, speeded up write locking

Modified: trunk/include/prothon/prothon.h
===================================================================
--- trunk/include/prothon/prothon.h	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/include/prothon/prothon.h	2004-03-26 04:27:31 UTC (rev 129)
@@ -139,19 +139,22 @@
 	obj_p	proto;
 } attr_proto_t;
 
+#define IMMEDIATE_DATA_LEN 8
+
 typedef union {
-	attr_key_t		key;
+	attr_key_t	key;
 	double		f64;
 	i64_t		i64;
-	i32_t		i32[2];
-	char		byte[8];
+	i32_t		i32[IMMEDIATE_DATA_LEN/4];
+	char		str[IMMEDIATE_DATA_LEN];
 	void*		ptr;
 } obj_data_t;
 
 typedef struct obj_s {
-	obj_type_t		data_type		:4;
 	u8_t			imm_data_len	:4;
+	obj_type_t		data_type		:3;
 	obj_state_t		state			:3;
+	u8_t			unmutable		:1;
 	u8_t			del_locked		:1;
 	u8_t			scanned			:1;	
 	u8_t 			has_attrs		:1;
@@ -160,11 +163,18 @@
 	u8_t			rdlock_cnt;
 	u8_t			wrlock_req_cnt;
 	apr_uint32_t	wrlock;
-	attr_proto_t		attr_proto;
+	attr_proto_t	attr_proto;
 	obj_data_t		data;
 	obj_p			next_obj;
 } obj_t;
 
+typedef struct  {
+	size_t	len;
+	char	str[];
+} pr_str_t;
+
+typedef pr_str_t* pr_str_p;
+
 //************************* MALLOC FUNCTIONS **********************************
 // These behave identical to the standard OS functions, but on segments smaller
 // than 64 bytes are much faster than most OS implementations.  See prmalloc.c.
@@ -664,9 +674,9 @@
 // see Int.c for example of usage
 #define DEF(slf, func, fparam_list) \
 	static obj_p slf##func(isp ist, obj_p self, int pcnt, obj_p* parms, obj_p dlocals); \
-	static void slf##func##init(void) {																	\
+	static void slf##func##init(void) {													\
 		set_attr(ist, slf, sym(ist, #func), new_func_obj(ist, slf##func, fparam_list));	\
-	}																						\
+	}																					\
 	static obj_p slf##func(isp ist, obj_p self, int pcnt, obj_p* parms, obj_p dlocals)
 
 // FORM_RPARAM: convenience macro for single formal right parameter
@@ -712,12 +722,12 @@
 
 // CALL_FUNCn: Macros to easily call functions with zero or one param
 obj_p call_func1_f(isp ist, obj_p self, obj_p sym, obj_p parm);
-#define call_func0(ist, self, sym)			call_func(ist, self, sym, 0, NULL, NULL)
-#define call_func1(ist, self, sym, parm)	call_func1_f(ist, self, sym, parm)
+#define call_func0(ist, self, sym)			call_func((ist), (self), (sym), 0, NULL, NULL)
+#define call_func1(ist, self, sym, parm)	call_func1_f((ist), (self), (sym), (parm))
 
-// STR: Call __str__ function on any object
-// Get string representation of any object by calling __str__ function on it.
-#define str(ist, obj) ((char*)obj_data_p(call_func0(ist, (obj), SYM(__STR__))))
+// AS_STR: Call __str__ function on any object
+// Get C string representation of any object by calling __str__ function on it.
+#define as_str(ist, obj) strch(call_func0((ist), (obj), SYM(__STR__)))
 
 // COVERS: Macro to determine if a type can be coerced to another type
 // Returns true if data type of o1 can represent all data that type of o2 can
@@ -725,7 +735,7 @@
 // int type.  Covering a value does not mean that some precision will not be lost.
 // This test determines when coercion is allowed.  It is up to the prototype
 // objects to decide which objects they cover by offering the __covers__ function.
-#define covers(o1, o2) (call_func1(ist, (o1), SYM(__COVERS__), (o2)) == OBJ(TRUE))
+#define covers(o1, o2) (call_func1((ist), (o1), SYM(__COVERS__), (o2)) == OBJ(TRUE))
 
 //********************************* EXCEPTIONS ******************************************
 // Exceptions are raised by calling raise_exception(ist, proto, doc). Proto is a proto
@@ -769,15 +779,25 @@
 void  obj_free   (isp ist, obj_p obj);
 
 // OBJ_DATA_P: returns the C ptr to the data area for an object.
-// Example:  A string object accesses it's C string this way: ((char*)obj_data_p(str_obj))
 #define obj_data_p(obj)															\
 	(                                 !obj ?   NULL            :				\
 	( (obj)->data_type == OBJ_TYPE_IMMDATA ? &((obj)->data)    :				\
 	( (obj)->data_type == OBJ_TYPE_DATAPTR ?   (obj)->data.ptr :	NULL ) ) )
 
-// strch: Convenience macro to access C string in string object
-#define strch(str_obj)  ((char*)obj_data_p(str_obj))
+// STRCH: macro to retreive string object as a C string
+// warning, string objects may contain null chars so C string result may be short
+#define strch(str_obj)																			\
+(                               !(str_obj) ?                                   NULL :			\
+  (str_obj)->data_type == OBJ_TYPE_IMMDATA ?             (str_obj)->data.str        :			\
+ ((str_obj)->data_type == OBJ_TYPE_DATAPTR ? ((pr_str_p)((str_obj)->data.ptr))->str : NULL) )
 
+// pr_strlen: macro to retreive string length of a string object
+// warning, string objects may contain null chars that this length ignores
+#define pr_strlen(str_obj)																	\
+	( ((str_obj)->data_type == OBJ_TYPE_IMMDATA) ?    (size_t)((str_obj)->imm_data_len)   :	\
+	 (((str_obj)->data_type == OBJ_TYPE_DATAPTR) ? ((pr_str_p)((str_obj)->data.ptr))->len : 0 ) )
+
+
 //************************** OBJECT LOCKING ***********************************
 // Prothon allows multiple threads to run at once and even multiple interpreters.
 // Data is shared at the object level.  There is only one set of objects that

Deleted: trunk/include/prothon/prstring.h
===================================================================
--- trunk/include/prothon/prstring.h	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/include/prothon/prstring.h	2004-03-26 04:27:31 UTC (rev 129)
@@ -1,71 +0,0 @@
-/* ====================================================================
- * The Prothon License Agreement, Version 1.0
- *
- * Copyright (c) 2004 Mark C. Hahn <[email protected]>. All rights
- * reserved.
- *
- * 1. This LICENSE AGREEMENT is between Mark C. Hahn ("MCH"), and the
- * Individual or Organization ("Licensee") accessing and otherwise using
- * Prothon software in source or binary form and its associated
- * documentation.
- * 
- * 2. Subject to the terms and conditions of this License Agreement, MCH
- * hereby grants Licensee a nonexclusive, royalty-free, world-wide license
- * to reproduce, analyze, test, perform and/or display publicly, prepare
- * derivative works, distribute, and otherwise use Prothon alone or in any
- * derivative version, provided, however, that MCH's License Agreement and
- * MCH's notice of copyright, i.e., "Copyright (c) 2004 Mark C. Hahn; All
- * Rights Reserved" are retained in Prothon alone or in any derivative
- * version prepared by Licensee.
- * 
- * 3. In the event Licensee prepares a derivative work that is based on or
- * incorporates Prothon or any part thereof, and wants to make the
- * derivative work available to others as provided herein, then Licensee
- * hereby agrees to include in any such work a brief summary of the
- * changes made to Prothon.
- * 
- * 4. MCH is making Prothon available to Licensee on an "AS IS" basis.
- * MCH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  BY WAY
- * OF EXAMPLE, BUT NOT LIMITATION, MCH MAKES NO AND DISCLAIMS ANY
- * REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY
- * PARTICULAR PURPOSE OR THAT THE USE OF PROTHON WILL NOT INFRINGE ANY
- * THIRD PARTY RIGHTS.
- * 
- * 5. MCH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PROTHON
- * FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A
- * RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PROTHON, OR ANY
- * DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
- * 
- * 6. This License Agreement will automatically terminate upon a material
- * breach of its terms and conditions.
- * 
- * 7. Nothing in this License Agreement shall be deemed to create any
- * relationship of agency, partnership, or joint venture between MCH and
- * Licensee.  This License Agreement does not grant permission to use MCH
- * trademarks or trade name in a trademark sense to endorse or promote
- * products or services of Licensee, or any third party.
- * 
- * 8. By copying, installing or otherwise using Prothon, Licensee agrees
- * to be bound by the terms and conditions of this License Agreement.
- * ====================================================================
- */
-
-
-// prString.h
-
-typedef union {
-	i64_t	len;
-	char	byte[];
-} str_t;
-
-typedef str_t* str_p;
-
-strlen(str_obj)																				\
-	( ((str_obj)->data_type == OBJ_TYPE_IMMDATA) ?  (i64_t)((str_obj)->imm_data_len)   :	\
-	 (((str_obj)->data_type == OBJ_TYPE_DATAPTR) ? ((str_p)((str_obj)->data.ptr))->len : 0 : 0) )
-
-stritem(str_obj, i)																			\
-( ((str_obj)->data_type == OBJ_TYPE_IMMDATA) ? (str_obj)->data.byte[i]				   :	\
- (((str_obj)->data_type == OBJ_TYPE_DATAPTR) ? ((str_p)((str_obj)->data.ptr))->byte[i] : 0 : 0) )
-
-

Modified: trunk/modules/File/File.c
===================================================================
--- trunk/modules/File/File.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/modules/File/File.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -204,9 +204,10 @@
 #endif
 DEF(FILE_PROTO, read, list2( sym(ist, "size"), new_int_obj(-1))) {
 	int readall = FALSE;
-	i64_t size;
-	size_t total_read=0, num_read;
+	i64_t size_in;
+	size_t size, total_read=0, num_read;
 	obj_p str_obj;
+	pr_str_p obj_str;
 	char* buf;
 	apr_status_t aprerr;
 	char err_buf[1024];
@@ -219,49 +220,64 @@
 		raise_exception(ist, OBJ(IOEXCEPTION), "read called on closed file");
 		return NULL;
 	}
-	size = parms[1]->data.i64;
-	if (!size) return new_string_obj("");
-	if (size < 0) {
+	size_in = parms[1]->data.i64;
+	if (!size_in) return new_string_obj("");
+	if (size_in < 0) {
 		readall = TRUE;
 		size = BUFSIZE(self);
+	} else
+		size = (size_t) size_in;
+	str_obj = new_object(OBJ(STRING_PROTO));
+	if (size < IMMEDIATE_DATA_LEN) {
+		str_obj->data_type = OBJ_TYPE_IMMDATA;
+		buf = str_obj->data.str;
+	} else {
+		obj_str = obj_malloc(str_obj, sizeof(pr_str_t)+size+1);
+		buf = obj_str->str;
 	}
-	str_obj = new_object(OBJ(STRING_PROTO));
-	buf = obj_malloc(str_obj, (size_t) size+1);
-
-	num_read = (size_t) size;
+	num_read = size;
 	aprerr = apr_file_read(STREAM(self), buf, &num_read);
 	if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
 		raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr, err_buf, sizeof(err_buf)));
 		return NULL;
 	}
 	total_read += num_read;
-
 	while(aprerr != APR_EOF && (readall || total_read < size)) {
-		size_t next_read = (readall ? (size_t) size : (size_t) size - total_read);
-
-		buf = obj_realloc(ist, str_obj, (total_read + next_read + 1));
+		size_t next_read = (readall ? size : size - total_read);
+		size_t new_len   =  total_read + next_read;
+		if (str_obj->data_type == OBJ_TYPE_IMMDATA && new_len >= IMMEDIATE_DATA_LEN) {
+			obj_str = obj_malloc(str_obj, sizeof(pr_str_t)+new_len+1);
+			buf = obj_str->str;
+		} else {
+			obj_str = obj_realloc(ist, str_obj, sizeof(pr_str_t)+new_len+1);
+			buf = obj_str->str;
+		}
 		num_read = next_read;
-
 		aprerr = apr_file_read(STREAM(self), buf + total_read, &num_read);
 		if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
-			raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr, err_buf,
-					sizeof(err_buf)));
+			raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr, err_buf, sizeof(err_buf)));
 			return NULL;
 		}
 		total_read += num_read;
 	}
-
-	buf = obj_realloc(ist, str_obj, (size_t)(total_read+1));
+	if (str_obj->data_type == OBJ_TYPE_IMMDATA)
+		str_obj->imm_data_len = (int) total_read;
+	else {
+		obj_str = obj_realloc(ist, str_obj, sizeof(pr_str_t)+total_read+1);
+		obj_str->len = total_read;
+		buf = obj_str->str;
+	}
 	buf[total_read] = 0;
-
+	str_obj->unmutable = TRUE;
 	return str_obj;
 }
 
 DEF(FILE_PROTO, readline, list2( sym(ist, "size"), new_int_obj(-1))) {
 	int readall = FALSE;
-	i64_t size;
-	size_t total_read;
+	i64_t  size_in;
+	size_t size, total_read;
 	obj_p str_obj;
+	pr_str_p obj_str;
 	char* buf;
 	apr_status_t aprerr;
 	char err_buf[1024];
@@ -274,41 +290,62 @@
 		raise_exception(ist, OBJ(IOEXCEPTION), "readline called on closed file");
 		return NULL;
 	}
-	size = (size_t)(parms[1]->data.i64);
-	if (!size) return new_string_obj("");
-	if (size < 0) {
+	size_in = parms[1]->data.i64;
+	if (!size_in) return new_string_obj("");
+	if (size_in < 0) {
 		readall = TRUE;
 		size = BUFSIZE(self);
+	} else
+		size = (size_t) size_in;
+	str_obj = new_object(OBJ(STRING_PROTO));
+	if (size < IMMEDIATE_DATA_LEN) {
+		str_obj->data_type    = OBJ_TYPE_IMMDATA;
+		buf = str_obj->data.str;
+	} else {
+		obj_str = obj_malloc(str_obj, sizeof(pr_str_t)+size+1);
+		buf = obj_str->str;
 	}
-	str_obj = new_object(OBJ(STRING_PROTO));
-	buf = obj_malloc(str_obj, (size_t) size + 1);
 	aprerr = apr_file_gets(buf, (int)(size + 1), STREAM(self));
 	if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
 		raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr, err_buf, sizeof(err_buf)));
 		return NULL;
 	}
 	total_read = strlen(buf);
-	while (aprerr != APR_EOF && buf[total_read-1] != '\n' &&
-			(readall || total_read < size)) {
-		size_t next_read = (readall ? (size_t) size : (size_t) size - total_read);
-		buf = obj_realloc(ist, str_obj, (size_t)(total_read+next_read+1));
+	while (aprerr != APR_EOF && buf[total_read-1] != '\n' && (readall || total_read < size)) {
+		size_t next_read = (readall ? size : size - total_read);
+		size_t new_len = total_read + next_read;
+		if (str_obj->data_type == OBJ_TYPE_IMMDATA && new_len >= IMMEDIATE_DATA_LEN) {
+			obj_str = obj_malloc(str_obj, sizeof(pr_str_t)+new_len+1);
+			buf = obj_str->str;
+		} else {
+			obj_str = obj_realloc(ist, str_obj, sizeof(pr_str_t)+new_len+1);
+			buf = obj_str->str;
+		}
 		aprerr = apr_file_gets(buf + total_read, (int)(next_read + 1), STREAM(self));
 		if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
-			raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr, err_buf,
-					sizeof(err_buf)));
+			raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr, err_buf, sizeof(err_buf)));
 			return NULL;
 		}
 		total_read = strlen(buf);
 	}
-	obj_realloc(ist, str_obj, (size_t)(total_read+1));
+	if (str_obj->data_type == OBJ_TYPE_IMMDATA)
+		str_obj->imm_data_len = (int) total_read;
+	else {
+		obj_str = obj_realloc(ist, str_obj, sizeof(pr_str_t)+total_read+1);
+		buf = obj_str->str;
+		obj_str->len = total_read;
+	}
+	buf[total_read] = 0;
+	str_obj->unmutable = TRUE;
 	return str_obj;
 }
 
 DEF(FILE_PROTO, readlines, list2( sym(ist, "size"), new_int_obj(-1))) {
 	int readall = FALSE;
-	i64_t size;
-	size_t total_read=0, num_read;
+	i64_t  size_in;
+	size_t size, total_read=0, num_read;
 	obj_p str_obj, list_obj;
+	pr_str_p obj_str;
 	char* buf;
 	apr_status_t aprerr;
 	char err_buf[1024];
@@ -321,17 +358,24 @@
 		raise_exception(ist, OBJ(IOEXCEPTION), "readlines called on closed file");
 		return NULL;
 	}
-	size = (parms[1]->data.i64);
-	if (!size) return new_string_obj("");
-	if (size < 0) {
+	size_in = parms[1]->data.i64;
+	if (!size_in) return new_string_obj("");
+	if (size_in < 0) {
 		readall = TRUE;
 		size = BUFSIZE(self);
-	}
+	} else
+		size = (size_t) size_in;
 	list_obj = new_list_obj(10);
 	aprerr = 0;
 	while (aprerr != APR_EOF && (readall || total_read < size)) {
 		str_obj = new_object(OBJ(STRING_PROTO));
-		buf = obj_malloc(str_obj, (size_t) size + 1);
+		if (size < IMMEDIATE_DATA_LEN) {
+			str_obj->data_type = OBJ_TYPE_IMMDATA;
+			buf = str_obj->data.str;
+		} else {
+			obj_str = obj_malloc(str_obj, sizeof(pr_str_t)+size+1);
+			buf = obj_str->str;
+		}
 		aprerr = apr_file_gets(buf, (int)(size - total_read + 1), STREAM(self));
 		if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
 			raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr,
@@ -341,8 +385,15 @@
 		total_read += num_read = strlen(buf);
 		while ( aprerr != APR_EOF && buf[num_read-1] != '\n' &&
 				                   (readall || total_read < size) ) {
-			size_t next_read = (readall ? (size_t) size : (size_t) size - total_read);
-			buf = obj_realloc(ist, str_obj, total_read + next_read + 1);
+			size_t next_read = (readall ? size : size - total_read);
+			size_t new_len = num_read + next_read;
+			if (str_obj->data_type == OBJ_TYPE_IMMDATA && new_len >= IMMEDIATE_DATA_LEN) {
+				obj_str = obj_malloc(str_obj, sizeof(pr_str_t)+new_len+1);
+				buf = obj_str->str;
+			} else {
+				obj_str = obj_realloc(ist, str_obj, sizeof(pr_str_t)+new_len+1);
+				buf = obj_str->str;
+			}
 			aprerr = apr_file_gets(buf + num_read, (int)(next_read + 1), STREAM(self));
 			if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
 				raise_exception(ist, OBJ(IOEXCEPTION), apr_strerror(aprerr,
@@ -351,7 +402,15 @@
 			}
 			total_read += num_read = strlen(buf);
 		}
-		obj_realloc(ist, str_obj, (size_t)(num_read+1));
+		if (str_obj->data_type == OBJ_TYPE_IMMDATA)
+			str_obj->imm_data_len = (int) num_read;
+		else {
+			obj_str = obj_realloc(ist, str_obj, sizeof(pr_str_t)+num_read+1);
+			buf = obj_str->str;
+			obj_str->len = num_read;
+		}
+		buf[num_read] = 0;
+		str_obj->unmutable = TRUE;
 		list_append(ist, list_obj, str_obj);
 	}
 	return list_obj;
@@ -447,8 +506,8 @@
 		return NULL;
 	}
 
-	str = strch(parms[1]);
-	size = strlen(str);
+	str  = strch(parms[1]);
+	size = pr_strlen(parms[1]);
 
 	aprerr = apr_file_write(STREAM(self), str, &size);
 	if (aprerr != APR_SUCCESS) {
@@ -474,8 +533,8 @@
 	}
 
 	if (has_proto(ist, parms[1], OBJ(STRING_PROTO))) {
-		str = strch(parms[1]);
-		size = strlen(str);
+		str  = strch(parms[1]);
+		size = pr_strlen(parms[1]);
 		aprerr = apr_file_write(STREAM(self), str, &size);
 		if (aprerr != APR_SUCCESS) {
 			raise_exception(ist, OBJ(IOEXCEPTION),
@@ -490,8 +549,8 @@
 				raise_exception(ist, OBJ(TYPE_EXC), "file writelines lst item must be a string");
 				return NULL;
 			}
-			str = strch(item);
-			size = strlen(str);
+			str  = strch(item);
+			size = pr_strlen(item);
 			aprerr = apr_file_write(STREAM(self), str, &size);
 			if (aprerr != APR_SUCCESS) {
 				raise_exception(ist, OBJ(IOEXCEPTION),

Modified: trunk/modules/Re/Re.c
===================================================================
--- trunk/modules/Re/Re.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/modules/Re/Re.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -157,6 +157,7 @@
 				else          list_append(ist, tuple_obj, new_string_obj_n(s+sp,ep-sp));
 			}
 			list_append(ist, res, tuple_obj);
+			tuple_obj->unmutable = TRUE;
 		}
 	}
 	pr_free(m);
@@ -525,6 +526,7 @@
 	res = new_tuple_obj(2);
 	list_append(ist, res, list_item(ist, self, 2*grp  ));
 	list_append(ist, res, list_item(ist, self, 2*grp+1));
+	res->unmutable = TRUE;
 	return res;
 }
 
@@ -596,6 +598,7 @@
 			if (sp == -1) list_append(ist, res, OBJ(NONE));
 			else		  list_append(ist, res, new_string_obj_n(orig_s+sp, ep-sp));
 		}
+		res->unmutable = TRUE;
 		return res;
 	}
 }
@@ -612,6 +615,7 @@
 		if (sp == -1) list_append(ist, res, parms[1]);
 		else		  list_append(ist, res, new_string_obj_n(orig_s+sp, ep-sp));
 	}
+	res->unmutable = TRUE;
 	return res;
 }
 

Modified: trunk/modules/String/String.c
===================================================================
--- trunk/modules/String/String.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/modules/String/String.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -81,20 +81,34 @@
 }
 
 DEF(STR_PROTO_OBJ, __add__, FORM_RPARAM){
-	obj_p res, other = parms[1];
-	char *r,*s,*o;
+	obj_p obj, other = parms[1];
+	pr_str_p obj_str;
+	size_t slen, olen, tlen;
 	if (!is_String(other)) other = call_func0(ist, other, SYM(__STR__));
-	r = pr_malloc(strlen(s=strch(self))+strlen(o=strch(other))+1);
-	strcpy(r, s); strcat(r, o);
-	res = new_string_obj(r);
-	pr_free(r);
-	return res;
+	slen = pr_strlen(self); olen = pr_strlen(other);
+	tlen = slen + olen;
+	obj = new_object(OBJ(STRING_PROTO));
+	if (tlen < IMMEDIATE_DATA_LEN) {
+		obj->data_type    = OBJ_TYPE_IMMDATA;
+		obj->imm_data_len = (int) tlen;
+		memcpy(&(obj->data.str[0]),    strch(self),  slen);
+		memcpy(&(obj->data.str[slen]), strch(other), olen);
+		obj->data.str[tlen] = 0;
+	} else {
+		obj_str = obj_malloc(obj, sizeof(pr_str_t)+tlen+1);
+		obj_str->len = tlen;
+		memcpy(&(obj_str->str[0]),    strch(self),  slen);
+		memcpy(&(obj_str->str[slen]), strch(other), olen);
+		obj_str->str[tlen] = 0;
+	}
+	obj->unmutable = TRUE;
+	return obj;
 }
 
 DEF(STR_PROTO_OBJ, __mul__, FORM_RPARAM){
-	obj_p res;
-	char *res_str, *self_str = strch(self);
-	size_t i, times, len = strlen(self_str);
+	obj_p obj;
+	pr_str_p obj_str;
+	size_t i, times, tlen, len = pr_strlen(self);
 	if (!has_proto(ist, parms[1], OBJ(INT_PROTO))) {
 		raise_exception(ist, OBJ(TYPE_EXC), "multiply times parameter must be an integer");
 		return NULL;
@@ -102,16 +116,27 @@
 	times = (size_t) parms[1]->data.i64;
 	if(times == 0) return new_string_obj("");
 	if(times == 1) return self;
-	res = new_string_obj("");
-	res_str = obj_malloc(res, len*times+1);
-	if(!res_str) {
-		raise_exception(ist, OBJ(OUTOFMEMORY_EXC), "memory allocation failed for string multiplication");
-		return NULL;
+	tlen = len*times+1;
+	obj = new_object(OBJ(STRING_PROTO));
+	if (tlen < IMMEDIATE_DATA_LEN) {
+		obj->data_type    = OBJ_TYPE_IMMDATA;
+		obj->imm_data_len = (int) tlen;
+		for(i=0; i < times; i++)
+			memcpy(obj->data.str+i*len, strch(self), len);
+		obj->data.str[tlen] = 0;
+	} else {
+		obj_str = obj_malloc(obj, sizeof(pr_str_t)+tlen+1);
+		if(!obj_str) {
+			raise_exception(ist, OBJ(OUTOFMEMORY_EXC), "memory allocation failed for string multiplication");
+			return NULL;
+		}
+		obj_str->len = tlen;
+		for(i=0; i < times; i++)
+			memcpy(obj_str->str+i*len, strch(self), len);
+		obj_str->str[tlen] = 0;
 	}
-	for(i=0; i < times; i++)
-		memcpy(res_str+i*len, self_str, len);
-	res_str[len*times] = 0;
-	return res;
+	obj->unmutable = TRUE;
+	return obj;
 }
 
 DEF(STR_PROTO_OBJ, __gen__, NULL) {
@@ -144,30 +169,56 @@
 }
 
 DEF(STR_PROTO_OBJ, join, FORM_RPARAM) {
-	char *s, *self_s, *item_s;
-	obj_p res, list;
+	char *self_str, *dest_ptr;
+	pr_str_p obj_str;
+	obj_p obj, list, str_list;
 	int i, llen;
+	size_t ofs, self_len, tlen;
 	if (!has_proto(ist, parms[1], OBJ(LIST_PROTO))) {
 		raise_exception(ist, OBJ(TYPE_EXC), "join function parameter must be a list");
 		return NULL;
 	}
 	list = parms[1];
 	llen = list_len(ist, parms[1]);
-	self_s = strch(self);
-	s = pr_malloc(1); s[0] = 0;
+	if (!llen) return new_string_obj("");
+	str_list = new_list_obj(llen);
+	self_str = strch(self);
+	self_len = pr_strlen(self);
+	tlen = 0;
 	for (i=0; i < llen; i++) {
-		item_s = str(ist, list_item(ist, list, i)); if_exc_return NULL;
+		obj_p str_obj = call_func0(ist, list_item(ist, list, i), SYM(__STR__)); if_exc_return NULL;
+		list_append(ist, str_list, str_obj);
+		tlen += pr_strlen(str_obj); 
+		if (i != llen-1) tlen += self_len;
+	}
+	obj = new_object(OBJ(STRING_PROTO));
+	if (tlen < IMMEDIATE_DATA_LEN) {
+		obj->data_type    = OBJ_TYPE_IMMDATA;
+		obj->imm_data_len = (int) tlen;
+		dest_ptr = obj->data.str;
+	} else {
+		obj_str = obj_malloc(obj, sizeof(pr_str_t)+tlen+1);
+		if(!obj_str) {
+			raise_exception(ist, OBJ(OUTOFMEMORY_EXC), "memory allocation failed for string multiplication");
+			return NULL;
+		}
+		obj_str->len = tlen;
+		dest_ptr = obj_str->str;
+	}
+	for(i=0, ofs=0; i < llen; i++) {
+		obj_p  str_obj = list_item(ist, str_list, i);
+		size_t str_len = pr_strlen(str_obj);
+		memcpy(dest_ptr+ofs, strch(str_obj), str_len);
+		ofs += str_len;
 		if (i != llen-1) {
-			s = pr_realloc(s, strlen(s)+strlen(item_s)+strlen(self_s)+1);
-			strcat(s, item_s);  strcat(s, self_s);  
-		} else {
-			s = pr_realloc(s, strlen(s)+strlen(item_s)+1);
-			strcat(s, item_s);
+			memcpy(dest_ptr+ofs, self_str, self_len);
+			ofs += self_len;
 		}
 	}
-	res = new_string_obj(s);
-	pr_free(s);
-	return res;
+	dest_ptr[tlen] = 0;
+	obj->unmutable = TRUE;
+	del_unlock(ist, str_list);
+	return obj;
 }
 
 DEF(STR_PROTO_OBJ, __in__, FORM_RPARAM) {
@@ -185,7 +236,7 @@
 }
 
 DEF(STR_PROTO_OBJ, len, NULL) {
-	return new_int_obj(strlen(strch(self)));
+	return new_int_obj(pr_strlen(self));
 }
 
 install_module(){

Modified: trunk/modules/Tuple/Tuple.c
===================================================================
--- trunk/modules/Tuple/Tuple.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/modules/Tuple/Tuple.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -106,7 +106,11 @@
 	}
 	times = (int)parms[1]->data.i64;
 	size  = len*times;
-	if(times == 0) return new_tuple_obj(0);
+	if(times == 0) { 
+		obj_p res = new_tuple_obj(0);
+		res ->unmutable = TRUE;
+		return res;
+	}
 	if(times == 1) return self;
 	res = new_object(OBJ(TUPLE_PROTO));
 	lstp = res->data.ptr = pr_malloc((LIST_OVERHEAD+size)*sizeof(list_t));

Modified: trunk/pr/re_test.pr
===================================================================
--- trunk/pr/re_test.pr	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/pr/re_test.pr	2004-03-26 04:27:31 UTC (rev 129)
@@ -2,7 +2,9 @@
 
 def findall(r,s):
 	result=[]
-	def foundone(mo): &result.append!(mo.group())
+	def foundone(mo): 
+		&result.append!(mo.group())
+		return ''
 	r.sub(foundone, s)
 	return result
 

Modified: trunk/src/builtins.c
===================================================================
--- trunk/src/builtins.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/builtins.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -217,7 +217,7 @@
 DEF(EXCEPTION_OBJ, __init__,  FORM_STAR_PARAM) {
 	obj_p res;
 	if (list_len(ist, parms[1]) > 0)
-		raise_exception(ist, self, str(ist, list_item(ist, parms[1], 0)));
+		raise_exception(ist, self, as_str(ist, list_item(ist, parms[1], 0)));
 	else
 		raise_exception(ist, self, NULL);
 	res = ist->exception_obj;
@@ -258,7 +258,7 @@
 	for (i=0; i < len; i++) {
 		char* item_str;
 		obj_p item = list_item(ist, self,i);
-		if ((uintptr_t)item > 10) item_str = str(ist, item);
+		if ((uintptr_t)item > 10) item_str = as_str(ist, item);
 		else {
 			sprintf(msg, "<objptr:%lx>", (unsigned long)(uintptr_t)item);
 			item_str = msg;
@@ -284,8 +284,8 @@
 	int exp_len, self_len, slice_len = list_len(ist, slice);
 	char* self_str = NULL;
 	if (seq_type == SEQ_TYPE_STRING) {
+		self_len = (int) pr_strlen(self);
 		self_str = strch(self);
-		self_len = (int)strlen(self_str);
 	} else
 		self_len = list_len(ist, self);
 	slice_item1 = list_item(ist, slice,0);
@@ -306,8 +306,7 @@
 		}
 		if (slice_len == 1) {
 			if (seq_type == SEQ_TYPE_STRING) {
-				char s[2]; s[0] = self_str[index1]; s[1] = 0;
-				return new_string_obj(s);
+				return new_string_obj_n(self_str+index1, 1);
 			} else
 				return list_item(ist, self, index1);
 		}
@@ -365,8 +364,7 @@
 			char* s = pr_malloc(exp_len+2);
 			for(i = index1, j=0; i < index2; i += index3, j++)
 				s[j] = self_str[i];
-			s[j]=0;
-			res = new_string_obj(s);
+			res = new_string_obj_n(s, j);
 			pr_free(s);
 		}   break;
 		}
@@ -391,8 +389,7 @@
 			char* s = pr_malloc(exp_len+2);
 			for(i = index1, j=0; i > index2; i += index3, j++)
 				s[j] = self_str[i];
-			s[j]=0;
-			res = new_string_obj(s);
+			res = new_string_obj_n(s, j);
 		}   break;
 		}
 	}
@@ -408,7 +405,7 @@
 
 DEF(STRING_OBJ, __hash__, NULL) {
 	i32_t res = 0x9a7c5e3;
-	char* p;
+	char *p;
 	for(p=strch(self); *p; p++) res += 131 * (*p);
 	return new_hash_obj(res);
 }
@@ -695,8 +692,8 @@
 	obj_p vals = dict_values(ist, self);
 	strcpy(res, "{");
 	for (i=0; i < len; i++) {
-		char* str1 = str(ist, list_item(ist, keys,i));
-		char* str2 = str(ist, list_item(ist, vals,i));
+		char* str1 = as_str(ist, list_item(ist, keys,i));
+		char* str2 = as_str(ist, list_item(ist, vals,i));
 		res = pr_realloc(res, strlen(res)+strlen(str1)+1+strlen(str2)+( i != len-1 ? 3 : 2));
 		strcat(res, str1);
 		strcat(res, ":");
@@ -729,7 +726,7 @@
 	}
 	if (!(res = dict_item(ist, self, list_item(ist, parms[1],0)))) {
 		char msg[1024];
-		sprintf(msg, "no entry found with key: %s", str(ist, list_item(ist, parms[1],0)));
+		sprintf(msg, "no entry found with key: %s", as_str(ist, list_item(ist, parms[1],0)));
 		raise_exception(ist, OBJ(INDEX_EXC), msg);	
 		return NULL;
 	}

Modified: trunk/src/console.c
===================================================================
--- trunk/src/console.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/console.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -226,7 +226,7 @@
 			ist->frame = NULL;
 		} else {
 			if (res && res != OBJ(NONE)) {
-				char* res_str = str(ist, res);
+				char* res_str = as_str(ist, res);
 				if (res_str[strlen(res_str)-1] == '\n')
 					printf("%s", res_str);
 				else

Modified: trunk/src/interp.c
===================================================================
--- trunk/src/interp.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/interp.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -871,7 +871,7 @@
 				if (intrp_exobj) break;
 				if (!func_obj) {
 					char str[1024];
-					sprintf(str, "Function %s not found", str(ist, fr_stack[fr_sp+1]));
+					sprintf(str, "Function %s not found", as_str(ist, fr_stack[fr_sp+1]));
 					raise_exception(ist, OBJ(FUNCNOTFOUND_EXC), str);
 					break;
 				}
@@ -923,7 +923,7 @@
 							goto call_get_func;
 						}
 					}
-					sprintf(str, "Function not found: \"%s\"", str(ist, fr_stack[fr_sp+1]));
+					sprintf(str, "Function not found: \"%s\"", as_str(ist, fr_stack[fr_sp+1]));
 					raise_exception(ist, OBJ(FUNCNOTFOUND_EXC), str);
 				}
 			}	break;
@@ -993,7 +993,7 @@
 					if (fr_stack[fr_sp+i]) {
 						obj_p str_obj = call_func0(ist, fr_stack[fr_sp+i], SYM(__STR__));
 						if (intrp_exobj) break;
-						printf("%s ", (char *)obj_data_p(str_obj));
+						printf("%s ", strch(str_obj));
 					} else if (i == param-1) goto endcase;
 				printf("\n");
 			}   break;
@@ -1091,7 +1091,7 @@
 		func_obj = get_proto_attr(ist, self, func_sym, NULL); if_exc_return NULL;
 		if (!func_obj) {
 			char err_str[1024];
-			sprintf(err_str, "Function not found: \"%s\"", str(ist, func_sym));
+			sprintf(err_str, "Function not found: \"%s\"", as_str(ist, func_sym));
 			if (!ist) {
 				printf("Internal error with exceptions disabled: %s", err_str);
 				pr_exit(1);
@@ -1178,9 +1178,9 @@
 					 has_proto(ist, exc, OBJ(EXCEPTION)) ) {
 					obj_p doc = get_attr(ist, exc, SYM(__DOC__));
 					if (doc && exc != orig_excobj)
-						printf("%s, ", (char *)obj_data_p(doc));
+						printf("%s, ", strch(doc));
 					else if (doc)
-						printf("%s.\n\n", (char *)obj_data_p(doc));
+						printf("%s.\n\n", strch(doc));
 				}
 			}
 		return orig_excobj;

Modified: trunk/src/lock.c
===================================================================
--- trunk/src/lock.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/lock.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -63,8 +63,6 @@
 #include "lock.h"
 
 #define lockstack	((clist_p)(ist->lock_stack))
-#define NO_WAIT	0
-#define WAIT	1
 
 apr_thread_cond_t	*obj_wrlock_cond;
 apr_thread_mutex_t	*obj_wrlock_mutex;
@@ -92,6 +90,10 @@
 //********************************* read_lock_try *****************************
 int read_lock_try(isp ist, obj_p obj) {
 	if (!lock((obj)->wrlock)) return FALSE;
+	if (obj->unmutable) {
+		free_obj_wrlock(obj);
+		return TRUE;
+	}
 	if (obj->wrlock_req_cnt) {
 		free_obj_wrlock(obj);
 		return FALSE;
@@ -106,6 +108,10 @@
 //********************************* read_lock *********************************
 void read_lock(isp ist, obj_p obj) {
 	get_wrlock(obj, NO_WAIT);
+	if (obj->unmutable) {
+		free_obj_wrlock(obj);
+		return;
+	}
 	if (obj->wrlock_req_cnt && !clist_in(lockstack, obj)) { 
 		while(obj->wrlock_req_cnt) {
 			free_obj_wrlock(obj);
@@ -123,6 +129,10 @@
 void read_unlock(isp ist, obj_p obj) {
 	int	write_ready_flag;
 	get_wrlock(obj, NO_WAIT);
+	if (obj->unmutable) {
+		free_obj_wrlock(obj);
+		return;
+	}
 	write_ready_flag = !(--(obj->rdlock_cnt)) && obj->wrlock_req_cnt;
 	free_obj_wrlock(obj);
 	if (write_ready_flag) apr_thread_cond_broadcast(write_cond);
@@ -137,6 +147,11 @@
 //********************************* write_lock_try ****************************
 int write_lock_try(isp ist, obj_p obj) {
 	if (!lock((obj)->wrlock)) return FALSE;
+	if (obj->unmutable) {
+		raise_exception(ist, OBJ(LOCK_EXC), "write_lock attempted on an unmutable object");
+		free_obj_wrlock(obj);
+		return FALSE;
+	}
 	if (obj->rdlock_cnt || obj->wrlock_req_cnt) {
 		free_obj_wrlock(obj);
 		return FALSE;
@@ -149,26 +164,35 @@
 void write_lock(isp ist, obj_p obj) {
 	int sav_cnt = 0;
 	get_wrlock(obj, NO_WAIT);
-	if(clist_in(lockstack, obj)) {
-		raise_exception(ist, OBJ(LOCK_EXC), "write_lock performed on a read_locked object");
-		obj->rdlock_cnt -= sav_cnt = clist_in_cnt(lockstack, obj);
-	}
-	apr_thread_mutex_lock(write_mutex);
-	while (obj->rdlock_cnt) {
-		obj->wrlock_req_cnt++;
+	if (obj->unmutable) {
+		raise_exception(ist, OBJ(LOCK_EXC), "write_lock attempted on an unmutable object");
+		// something should be done to stop code from actually modifying object XXX
 		free_obj_wrlock(obj);
-		apr_thread_cond_timedwait(write_cond, write_mutex, PAUSE_MS*1000);
-		get_wrlock(obj, NO_WAIT);
-		obj->wrlock_req_cnt--;
+		return;
 	}
-	apr_thread_mutex_unlock(write_mutex);
-	obj->rdlock_cnt += sav_cnt;
+	if(obj->rdlock_cnt) {
+		if(clist_in(lockstack, obj)) {
+			raise_exception(ist, OBJ(LOCK_EXC), "write_lock performed on a read_locked object");
+			obj->rdlock_cnt -= sav_cnt = clist_in_cnt(lockstack, obj);
+		}
+		apr_thread_mutex_lock(write_mutex);
+		while (obj->rdlock_cnt) {
+			obj->wrlock_req_cnt++;
+			free_obj_wrlock(obj);
+			apr_thread_cond_timedwait(write_cond, write_mutex, PAUSE_MS*1000);
+			get_wrlock(obj, NO_WAIT);
+			obj->wrlock_req_cnt--;
+		}
+		apr_thread_mutex_unlock(write_mutex);
+		obj->rdlock_cnt += sav_cnt;
+	}
 	obj->long_wrlock = TRUE;
 }
 
 //********************************* write_unlock ******************************
 void write_unlock(isp ist, obj_p obj) {
 	int write_ready_flag;
+	if (obj->unmutable) return;
 	assert(obj->wrlock);
 	obj->long_wrlock = FALSE;
 	obj->archived = FALSE;

Modified: trunk/src/lock.h
===================================================================
--- trunk/src/lock.h	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/lock.h	2004-03-26 04:27:31 UTC (rev 129)
@@ -98,4 +98,11 @@
 	if (obj_wrlock_waiting)							\
 		apr_thread_cond_broadcast(obj_wrlock_cond)
 
+#define NO_WAIT	0
+#define WAIT	1
+
+void get_wrlock(obj_p obj, int force_wait);
+
 #endif // #ifndef LOCK_H
+
+

Modified: trunk/src/memory_mgr.c
===================================================================
--- trunk/src/memory_mgr.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/memory_mgr.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -56,6 +56,7 @@
 #include "object.h"
 #include "interp.h"
 #include "memory_mgr.h"
+#include "lock.h"
 
 #ifdef WIN32
 #include <windows.h>
@@ -83,6 +84,22 @@
 i64_t hi_mem_boundary;
 i64_t lo_mem_boundary;
 
+//********************************* mm_write_lock ********************************
+void mm_write_lock(isp ist, obj_p obj) {
+	get_wrlock(obj, NO_WAIT);
+	if(obj->rdlock_cnt) {
+		apr_thread_mutex_lock(write_mutex);
+		while (obj->rdlock_cnt) {
+			obj->wrlock_req_cnt++;
+			free_obj_wrlock(obj);
+			apr_thread_cond_timedwait(write_cond, write_mutex, PAUSE_MS*1000);
+			get_wrlock(obj, NO_WAIT);
+			obj->wrlock_req_cnt--;
+		}
+		apr_thread_mutex_unlock(write_mutex);
+	}
+	obj->long_wrlock = TRUE;
+}
 
 //********************************* mm_write_unlock ***************************
 void mm_write_unlock(obj_p obj) {
@@ -128,7 +145,7 @@
 		obj=obj_list_root;
 		pr_unlock(&object_list_lock); 
 		while(obj) {
-			write_lock(ist, obj);
+			mm_write_lock(ist, obj);
 			obj->state = OBJ_STATE_UNMARKED;
 			obj->scanned = FALSE;
 			mm_write_unlock(obj);
@@ -146,7 +163,7 @@
 		mem_mgr_phase = MM_PHASE_MARKING;     
 		obj = OBJ(ROOT_GLOBALS);			
 		to_be_scanned_list = new_clist(1000); 
-		write_lock(ist, obj);
+		mm_write_lock(ist, obj);
 		obj->state = OBJ_STATE_NEW_OR_MARKED;
 		obj->scanned = TRUE;
 		mm_write_unlock(obj);
@@ -161,7 +178,7 @@
 				for(i=ATTRS_OVERHEAD; i < ATTRS_OVERHEAD+attr_blen(attrs); i++){
 					val = attrs[i].attr.value;
 					if(val > min_obj && val != obj && !val->scanned) {
-						write_lock(ist, val);
+						mm_write_lock(ist, val);
 						val->state = OBJ_STATE_NEW_OR_MARKED;
 						val->scanned = TRUE;
 						mm_write_unlock(val);
@@ -175,7 +192,7 @@
 					if ( attrs[i].attr.key > 0 &&
 						 (val = attrs[i].attr.value) > min_obj && 
 						  val != obj && !val->scanned ) {
-						write_lock(ist, val);
+						mm_write_lock(ist, val);
 						val->state = OBJ_STATE_NEW_OR_MARKED;
 						val->scanned = TRUE;
 						mm_write_unlock(val);
@@ -187,7 +204,7 @@
 			}
 			if (obj->data_type == OBJ_TYPE_DATAPTR) {
 				obj_p obj_list;
-				write_lock(ist, mm_obj_list);
+				mm_write_lock(ist, mm_obj_list);
 				listlen(mm_obj_list) = 0;
 				write_unlock(ist, mm_obj_list);
 				obj_list = call_func(ist, obj, SYM(__OBJLIST__), 2, mm_obj_act_param, NULL);
@@ -202,7 +219,7 @@
 					for(i=0; i < llen; i++) {
 						obj_p val = listitem(obj_list, i);
 						if (val > min_obj && val != obj && !val->scanned) {
-							write_lock(ist, val);
+							mm_write_lock(ist, val);
 							val->state = OBJ_STATE_NEW_OR_MARKED;
 							val->scanned = TRUE;
 							mm_write_unlock(val);
@@ -254,7 +271,7 @@
 			if (obj->state != OBJ_STATE_NEW_OR_MARKED && !obj->del_locked) {
 				call_func(ist, obj, SYM(__DEL__), 0, NULL, NULL);
 				ist->exception_obj = 0;
-				write_lock(ist, obj);
+				mm_write_lock(ist, obj);
 				obj->state = OBJ_STATE_DELETED;
 				pr_lock(&object_list_lock); 
 				if (last_obj)

Modified: trunk/src/object.c
===================================================================
--- trunk/src/object.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/object.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -704,11 +704,12 @@
 	if (size <= sizeof(obj_data_t)){
 		obj->data_type    = OBJ_TYPE_IMMDATA;
 		obj->imm_data_len = (int) size;
+		return &obj->data;
 	} else {
 		obj->data_type = OBJ_TYPE_DATAPTR;
 		obj->data.ptr  = pr_malloc(size);
+		return obj->data.ptr;
 	}
-	return obj_data_p(obj);
 }
 
 //********************************* obj_realloc *******************************
@@ -753,6 +754,7 @@
 	obj->data_type = OBJ_TYPE_IMMDATA;
 	obj->imm_data_len = 8;
 	obj->data.i64 = num;
+	obj->unmutable = TRUE;
 	return obj;
 }
 
@@ -762,29 +764,51 @@
 	obj->data_type = OBJ_TYPE_IMMDATA;
 	obj->imm_data_len = 8;
 	obj->data.f64 = num;
+	obj->unmutable = TRUE;
 	return obj;
 }
 
 //********************************* new_string_obj ****************************
+// this cannot be used with binary data, for C strings only
+// for binary data with embedded nulls use new_string_obj_n()
 obj_p new_string_obj(char* str){
 	obj_p obj;
-	char* obj_str;
+	pr_str_p obj_str;
+	size_t len;
 	if(!str) return NULL;
+	len = strlen(str);
 	obj = new_object(OBJ(STRING_PROTO));
-	obj_str = obj_malloc(obj, strlen(str) + 1);
-	strcpy(obj_str, str);
+	if (len < IMMEDIATE_DATA_LEN) {
+		obj->data_type    = OBJ_TYPE_IMMDATA;
+		obj->imm_data_len = (int) len;
+		strcpy(obj->data.str, str);
+	} else {
+		obj_str = obj_malloc(obj, sizeof(pr_str_t)+len+1);
+		obj_str->len = len;
+		strcpy(&(obj_str->str[0]), str);
+	}
+	obj->unmutable = TRUE;
 	return obj;
 }
 
-//********************************* new_string_obj ****************************
-obj_p new_string_obj_n(char* str, size_t n){
+//********************************* new_string_obj_n ****************************
+obj_p new_string_obj_n(char* str, size_t len){
 	obj_p obj;
-	char* obj_str;
+	pr_str_p obj_str;
 	if(!str) return NULL;
 	obj = new_object(OBJ(STRING_PROTO));
-	obj_str = obj_malloc(obj, n+1);
-	strncpy(obj_str, str, n);
-	obj_str[n] = 0;
+	if (len < IMMEDIATE_DATA_LEN) {
+		obj->data_type    = OBJ_TYPE_IMMDATA;
+		obj->imm_data_len = (int) len;
+		memcpy(obj->data.str, str, len);
+		obj->data.str[len] = 0;
+	} else {
+		obj_str = obj_malloc(obj, sizeof(pr_str_t)+len+1);
+		obj_str->len = len;
+		memcpy(&(obj_str->str[0]), str, len);
+		obj_str->str[len] = 0;
+	}
+	obj->unmutable = TRUE;
 	return obj;
 }
 
@@ -795,6 +819,7 @@
 	hash_obj->imm_data_len = 4;
 	hash_obj->data.i32[0] = num & HASH_MASK;
 	if (!(hash_obj->data.i32[0])) hash_obj->data.i32[0] = 1;
+	hash_obj->unmutable = TRUE;
 	return hash_obj;
 }
 
@@ -906,6 +931,7 @@
 				list_append_no_lock(slice_obj,ind3);
 		}
 	}
+	slice_obj->unmutable = TRUE;
 	return slice_obj;
 }
 
@@ -914,6 +940,7 @@
 	obj_p super_obj = new_object(OBJ(SUPER_PROTO));
 	super_obj->data_type = OBJ_TYPE_DATAPTR;
 	super_obj->data.ptr = symbol;
+	super_obj->unmutable = TRUE;
 	return super_obj;
 }
 
@@ -1200,7 +1227,7 @@
 	obj_p doc;
 	doc = get_attr(ist, obj, SYM(__DOC__));
 	if (doc) {fprintf(fout,"obj(%lx) doc: %s\n", (unsigned long)(uintptr_t)obj, strch(doc)); prt_flg = 1;}
-	else     {fprintf(fout,"%s\n",str(ist, obj)); prt_flg = 1;}
+	else     {fprintf(fout,"%s\n",as_str(ist, obj)); prt_flg = 1;}
 	for(i=0; i < clist_len(object_list); i++)
 		if (clist_item(object_list, i) == obj)
 			return;
@@ -1218,7 +1245,7 @@
 	if(obj->data_type == OBJ_TYPE_IMMDATA){
 		fprintf(fout, "%08x %08x \"%s\"\n", 
 							obj->data.i32[0], obj->data.i32[1], 
-							obj->data.byte );
+							obj->data.str );
 	} else if(obj->data_type != OBJ_TYPE_NONE){
 		fprintf(fout,"%08x\n", obj->data.i32[0]);
 	}

Modified: trunk/src/parser_routines.c
===================================================================
--- trunk/src/parser_routines.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/parser_routines.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -1062,10 +1062,22 @@
 }
 code* string_to_obj(void* param, char* str, int long_flag){
 	code* p = new_code(param, 2, 1, 1, OP_PUSH);
+	pr_str_p obj_str;
+	size_t len = strlen(str);
 	obj_p obj = new_object(
 			(long_flag == NEW_LONG? OBJ(LONG_PROTO) : OBJ(STRING_PROTO)) );
-	char* obj_str = obj_malloc(obj, strlen(str) + 1);
-	strcpy(obj_str, str);
+	if (len < IMMEDIATE_DATA_LEN) {
+		obj->data_type    = OBJ_TYPE_IMMDATA;
+		obj->imm_data_len = (int) len;
+		memcpy(obj->data.str, str, len);
+		obj->data.str[len] = 0;
+	} else {
+		obj_str = obj_malloc(obj, sizeof(pr_str_t)+len+1);
+		obj_str->len = len;
+		memcpy(&(obj_str->str[0]), str, len);
+		obj_str->str[len] = 0;
+	}
+	obj->unmutable = TRUE;
 	p->code_data[0].bytecode.param = 2;
 	p->code_data[1].data = obj;
 	add_to_const_list(param, obj);

Modified: trunk/src/symbol.c
===================================================================
--- trunk/src/symbol.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/symbol.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -244,7 +244,10 @@
 	obj_p s_obj;
 	if (sym_obj) {
 		s_obj = get_attr(ist, sym_obj, SYM(__STRING__));
-		if (s_obj) return strch(s_obj);
+		if (s_obj) {
+			char* tmp = strch(s_obj);
+			return tmp;
+		}
 	}
 	return NULL;
 }

Modified: trunk/src/sys.c
===================================================================
--- trunk/src/sys.c	2004-03-26 00:27:20 UTC (rev 128)
+++ trunk/src/sys.c	2004-03-26 04:27:31 UTC (rev 129)
@@ -180,6 +180,7 @@
 	list_append(ist, vers_tuple, new_string_obj(PROTHON_VERSION_NUMBER));
 	list_append(ist, vers_tuple, new_string_obj(numonly(PROTHON_VERSION_BUILD, path)));
 	list_append(ist, vers_tuple, new_string_obj(PROTHON_VERSION_DATE));
+	vers_tuple->unmutable = TRUE;
 	set_attr(ist, sys_module, sym(ist, "version"), vers_tuple);
 	set_attr(ist, sys_module, sym(ist, "maxint"),  new_int_obj(MAX_INT_VAL));
 	set_attr(ist, sys_module, sym(ist, "modules"), OBJ(MODULES));


_______________________________________________
Prothon-commits mailing list
[email protected]
http://lists.prothon.org/mailman/listinfo/prothon-commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.