REF SYSIO                                           John Gibson Apr 1996
                                            Revised John Gibson Apr 1999

        COPYRIGHT University of Sussex 1999. All Rights Reserved.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<                             >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<    DEVICES AND SYSTEM       >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<     INPUT AND OUTPUT        >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<        PROCEDURES           >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<                             >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

This file describes the most basic level of input and output  facilities
in  Poplog,   namely  input   and  output   via  device   records.   For
character-stream input and output procedures, see REF * CHARIO.

         CONTENTS - (Use <ENTER> g to access required sections)

  1   Introduction
      1.1   System vs User Devices

  2   Opening System Devices

  3   Reading Devices

  4   Writing Devices

  5   Line Repeaters and Consumers

  6   File Control Operations

  7   File Information

  8   Predicates on Devices

  9   Device Information

 10   Standard Devices

 11   Constructing User Devices

 12   Miscellaneous



---------------
1  Introduction
---------------

This file describes the most basic level of input and output  facilities
in  Poplog,   namely  input   and  output   via  device   records.   For
character-stream input/output procedures, see REF * CHARIO.

    System  device  records  are  created  for  files  with  sysopen  or
syscreate (also  syspipe in  Unix  and sysmailbox  in  VMS). As  far  as
possible, the device input and  output facilities have been designed  to
provide a Unix style interface (i.e. the ability to read/write any  file
as  a  stream  of  bytes),  but  with  extensions  where  necessary;  in
particular, the  above  device-creating procedures  take  an  additional
argument to their Unix counterparts, which specifies the  `organisation'
of the file (and allows compatibility between Unix and VMS Poplog).

    (As part  of  this  in  Unix  Poplog,  every  device  representing a
terminal maintains a full  set of terminal parameters  which are set  on
the terminal whenever that device is used (unless it is already set  for
that  device).   In   this   way   multiple   devices   with   different
characteristics can be made  to work for  the same underlying  terminal,
with automatic switching between different settings as appropriate.  See
sys_io_control below for more information.)

    Interfaces  to  operating  system  I/O  calls  are  provided   where
appropriate, wherever possible  in a  form that can  be made  compatible
across   all   Poplog    implementations.   Various   other    operating
system-related facilities (e.g. filename  processing) are dealt with  in
REF * SYSUTIL.

In Unix systems, see also REF * SOCKETS, which provides an interface  to
the Berkeley Unix socket facilities for network communications.


1.1  System vs User Devices
---------------------------
In addition to the system devices created by sysopen, etc, there is also
a facility for creating user devices (with consdevice). User devices can
specify arbitrary procedures to deal  with I/O requests from  procedures
like sysread  and syswrite  applied to  them, and  can thus  be used  to
implement simulated I/O channels. (For example, this facility is used in
the Ved editor to allow device I/O on Ved buffers).

Note that in  the descriptions  that follow,  sdev is  used to  denote a
system device, udev a user device, and dev either kind.




-------------------------
2  Opening System Devices
-------------------------

The procedures  sysopen,  syscreate, syspipe  and  sysmailbox  described
below all take an  argument org to specify  the organisation of a  file.
This argument can currently take the  following values (which are by  no
means satisfactory, and will hopefully be improved in the future):

false
    For terminals, this gives normal interactive line mode, with prompts
    given by popprompt.

    For terminals and  other Unix 'interactive'  devices (such as  pipes
    and sockets), this value  means that a sysread  of N bytes will  not
    attempt to read  the full N  bytes if less  are available, i.e.  the
    call may return less than N.

    For  Unix  disk  files,  the  full  N  bytes  are  read  except   at
    end-of-file.

    For VMS disk files and  mailboxes, this value means  record-oriented
    processing, i.e.  the file  is a  sequence of  records (lines)  each
    (possibly) ending with either an explicit newline or implicit one as
    specified by the "Implicit C/R"  attribute of a file.  Newly-created
    disk files  are  given "Implicit  C/R"  attribute. In  reading,  the
    newlines are inserted by the  system where necessary; in  writing, a
    newline is taken as end of  record. The file is then considered  (in
    Unix fashion) as a byte-stream.

    However,  VMS   terminals  and   mailboxes   behave  as   for   Unix
    'interactive' devices, i.e. a sysread of N bytes will not attempt to
    read the full N bytes if  the current record contains less; for  VMS
    files, N  will be  supplied even  though a  record boundary  may  be
    crossed. (Similarily, one syswrite can actually write the characters
    of more than one record at a time.)

the word "line"
    For all kinds of  device, this value will  mean that a sysread  of N
    bytes from  the  device  will  only read  up  to  the  next  newline
    character, e.g. sysread(dev, buff, 512) will read the next line  and
    return the number of characters read.

    In VMS, the characters of adjoining records are never conflated in a
    single read or write operation; in other respects, this is the  same
    as false.

the word "record"
    In Unix, this  is the same  as "line". In  VMS however, "record"  is
    different from "line"  in that  newlines are not  appended to  input
    records, nor  stripped  from output  records  (as with  "line",  the
    characters of adjoining records are never conflated in a single read
    or write  operation).  An  output  disk file  is  not  created  with
    `Implicit C/R' attribute.

true
    For Unix terminals, the device is  initially set up for `rare'  mode
    (i.e. cbreak, -echo, -nl,  -tabs) and no prompt  is output for  read
    operations (see sys_io_control below.). VMS terminals give a similar
    mode, i.e.  no  echoing,  no prompts,  all  characters  are  `break'
    characters, no formatting of output, etc.

    For other Unix 'interactive' devices (such as pipes and  sockets), a
    sysread of N  bytes will always  attempt to read  the full N  bytes,
    i.e. the call can only return less than N at end-of-file.

    For Unix disk files, true is the same as false.

    For VMS disk or  tape files this implies  block I/O, i.e. the  bytes
    from the virtual blocks of the file are supplied neat, with  nothing
    added, and there  are no  record boundaries. Output  disk files  are
    created as fixed-length, 512 byte records.

