[m-rev.] for review: make some io procedures return "" instead of NULL

Ian MacLarty maclarty at cs.mu.OZ.AU
Thu May 19 16:05:16 AEST 2005


For review by anyone.

Estimated hours taken: 1
Branches: main and 0.12

Make some procedures in the io library return strings instead of NULL.  This
is a problem for the debugger since it segfaults when trying to display the
strings on screen.  mdb should probably be made to handle invalid string
pointers better, but that requires a bigger change.

library/io.m:
	Make ML_maybe_make_err_msg, ML_maybe_make_win32_err_msg and
	read_line_as_string_2 return an empty string instead of NULL.

tests/debugger/declarative/Mmakefile:
tests/debugger/declarative/sort.exp:
tests/debugger/declarative/sort.inp:
tests/debugger/declarative/sort.input:
tests/debugger/declarative/sort.m:
	Add a regression test.  This test segfaulted previously.

Index: library/io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.329
diff -u -r1.329 io.m
--- library/io.m	18 May 2005 05:25:58 -0000	1.329
+++ library/io.m	18 May 2005 07:38:05 -0000
@@ -1928,7 +1928,7 @@
 		memcpy(RetString, read_buffer, i * sizeof(MR_Char));
 		RetString[i] = '\\0';
 	} else {
-		RetString = NULL;
+		RetString = MR_make_string_const("""");
 	}
 	if (read_buffer != initial_read_buffer) {
 		MR_free(read_buffer);
@@ -8360,7 +8360,7 @@
 /*
 ** ML_maybe_make_err_msg(was_error, errno, msg, procname, error_msg):
 **	if `was_error' is true, then append `msg' and `strerror(errno)'
-**	to give `error_msg'; otherwise, set `error_msg' to NULL.
+**	to give `error_msg'; otherwise, set `error_msg' to "".
 **
 ** WARNING: this must only be called when the `hp' register is valid.
 ** That means it must only be called from procedures declared
@@ -8390,7 +8390,7 @@
 			strcpy((error_msg), msg);			\\
 			strcat((error_msg), errno_msg);			\\
 		} else {						\\
-			(error_msg) = NULL;				\\
+			(error_msg) = MR_make_string_const("""");		\\
 		}							\\
 	} while(0)

@@ -8398,7 +8398,7 @@
 ** ML_maybe_make_win32_err_msg(was_error, error, msg, procname, error_msg):
 **	if `was_error' is true, then append `msg' and the string
 **	returned by the Win32 API function FormatMessage() for the
