Universal read_line and print_line cure mac file read problems



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