The following table summarises the intended uses of each org value:

        org         Use For
        ---         -------
        false       Character-stream  I/O   on   'interactive'   devices
                    (terminals, pipes,  sockets,  mailboxes),  and  text
                    files.

        "line"      Line I/O on 'interactive' devices and text files.

        "record"    VMS record  I/O  on any  kind  of  record-orientated
                    files (in Unix, same as "line").

        true        `Raw' mode I/O on  terminals; I/O on non-text  files
                    (including block mode in VMS).

Note that all the procedures below which take a filename argument  first
translate the given name with sysfileok (see REF * SYSUTIL).


sysopen(filename, access_mode, org)           -> sdev        [procedure]
sysopen(filename, access_mode, org, err_char) -> sdev
        Returns a  system  device  record  sdev  for  the  filename  (or
        operating system  device, etc)  named  by the  string  filename,
        opened  for  access  mode  access_mode  with  organisation  org.
        Permissible values of access_mode are

                0   Read only
                1   Write only
                2   Read and Write

        Permissible values for org are as described above.

        The optional  err_char argument  is  an integer  character  code
        specifying whether to  return false (as  opposed to  producing a
        mishap) if  the  file  cannot  be  opened.  This  can  take  the
        following values:

           Value    Action
           -----    ------
            `A`     Return false for any  error concerned with  filename
                    or its existence/accessibility.

            `D`     Return false for a non-existent directory or file.

            `F`     Return false if the  directory exists, but the  file
                    doesn't. This is the default if err_char is omitted.

            `N`     Never return false (i.e. mishap for any error).

        (Note that for  `A`, a  mishap can  still occur  for errors  not
        concerned directly with filename, e.g. the file can't be  opened
        because the operating system's limit on the number of open files
        has been reached.)


readable(filename) -> sdev                                   [procedure]
        This procedure is the same as

               sysopen(filename, 0, false, `A`) -> sdev

        i.e. filename opened  for reading with  org argument false  (and
        false returned for any open errors).


syscreate(filename, access_mode, org)           -> sdev      [procedure]
syscreate(filename, access_mode, org, err_char) -> sdev
        Returns a system  device record sdev  for filename, created  for
        access mode  access_mode with  organisation org.  The values  of
        access_mode and org are as for sysopen. A mishap results if  for
        any reason the file cannot be created.

        The optional  err_char argument  is  an integer  character  code
        allowing special behaviour in one case:

           Value    Action
           -----    ------
            `F`     If the file already exists,  treat this as an  error
                    and return false (note  the difference between  this
                    and `F` for sysopen).  The operation of testing  for
                    the file's presence  and creating it  if it  doesn't
                    exist is guaranteed to be atomic, i.e. no other  O/S
                    process can create the file in between (`F` is  thus
                    suitable for creating lockfiles).

            `N`     Never  return  false  --  this  is  the  default  if
                    err_char is omitted.


pop_file_mode -> int                                          [variable]
int -> pop_file_mode
        (Unix  ONLY)   This  integer   variable  supplies   the   access
        permissions  mode  given  to  the  Unix  creat  system  call  by
        syscreate. (See  chmod(2) in  the  Unix Programmers  Manual  for
        possible values; the default value is 8:664, i.e. read and write
        by owner and group, read only for world.)

        Note that this variable is only used by syscreate when  creating
        a NEW file: if a file exists already, its access permissions are
        left unchanged.


pop_file_versions -> int_or_false                             [variable]
int_or_false -> pop_file_versions
        In Unix, this integer variable  controls the creation of  `back'
        file versions by syscreate. Poplog uses a convention that `back'
        versions of a disk file are named by suffixing the original file
        name with one or more `-` characters (i.e. the most recent  back
        file of 'foo' is 'foo-', the next most recent is 'foo--', and so
        on).

        The  action  of  syscreate  is  therefore  to  try  to  maintain
        pop_file_versions of a file (e.g. 2 means the original file plus
        1 back version, 3 means the original plus 2 back versions, etc).
        This is  done  by 'moving  back'  all existing  versions  up  to
        pop_file_versions, the oldest one being deleted.

        The exact operation of 'moving  back' a file depends on  whether
        the file has only 1 link, or more than 1: in the former case the
        file is simply renamed as the  'back' name, while in the  latter
        case (to preserve the links), the file is copied to a new one of
        that name.

        The procedure  sysdelete  (see  REF * SYSUTIL)  also  uses  this
        variable to 'move  forward' old versions  when deleting a  file.
        That  is,  if  back  versions  of  the  file  within  the  range
        pop_file_versions exist, then the  above process is reversed  to
        bring the back versions forward. (In order to suppress this make
        pop_file_versions locally false.)

        Setting pop_file_versions  to  false  in Unix  is  the  same  as
        setting it to 1 (i.e. disable the back file mechanism).

        In  VMS,  pop_file_versions   contains  false   or  an   integer
        specifying the  number  of versions  of  a file  that  syscreate
        should maintain, i.e.  a value  of 2 means  maintain the  latest
        version and one  old version, etc.  If the value  is false  (the
        default)  then  Poplog  just  allows  the  normal  VMS   version
        mechanisms to  operate (and  hence any  limit on  the number  of
        versions   is   imposed   by   VMS   settings).   Unlike   Unix,
        pop_file_versions has no affect on sysdelete in VMS.


syspipe(org) -> (out_sdev, in_sdev)                          [procedure]
        (Unix Only) Creates  a Unix  pipe and returns  input and  output
        system devices  for  it.  Permissible  values  for  org  are  as
        described above.


sysmailbox(logname, access_mode, org) -> sdev                [procedure]
        (VMS Only) Returns a system  device for a temporary VMS  mailbox
        (i.e. a virtual device that can be used to send data between VMS
        processes). When  a mailbox  is created,  it is  given a  'real'
        device name which is something  like 'MBAxx', but access to  the
        mailbox is usually through a  logical name whose translation  is
        the real name.

        The string  logname is  the  logical name  of the  mailbox;  two
        situations can occur:

            (a) logname already translates to a mailbox name -- in this
                case that mailbox is simply opened;

            (b) logname has no translation, in which case a mailbox is
                created and opened, logname being entered into the job
                logical name table with translation the real name of
                the mailbox (i.e. MBAxx or whatever).

        The access  mode access_mode  and the  org argument  are as  for
        syscreate, except  that  org may  only  have the  values  false,
        "line" or "record". If false, newline is taken as end of record;
        if "line"  or  "record",  every syswrite  to  the  mailbox  is a
        separate record.

        VMS mailboxes support special `end of file' records. In  Poplog,
        these are read as 0-byte records (i.e. a sysread returns 0,  and
        a character  repeater for  the  mailbox returns  termin).  For a
        mailbox open for writing, an end of file record is written  when
        the device is closed (and can also be written by a syswrite  for
        0 bytes).

        (Note that a temporary mailbox exists only while one or more VMS
        processes have it open -- if  all processes have closed it,  the
        mailbox will be deleted along with the entry in the job  logical
        name table.)


