REF PRINT                                          John Gibson Feb 1995

        COPYRIGHT University of Sussex 1995. All Rights Reserved.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<                             >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<    PRINTING PROCEDURES      >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<                             >>>>>>>>>>>>>>>>>>>>>>
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

This REF  file deals  with the  various Poplog  printing procedures.  It
groups these into those dealing with: standard printing, printing  items
off the  stack, formatted  printing,  and printing  into strings  or  as
character codes. It also details several useful printing constants.

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

  1   Introduction

  2   Standard Printing Procedures

  3   Printing Items off the Stack

  4   Formatted Printing

  5   Printing Into Strings/Character Codes

  6   Useful Printing Constants




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

The basic printing procedure  in Poplog is  sys_syspr, which prints  any
item in its  standard format. While  this can be  called directly if  so
desired, the system additionally provides the procedures pr and syspr as
a two-stage mechanism for printing objects in a way that allows  dynamic
redefinition of the actual printing procedures used.

    The mechanism  is based  on the  convention that  programs  normally
print objects using the variable procedure pr, which in the first  place
can be redefined in any desired  way. However, the default value of  the
variable pr is the  procedure syspr, which prints  an object by  calling
its * class_print procedure with the object as argument (for details see
REF * KEYS); thus secondly, the printing of individual data types can be
altered by redefining their class_print procedures. Because the  default
class_print of any type is sys_syspr (printing in standard format),  the
normal sequence of events is therefore:

      pr(item)
          -------> syspr(item)
                     --------> class_print(datakey(item))(item)
                                    -------> sys_syspr(item)

To enable the redefinition of  printing procedures for given data  types
to take effect  at any  level, sys_syspr always  calls pr  to print  the
sub-components of  any  data structure  (i.e.  list, vector  and  record
elements, etc).  (Thus saying  that sys_syspr  "prints any  item in  its
standard  format"  is  not  strictly  correct,  since  the  printing  of
sub-components  will  depend  on  pr.  A  completely  standard  printing
procedure would be

        define pr_standard(item)
            dlocal pr = sys_syspr;
            sys_syspr(item)
        enddefine;

i.e. one that locally redefines pr to be sys_syspr.)

    Objects are actually printed by sys_syspr by passing each  character
in  its  printed  representation  to  the  standard  character  consumer
* cucharout. See REF * CHARIO for a description of character stream  I/O
(including formatting of line output, etc).

 See also * sys_pr_message, which prints mishap and warning messages.




-------------------------------
2  Standard Printing Procedures
-------------------------------

sys_syspr(item)                                              [procedure]
        This is the basic  printing procedure in  the system: it  prints
        any item item in  its standard format, calling  pr to print  the
        sub-components of data structures (e.g. list, vector, and record
        elements, etc).  Printing  characters  produced  are  passed  to
        cucharout.

        Certain  aspects  of  the   way  sys_syspr  prints  things   are
        controlled by the pop_pr_ variables below.


pop_pr_level -> int                                           [variable]
int -> pop_pr_level
        The integer in this active variable (default 1000) specifies the
        depth to  which sub-components  of structures  are printed.  Its
        value is dynamically  local to syspr,  which decrements it  by 1
        locally before calling the appropriate printing procedure for an
        object (this is also true for sys_syspr, EXCEPT when called from
        syspr). As  recursive printing  calls for  structure  components
        proceed, the  value is  decremented until  it reaches  0  (after
        which it  is  not decremented  further).  When 0,  the  standard
        printing   routines   in   sys_syspr   will   then   print   any
        data-structure (i.e.  one  with  components to  which  pr  would
        normally be applied recursively) just in "minimal" format, e.g.

            <list>  <pair>  <vector>

        etc (numbers, words and strings are printed as normal).

        Note that, while it decrements the variable, syspr always  calls
        the class_print procedure regardless of whether pop_pr_level  is
        0 or  not;  thus it  is  the responsibility  of  a  user-defined
        class_print procedure  to test  for this  condition itself,  and
        take appropriate action.


pop_pr_quotes -> bool                                         [variable]
bool -> pop_pr_quotes
        This boolean  variable determines  how  strings are  printed  by
        sys_syspr. If true, sys_syspr will print them enclosed in string
        quotes '...'  (this  is useful  in  some circumstances  --  e.g.
        mishap messages  -- to  enable words  to be  distinguished  from
        strings).

        If  false  (the  default),  strings  are  printed  without   any
        decoration (and thus appear the same as words). For example,

            [hello 'hello'] =>
            ** [hello hello]

            true -> pop_pr_quotes;

            [hello 'hello'] =>
            ** [hello 'hello']


