Universal read_line and print_line cure mac file read problems
Subject: Universal read_line and print_line cure mac file read problems
From: Edwin Woollett
Date: Sat, 11 Jun 2011 15:43:14 -0700
The present Maxima functions readline and
printline behave as if mac text files have no
end of line chars, so blank lines are ignored
and everything in the file is returned as
one string on one line.
(This is, at least, what I observe on my
Windows XP machine with xmaxima
and ver. 5.24.0).
Hence (as part of my effort to create a universal
read_data, etc function(s) in connection with
ch 2, Maxima by Example revisions),
I have written new read_line and new print_line
functions which hopefully should cure these problems.
The new function read_line should replace
readline in all my posted string manipulation
functions.
Here is a short demo using a three line
mac text file, with text on the first line,
followed by a blank line, followed by
more text on the third line:
-----------------------------------
(%i1) display2d:false$
(%i2) load(eol_chars);
(%o2) "c:/work2/eol_chars.mac"
(%i3) eol_chars ("line1b1m.txt");
(%o3) [13]
(%i4) printfile ("line1b1m.txt")$
The calculation of the effective cross section is much simplified if
onlythose collisi
ons are considered for which the impact parameter is large, so
(%i5) print_file ("line1b1m.txt")$
The calculation of the effective cross section is much simplified if only
those collisions are considered for which the impact parameter is large, so
(%i6) ss : openr("line1b1m.txt");
(%o6) ?\#\<input\ stream\ line1b1m\.txt\>
(%i7) readline(ss);
(%o7) "The calculation of the effective cross section is much simplified if
onlythose
collisions are considered for which the impact parameter is large, so"
(%i8) readline(ss);
(%o8) false
(%i9) fposition (ss,1);
(%o9) true
(%i10) read_line(ss);
(%o10) "The calculation of the effective cross section is much simplified if
only"
(%i11) read_line (ss);
(%o11) ""
(%i12) read_line (ss);
(%o12) "those collisions are considered for which the impact parameter is
large, so"
(%i13) read_line (ss);
(%o13) false
(%i14) close(ss);
(%o14) true
--------------------------------
The code for read_line is
--------------------------------------
read_line(%str) :=
block ([%l,%ls,%lls,%n, %rL:[],%tfflag:false,
%lp,%lps,%llps,%np,%p,%bflag:false ],
do (
%p : fposition(%str),
%l : ?read\-char (%str, false),
if %l = false then
(%tfflag:true,return()),
%ls : cunlisp (%l),
%lls : slength (%ls),
if %lls = 0 then
(disp("string of length 0"),%tfflag:true,return()),
%n : cint (%ls),
if lfreeof ([10,13],%n)
then %rL : cons (ascii (%n), %rL)
else ( /* if we are here after reading just the first char on
the line, then we have a blank line case */
if %p = 1 then %bflag:true,
/* We have found the first and maybe only
eol char. */
%p : fposition(%str),
/* The next char is either another eol char
(which could be the end of a blank line)
or else the first char of the next line
or else end of file. */
%lp : ?read\-char (%str,false),
if %lp = false then return(),
%lps : cunlisp(%lp),
%llps : slength(%lps),
if %llps = 0 then
(disp("string of length 0"),%tfflag:true,return()),
%np : cint (%lps),
if not lfreeof([10,13],%np) then
(if %np = %n then fposition(%str,%p), return())
else (fposition(%str,%p),return()))),
if %bflag then ""
else if %tfflag then false
else if (length (%rL) = 0) then ""
else simplode (reverse (%rL)))$
-----------------------------------------
The code for print_file, which uses
read_line, is
---------------------------------
print_file (%mf) := block ([%s,%al],
if not stringp (%mf)
then ( disp (" file name must be a Maxima string "),
return (false)),
if not file_search (%mf) then
(disp (" file not found "),return (false)),
%s : openr (%mf),
while ( %al : read_line (%s)) # false do
printf(true,"~a~%",%al),
close(%s))$
--------------------------
Finally, a serious bug has been cured in eol_chars
which now has the code:
---------------------------------------
eol_chars(%fname) :=
block([%s,%lch,eolL :[],%nch,%Nf : 0,%n1:-1 ],
if not file_search (%fname)
then (disp(" file not found "),return(false)),
%s : openr (%fname),
do
( %lch : ?read\-char (%s,false),
if %lch = false then return(),
%nch : cint (cunlisp (%lch)),
if not lfreeof ([10,13],%nch) then
( %Nf : %Nf + 1,
if %Nf = 1 then
( %n1:%nch,
eolL : cons (%nch,eolL))
else
( if (%nch # %n1) then
(eolL : cons (%nch,eolL)),
return ()))),
close(%s),
reverse (eolL))$
---------------------------------
Users of both mac and unix based machines are invited to
test these new functions for proper behavior. Another purpose
of these functions are to avoid behaviors which differ
depending on the lisp version.
Hence I avoid the common lisp function read-line, which
is the basis of the current readline, and I only use
the lisp function read-char.
Ted Woollett