sysclose(dev)                                                [procedure]
        Closes the (system or  user) device dev  (note that all  garbage
        collected system device records are closed automatically, as are
        all system devices on system exit).




------------------
3  Reading Devices
------------------

sysread(dev, bsub, bytestruct, nbytes) -> nread              [procedure]
sysread(dev, bytestruct, nbytes) -> nread
        Reads up to nbytes bytes from the device dev into the  structure
        bytestruct starting  at  byte  subscript bsub,  and  returns  as
        result the actual number nread of bytes read.

        In general, nread will be nbytes for disk/tape (except  possibly
        near or at  end-of-file); for terminals  and pipes/mailboxes  it
        will be whatever is available, depending on the value of the org
        argument when the device  was opened. A result  of 0 bytes  read
        indicates end-of-file.

        The structure bytestruct must be  'byte accessible', for a  full
        explanation of which see REF * DATA. The bytes are read into the
        structure bytestruct starting at byte subscript bsub, the  first
        applicable byte of  the structure having  subscript 1 (which  as
        explained in REF * DATA  is the  first byte  at the  structure's
        pointer).

        This means  that if  bytestruct is  any kind  of vector  (like a
        string), the bytes are read in starting at the 1st component; if
        bytestruct is a  record the  bytes will occupy  fields from  the
        pointer position onwards.  In all cases,  the structure must  be
        large enough to contain all bytes read.

        The second form of the call with bsub omitted is the same as

           sysread(dev, 1, bytestruct, nbytes)

        i.e. bsub defaults to 1.


getc(dev) -> char                                            [procedure]
        Uses sysread to  read a single  byte char from  the device  dev,
        which must be  open for reading.  termin is returned  at end  of
        file.


sys_read_lines(file, l1, l2)                                 [procedure]
                          -> (line_l1, ..., line_l2, nread)
sys_read_lines(file, l1, l2, bool)
                          -> (line_l1, ..., line_l2, nread)
        Extracts the lines numbered  l1 through l2  from the file  file,
        which should either be  the name of a  file, or a device  record
        opened for reading (with org  false or "line"). If the  optional
        boolean argument  bool  is  supplied  and  true,  the  procedure
        vedfile_line_repeater is  used  to  read  the  specified  lines,
        otherwise the  lines  are  read  with  sysread.  The  lines  are
        returned as strings  on the stack  (without terminating  newline
        characters), followed  by  an  integer  (nread)  signifying  the
        number of lines read (which should be equal to l2 - l1 + 1).  An
        error is signalled if there are too few lines in the file.

        Note that sys_read_lines uses an internal buffer of size 255, so
        file should not contain lines longer than this.

        See also  REF * line_repeater, REF * vedfile_line_repeater,  and
        REF * vedreadin.


popprompt -> string_or_p                                      [variable]
string_or_p -> popprompt
        The value  of this  variable  determines the  prompt  characters
        output by sysread when  reading from a  terminal in normal  line
        mode (i.e. device  opened with  org argument false).  It may  be
        either an actual prompt string, or a procedure p of no arguments
        returning one, i.e.

                p() -> string


pop_timeout_secs -> false_or_int                              [variable]
false_or_int -> pop_timeout_secs
        Holds an integer or false, to control timing-out of all terminal
        read requests with sysread. If the value is a integer >= 0, then
        any terminal read operation will be timed-out after that  number
        of seconds, the variable procedure pop_timeout being called when
        this happens. (Default value false.)


pop_timeout()                                       [procedure variable]
        The procedure in  this variable  is called  whenever a  terminal
        read operation is timed-out with pop_timeout_secs. The procedure
        is called  inside  sysread; if  it  returns normally,  the  read
        operation is restarted. (Default value identfn).