pop_pr_radix -> int                                           [variable]
int -> pop_pr_radix
        This variable contains an integer controlling the base to  which
        all kinds of  numbers are  printed by  sys_syspr (including  the
        printing of fractional places in floating-point numbers).

        Thus a value of 2 will cause them to be printed in binary, 16 in
        hexadecimal, etc. Allowable values are 2 to 36, the letters  A-Z
        being used as numerals for digit values of 10 to 35. The default
        value is 10 (i.e. print in decimal). E.g.

            pop_pr_radix =>
            ** 10

            2 -> pop_pr_radix;
            29 =>
            ** 11101

        (See also  * radix_apply  below, which  can be  used to  apply a
        printing procedure in an  environment in which pop_pr_radix  has
        been altered temporarily.)


pop_pr_ratios -> bool                                         [variable]
bool -> pop_pr_ratios
        This  boolean  variable  controls  the  printing  of  ratios  by
        sys_syspr. If true (the default),  ratios are printed as  ratios
        in the itemisable form  N_/D, where N  is the integer  numerator
        and D the integer denominator. Otherwise, ratios are printed  as
        floating-point numbers. E.g.

            true -> pop_pr_ratios;
            6_/10 =>
            ** 3_/5

            false -> pop_pr_ratios;
            6_/10 =>
            ** 0.6

        (In non-mathematical  applications, where  precise knowledge  of
        how  a  particular  numeric  quantity  is  represented  is   not
        relevant, the  latter  may  be preferable  since  decimal  point
        notation is often easier to comprehend.)


pop_pr_places -> int                                          [variable]
int -> pop_pr_places
        The bottom 16 bits of the integer in this variable specifies the
        maximum number  of  fractional places  to  which  floating-point
        numbers are printed by sys_syspr; numbers printed are rounded to
        this many places  (a value  of 0 causes  them to  be printed  as
        integers).

        Note that  this is  normally the  maximum number  of  fractional
        places  output,  in  the  sense  that  trailing  zeros  in   the
        fractional  part  are   truncated.  However,  if   pop_pr_places
        contains a non-zero value above  the bottom 16 bits, this  value
        is taken to be  a padding character to  be output in each  place
        containing a trailing zero. E.g.

                (`\s` << 16)  ||  6 -> pop_pr_places;

        will ensure that  6 places  are always  produced, with  trailing
        zeros replaced by spaces. (Default value 6.)


pop_pr_exponent -> bool_or_int                                [variable]
bool_or_int -> pop_pr_exponent
        This variable  (default value  false) controls  in which  format
        sys_syspr prints floating-point numbers.  If false, numbers  are
        printed in  normal  format; if  true,  printing is  in  exponent
        format, i.e in the form

                    I.FFFFFFeSE

        where  1  <=  I   <  pop_pr_radix,  there   are  a  maximum   of
        pop_pr_places fractional places F  after the dot,  and S is  the
        sign of the exponent E (E is always printed in base 10).

        For example,

            true -> pop_pr_exponent;
            345.789 =>
            ** 3.45789e+2

        Note that the exponent value  specifies a power of the  printing
        radix, e.g.

            2 -> pop_pr_radix;
            6.5 =>
            ** 1.101e+2

        The value of pop_pr_exponent can also be an integer, the  bottom
        16 bits of which specify the  field width for the exponent  E. E
        is then padded on the left to this width, the padding  character
        being taken  from  the bits  above  the  bottom 16  if  this  is
        non-zero, or defaulting to the character `0` otherwise.


syspr(item)                                                  [procedure]
        This procedure does

                class_print(datakey(item))(item)

        i.e. apply the * class_print of the  data type of item to  item.
        The default class_print  of every  data type  is sys_syspr,  but
        this can be redefined as desired -- see REF * KEYS.


pr(item)                                            [procedure variable]
        This variable procedure is conventionally used by all procedures
        in the system which print something; its default value is syspr.


npr(item)                                                    [procedure]
        Prints item followed by a newline, i.e.

            pr(item), cucharout(`\n`);


spr(item)                                                    [procedure]
        Prints item followed by a space, i.e.

                pr(item), cucharout(`\s`);


ppr(item)                                                    [procedure]
        For item a list, prints item "flattened" (i.e. with the list and
        all its sublists without  list brackets); for  item not a  list,
        does spr(item). Defined as

                if ispair(item) then
                    applist(item, ppr)
                else
                    spr(item)
                endif;

        (Compare  with   pretty,   which  attempts   to   print   Pop-11
        data-structures in a readable format by inserting line-breaks in
        appropriate places.)


sp(n)                                                        [procedure]
tabs(n)                                                      [procedure]
nl(n)                                                        [procedure]
        These procedures respectively output  n spaces (ASCII 32),  tabs
        (ASCII 9) and newlines (ASCII 10) to cucharout.


