make_aligned_string etc. changes

Fergus Henderson fjh at kryten.cs.mu.OZ.AU
Wed Feb 19 11:47:28 AEDT 1997


Hi dgj, 

Can you please review this one?

Some improvements to const-correctness in the string handling code.

runtime/mercury_string.h:
	Change make_aligned_string() so that the first (target)
	argument is of type `ConstString' (const char *)
	rather than of type `String' (char *), since it should
	be const, because it can point to a string literal.
	Also improve the documentation.

library/std_util.m:
	Change the code so that it matches the new definition
	of make_aligned_string.
	Also make the `functor' field of expand_info a `ConstString'
	rather than a `String', since it can point to a string literal.

library/io.m:
	Change a call to make_aligned_string so that it matches the new
	definition.

--- old/mercury_string.h	Wed Feb 19 11:34:30 1997
+++ new/mercury-string.h	Wed Feb 19 11:32:48 1997
@@ -14,35 +14,77 @@
 #include "heap.h"	/* for incr_hp_atomic */
 
 
-typedef char Char;	/* we may eventually move to using wchar_t */
+/*
+** Mercury characters are given type `Char', which is a typedef for `char'.
+** Mercury strings are stored as pointers to '\0'-terminated arrays of Char.
+**
+** We may eventually move to using wchar_t for Mercury characters and strings,
+** so it is important to use these typedefs.
+*/
+typedef char Char;
 
 typedef Char *String;
 typedef const Char *ConstString;
 
+/*
+** string_const("...", len):
+**	Given a C string literal and its length, returns a Mercury string.
+*/
 #define string_const(string, len) ((Word)string)
-#define string_equal(s1,s2) (strcmp((char*)(s1),(char*)(s2))==0)
 
+/*
+** bool string_equal(ConstString s1, ConstString s2):
+**	Return true iff the two Mercury strings s1 and s2 are equal.
+*/
+#define string_equal(s1,s2) (strcmp((char*)(s1),(char*)(s2))==0)
 
 /* 
-** If the string is aligned, set ptr equal to it, otherwise allocate one
-** on the heap.
+** void make_aligned_string(ConstString & ptr, const char * string):
+**	Given a C string `string', set `ptr' to be a Mercury string
+**	with the same contents.  (`ptr' must be an lvalue.)
+**	If the resulting Mercury string is to be used by Mercury code,
+**	then the string pointed to by `string' should have been either
+**	statically allocated or allocated on the Mercury heap.
+**	
+** BEWARE: this may modify `hp', so it must only be called from
+** places where `hp' is valid.  If calling it from inside a C function,
+** rather than inside Mercury code, you may need to call
+** save/restore_transient_regs().
+**
+** Algorithm: if the string is aligned, just set ptr equal to it.
+** Otherwise, allocate space on the heap and copy the C string to
+** the Mercury string.
 */
-#define make_aligned_string(ptr, string) \
-	( tag((Word)string) != 0 ? 					\
-		(incr_hp_atomic(LVALUE_CAST(Word, (ptr)), 		\
-		    (strlen(string) + sizeof(Word)) / sizeof(Word)),	\
-		strcpy((ptr), (string)))				\
-	: 								\
-		((ptr) = (string))					\
-	)
+#define make_aligned_string(ptr, string) 				\
+	do { 								\
+	    Word make_aligned_string_tmp;				\
+	    char * make_aligned_string_ptr;				\
+									\
+	    if (tag((Word) (string)) != 0) { 				\
+	    	incr_hp_atomic(make_aligned_string_tmp, 		\
+	    	    (strlen(string) + sizeof(Word)) / sizeof(Word));	\
+	    	make_aligned_string_ptr =				\
+		    (char *) make_aligned_string_tmp;			\
+	    	strcpy(make_aligned_string_ptr, (string));		\
+	    	(ptr) = make_aligned_string_ptr;			\
+	    } else { 							\
+	    	(ptr) = (string);					\
+	    }								\
+	} while(0)
 
 /*
+** do_hash_string(int & hash, Word string):
+**	Given a Mercury string `string', set `hash' to the hash value
+**	for that string.  (`hash' must be an lvalue.)
+**
+** This is an implementation detail used to implement hash_string().
+** It should not be used directly.  Use hash_string() instead.
+**
 ** Note that hash_string is also defined in library/string.m.
 ** The definition here and the definition in string.m
 ** must be kept equivalent.
 */
-
-#define do_hash_string(hash,s)				\
+#define do_hash_string(hash, s)				\
 	{						\
 	   int len = 0;					\
 	   hash = 0;					\
@@ -54,19 +96,23 @@
 	   hash ^= len;					\
 	}
 
-extern	int	hash_string(Word);
+/*
+** hash_string(s):
+**	Given a Mercury string `s', return a hash value for that string.
+*/
+int	hash_string(Word);
 
 #ifdef __GNUC__
 #define hash_string(s)					\
 	({ int hash;					\
-	   do_hash_string(hash,s);			\
+	   do_hash_string(hash, s);			\
 	   hash;					\
 	})
 #endif
 
 /* 
-** if we're not using gcc, the actual definition of hash_string is in aux.c
-** it uses the macro HASH_STRING_FUNC_BODY below
+** If we're not using gcc, the actual definition of hash_string is in misc.c;
+** it uses the macro HASH_STRING_FUNC_BODY below.
 */
 
 #define HASH_STRING_FUNC_BODY				\
