rev 605 - in trunk: include/prothon pr/test src

SVN User <[email protected]> Sat, 12 Jun 2004 01:28:27 -0400
Newsgroups gmane.comp.lang.prothon.cvs
Message-ID <[email protected]>
Author: mark
Date: 2004-06-12 01:28:24 -0400 (Sat, 12 Jun 2004)
New Revision: 605

Modified:
   trunk/include/prothon/prothon.h
   trunk/pr/test/test.pr
   trunk/src/builtins-string.c
Log:
added string.fmt() and string.str_(spec)

Modified: trunk/include/prothon/prothon.h
===================================================================
--- trunk/include/prothon/prothon.h	2004-06-12 00:00:35 UTC (rev 604)
+++ trunk/include/prothon/prothon.h	2004-06-12 05:28:24 UTC (rev 605)
@@ -981,8 +981,9 @@
 	(var) = int2i64t(ist, index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); }
 i64_t int2i64t(isp ist, obj_p self);
 
-#define STRING_PARAM(index, var)   \
-{	if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)), OBJ(STRING_PROTO))) {					\
+#define STRING_PARAM(index, var)											\
+{	if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] :               \
+                   list_item(ist, parms[1], -index)), OBJ(STRING_PROTO))) {	\
 		raise_exception(ist, OBJ(TYPE_EXC),									\
 				"expected a string in parameter " #index);					\
 		return NULL;														\

Modified: trunk/pr/test/test.pr
===================================================================
--- trunk/pr/test/test.pr	2004-06-12 00:00:35 UTC (rev 604)
+++ trunk/pr/test/test.pr	2004-06-12 05:28:24 UTC (rev 605)
@@ -1,3 +1,3 @@
 #!/usr/bin/env prothon
 
-print "abc" * (-1)
\ No newline at end of file
+print "{0} likes {1}".fmt('mark', 'linda')
\ No newline at end of file

Modified: trunk/src/builtins-string.c
===================================================================
--- trunk/src/builtins-string.c	2004-06-12 00:00:35 UTC (rev 604)
+++ trunk/src/builtins-string.c	2004-06-12 05:28:24 UTC (rev 605)
@@ -404,9 +404,64 @@
 	return OBJ(NONE);
 }
 
-DEF(String, str_, NULL) {
+DEF(String, str_, FPARM1(spec, NEW_STRING(""))) {
+	obj_p res;
+	char *spec, *wid_p = NULL, *prec_p = NULL, *p;
+	int left_align = FALSE;
+	int zero_pad   = FALSE;
+	int width, precision, i, self_len, res_len;
+	ch3_p self_ptr, res_ptr, ptr;
+
 	BIN_STR_CHK(String);
-	return self;
+	STRING_PARAM(1, spec);
+	if (*spec == 0) return self;
+	for(p=spec; *p; p++) {
+		if (!wid_p && !prec_p && *p == '-') left_align = TRUE;
+		else if (!wid_p && !prec_p && *p == '0') zero_pad   = TRUE;
+		else if (!wid_p && !prec_p && *p > '0' && *p <= '9') wid_p = p;
+		else if (!prec_p && *p == '.') { prec_p = p+1; *p = 0; }
+		else if (*p == 's' || *p == 'S') {
+			if (*(p+1) != 0) {
+				raise_exception(ist, OBJ(TYPE_EXC), "character found after s in string fmt spec");
+				return NULL;
+			}
+			*p = 0; 
+			break; 
+		} else if (*p < '0' || *p > '9') {
+			raise_exception(ist, OBJ(VALUE_EXC), "ivalid fmt spec in str_ parameter: \"%s\"", spec);
+			return NULL;
+		}
+	}
+	if (!wid_p && !prec_p) return self;
+	if (wid_p)  width     = atoi(wid_p);
+	if (prec_p) precision = atoi(prec_p);
+	self_len = pr_strlen(self);
+	self_ptr = pr_ch3ptr(self);
+	if (prec_p)
+		self_len = min(precision, self_len);
+	if (wid_p)
+		res_len = max(self_len, width);
+	else
+		res_len = self_len;
+	ptr = res_ptr = pr_malloc(res_len*3);
+	if (!left_align)
+		for (i=0; i < res_len-self_len; i++, ptr++) {
+			ptr->b0 = (u8_t) (zero_pad ? '0' : ' ');
+			ptr->b1 = 0;  ptr->b2 = 0;
+		}
+	for (i=0; i < self_len; i++, ptr++, self_ptr++) {
+		ptr->b0 = self_ptr->b0;
+		ptr->b1 = self_ptr->b1;
+		ptr->b2 = self_ptr->b2;
+	}
+	if (left_align)
+		for (i=0; i < res_len-self_len; i++, ptr++) {
+			ptr->b0 = (u8_t) ' ';
+			ptr->b1 = 0;  ptr->b2 = 0;
+		}
+	res = new_string_ch3_obj(ist, res_ptr, res_len);
+	pr_free(res_ptr);
+	return res;
 }
 
 DEF(String, hash_, NULL) {
@@ -548,6 +603,96 @@
 	return res;
 }
 
+#define BRACE_LEFT	0x7B
+#define BRACE_RIGHT 0x7D
+
+#define CH3MOVE(src)						\
+do {										\
+	if (dstp == resp+res_len) {				\
+		resp = pr_realloc(resp, res_len*6);	\
+		dstp = resp+res_len;				\
+		res_len *= 2;						\
+	}										\
+	dstp->b0 = src->b0;						\
+	dstp->b1 = src->b1;						\
+	dstp->b2 = src->b2;						\
+	dstp++;									\
+	src++;									\
+} while (FALSE)
+
+DEF(String, fmt, FORM_STAR3_PARAM) {
+	obj_p res, list = parms[1], dict = parms[3];
+	ch3_p srcp = pr_ch3ptr(self);
+	data_size_t src_len = pr_strlen(self), i, res_len = src_len*2, ins_len;
+	ch3_p endp = srcp+src_len, resp = pr_malloc(res_len*3), dstp=resp, insp;
+	while (srcp < endp) {
+		u32_t ch;
+		char buf[256], *p, *pend, *var, *spec;
+		obj_p value, ins_text;
+		while (srcp < endp && ORD(srcp) != BRACE_LEFT) CH3MOVE(srcp);
+		if (srcp == endp) break;
+		srcp++;
+		if (srcp < endp && ORD(srcp) == BRACE_LEFT) {
+			CH3MOVE(srcp);
+			continue;
+		}
+		for ( p = buf, pend = buf + sizeof(buf); 
+			  p < pend && srcp < endp && (ch = ORD(srcp)) != BRACE_RIGHT;
+			  p++, srcp++ ) {
+			if (ch < 0x20 || ch > 0x7f) {
+				raise_exception(ist, OBJ(VALUE_EXC), "invalid character in formatting spec");
+				return NULL;
+			}
+			*p = (char) ch;
+		}
+	    *p = 0;
+		if (ch != BRACE_RIGHT) {
+			raise_exception(ist, OBJ(VALUE_EXC), "unterminated formatting spec");
+			return NULL;
+		}
+		srcp++;
+		var = spec = buf;
+		for(; *spec; spec++)
+			if (*spec == ':') {
+				*spec = 0; 
+				spec++;
+				break;
+			}
+		if (*var >= '0' && *var <= '9') {
+			size_t index;
+			for (p=var+1; *p; p++)
+				if (*p < '0' || *p > '9') {
+					raise_exception(ist, OBJ(VALUE_EXC), "invalid character in fmt spec list index (%s)", var);
+					return NULL;
+				}
+			index = atoi(var);
+			if (index >= list_len(ist, list)) {
+				raise_exception(ist, OBJ(VALUE_EXC), "fmt spec list index too big (%s)", var);
+				return NULL;
+			}
+			value = list_item(ist, list, (int) index);
+		} else
+			value = dict_item(ist, dict, NEW_STRING(var));
+		if_exc_return NULL;
+		if (!value) {
+			raise_exception(ist, OBJ(VALUE_EXC), "no match in dictionary for fmt spec variable \"%s\"", var);
+			return NULL;
+		}
+		if (*spec) {
+			ins_text = call_func1(ist, value, SYM(STR_), NEW_STRING(spec)); if_exc_return NULL;
+		} else {
+			ins_text = call_func0(ist, value, SYM(STR_)); if_exc_return NULL;
+		}
+		insp    = pr_ch3ptr(ins_text);
+		ins_len = pr_strlen(ins_text);
+		for(i=0; i < ins_len; i++) CH3MOVE(insp);
+		del_unlock(ins_text);
+	}
+	res = new_string_ch3_obj(ist, resp, dstp-resp);
+	pr_free(resp);
+	return res;
+}
+
 DEF(String, ord, NULL) {
 	BIN_CONTENT_CHK(String);
 	if (!pr_strlen(self)) {
@@ -962,6 +1107,7 @@
 	MODULE_ADD_SYM(String, add_);
 	MODULE_ADD_SYM(String, mul_);
 	MODULE_ADD_SYM(String, mod_);
+	MODULE_ADD_SYM(String, fmt);
 	MODULE_ADD_SYM(String, iter_);
 	MODULE_ADD_SYM(String, join);
 	MODULE_ADD_SYM(String, in__QUES);