quote_pr(item)                                               [procedure]
        Prints item using pr, surrounded by the appropriate Pop-11 quote
        characters if item is a word  or string, i.e. single quotes  (')
        for strings, double quotes (") for words.


printlength(item) -> n                                       [procedure]
        Returns the number of characters  that pr(item) would output  to
        cucharout.


outcharitem(char_cons) -> item_cons                          [procedure]
        Given a character consumer procedure char_cons (such as charout,
        or one  returned by  discout), returns  an item  print  consumer
        procedure item_cons, i.e. a procedure  which when given an  item
        item will do pr(item) with cucharout locally set to char_cons.




-------------------------------
3  Printing Items off the Stack
-------------------------------

sysprarrow(all)                                              [procedure]
        This is the procedure  called by the Pop-11  print arrow =>.  It
        prints the  string in  pop_=>_flag (normally  '**\s'), and  then
        either

          # Prints (and removes from the stack) one item only, if all is
            false;

          # Prints and clears from  the stack all  items upto the  stack
            length as it was on entry to pop11_compile, if all is true.

        Each  item  is  printed  with  spr,  printing  finishing  with a
        newline, i.e. cucharout(`\n`).


pretty(item)                                                 [procedure]
        This procedure attempts to print items in a more readable format
        than sysprarrow (and is the procedure used by the Pop-11  pretty
        print arrow ==>).  Basically, it  prints an  item starting  with
        pop_=>_flag  and  ending with  a newline, but  will start a  new
        line with  appropriate indentation,  etc for  each structure  or
        sub-structure that will not fit into a single line.


pop_=>_flag -> string                                         [variable]
string -> pop_=>_flag
        This variable contains  the string to  be printed by  sysprarrow
        and pretty before  printing things  off the  stack. The  default
        value is

            '**\s'




---------------------
4  Formatted Printing
---------------------

printf(itemN, ..., item2, item1, string)                     [procedure]
printf(string, item_list)
        This procedure  provides  formatted  printing,  where  printable
        characters in the  string string  may be  intermixed with  field
        specifiers that cause the  next item argument  to be printed  at
        that position.

        A field specifier is the  character % immediately followed  by a
        selector  character,  which  may  (currently)  be  one  of   the
        following:

            p   any Poplog item, printed with pr
            P   any Poplog item, printed with sys_syspr
            s   a string printed recursively with printf
            S   a string (or word) printed literally
            c   an integer interpreted as an ASCII character code
            M   last operating system error message (see below)
            %   output a % character

        (The characters b, d, i and x are also meaningful, but  reserved
        for system use.)

        The characters  of  string  are  scanned  from  left  to  right,
        printable characters being output with cucharout, and (with  the
        exception of %% or %M), each field specifier encountered causing
        the next item argument to be printed as per the specifier;  thus
        the I-th field specifier in the string selects the I-th argument
        item.

        In the first form  of the call the  arguments are taken off  the
        stack one  by one  (and  must therefore  be stacked  in  REVERSE
        order), whereas in the second form the arguments are supplied in
        a list item_list. E.g.

            printf('The sum of %p and %p is %p.\n', [65 66 131]);
            printf(131, 66, 65, 'The sum of %p and %p is %p.\n');

        both produce the line

            The sum of 65 and 66 is 131.

        Note that the first form is incompatible with contexts in  which
        cucharout is redefined to leave characters on the stack (because
        then the characters get mixed up with the printf arguments), and
        so the second form is the "preferred" one.

        %M specifier
        Whenever Poplog system procedures call operating system routines
        which result  in an  error,  they leave  the  error code  in  an
        internal variable  (like  the  variable  errno  in  C).  The  %M
        specifier prints an  error message string  corresponding to  the
        current value of this variable. (And can therefore be used after
        errors in things like sysopen, syscreate, sysread, syswrite etc,
        to  provide   information   about   the   problem.   Note   that
        sprintf('%M') will return the error message as a string.)


nprintf(itemN, ..., item2, item1, string)                    [procedure]
nprintf(string, item_list)
        As printf, but followed by a newline, i.e.

            printf(string, item_list), cucharout(`\n`);


sys_message_printf(string, item_list) -> rem_item_list       [procedure]
        This procedure is  used by  sys_pr_message to  print mishap  and
        warning message strings.

        If string begins with a % character, then string (excluding  the
        first %) is printed with  printf, using item_list as the  second
        argument.  In  addition,  the  trailing  sublist  of   item_list
        containing any  items not  picked up  by %  field specifiers  in
        string is returned.

        If string does not begin with  a %, string is printed  literally
        and item_list is returned unchanged.


pr_field(item, width, lpad_char, rpad_char, pr_p)            [procedure]
pr_field(item, width, lpad_char, rpad_char)
        Prints item in a field of width width, using the procedure  pr_p
        to print the item if this is supplied, or pr otherwise. The item
        can be left-justified, right-justified, or centred in the field,
        depending on the the values of lpad_char and rpad_char, both  of
        which may be an integer ASCII character or false.

        If lpad_char is a character and rpad_char is false, the item  is
        right-justified, by being  left-padded to the  field width  with
        lpad_char (or left-truncated if too long).

        Alternatively,  if  lpad_char  is   false  and  rpad_char   is a
        character, the item is left-justified, by being right-padded  to
        the field  width  with  rpad_char. (or  right-truncated  if  too
        long).

        Finally, if  both are  characters, the  item is  centred in  the
        field, by being left-padded with lpad_char and right-padded with
        rpad_char as appropriate (or right-truncated if too long).

        (If both are false,  then rpad_char defaults  to `\s`, i.e.  the
        item is left-justified, padded on the right with spaces.)


prnum(num, int_places, frac_places)                          [procedure]
        This procedure takes any non-complex number num and prints it in
        floating-point format.

        int_places is  an integer  specifying  the number  of  character
        positions that the integer part should occupy (including a minus
        sign if num is negative);  this will be left-padded with  spaces
        to the given width.

        frac_places specifies  the number  of positions  the  fractional
        part should  occupy, including  the fractional  point;  trailing
        zeros are printed to this width if necessary (if frac_places  is
        1, only  the fractional  point  is printed,  if  0 then  num  is
        printed as an integer).

        (This   procedure   uses   pr_field   and   pop_pr_places,   see
        SHOWLIB * PRNUM.)


format_print(string, item_struct)                            [procedure]
        This procedure gives the formatted printing capabilities of  the
        Common  LISP  function  FORMAT.  See  HELP * FORMAT_PRINT  for a
        description.


radix_apply(item1, item2, ..., itemN, p, radix)              [procedure]
        Used for printing  with a non-standard  value for  pop_pr_radix.
        The integer radix is assigned  locally to pop_pr_radix and  then
        the  procedure  p  is  invoked,  taking  whatever  arguments  it
        requires off the stack. p could be any print procedure (e.g. pr,
        prnum, printf, etc). radix_apply could be defined thus:

            define radix_apply(p, pop_pr_radix);
                lvars procedure p;
                dlocal pop_pr_radix;
                p()
            enddefine;

        For example:

            radix_apply(15,pr,2);
            1111

            radix_apply(15,pr,10);
            15

            radix_apply(15,pr,16);
            F

            radix_apply(17,pr,16);
            11

            radix_apply(17,pr,32);
            H




----------------------------------------
5  Printing Into Strings/Character Codes
----------------------------------------

sprintf(itemN, ..., item2, item1, string) -> pr_string       [procedure]
sprintf(string, item_list)                -> pr_string
        Same as * printf above, but the characters that the latter would
        print are instead returned as a string.


item1 >< item2 -> pr_string                                 [operator 5]
        Produces, for any two items item1  and item2, a string which  is
        the concatenation of  the printed representations  of item1  and
        item2. E.g.

                'abcd' >< 'efgh'     is   'abcdefgh'
                "word" >< 'string'   is   'wordstring'
                {1 2 3} >< [a b c]   is   '{1 2 3}[a b c]'
                false >< true        is   '<false><true>'

        The two items are "printed" by using pr and redefining cucharout
        to get the printing characters.

        Note that >< always constructs a new string, even if one of  the
        arguments is empty (compare with REF * <>).


item1 sys_>< item2 -> pr_string                             [operator 5]
        Same as ><,  but uses  sys_syspr to "print"  the items,  locally
        setting all the pop_pr_ variables (see above) to their  standard
        values.


dest_characters(item) -> (char1, char2, ..., charN)          [procedure]
        Prints item with sys_syspr, but leaving all the character  codes
        on the user stack (by  redefining cucharout to be identfn).  All
        the pop_pr_ variables are locally  set to their standard  values
        during the call  of sys_syspr. This  procedure could be  defined
        as:

            define dest_characters(item);
                lvars item;
                dlocal  cucharout       = identfn,
                        pop_pr_exponent = false,
                        pop_pr_places   = 6,
                        pop_pr_quotes   = false,
                        pop_pr_radix    = 10;
                sys_syspr(item);
            enddefine;




----------------------------
6  Useful Printing Constants
----------------------------

space -> word                                                 [constant]
tab -> word                                                   [constant]
newline -> word                                               [constant]
        These three constants contain words whose single characters  are
        respectively a space (ASCII 32), a tab (ASCII 9), and a  newline
        (ASCII 10).



--- C.all/ref/print
--- Copyright University of Sussex 1995. All rights reserved.