sys_input_waiting(dev) -> N_or_false                         [procedure]
sys_input_waiting(dev_list1) -> dev_list2   (Unix Only)
        For a readable `interactive'-type  device (i.e. a terminal  or a
        pipe/mailbox), returns an integer count N of the number of input
        characters currently available to be  read on the given  device;
        false is  returned if  none are  available (and  a read  on  the
        device would hang waiting for input).

        For all other kinds  of input device (which  can't hang up  on a
        read), returns the  number of characters  currently in  Poplog's
        input buffer for the device (which could be 0).

        The second (Unix only) form is the same as

          sys_device_wait(dev_list1, [], [], false) -> (dev_list2, , );

        i.e. takes a  list of  readable devices  and returns  a list  of
        those  for  which  input  is  available  (see  * sys_device_wait
        below).


sys_clear_input(dev)                                         [procedure]
        For  a   readable   `interactive'-type   device   (terminal   or
        pipe/mailbox), clears any  input characters currently  available
        to  be  read  on  the  device  (e.g.  including  typeahead  on a
        terminal). If  dev is  also writeable,  any buffered  output  is
        written out first.

        For all other  kinds of  input device,  it just  writes out  any
        buffered output (if the device is also writeable).




------------------
4  Writing Devices
------------------

syswrite(dev, bsub, bytestruct, nbytes)                      [procedure]
syswrite(dev, bytestruct, nbytes)
        Writes nbytes bytes from the structure bytestruct to the  device
        dev, starting at byte bsub after the structure's key, or  byte 1
        if bsub is  absent Thus  syswrite is similar  to sysread  except
        that bytes  are  written rather  than  read, and  no  result  is
        returned.

        In addition for syswrite, the bytestruct argument may be a word:
        in this case, bytes are written out from the string held in  the
        word record.


pop_buffer_charout -> bool                                    [variable]
bool -> pop_buffer_charout
        This boolean  variable  (default true)  controls  whether  write
        operations to  normal  line-mode  terminals  or  pipes/mailboxes
        (i.e. device opened  with org argument  false) are buffered.  If
        true, then  characters  are  only actually  written  out  when a
        control  character  (ASCII   value  <  32,   e.g.  newline)   is
        encountered;  otherwise,   all   characters  are   written   out
        immediately. (Note  that  all  other  devices  are  buffered  by
        default -- use sysflush to force data to be written out.)


sysflush(dev)                                                [procedure]
sysflush(dev, sync_file)
        For any  writeable device  dev, flushes  (i.e. writes  out)  any
        bytes outstanding in Poplog's buffer.

        sync_file is an optional boolean  argument (which is ignored  in
        VMS). For a disk  file in Unix, this  argument being true  means
        'sync' the file, i.e. force  any data buffered by the  operating
        system to be written to disk  (if sync_file is absent or  false,
        the current  state  of the  file  is therefore  not  necessarily
        reflected on disk).


pop_file_write_error(dev)                           [procedure variable]
        If a write error occurs while  writing to a disk or tape  device
        with syswrite (usually, with disk files,  due to a full disk  or
        exceeded quota), the device is immediately closed. The device is
        then given as argument to this variable procedure, which  should
        take appropriate  action  with  the  partly-written  file  (e.g.
        delete  it  with  sysdelete(device_full_name(dev))  ).  (Default
        value erase).




-------------------------------
5  Line Repeaters and Consumers
-------------------------------

The following utility procedures operate on files at a line level:

