io.icn: Procedures for input and output

procedure ClearOut:        remove contents of output buffer
procedure DOS_FileParts:   parse DOSfile name
procedure Flush:           flush output buffer
procedure GetBack:         get back line written
procedure LookAhead:       look at next line
procedure PutBack:         put back line read
procedure Read:            read a line in buffered mode
procedure ReadAhead:       read ahead
procedure Write:           write in buffered mode
procedure components:      get components of file name
procedure dopen:           open file on DPATH
procedure dosdir:          process DOS directory
procedure dosdirlist:      get list of DOS directory
procedure dosfiles:        DOS file names
procedure dosname:         convert file name to DOS format
procedure dpath:           full path to file on DPATH
procedure exists:          test file existence
procedure directory:       succeed if name is a directory
procedure fcopy:           copy file
procedure filelist:        get list of files
procedure filetext:        read file into list
procedure getdrive:        get current DOS drive
procedure getwd:           get DOS working directory
procedure pathfind:        find file on path
procedure pathload:        load C function from $FPATH
procedure readline:        assemble backslash-continued lines
procedure splitline:       split line into pieces
procedure suffix:          find suffix of file name
procedure tail:            find tail of file name
procedure tempfile:        get temporary file
procedure tempname:        get temporary file name

link io
June 5, 2013; Ralph E. Griswold
Contributors: Paul Abrahams, Bob Alexander, Will Evans, David A. Gamey, Richard L. Goerwitz, Will Menagarini, Charles Shartsis, Carl Sturtivant, and Gregg Townsend.
Requires: Appropriate operating system for procedures used. Some require loadfunc().
This file is in the public domain.

They provide facilities for handling input, output, and files.

There are other modules in the Icon program library that deal with
input and output.  They are not included here because they conflict
with procedures here or each other.
____________________________________________________________

File copying:

     fcopy(fn1, fn2) copies a file named fn1 to file named fn2.
____________________________________________________________

File existence:

     exists(name)    succeeds if name exists as a file but fails
                     otherwise.

     directory(name) succeeds if name exists as a directory
                     but fails otherwise.
____________________________________________________________

File lists:

     filelist(s,x)   returns a list of the file names that match the
                     specification s.  If x is nonnull, any directory
                     is stripped off.  At present it only works for
                     UNIX.  Users of other platforms are invited to add
                     code for their platforms.
____________________________________________________________

Reading and writing files:

     filetext(f)     reads the lines of f into a list and returns that
                     list

     readline(file)  assembles backslash-continued lines from the specified
                     file into a single line.  If the last line in a file
                     ends in a backslash, that character is included in the
                     last line read.

     splitline(file, line, limit)
                     splits line into pieces at first blank after
                     the limit, appending a backslash to identify split
                     lines (if a line ends in a backslash already, that's
                     too bad). The pieces are written to the specified file.
____________________________________________________________

Buffered input and output:

      ClearOut()     remove contents of output buffer without writing
      Flush()        flush output buffer
      GetBack()      get back line writen
      LookAhead()    look ahead at next line
      PutBack(s)     put back a line
      Read()         read a line
      ReadAhead(n)   read ahead n lines
      Write(s)       write a line
____________________________________________________________

Path searching:

     dopen(s)        opens and returns the file s on DPATH.

     dpath(s)        returns the path to s on DPATH.

                     Both fail if the file is not found.

     pathfind(fname, path)
             returns the full path of fname if found along the list of
             directories in "path", else fails.  If no path is given,
             getenv("DPATH") is the default.  As is customary in Icon
             path searching, "." is prepended to the path.

     pathload(fname, entry)
             calls loadfunc() to load entry from the file fname found on the
             function path.  If the file or entry point cannot be found, the
             program is aborted.  The function path consists of the current
             directory, then getenv("FPATH"), to which iconx automatically
             appends the directory containing the standard libcfunc.so file.
____________________________________________________________

Parsing file names:

     suffix()        parses a hierarchical file name, returning a 2-element
                     list:  [prefix,suffix].  E.g. suffix("/a/b/c.d") ->
                     ["/a/b/c","d"]

     tail()          parses a hierarchical file name, returning a 2-element
                     list:  [head,tail].  E.g. tail("/a/b/c.d") ->
                     ["/a/b","c.d"].

     components()    parses a hierarchical file name, returning a list of
                     all directory names in the file path, with the file
                     name (tail) as the last element.  For example,
                     components("/a/b/c.d") -> ["/","a","b","c.d"].
