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.