line_repeater(file, int_or_string) -> line_rep               [procedure]
        Returns a  `line  repeater' procedure  for  the file.  The  file
        argument can  be a  file name,  or a  device record  opened  for
        reading (with org false or "line"). If the second argument is an
        integer it is  taken as the  maximum length of  any line in  the
        file; if a string,  it is used as  the input buffer for  sysread
        (the string length should be one more than the expected  maximum
        line length).

        line_rep is a procedure of the form:

            line_rep() -> string_or_termin

        i.e. each time line_rep is called it returns the next line  from
        the  file  (without  the  terminating  newline  character),   or
        termin if it has reached end of file.

        See also REF * sys_read_lines, * vedfile_line_repeater.


postscript_line_consumer(file)           -> line_cons        [procedure]
postscript_line_consumer(file, arg_list) -> line_cons
postscript_line_consumer(file, arg_list, font_name, font_height,
                        font_pixel_height, line_pixel_height,
                        colour_vec, X_width_p) -> line_cons
        Takes a  filename or  output  device file,  and returns  a  line
        consumer, i.e. a procedure which takes strings and dstrings (see
        Display Strings  in  REF * STRINGS)  and  writes  them  to  file
        encoded as ASCII PostScript  instructions suitable for  printing
        on PostScript printers.

        file is given to  * discout to create an  output device, and  so
        can be any argument suitable for that procedure.

        The returned line_cons is a procedure of the form

            line_cons(string_or_termin)

        which each time it  is called with a  string as argument  writes
        the PostScript code for printing the string to file. Each string
        is a separate line. If the given string is a dstring,  line_cons
        generates the appropriate  PostScript code to  print the  string
        using its character  attributes. Calling line_cons(termin)  will
        generate the PostScript code to eject the current page, and also
        closes the device (either the one supplied or the one created).

        All  Ved  character  attributes  are  translated  appropriately,
        including bold, italic,  underline etc. For  coloured text,  the
        consumer  will  print  foreground   and  background  using   the
        following grey-levels (0% = black, 100% = white):

            Colour   Fg   Bg      Colour   Fg   Bg
            ------   --   --      ------   --   --
               0      0  100         1    100    0
               2     50  100         3      0   80
               4     70  100         5    100   30
               6     30  100         7     30   80

        The following Ved extended characters  are also dealt with  (See
        REF * ITEMISE):

            Ved Graphics Characters
            Ved Special Space Characters
            ISOLatin1 characters

        Optional Arguments
        If supplied, arg_list must be a list of argument strings of the
        form

            'keyword=value'

        where the following keywords are allowed:

            font    Controls the  set of  fonts and  the font  and  line
                    heights. value must be of the form

                        font_name:font_height:line_height

                    where font_name selects the set of fonts to be used,
                    font_height is the height to be used for the  actual
                    characters, and line_height  is the  height of  each
                    line. Both heights are  measured in points, and  may
                    be either an  integer or a  float. The  :line_height
                    part may be  omitted, in which  case it defaults  to
                    11/10 * font_height. For example

                        font=helvetica:14.2

                    The default is

                        font=courier:11

                    (i.e. 11 point courier, with 12.1 line height).  See
                    LIB * postscript_line_consumer for  a  list  of  the
                    possible font names  (but note that  courier is  the
                    only fixed-width font available).

            paper   Specifies the paper size -- possible values are  a3,
                    a4, a5, a6 and letter. The default is 'paper=a4'.

            hmargin Point size for the  horizontal margins. The  default
                    is 'hmargin=25'.

            vmargin Point size for the vertical margins. The default  is
                    'vmargin=25'.

            margin  Point size for both vertical and horizontal margins.

        (N.B. 1 point is approximately 1/72 of an inch.)

        The last  form  of the  call  includes another  6  arguments  in
        addition to arg_list.  These are used  by * ved_print to  enable
        text to be laid  out identically to an  XVed window in  variable
        width mode (including replication of the window colours).

        See also * vedfile_line_consumer and HELP * ved_print.




--------------------------
6  File Control Operations
--------------------------

sysseek(dev, fileptr, mode, true) -> pos                     [procedure]
sysseek(dev, fileptr, mode)
        For a device dev,  controls at which byte  in the file the  next
        read or write  will operate, dependent  on the integers  fileptr
        and mode as follows:

            Mode    Meaning
            ----    -------
             0      fileptr is an absolute byte position within the file
                    (1st byte = 0)

             1      fileptr  is  a   byte  offset  (possibly   negative)
                    relative to the current byte (i.e. the next one that
                    would be read or written).

             2      fileptr is  a  byte  offset  relative  to  the  byte
                    immediately after the last byte in the file.

        With an  optional  4th argument  of  true, sysseek  returns  the
        absolute byte position pos within the file after the seek.

        (In VMS, sysseek can only be used on files opened for block I/O,
        i.e. with org argument true.)


sys_io_control(sdev, request, bytestruct) -> bool            [procedure]
sys_io_control(sdev, request) -> bool
        (Unix ONLY) This  procedure provides  an interface  to the  Unix
        ioctl system call, and has essentially the same arguments as the
        latter.  sdev  is  a  system  device,  request  is  an   integer
        specifying the desired operation to be performed, and bytestruct
        is an  (optional)  byte-accessible  structure  argument  through
        which  data  is  passed   or  returned  (see  REF * DATA   for a
        definition of byte-accessible structures).

        In all cases, a call of sys_io_control performs a straight ioctl
        system call  for the  file descriptor  allocated to  sdev,  with
        request value  as supplied  and with  bytestruct passed  as  the
        address of its byte  data (or 0 if  bytestruct is omitted).  The
        result bool is true if the call succeeds, false if not.

        For terminal  devices, sys_io_control  does additional  work  to
        keep the  stored device  parameters in  step with  the  terminal
        state. Every device representing a terminal in Poplog  maintains
        a full set of terminal parameters which are set on the  terminal
        whenever that device is used (unless it is already set for  that
        device).  In   this   way  multiple   devices   with   different
        characteristics can  be made  to work  for the  same  underlying
        terminal, with automatic switching between different settings as
        appropriate. To maintain this relationship, sys_io_control  sets
        the terminal  state according  to the  stored device  parameters
        before the  ioctl system  call  is made,  and then  updates  the
        device parameters from the (possibly changed) terminal state  if
        the call returns successfully. The  new parameters will then  be
        set automatically on any subsequent use of the device.


sys_link_tty_params(dev_list)                                [procedure]
        (Unix Only) This procedure is used  to make two or more  devices
        which  represent  the  same   actual  terminal  share   terminal
        parameters, so that changing any one of them with sys_io_control
        automatically affects the other(s).

        The argument dev_list  is a  list of  devices; for  each set  of
        system devices  in  the list  which  represent the  same  actual
        terminal, all members of that set are changed permanently to use
        the parameter  structure of  the first-occurring  member of  the
        set. Non-terminal (or user) devices in the list are ignored.


set_process_entry_term()                                     [procedure]
        (Unix Only) If  the standard  input of the  Poplog process  is a
        terminal, resets the  terminal characteristics to  be what  they
        were on entry to the Poplog system (otherwise, does nothing).




-------------------
7  File Information
-------------------

sys_file_stat(file, fvec) -> fvec                            [procedure]
sys_file_stat(file, fvec, follow_symlinks) -> fvec
        Where file is either a string naming a file, or a system  device
        record for an open file, puts information about the file in  the
        standard full vector fvec, returning  fvec as the result;  false
        is returned if the file is nonexistent or is not a disk or  tape
        file, or cannot be opened due to a protection violation.

        The optional  boolean  argument follow_symlinks  says  whether a
        named file should be dereferenced if it is a Unix symbolic  link
        (default true). (This argument is ignored in VMS.)

        For Unix  Poplog, the  information  returned in  each  subscript
        position of  the  vector fvec  is  as follows  (UNIX * stat  for
        further details):

            Subscript   Information Returned
            ---------   --------------------
                1       Size of file in bytes
                2       Last modified time (MTIME)
                3       Group id of owner
                4       User id of owner
                5       Mode flags
                6       Number of links
                7       Major/minor device
                8       I-node number
                9       Last accessed time (ATIME)
               10       Last status change time (CTIME)

        In VMS Poplog, the information returned is

            Subscript   Information Returned
            ---------   --------------------
                1       Size of file in bytes
                2       Creation date
                3       Group number of owner
                4       Member number of owner
                5       Protection bits

        Note that  for compatibility  with Unix  Poplog, fvec(2)  is  an
        integer in  Unix time,  i.e.  a number  of seconds  since  00:00
        January 1 1970. (This can be  converted to an ASCII string  date
        with

                sys_convert_date(fvec(2), true)

        See REF * TIMES.)

        All values returned  in fvec are  integers or bigintegers.  fvec
        may be any length (including 0); if its length is less than  the
        maximum, only the information that will fit in is given, e.g. if
        the length is 1 only the size,  if 2 then the size and the  last
        modified time/creation date, etc.


sys_file_exists(file) -> bool                                [procedure]
        Returns true  if  the  file  named by  file  exists,  and  false
        otherwise. Uses sys_file_stat.


sysfilesize(file) -> nbytes                                  [procedure]
        Returns the size in bytes nbytes of the file represented by  the
        system device or file name  string file (which must be  either a
        disk or tape file). Same as fvec(1) from sys_file_stat.


sysmodtime(file) -> modtime                                  [procedure]
        Returns the Unix last-modified time or VMS creation date of  the
        file represented by the system  device or file name string  file
        (which must be either a disk or tape file). Same as fvec(2) from
        sys_file_stat.


sysfileowner(file) -> uid                                    [procedure]
uid -> sysfileowner(file)
        Returns an integer denoting the user id (Unix) or member  number
        (VMS) of the owner  of file. The updater  can be used to  change
        the ownership  of  file  (subject  to  normal  operating  system
        restrictions). Unix users can use sysgetpasswdentry to convert a
        user id to a user name string.


sysfileinode(file) -> inode                                  [procedure]
        (Unix ONLY) Returns the inode  number of file. If  inaccessible,
        returns false. Same as fvec(8) from sys_file_stat.




------------------------
8  Predicates on Devices
------------------------

isdevice(item) -> bool                                       [procedure]
        Returns true if item is a device, false if not.


systrmdev(dev) -> bool                                       [procedure]
        Returns true if  the device  dev is a  terminal (including  user
        `logical terminal' devices), false if not.

        In Berkeley Unix, termin is returned  if the device is a  (real)
        terminal, but the Poplog process is backgrounded with respect to
        it (i.e. an attempt  to read from it  will cause the process  to
        stop).