-**	last error to give `error_msg'; otherwise, set `error_msg' to NULL.
+**	last error to give `error_msg'; otherwise, set `error_msg' to "".
 **	Aborts if MR_WIN32 is not defined.
 **
 ** WARNING: this must only be called when the `hp' register is valid.
@@ -8450,7 +8450,7 @@
 				LocalFree(err_buf);			\\
 			}						\\
 		} else {						\\
-			(error_msg) = NULL;				\\
+			(error_msg) = MR_make_string_const("""");	\\
 		}							\\
 	} while(0)

@@ -8701,7 +8701,7 @@
 		Status = 1;
 	}
 #else /* !MR_HAVE_READLINK */
-	TargetFileName = NULL;
+	TargetFileName = MR_make_string_const("""");
 	Status = 0;
 #endif
 	MR_update_io(IO0, IO);
Index: tests/debugger/declarative/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/declarative/Mmakefile,v
retrieving revision 1.75
diff -u -r1.75 Mmakefile
--- tests/debugger/declarative/Mmakefile	13 Apr 2005 09:32:17 -0000	1.75
+++ tests/debugger/declarative/Mmakefile	19 May 2005 01:19:28 -0000
@@ -75,7 +75,8 @@
 # decldebug grade.
 #
 DECLDEBUG_DECLARATIVE_PROGS=	\
-	builtin_call_rep
+	builtin_call_rep	\
+	sort

 # The following should not be run in decldebug grades.
 #
@@ -418,6 +419,11 @@
 	$(MDB) ./solutions < solutions.$(DECLDEBUG_INP) 2>&1 | \
 		sed -e 's/std_util.m:[0-9]*/std_util.m:NNNN/g' \
 		> solutions.out 2>&1 \
+	|| { grep . $@ /dev/null; exit 1; }
+
+sort.out: sort sort.inp
+	$(MDB_STD) ./sort sort.input < sort.inp \
+		> sort.out 2>&1 \
 	|| { grep . $@ /dev/null; exit 1; }

 special_term_dep.out: special_term_dep special_term_dep.inp
Index: tests/debugger/declarative/sort.exp
===================================================================
RCS file: tests/debugger/declarative/sort.exp
diff -N tests/debugger/declarative/sort.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/sort.exp	19 May 2005 04:35:21 -0000
@@ -0,0 +1,55 @@
+      E1:     C1 CALL pred sort.main/2-0 (det) sort.m:27
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> table_io start
+I/O tabling started.
+mdb> finish
+ian
+ian
+ian
+ian
+      E2:     C1 EXIT pred sort.main/2-0 (det) sort.m:27
+mdb> set format pretty
+mdb> set depth 1
+mdb> dd
+main(...)
+16 tabled IO actions:
+command_line_arguments(...)
+do_open_text(...)
+get_stream_db(...)
+set_stream_db(...)
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+write_string(...)
+write_string(...)
+write_string(...)
+write_string(...)
+write_string(...)
+write_string(...)
+write_string(...)
+Valid? set depth 10
+dd> print io 9
+read_line_as_string_2(<<foreign>>, yes, -1, "")
+dd> set depth 1
+dd> no
+open_stream(...)
+3 tabled IO actions:
+do_open_text(...)
+get_stream_db(...)
+set_stream_db(...)
+Valid? yes
+read_lines(...)
+5 tabled IO actions:
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+read_line_as_string_2(...)
+Valid? quit
+Diagnosis aborted.
+      E2:     C1 EXIT pred sort.main/2-0 (det) sort.m:27
+mdb> quit -y
Index: tests/debugger/declarative/sort.inp
===================================================================
RCS file: tests/debugger/declarative/sort.inp
diff -N tests/debugger/declarative/sort.inp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/sort.inp	19 May 2005 04:34:58 -0000
@@ -0,0 +1,14 @@
+echo on
+register --quiet
+table_io start
+finish
+set format pretty
+set depth 1
+dd
+set depth 10
+print io 9
+set depth 1
+no
+yes
+quit
+quit -y
Index: tests/debugger/declarative/sort.input
===================================================================
RCS file: tests/debugger/declarative/sort.input
diff -N tests/debugger/declarative/sort.input
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/sort.input	19 May 2005 01:15:55 -0000
@@ -0,0 +1,4 @@
+ian
+zoltan
+rafe
+julien
Index: tests/debugger/declarative/sort.m
===================================================================
RCS file: tests/debugger/declarative/sort.m
diff -N tests/debugger/declarative/sort.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/sort.m	19 May 2005 01:15:21 -0000
@@ -0,0 +1,149 @@
+%----------------------------------------------------------------------------%
+
+:- module sort.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%----------------------------------------------------------------------------%
+%----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module exception.
+:- import_module int.
+:- import_module list.
+:- import_module std_util.
+:- import_module string.
+
+%----------------------------------------------------------------------------%
+
+:- type line  == string.
+:- type lines == list(string).
+
+main(!IO) :-
+	io.command_line_arguments(Args, !IO),
+	open_stream(Args, MaybeStream, !IO),
+	(
+		MaybeStream = ok(InputStream),
+		some [!Words] (
+			read_lines(InputStream, !:Words, !IO),
+ 			sort_lines(!Words),
+			print_lines(!.Words, !IO)
+		)
+	;
+		MaybeStream = error(ErrorMessage),
+		io.stderr_stream(StdErr, !IO),
+		io.format(StdErr, "%s\n", [s(ErrorMessage)], !IO),
+		io.set_exit_status(1, !IO)
+	).
+
+%----------------------------------------------------------------------------%
+
+:- pred open_stream(list(string)::in, maybe_error(io.input_stream)::out,
+	io::di, io::uo) is det.
+
+open_stream([], MaybeStream, !IO) :-
+	io.stdin_stream(Stdin, !IO),
+	MaybeStream = ok(Stdin).
+open_stream([Arg], MaybeStream, !IO) :-
+	io.open_input(Arg, MaybeStream0, !IO),
+	(
+		MaybeStream0 = ok(Stream),
+		MaybeStream  = ok(Stream)
+	;
+		MaybeStream0 = error(Error),
+		io.error_message(Error, ErrorMessage),
+		MaybeStream  = error(ErrorMessage)
+	).
+open_stream([_,_|_], error(ErrorMessage), !IO) :-
+	ErrorMessage = "usage: sort [Input]".
+
+%----------------------------------------------------------------------------%
+
+:- pred read_lines(io.input_stream::in, lines::out, io::di, io::uo) is det.
+
+read_lines(Stream, Lines, !IO) :-
+	read_lines_2(Stream, [], Lines, !IO).
+
+:- pred read_lines_2(io.input_stream::in, lines::in,
+	lines::out, io::di, io::uo) is det.
+
+read_lines_2(Stream, !Lines, !IO) :-
+	io.read_line_as_string(Stream, Result, !IO),
+	(
+		Result = ok(Line),
+		list.cons(Line, !Lines),
+		read_lines_2(Stream, !Lines, !IO)
+	;
+		Result = eof
+	;
+		Result = error(Error),
+		io.error_message(Error, ErrorMessage),
+		throw(ErrorMessage)
+	).
+
+%----------------------------------------------------------------------------%
+
+:- pred sort_lines(lines::in, lines::out) is det.
+
+sort_lines(Us, Ss) :-
+	N = list.length(Us),
+	msort_n(N, Us, Ss, _).
+
+:- pred msort_n(int::in, lines::in, lines::out, lines::out) is det.
+
+msort_n(N, Unsorted, SortedPart, Rest) :-
+	(
+		N =< 0
+	->
+		SortedPart = [],
+		Rest = Unsorted
+	;
+		N = 1
+	->
+		(
+			Unsorted = [U | Us],
+			SortedPart = [U],
+			Rest = Us
+		;
+			Unsorted = [],
+			throw("Unsorted = [] and N = 0")
+		)
+	;
+		N1 = N // 2,
+		sort.msort_n(N1, Unsorted, Ss1, Us2),
+		N2 = N - N1,
+		msort_n(N2, Us2, Ss2, Rest),
+		sort.merge(Ss1, Ss2, SortedPart)
+	).
+
+:- pred merge(lines::in, lines::in, lines::out) is det.
+
+merge([], [], []).
+merge([S | Ss], [], [S | Ss]).
+merge([], [S | Ss], [S | Ss]).
+merge([A | As], [B | Bs], [C | Cs]) :-
+	compare(Cmp, A, B),
+	(
+		( Cmp = (<) ; Cmp = (=) )
+	->
+		sort.merge(As, [B | Bs], Cs),
+		C = A
+	;
+		sort.merge(As, [B | Bs], Cs), % BUG
+		C = B
+	).
+
+%----------------------------------------------------------------------------%
+
+:- pred print_lines(lines::in, io::di, io::uo) is det.
+
+print_lines(Lines, !IO) :- io.write_list(Lines, "", io.write_string, !IO).
+
+%----------------------------------------------------------------------------%
+:- end_module sort.
+%----------------------------------------------------------------------------%

--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list