Index: std_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/std_util.m,v
retrieving revision 1.70
diff -u -r1.70 std_util.m
--- 1.70	1997/02/13 16:41:15
+++ std_util.m	1997/02/18 18:57:18
@@ -855,7 +855,7 @@
 
 
 typedef struct mercury_expand_info {
-	String functor;
+	ConstString functor;
 	int arity;
 	Word *argument_vector;
 	Word *type_info_vector;
@@ -1031,7 +1031,7 @@
 	/* the functors are stored after the enum_indicator and
 	 * the number of functors
 	 */
-	info->functor = (String) ((Word *) entry_value)[data_value +
+	info->functor = (ConstString) ((Word *) entry_value)[data_value +
 		TYPELAYOUT_CONST_FUNCTOR_OFFSET];	
 	info->arity = 0;
 	info->argument_vector = NULL;
@@ -1057,7 +1057,7 @@
 	 * the number of functors
 	 */
 
-	info->functor = (String) ((Word *) entry_value)[data_value + 
+	info->functor = (ConstString) ((Word *) entry_value)[data_value + 
 		TYPELAYOUT_ENUM_FUNCTOR_OFFSET];	
 	info->arity = 0;
 	info->argument_vector = NULL;
@@ -1158,11 +1158,14 @@
 		/* XXX should escape characters correctly */
 
 		if (info->need_functor) {
-			incr_saved_hp_atomic(LVALUE_CAST(Word, info->functor), 
+			char *str;
+
+			incr_saved_hp_atomic(LVALUE_CAST(Word, str),
 				(strlen((String) data_value) + 2 + 
 					sizeof(Word)) / sizeof(Word));
-			sprintf(info->functor, ""%c%s%c"", '""', 
+			sprintf(str, ""%c%s%c"", '""', 
 				(String) data_value, '""');
+			info->functor = str;
 		}
 		info->argument_vector = NULL;
 		info->type_info_vector = NULL;
@@ -1173,11 +1176,14 @@
 		if (info->need_functor) {
 			char buf[500];
 			Float f;
+			char *str;
+
 			f = word_to_float(data_value);
 			sprintf(buf, ""%#.15g"", f);
-			incr_saved_hp_atomic(LVALUE_CAST(Word, info->functor), 
+			incr_saved_hp_atomic(LVALUE_CAST(Word, str), 
 				(strlen(buf) + sizeof(Word)) / sizeof(Word));
-			strcpy(info->functor, buf);
+			strcpy(str, buf);
+			info->functor = str;
 		}
 		info->argument_vector = NULL;
 		info->type_info_vector = NULL;
@@ -1187,11 +1193,13 @@
 	case TYPELAYOUT_INT_VALUE:
 		if (info->need_functor) {
 			char buf[500];
+			char *str;
 
 			sprintf(buf, ""%ld"", (long) data_value);
-			incr_saved_hp_atomic(LVALUE_CAST(Word, info->functor), 
+			incr_saved_hp_atomic(LVALUE_CAST(Word, str), 
 				(strlen(buf) + sizeof(Word)) / sizeof(Word));
-			strcpy(info->functor, buf);
+			strcpy(str, buf);
+			info->functor = str;
 		}
 
 		info->argument_vector = NULL;
@@ -1203,9 +1211,12 @@
 		/* XXX should escape characters correctly */
 
 		if (info->need_functor) {
-			incr_saved_hp_atomic(LVALUE_CAST(Word, info->functor), 
+			char *str;
+
+			incr_saved_hp_atomic(LVALUE_CAST(Word, str), 
 				(3 + sizeof(Word)) / sizeof(Word));
-			sprintf(info->functor, ""\'%c\'"", (char) data_value);
+			sprintf(str, ""\'%c\'"", (char) data_value);
+			info->functor = str;
 		}
 		info->argument_vector = NULL;
 		info->type_info_vector = NULL;
@@ -1225,8 +1236,7 @@
 
 	case TYPELAYOUT_PREDICATE_VALUE:
 		if (info->need_functor) {
-			make_aligned_string(LVALUE_CAST(String, info->functor), 
-				""<<predicate>>"");
+			make_aligned_string(info->functor, ""<<predicate>>"");
 		}
 		info->argument_vector = NULL;
 		info->type_info_vector = NULL;
@@ -1330,7 +1340,7 @@
 	restore_transient_registers();
 
 		/* Copy functor onto the heap */
-	make_aligned_string(LVALUE_CAST(String, Functor), info.functor);
+	make_aligned_string(LVALUE_CAST(ConstString, Functor), info.functor);
 
 	Arity = info.arity;
 
@@ -1404,7 +1414,7 @@
 	restore_transient_registers();
 
 		/* Get functor */
-	make_aligned_string(LVALUE_CAST(String, Functor), info.functor);
+	make_aligned_string(LVALUE_CAST(ConstString, Functor), info.functor);
 
 		/* Get arity */
 	Arity = info.arity;
Index: io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.111
diff -u -r1.111 io.m
--- 1.111	1997/02/13 23:58:28
+++ io.m	1997/02/19 00:37:11
@@ -2024,8 +2024,8 @@
 		   it should be of type `ConstString' (const char *),
 		   but fixing that requires a fair bit of work
 		   on the compiler.  */
-		make_aligned_string(PrognameOut,
-			(String) (Word) progname);
+		make_aligned_string(LVALUE_CAST(PrognameOut, ConstString),
+			progname);
 	} else {
 		PrognameOut = DefaultProgname;
 	}



More information about the developers mailing list