isclosed(dev_or_char_rep) -> bool                            [procedure]
        For dev_or_char_rep  a device,  returns true  if the  device  is
        closed (i.e. has  had sysclose applied  to it), false  if it  is
        still open.  This  procedure  is also  applicable  to  character
        repeaters produced by discin, see REF * CHARIO.




---------------------
9  Device Information
---------------------

device_open_name(dev) -> string                              [procedure]
        Returns the open name  string of the device  dev, i.e. the  name
        with which the device was opened/created.


device_full_name(dev) -> full_name                           [procedure]
full_name -> device_full_name(dev)
        Returns or updates the `full  name' of the device dev.  Updating
        is only allowed for user devices.

        For a  device  produced  by syspipe,  device_full_name  will  be
        false, but for all  other kinds of system  devices it is a  full
        absolute pathname string, with any environment  variable/logical
        name components  etc translated  (and  in Unix,  symbolic  links
        dereferenced).

        If dev is a user device, full_name is whatever was given to  the
        call of consdevice that created it, or whatever was assigned  to
        it with device_full_name.


device_os_channel(dev) -> int_or_false                       [procedure]
        For a system  device dev, returns  the Unix file  descriptor/VMS
        channel number  associated with  dev (an  integer). For  a  user
        device, returns false.


device_user_data(dev) -> user_data_or_false                  [procedure]
        For a  system device  dev,  returns false.  For a  user  device,
        returns the user_data argument  supplied to consdevice when  the
        device was  constructed.  (Note  that since  a  user_data  value
        cannot be false, the truthvalue of device_user_data can be  used
        to distinguish user and system devices.)




--------------------
10  Standard Devices
--------------------

pop_charin_device -> dev                                      [variable]
dev -> pop_charin_device
pop_charout_device -> dev                                     [variable]
dev -> pop_charout_device
pop_charerr_device -> dev                                     [variable]
dev -> pop_charerr_device
        The devices  held  by  these (active)  variables  represent  the
        current `logical' standard input, output and error channels, and
        are  used  by  the   procedures  charin,  charout  and   charerr
        respectively to perform character stream I/O (see REF * CHARIO).

        Depending on the context, they may contain either system or user
        devices. On system  startup, they  contain the  same devices  as
        popdevin,  popdevout  and   popdeverr  respectively  (i.e.   the
        standard input, output and error of the Poplog process). In  the
        Ved editor,  e.g. during  compilation and  in `immediate  mode',
        they contain  user  devices which  read  from or  write  to  Ved
        buffers.

        Always use  these devices  rather  than popdevin,  popdevout  or
        popdeverr unless your  program specifically wants  to deal  with
        the standard I/O of the  Poplog process (i.e. where  interaction
        with the operating system is involved).


poprawdevin -> dev                                            [variable]
dev -> poprawdevin
poprawdevout -> dev                                           [variable]
dev -> poprawdevout
        When either the standard input or standard output of the  Poplog
        process is  a  terminal, these  (active)  variables are  set  up
        initially to hold reading  and writing devices respectively  for
        that terminal, opened with org  argument true, to give  terminal
        input and output in `raw'  mode (as described above). (In  Unix,
        the  two  devices  have  their  terminal  parameters  linked  by
        sys_link_tty_params, see above.)

        If neither standard  channel is  a terminal, the  value of  both
        these variables  is an  undef  record, <undef  poprawdevin>  and
        <undef poprawdevout>  (which  will produce  the  mishap  'DEVICE
        NEEDED' if  an attempt  is made  to  use them  for I/O).  It  is
        therefore advisable to test with isdevice first if your  program
        might attempt to use them in this situation.

        poprawdevin is used  by rawcharin, and  poprawdevout is used  by
        rawcharout and rawsubstringout, which procedures are used by the
        Ved editor for screen I/O. See REF * CHARIO.


popdevin -> sdev                                              [variable]
sdev -> popdevin
popdevout -> sdev                                             [variable]
sdev -> popdevout
popdeverr -> sdev                                             [variable]
sdev -> popdeverr
        These (active)  variables hold  system  device records  for  the
        standard input, output  and error channels  respectively of  the
        operating-system Poplog  process  (corresponding  to  Unix  file
        descriptors 0,  1,  and  2,  or  VMS  logical  names  sys$input,
        sys$output, sys$error).

        The devices are opened initially with org argument false, giving
        normal line mode I/O for terminals, etc. (In Unix, when any  two
        or all three of these devices represent the same terminal, their
        terminal parameters are linked together with sys_link_tty_params
        (see above), which  means that changing  the characteristics  of
        one automatically affects the other(s).)

        You can only assign system devices to these variables, not  user
        ones; in  Unix,  assigning  a  new system  device  to  one  will
        redirect the standard channel for the Poplog process (this could
        be done e.g. after a sys_fork, see REF * SYSUTIL).

        You should  only use  these  variables at  all if  your  program
        specifically wants to deal with  the standard I/O of the  Poplog
        process, i.e.  where interaction  with the  operating system  is
        involved. When  this is  not  the case,  use  pop_charin_device,
        pop_charout_device or pop_charerr_device instead.


pop_null_device -> dev                                        [constant]
        The standard "null" device. If  read, always at EOF. If  written
        to, output is  discarded. Other device  operations (test  input,
        clear input, flush, seek, and close) have no effect. Useful  for
        programs that wish to temporarily disable terminal i/o.




-----------------------------
11  Constructing User Devices
-----------------------------

consdevice(open_name, full_name, user_data, flags,           [procedure]
                                       methods_vec) -> udev
        Constructs and returns a user device udev. The arguments to this
        procedure are as follows:

        open_name
            A  string  giving  the  name  under  which  the  device  was
            `opened'; it is returned by device_open_name applied to  the
            device.

        full_name
            This is supposed to  be the `full name'  of the device,  but
            can actually be anything; it is returned by device_full_name
            applied to  the  device.  (Note that  the  class_print  of a
            device record prints it as <device item>, where item is  its
            device_full_name   if    this   is    non-false,   or    its
            device_open_name otherwise.)

        user_data
            This  argument   allows  any   necessary  user   information
            pertaining to the `internal state' of the device to be  held
            in  the  record,  and  can   be  accessed  from  udev   with
            device_user_data. It  may be  anything except  false,  since
            false is  returned  by device_user_data  when  applied  to a
            system device. (Note  that user_data  should generally  be a
            structure; device_user_data does not have an updater on  the
            assumption that you will update information in the user_data
            structure, not the device_user_data field itself.)

        flags
            An integer, the bits in which specify special attributes for
            the device. Currently, only bit 0 (flags = 1) is meaningful:

                Bit     Meaning
                ---     -------
                 0      If set, the device  is a logically a  `terminal'
                        (i.e. interfaces to a human user), and systrmdev
                        will return true for it.

        methods_vec
            A full vector giving the  `methods' (procedures) to be  used
            by the  relevant  system  procedures  when  applied  to  the
            device. Currently this has 4 elements,

                read_vec, write_vec, seek_p, close_p

            where  each  element  may  be  either  false,  or  a  single
            procedure/vector of procedures, as follows:

            read_vec
                A full vector  of `read'  methods for  a readable  (i.e.
                input) device, or false if  the device is not  readable.
                If a vector, it must contain 3 procedures, namely

                    read_p, test_input_p, clear_input_p

                read_p
                    This procedure will  be called by  a sysread on  the
                    device, as

                        read_p(udev, bsub, bytestruct, nbytes) -> nread

                    It  should  read  up  to  nbytes  into  the   buffer
                    bytestruct starting  at  byte  subscript  bsub,  and
                    return nread, the number  of bytes actually read  (a
                    zero return indicates end of file).

                test_input_p
                    This procedure will be called by a sys_input_waiting
                    on the device, as follows

                        test_input_p(udev) -> n_or_false

                    It should return  false if a  sysread on the  device
                    would  `block',  i.e.  hang-up  waiting  for  input.
                    Otherwise, the  result must  be  an integer  N  >= 0
                    indicating how many bytes  are available to read  (0
                    if the actual number is not known, or not relevant).

                clear_input_p
                    This procedure will be  called by a  sys_clear_input
                    on the device, i.e.

                        clear_input_p(udev)

                    It  should  discard  any  `buffered'  input  on  the
                    device, as appropriate.

            write_vec
                A full vector of `write'  methods for a writeable  (i.e.
                output) device, or false if the device is not writeable.
                If a vector, it must contain 2 procedures, namely

                    write_p, flush_p

                write_p
                    This procedure will be called  by a syswrite on  the
                    device, as

                        write_p(udev, bsub, bytestruct, nbytes)

                    It should write out nbytes bytes from the bytestruct
                    buffer starting at byte subscript bsub.

                flush_p
                    This procedure will be called  by a sysflush on  the
                    device, as

                        flush_p(udev)

                    It should  write out  any `buffered'  output on  the
                    device, as appropriate.

            seek_p
                A procedure for  a `seekable'  device, or  false if  the
                device is  not  seekable. If  a  procedure, it  will  be
                called by a sysseek on the device as

                    seek_p(udev, fileptr, mode) -> pos

                See sysseek above  for an explanation  of the  arguments
                (note that unlike sysseek itself, seek_p always  takes 3
                arguments and must return the pos result).

            close_p
                A procedure to be called by a sysclose on the device, or
                false  if  no  action  is  required  on  closing.   If a
                procedure, it will be called as

                    close_p(udev)

                (Note that unlike system  devices, user devices are  NOT
                closed automatically  when  garbage  collected.  If  you
                require this, you should set up a destroy action on  the
                device after creating it, e.g.

                    sysclose -> sys_destroy_action(udev)

                See REF * PROPS.)




-----------------
12  Miscellaneous
-----------------

sys_device_wait(in_devs, out_devs, except_devs, wait)        [procedure]
                    -> (in_ready, out_ready, except_ready)
        (Unix Only) Provides an interface to the Unix select system call
        for multiplexing device I/O.

        Each of  in_devs, out_devs  and  except_devs are  either  single
        devices  or  lists  of  them  (possibly  []).  All  in_devs  and
        except_devs devices must be  readable, and all out_devs  devices
        writeable.

        sys_device_wait returns  three results  in_ready, out_ready  and
        except_ready, indicating  which devices  are respectively  ready
        for reading,  writing, or  have an  exception condition  pending
        (the last applies only to out-of-band data on sockets).

        Each result is either [], a single device, or a list of  them; a
        single device is returned only if the corresponding argument was
        one. (I.e, a list  argument will always give  a list result.  To
        avoid  creating  unnecessary  garbage,   list  results  may   be
        reclaimed with * sys_grbg_list when no longer required.)

        How  long  sys_device_wait   waits  for   ready  conditions   is
        controlled by the  wait argument, which  can take the  following
        values:

          # false, meaning  don't wait.  Return  is immediate  with  the
            three results reflecting which devices are ready now.

          # true, meaning wait until one or more devices are ready.

          # An integer timeout value usec in microseconds. If no devices
            are   ready   after   usec   microseconds   have    elapsed,
            sys_device_wait  returns,  but  with  false  for  all  three
            results to indicate timeout.

        (Note that all  three device  arguments may be  []. With  wait a
        timeout this is  equivalent to  a syssleep for  the given  time;
        with wait true it is equivalent to

                repeat syshibernate() endrepeat;

        i.e. the system just processes interrupts, X events etc.)


sys_async_io(sdev, condition) -> ast_p_or_false              [procedure]
ast_p_or_false -> sys_async_io(sdev, condition)
        This procedure allows  the association of  an asynchronous  trap
        procedure ast_p with a  device sdev to  handle a specified  'I/O
        ready' condition on the device.

        Possible condition  values (corresponding  to the  three  device
        arguments to sys_device_wait) are:

            condition   Meaning
            ---------   -------
                0       Input waiting
                1       Output possible
                2       Exception condition pending (applies only to
                        out-of-band data on sockets)

        (Note however that VMS Poplog currently supports only the  value
        of 0 for condition, i.e. input waiting.)

        If ast_p_or_false  is  not  false,  asynchronous  processing  is
        enabled; if  false, asynchronous  processing is  disabled.  When
        enabled, the  ast_p  procedure is  called  asynchronously  (i.e.
        inside  whatever  other   procedures  the   system  is   current
        executing)   when   the   specified   condition   occurs.   (See
        Asynchronous Trap Procedures in REF * ASYNC for full details  of
        the ast_p argument, which may also be a pair whose front is  the
        procedure.)

        Input Waiting
        A trap procedure for  condition 0 is  called when input  becomes
        available on sdev and  there is no  outstanding sysread for  it.
        This happens at  most once  between reads, i.e.  once ast_p  has
        been called, it will not be invoked again until after a  sysread
        on the device.

        A trap procedure will normally  read and process input from  the
        device. Note  that to  avoid unwanted  interactions which  could
        lead to the  procedure being  called when no  input is  actually
        available,  it   is   sensible   to  guard   the   read   with a
        sys_input_waiting test. Moreover,  the mechanism for  activating
        trap procedures  does not  take  into account  buffering  inside
        Poplog devices, so that it may  also be sensible to process  all
        available input  each time  the procedure  is called,  i.e.  the
        ast_p procedure should contain something like

            while sys_input_waiting(sdev) do
                 sysread(sdev, ...)
                 ...
            endwhile;

        etc.

        Output possible
        A trap procedure for condition  1 is called when output  becomes
        possible on sdev after a blocking condition (i.e. after the  O/S
        output buffer was full). Thus the ast_p procedure should contain
        something like

            while have-data-to-output and output_possible(sdev) do
                 syswrite(sdev, ...)
                 ...
            endwhile;

        where have-data-to-output is some  appropriate test for  whether
        the program has data to write to the device, and output_possible
        is defined as

            define lconstant output_possible(dev);
                lvars dev, ready;
                sys_device_wait([], dev, [], false) -> (, ready, );
                return(ready /== []);
            enddefine;

        The program  itself  must call  ast_p  when  have-data-to-output
        first becomes  true;  thereafter,  if output  is  blocked  (i.e.
        output_possible returns  false),  the ast_p  procedure  will  be
        called asynchronously when the blocking is removed.


sysstring -> string                                           [constant]
sysstringlen -> int                                           [constant]
        sysstring is a  string of length  sysstringlen, which  libraries
        and other programs  can use  as a  character buffer  to give  to
        routines   such   as   sysread   and   syswrite   (set   up   in
        LIB * SYSSTRING).


device_key -> key                                             [constant]
        This constant holds  the key structure  for device records  (see
        REF * KEYS).


Additional facilities,  notably  pipein  and pipeout  are  described  in
HELP * PIPEUTILS.



--- C.all/ref/sysio
--- Copyright University of Sussex 1999. All rights reserved.