____________________________________________________________

Temporary files:

     tempfile(prefix, suffix, path, len)
             produces a "temporary" file that can be written.  The name
             is chosen so as not to overwrite an existing file.
             The prefix and suffix are prepended and appended, respectively,
             to a randomly chosen number.  They default to the empty
             string.  The path is prepended to the file name; its default
             is "."  The randomly chosen number is fit into a field of len
             (default 8) by truncation or right filling with zeros as
             necessary.

             It is the user's responsibility to remove the file when it is
             no longer needed.

     tempname(prefix, suffix, path, len)
             produces the name of a temporary file.
____________________________________________________________

DOS helpers:

     dosdir(diropts) generates records of type dirinfo for each file
                     found in the directory, failing when no more files
                     are available, as in

                             every dirent := dosdir("*.*") do ....

     known problems:

     When used to traverse directories and sub-directories in nested every
     loops it doesn't work as expected - requires further investigation.
     Bypass by building lists of the subdirectories to be traversed.

     dosdirlist( dpath, dpart2, infotab )
             returns a list containing the qualified file names for files
             in dpath and matching file patterns and/or options specified
             in dpart2. For example,

                dirlist := dosdirlist( "..", "*.* /o:n /a:r-d" )

             returns a list of all read-only-non-directory files in the
             parent directory on a MS-DOS compatible system.

     If the optional infotab is specified,

     (1)   it must be a table or a run time error will result
     (2)   the contents of the table will be updated as follows
           a dirinfo record will be created for each filename
     (3)   the filename will be the key to the table

     For example,

      t := table()
      dirlist := dosdirlist( "..", "*.* /o:n /a:r-d", t )
      maxsize := 0  ;  every maxsize <:= t[!dirlist].size

     calculates the maximum size of the files.

     dosfiles(pfn)   accepts a DOS filename possibly containing wildcards.
                     The filename can also include a drive letter and path.
                     If the filename ends in "\" or ":", "*.*" is appended.
                     The result sequence is a sequence of the filenames
                     corresponding to pfn.

     dosname(s)      converts a file name by truncating to the
                     MS-DOS 8.3 format.  Forward slashes are converted
                     to backslashes and all letters are converted to
                     lower case.

Every disk drive on a MS-DOS system has a "working directory", which is
the directory referred to by any references to that drive that don't begin
with a backslash (& so are either direct references to that working
directory, or paths relative to it). There is also 1 "current drive", &
its working directory is called the "current working directory". Any paths
that don't explicitly specify a drive refer to the current drive. For
example, "name.ext" refers to the current drive's working directory, aka
the current working directory; "\name.ext" refers to the current drive's
root directory; & "d:name.ext" refers to the working directory on d:.

It's reasonable to want to inquire any of these values. The CD command
displays both, in the form of a complete path to the current working
directory. However, passing such a path to either CD or the Icon function
chdir() doesn't change to that dir on that drive; it changes that drive's
working directory to the specified path without changing the current
drive. The command to change the current drive is the system() function
of a command consisting of just the drive letter followed by ":".

This affects the design of inquiry functions. They could be implemented
with system(  "CD >" || ( name := tempname() )  ) & read(open(name)), but
because this requires a slow disk access (which could fail on a full disk)
it's unacceptable to need to do that *twice*, once for the drive & again
for the dir; so if that strategy were used, it'd be necessary to return a
structure containing the current drive & the working directory. That
structure, whether table, list, or string, would then need to be either
indexed or string-scanned to get the individual values, making the code
cumbersome & obscure. It's much better to have 2 separate inquiry
functions, 1 for each value; but for this to be acceptably efficient, it's
necessary to forgo the disk access & implement the functions with
interrupts.

     getdrive()      returns the current drive as a lowercase string with
                     the ":".

     getwd("g")
     getwd("g:")     return the working directory on drive g:, or
                     fail if g: doesn't exist. getwd() returns the current
                     working directory.  getwd(...) always returns
                     lowercase. It prepends the relevant drive letter
                     with its colon; that's harmless in a chdir(), & useful
                     in an open().

     DOS_FileParts(s)        takes a DOS file name and returns
                             a record containing various representations of
                             the file name and its components.  The name
                             given is returned in the fullname field.
                             Fields that cannot be determined are returned
                             as empty strings.

Source code | Program Library Page | Icon Home Page