diff: fix bugs with escaping special characters in C strings

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Jan 27 19:33:43 AEDT 1999


Estimated hours taken: 0.75

Fix some bugs where we were not properly escaping special characters in
C strings in the generated code.

compiler/llds_out.m:
	Change a number of places to call output_quoted_c_string instead of
	io__write_string, so that special characters will be properly escaped.
	Add new predicate llds_out__quote_c_string, for use by pragma_c_gen.m.

compiler/pragma_c_gen.m:
	Call llds_out__quite_c_string, to ensure that special characters
	in the generated "pragma_c_raw_code" are properly escaped.

tests/valid/int64.m:
tests/valid/Mmakefile:
	Regression test for the above-mentioned bug fix.

Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.101
diff -u -r1.101 llds_out.m
--- llds_out.m	1998/12/06 23:43:37	1.101
+++ llds_out.m	1999/01/27 08:18:16
@@ -98,6 +98,13 @@
 :- pred llds_out__qualify_name(string, string, string).
 :- mode llds_out__qualify_name(in, in, out) is det.
 
+	% Convert a string into a form suitable for outputting as a C string,
+	% by converting special characters into backslashes escapes.
+:- pred llds_out__quote_c_string(string, string).
+:- mode llds_out__quote_c_string(in, out) is det.
+
+	% Like quote_c_string except the resulting string is written to
+	% the current output stream.
 :- pred output_c_quoted_string(string, io__state, io__state).
 :- mode output_c_quoted_string(in, di, uo) is det.
 
@@ -1362,7 +1369,7 @@
 		{ FrameInfo = ordinary_frame(Msg, Num, MaybeStruct) },
 		( { MaybeStruct = yes(pragma_c_struct(StructName, _, _)) } ->
 			io__write_string("\tmkpragmaframe("""),
-			io__write_string(Msg),
+			output_c_quoted_string(Msg),
 			io__write_string(""", "),
 			io__write_int(Num),
 			io__write_string(", "),
@@ -1372,7 +1379,7 @@
 			io__write_string(");\n")
 		;
 			io__write_string("\tmkframe("""),
-			io__write_string(Msg),
+			output_c_quoted_string(Msg),
 			io__write_string(""", "),
 			io__write_int(Num),
 			io__write_string(", "),
@@ -1435,7 +1442,7 @@
 	{ ProfInfo = CallerLabel - _ },
 	output_label(CallerLabel),
 	io__write_string(", """),
-	io__write_string(TypeMsg),
+	output_c_quoted_string(TypeMsg),
 	io__write_string(""");\n").
 
 output_instruction(mark_hp(Lval), _) -->
@@ -1477,7 +1484,7 @@
 	io__write_string("\tincr_sp_push_msg("),
 	io__write_int(N),
 	io__write_string(", """),
-	io__write_string(Msg),
+	output_c_quoted_string(Msg),
 	io__write_string(""");\n").
 
 output_instruction(decr_sp(N), _) -->
@@ -1571,7 +1578,7 @@
 		io__write_string("#line "),
 		io__write_int(Line),
 		io__write_string(" """),
-		io__write_string(File),
+		output_c_quoted_string(File),
 		io__write_string("""\n")
 	;
 		[]
@@ -1593,7 +1600,7 @@
 		{ NextLine is Line + 1 },
 		io__write_int(NextLine),
 		io__write_string(" """),
-		io__write_string(FileName),
+		output_c_quoted_string(FileName),
 		io__write_string("""\n")
 	;
 		[]
@@ -3573,6 +3580,16 @@
 	;
 		[]
 	).
+
+llds_out__quote_c_string(String, QuotedString) :-
+	QuoteOneChar = (pred(Char::in, RevChars0::in, RevChars::out) is det :-
+		( quote_c_char(Char, QuoteChar) ->
+			RevChars = [QuoteChar, '\\' | RevChars0]
+		;
+			RevChars = [Char | RevChars0]
+		)),
+	string__foldl(QuoteOneChar, String, [], RevQuotedChars),
+	string__from_rev_char_list(RevQuotedChars, QuotedString).
 
 :- pred quote_c_char(char, char).
 :- mode quote_c_char(in, out) is semidet.
Index: compiler/pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.25
diff -u -r1.25 pragma_c_gen.m
--- pragma_c_gen.m	1998/12/16 16:35:30	1.25
+++ pragma_c_gen.m	1999/01/27 05:44:44
@@ -389,11 +389,12 @@
 	;
 		module_info_pred_info(ModuleInfo, PredId, PredInfo),
 		pred_info_name(PredInfo, Name),
+		llds_out__quote_c_string(Name, MangledName),
 		string__append_list(["\tMR_OBTAIN_GLOBAL_LOCK(""",
-			Name, """);\n"], ObtainLockStr),
+			MangledName, """);\n"], ObtainLockStr),
 		ObtainLock = pragma_c_raw_code(ObtainLockStr),
 		string__append_list(["\tMR_RELEASE_GLOBAL_LOCK(""",
-			Name, """);\n"], ReleaseLockStr),
+			MangledName, """);\n"], ReleaseLockStr),
 		ReleaseLock = pragma_c_raw_code(ReleaseLockStr)
 	},
 
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.32
diff -u -r1.32 Mmakefile
--- Mmakefile	1998/11/11 00:28:01	1.32
+++ Mmakefile	1999/01/27 08:27:01
@@ -52,6 +52,7 @@
 	indexing.m \
 	inhibit_warn_test.m \
 	inlining_bug.m \
+	int64.m \
 	intermod_lambda.m \
 	intermod_quote.m \
 	intermod_test.m \
Index: tests/valid/int64.m
===================================================================
RCS file: int64.m
diff -N int64.m
--- /dev/null	Wed Jan 27 19:05:01 1999
+++ int64.m	Wed Jan 27 19:33:15 1999
@@ -0,0 +1,18 @@
+% A development version of the Mercury compiler generated
+% invalid C code for this example, because it didn't properly
+% escape special characters such as \ in some of the C strings
+% that it generated.
+
+:- module int64.
+
+:- interface.
+
+:- type int64.
+
+:- func int64 /\ int64 = int64.
+
+:- implementation.
+
+:- type int64 == int.
+
+:- pragma c_code((A::in) /\ (B::in) = (C::out), [], "C = A & B;").
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh>  |   but source code lives forever"
PGP: finger fjh at 128.250.37.3        |     -- leaked Microsoft memo.



More information about the developers mailing list