@c =================================================================== @c
@c    serrano/prgm/project/bigloo/manuals/io.texi                      @c
@c    ------------------------------------------------------------     @c
@c    Author      :  Manuel Serrano                                    @c
@c    Creation    :  Mon Feb 25 11:07:08 2002                          @c
@c    Last change :                                                    @c
@c    Copyright   :  2002 Manuel Serrano                               @c
@c    ------------------------------------------------------------     @c
@c    Input and output                                                 @c
@c =================================================================== @c

@c ------------------------------------------------------------------- @c
@c    Input and Output                                                 @c
@c ------------------------------------------------------------------- @c
@node Input and Output, Structures and Records, Scheme Library, Standard Library
@comment  node-name,  next,  previous,  up
@section Input and output
@cindex input and output

This section describes Scheme operation for reading and writing data.
The section @ref{Files} describes functions for handling files.

@deffn {library procedure} call-with-input-file string proc
@deffnx {library procedure} call-with-output-file string proc
These two procedures call @var{proc} with one argument, a port obtained
by opening @var{string}.
See @ref{Ports,,r5rs.info,R5RS}, for more details.

@smalllisp
(call-with-input-file "/etc/passwd"
   (lambda (port)
      (let loop ((line (read-line port)))
         (if (not (eof-object? line))
             (begin
                (print line)
                (loop (read-line port)))))))
@end smalllisp
@end deffn

@deffn {procedure} input-port? obj 
@deffnx {procedure} input-string-port? obj 
@deffnx {procedure} output-port? obj
@deffnx {procedure} output-string-port? obj
@deffnx {procedure} port? obj
@end deffn

@deffn {bigloo procedure} input-port-name obj
Returns the file name for which @var{obj} has been opened.
@end deffn

@deffn {bigloo procedure} input-port-reopen! obj
Re-open the input port @var{obj}. That is, re-start reading from the first
character of the input port.
@end deffn

@deffn {procedure} current-input-port
@deffnx {procedure} current-output-port
@deffnx {bigloo procedure} current-error-port
@end deffn

@deffn {optional procedure} with-input-from-file string thunk
@deffnx {optional procedure} with-input-from-string string thunk
@deffnx {optional procedure} with-input-from-procedure procedure thunk
@deffnx {optional procedure} with-output-to-file string thunk
@deffnx {bigloo procedure} with-error-to-file string thunk
@deffnx {bigloo procedure} with-output-to-string thunk
@deffnx {bigloo procedure} with-error-to-string thunk
A port is opened from file @var{string}. This port is made the
current input port (resp. the current output port or the current error port) 
and @var{thunk} is called. 
See @ref{Ports,,r5rs.info,R5RS}, for more details.

@smalllisp
(with-input-from-file "/etc/passwd"
   (lambda ()
      (let loop ((line (read-line (current-input-port))))
         (if (not (eof-object? line))
             (begin
                (print line)
                (loop (read-line (current-input-port))))))))
@end smalllisp
@end deffn

@deffn {bigloo procedure} with-input-from-port port thunk
@deffnx {bigloo procedure} with-output-to-port port thunk
@deffnx {bigloo procedure} with-error-to-port port thunk

@code{with-input-from-port}, @code{with-output-to-port} and
@code{with-error-to-port} all suppose @var{port} to be a legal port. They 
call @var{thunk} making @var{port} the current input (resp. output or
error) port. None of these functions close @var{port} on the continuation 
of @var{thunk}.

@smalllisp
(with-output-to-port (current-error-port) 
   (lambda () (display "hello")))
@end smalllisp
@end deffn

@deffn {procedure} open-input-file file-name
If @var{file-name} is a regular file name, @code{open-input-file} behaves as
the function defined in the Scheme report. If @var{file-name} starts with
special prefixes it behaves differently. Here are the recognized prefixes:

@itemize @bullet
@item @code{| } (a string made of the characters @code{#\|} and @code{#\space})
Instead of opening a regular file, Bigloo opens an input pipe. 
The same syntax is used for output file. 

@smalllisp
(define pin (open-input-file "| cat /etc/passwd"))
(define pout (open-output-file "| wc -l"))

(display (read pin) pout)
(close-input-port pin)
(newline pout)
(close-output-port pout)
@end smalllisp

@item @code{pipe:}
Same as @code{| }.

@item @code{file:}
Opens a regular file.

@item @code{string:}
Opens a port on a string. This is equivalent to @code{open-input-string}. 
Example:

@smalllisp
(with-input-from-file "string:foo bar Gee"
   (lambda ()
      (print (read))
      (print (read))
      (print (read))))
   @print{} foo
   @print{} bar
   @print{} Gee
@end smalllisp

@item @code{http:server/path}

Opens an @emph{http} connection on @code{server} and open an input file
on file @code{path}.

@item @code{http:server:port-number/path}

Opens an @emph{http} connection on @code{server}, on port number
@code{port} and open an input file on file @code{path}.

@item @code{ftp:server/path}

Opens an @emph{http} connection on @code{server} and open an input file
on file @code{path}.

@end itemize
@end deffn
 
@deffn {bigloo procedure} open-input-string string
@cindex SRFI-6
Returns an @code{input-port} able to deliver characters from
@var{string}.
@end deffn

@deffn {bigloo procedure} open-input-c-string string
Returns an @code{input-port} able to deliver characters from
C string @var{string}. The buffer used by the input port is the exact
same string as the argument. That is, no buffer is allocated.
@end deffn

@deffn {bigloo procedure} open-input-procedure procedure
Returns an @code{input-port} able to deliver characters from
@var{procedure}. Each time a character has to be read, the @var{procedure}
is called. This procedure may returns a character, a string of characters, or
the boolean @code{#f}. This last value stands for the end of file. 

Example:

@smalllisp
(let ((p (open-input-procedure (let ((s #t))
				  (lambda ()
				     (if s
					 (begin (set! s #f) "foobar")
					 s))))))
   (read))
@end smalllisp
@end deffn

@deffn {procedure} open-output-file file-name
The same syntax as @code{open-input-file} for file names applies here.
When a file name starts with @samp{| }, Bigloo opens an output pipe
instead of a regular file.
@end deffn

@deffn {bigloo procedure} append-output-file file-name
If @code{file-name} exists, this function returns an @code{output-port}
on it, without removing it. New output will be appended to @var{file-name}.
If @code{file-name} does not exist, it is created.
@end deffn

@deffn {bigloo procedure} open-output-string
This function returns an @emph{output string port}. This object has almost
the same purpose as @code{output-port}. It can be used with all
the printer functions which accept @code{output-port}. An output
on a @emph{output string port} memorizes all the characters written. An
invocation of @code{flush-output-port} or @code{close-output-port} on an 
@emph{output string port} returns a new string which contains all the 
characters accumulated in the port.
@end deffn

@deffn {bigloo procedure} get-output-string output-port
@cindex SRFI-6
Given an output port created by @code{open-output-string}, 
returns a string consisting of the characters that have been 
output to the port so far. 
@end deffn

@deffn {procedure} close-input-port input-port
@deffnx {procedure} close-output-port output-port
According to R5RS, the value returned is unspecified. However, if
@emph{output-port} was created using @code{open-output-string}, the value
returned is the string consisting of all characters sent to the port.
@end deffn

@deffn {bigloo procedure} input-port-name input-port
Returns the name of the file used to open the @var{input-port}.
@end deffn

@deffn {bigloo procedure} input-port-position port
@deffnx {bigloo procedure} output-port-position port
Returns the current position (a character number), in the @var{port}.
@end deffn

@deffn {bigloo procedure} set-input-port-position! port pos
@deffnx {bigloo procedure} set-output-port-position! port pos
These functions set the file position indicator for @var{port}. The new 
position, measured in bytes, is specified by @var{pos}. It is an error 
to seek a port that cannot be changed (for instance, a string or a 
console port). The result of these functions is unspecified. An error
is raised if the position cannot be changed.
@end deffn

@deffn {bigloo procedure} input-port-reopen! input-port
This function re-opens the input @code{input-port}. That is, it reset the
position in the @var{input-port} to the first character.
@end deffn

@deffn {procedure} read [input-port]
@deffnx {bigloo procedure} read/case case [input-port]
@deffnx {bigloo procedure} read-case-sensitive [input-port]
@deffnx {bigloo procedure} read-case-insensitive [input-port]
Read a lisp expression. The case sensitivity of @code{read} is unspecified. 
If have to to enforce a special behavior regarding the case, use 
@code{read/case}, @code{read-case-sensitive} or @code{read-case-insensitive}. 
Let us consider the following source code: The value of the @code{read/case}'s
@var{case} argument may either be @code{upcase}, @code{downcase} or 
@code{sensitive}. Using any other value is an error.

@smalllisp
(define (main argv)
   (let loop ((exp (read-case-sensitive)))
      (if (not (eof-object? exp))
          (begin
             (display "exp: ")
             (write exp)
             (display " [")
             (display exp)
             (display "]")
             (print " eq?: " (eq? exp 'FOO) " " (eq? exp 'foo))
             (loop (read-case-sensitive))))))
@end smalllisp

Thus:
@display
> a.out
foo
  @print{} exp: foo [foo] eq?: #f #t
FOO
  @print{} exp: FOO [FOO] eq?: #t #f
@end display
@end deffn

@deffn {bigloo procedure} read/rp grammar port
@deffnx {bigloo procedure} read/lalrp lalrg rg port [emptyp]
These functions are fully explained in @ref{Regular Parsing},
and @ref{Lalr Parsing}.
@end deffn

@deffn {procedure} read-char [port]
@deffnx {procedure} peek-char [port]
@deffnx {procedure} eof-object? obj
@end deffn

@deffn {procedure} char-ready? [port]
@cindex run-process and char-ready?
@cindex char-ready? and run-process
@cindex run-process and input/output
As specified in the R5Rs, @ref{Ports,,r5rs.info,R5RS}, @code{char-ready?}
returns @t{#t} if a character is ready on the input @var{port} and
returns @t{#f} otherwise.  If @samp{char-ready} returns @t{#t} then
the next @samp{read-char} operation on the given @var{port} is guaranteed
not to hang.  If the @var{port} is at end of file then @samp{char-ready?}
returns @t{#t}.  @var{Port} may be omitted, in which case it defaults to
the value returned by @samp{current-input-port}.

When using @code{char-ready?} consider the latency that may exists
before characters are available. For instance, executing the
following source code:

@smalllisp
(let* ((proc (run-process "/bin/ls" "-l" "/bin" output: pipe:))
       (port (process-output-port proc)))
   (let loop ((line (read-line port)))
      (print "char ready " (char-ready? port))
      (if (eof-object? line)
          (close-input-port port)
          (begin
             (print line)
             (loop (read-line port))))))
@end smalllisp

@noindent Produces outputs such as:

@display
char ready #f
total 7168
char ready #f
-rwxr-xr-x    1 root     root         2896 Sep  6  2001 arch
char ready #f
-rwxr-xr-x    1 root     root        66428 Aug 25  2001 ash
char ready #t
...
@end display

For a discussion of Bigloo processes, see @ref{Process}.

@emph{Note:} Thanks to Todd Dukes for the example and the suggestion
of including it this documentation.
@end deffn

@deffn {bigloo procedure} read-line [input-port]
Reads characters from @var{input-port} until a @code{#\Newline}, 
a @code{#\Return} or an @code{end of file} condition is encountered. 
@code{read-line} returns a newly allocated string composed of the characters 
read.
@end deffn

@deffn {bigloo procedure} read-lines [input-port]
Accumulates all the line of an @var{input-port} into a list.
@end deffn

@deffn {bigloo procedure} read-of-strings [input-port]
Reads a sequence of non-space characters on @var{input-port}, makes a
string of them and returns the string.
@end deffn

@deffn {bigloo procedure} read-string [input-port]
Reads all the characters of @var{input-port} into a string.
@end deffn

@deffn {bigloo procedure} read-chars size [input-port]
Returns a newly allocated strings made of @var{size} characters read
from @var{input-port} (or from @code{(current-input-port)} if 
@var{input-port} is not provided). If less than @var{size} characters
are available on the input port, the returned string is smaller than
@var{size}. Its size is the number of available characters.
@end deffn

@deffn {bigloo procedure} send-chars input-port output-port [len]
Transfer the characters from @var{input-port} to @var{output-port}. This
procedure is sometimes mapped to a system call (such as @code{sendfile} under
Linux) and might thus be more efficient than copying the ports by hand.
@end deffn

@deffn {bigloo procedure} read-fill-string! s o len [input-port]
Fills the string @var{s} starting at offset @var{o} with at
most @var{len} characters read from the input port @var{input-port}
(or from @code{(current-input-port)} if @var{input-port} is not provided).
This function returns the number of fill characters (which may be smaller
than @var{len} if less characters are available).

Example:
@smalllisp
(let ((s (make-string 10 #\-)))
   (with-input-from-string "abcdefghijlkmnops"
      (lambda ()
         (read-fill-string! s 3 5)
         s)))
   @result{} ---abcde--
@end smalllisp
@end deffn

@deffn {library procedure} write obj [output-port]
@deffnx {library procedure} display obj [output-port]
@deffnx {bigloo procedure} print obj @dots{}
This procedure allows several objects to be displayed. When
all these objects have been printed, @code{print} adds a newline.
@end deffn

@deffn {bigloo procedure} display* obj @dots{}
This function is similar to @code{print} but does not add a newline.
@end deffn

@deffn {bigloo procedure} fprint output-port obj @dots{}
This function is the same as @code{print} except that a
port is provided.
@end deffn

@deffn {procedure} newline [output-port]
@deffnx {procedure} write-char char [output-port]
@deffnx {bigloo procedure} flush-output-port output-port
This procedure flushes the output port @var{output-port}.
@end deffn

@deffn {bigloo procedure} format format-string [objs]
@cindex SRFI-28

@emph{Note}: Many thanks to Scott G. Miller who is the author of
SRFI-28. Most of the documentation of this function is copied from the
SRFI documentation.

Accepts a message template (a Scheme String), and processes it,
replacing any escape sequences in order with one or more characters,
the characters themselves dependent on the semantics of the escape
sequence encountered.

An escape sequence is a two character sequence in the string where the
first character is a tilde @code{~}. Each escape code's meaning is as
follows:

@itemize @bullet
@item @code{~a} The corresponding value is inserted into the string 
as if printed with display.
@item @code{~s} The corresponding value is inserted into the string 
as if printed with write.
@item @code{~%} A newline is inserted.
@item @code{~~} A tilde @code{~} is inserted.
@end itemize

@code{~a} and @code{~s}, when encountered, require a corresponding
Scheme value to be present after the format string. The values
provided as operands are used by the escape sequences in order. It is
an error if fewer values are provided than escape sequences that
require them.

@code{~%} and @code{~~} require no corresponding value.

@smalllisp
(format "Hello, ~a" "World!") 
   @print{} Hello, World!
(format "Error, list is too short: ~s~%" '(one "two" 3)) 
   @print{} Error, list is too short: (one "two" 3)
@end smalllisp
@end deffn

@deffn {bigloo procedure} printf format-string [objs]
@deffnx {bigloo procedure} fprintf port format-string [objs]
Formats @var{objs} to the current output port or to the specified @var{port}.
@end deffn

@deffn {bigloo procedure} set-write-length! len
Sets to @var{len} the maximum number of atoms that can be printed
by @code{write} and @code{display}. This facility is useful in preventing
the printer from falling into an infinite loop when printing circular 
structures.
@end deffn

@deffn {bigloo procedure} get-write-length
Gets the current length of the printer. That is, @code{get-write-length}
returns the maximum number of Bigloo objects that are allowed to be printed 
when printing compound objects. This function is useful in preventing
the system from looping when printing circular data structures.
@end deffn

@deffn {bigloo procedure} set-printer! proc
Set the current printer to be @var{proc}; @var{proc} has to be a
procedure expecting at least one argument: an expression to
print; an output port is an optional, second argument.
@end deffn

@deffn {bigloo procedure} native-printer
Returns the native Bigloo's printer.
@end deffn

@deffn {bigloo procedure} current-printer
Returns the current Bigloo's printer.
@end deffn

@deffn {bigloo procedure} pp obj [output-port]
Pretty print @var{obj} on @var{output-port}.
@end deffn

@deffn {bigloo variable} *pp-case*
Sets the variable to @code{respect}, @code{lower} or @code{upper}
to change the case for pretty-printing.
@end deffn

@deffn {bigloo variable} *pp-width*
The width of the pretty-print.
@end deffn

@deffn {bigloo procedure} write-circle obj [output-port]
Display recursive object @var{obj} on @var{output-port}. Each component
of the object is displayed using the @code{write} library function.
@end deffn

@deffn {bigloo procedure} display-circle obj [output-port]
Display recursive object @var{obj} on @var{output-port}. Each component
of the object is displayed using the @code{display} library function.

For instance:
@smalllisp
(define l (list 1 2 3))
(set-car! (cdr l) l)
(set-car! (cddr l) l)
(display-circle l)  @print{} #0=(1 #0# #0#)
@end smalllisp
@end deffn
