Digital PDFs
Documents
Guest
Register
Log In
AA-MK70A-TE
July 1989
104 pages
Original
45MB
view
download
Document:
VAX LISP Implementation and Extensions to Common LISP
Order Number:
AA-MK70A-TE
Revision:
000
Pages:
104
Original Filename:
OCR Text
VAX LISP Implementation and Extensions to Common LISP Order Number: AA-MK70A-TE July 1989 This manual describes VAX LISP implementation-dependent language features and extensions to Common LISP. The information in this manual applies to both VMS and ULTRIX versions of VAX LISP, except where specified otherwise. Revision/Update Information: This is a new manual. Operating System and Version: VMS Version 5.1 or ULTRIX 3.0 Software Version: digital equipment corporation maynard, massachusetts VAX LISP Version 3.0 July 1989 The information in this document is subject to change without notice and should not be construed as a commitment by Digital Equipment Corporation. Digital Equipment Corporation assumes no responsibility for any errors that may appear in this document. The software described in this document is furnished under a license and may be used or copied only in accordance with the terms of such license. No responsibility is assumed for the use or reliability of software on equipment that is not supplied by Digital Equipment Corporation or its affiliated companies. © Digital Equipment Corporation 1989. All rights reserved. Printed in USA The Reader’s Comments form at the end of this document requests your critical evaluation to assist in preparing future documentation. The following are trademarks of Digital Equipment Corporation: AI VAXstation DEC DECnet DECUS MicroVAX MicroVAX II MicroVMS PDP ULTRIX ULTRIX—11 ULTRIX—32 UNIBUS VAX VAX LISP VAX LISP/ULTRIX VAX LISPA/MS VAXstation VAXstation II VMS TM MLO-S832 This document was prepared using VAX DOCUMENT, Version 1.1. Contents P re fa c e ..................................................................................................................................................... Chapter 1 vii VAX LISP Implementation Notes 1.1 Data Representation.................................................................................................. 1.1.1 Numbers ................................................................................................... 1.1.1.1 Integers................................................................................... 1.1.1.2 Floating-Point Numbers........................................................... 1.1.1.3 Complex Numbers ............................................................... 1.1.2 C haracters................................................................................................ 1.1.3 A rra y s ....................................................................................................... 1.1.4 S trings....................................................................................................... 1.1.5 Functions................................................................................................... 1-1 1-2 1-2 1-2 1-4 1-4 1-5 1-5 1-5 1.2 Garbage C o lle c to r..................................................................................................... 1.2.1 Memory Management ............................................................................. 1.2.2 Types of Garbage C ollection................................................................... 1.2.3 Tuning Garbage Collection Performance ................................................ 1.2.4 Increasing Available S p a c e ...................................................................... 1.2.5 Garbage Collection Failure ...................................................................... 1.2.6 Controlling Messages ............................................................................. 1.2.7 Effect on Static Space ............................................................................. 1.2.8 Effect on VMS Interrupt Functions .......................................................... 1-6 1-6 1—7 1-7 1-8 1-9 1—9 1—10 1-10 1.3 Input and O u tp u t....................................................................................................... 1.3.1 Newline Character.................................................................................... 1.3.2 Terminal In p u t........................................................................................... 1.3.3 Terminal Output on ULTRIX Systems ..................................................... 1.3.4 End-of-File O perations............................................................................. 1.3.5 Record Length on VMS S ystem s............................................................ 1.3.6 File Organization...................................................................................... 1.3.7 I/O Functions ........................................................................................... 1.3.7.1 OPEN Function....................................................................... 1.3.7.2 WRITE-CHAR Function........................................................... 1.3.7.3 FILE-LENGTH Function onVMSS ystem s............................... 1.3.7.4 FILE-POSITION Function on VMS System s.......................... 1-10 1-10 1-11 1-12 1-12 1-12 1-13 1-13 1-13 1-14 1-14 1-14 1.4 VAX LISP/VMS Interrupt andKeyboard F u n ctio n s.................................................. 1-14 1.5 VAX LISP/ULTRIX Keyboard F u nctions.................................................................... 1-15 1.6 Functions and M a c ro s .............................................................................................. 1-16 Chapter 2 VAX LISP Extensions to I/O 2.1 Defining New Types of Stream s............................................................................... 2.1.1 Overview of VAX LISP I/O ........................................................................ 2.1.2 Defining Stream S tructures...................................................................... 2.1.3 Stream Dispatch F unctions...................................................................... 2-1 2-1 2-2 2-3 2.2 Getting Information About S tre a m s ........................................................................ 2-^t 2.3 Additional I/O F u n c tio n s ........................................................................................... 2-5 Chapter 3 Window Streams 3.1 Creating and Changing Window S tre a m s............................................................... 3.1.1 Validity for Input Operations...................................................................... 3.1.2 Viewing Area.............................................................................................. 3.1.2.1 Viewing Area Coordinate Systems ....................................... 3.1.2.2 Obtaining Viewing Area Dim ensions..................................... 3.1.2.3 Changing Viewing Area Dim ensions..................................... 3.1.2.4 Erasing Viewing Area Contents ............................................ 3.1.2.5 Scrolling Viewing Area Contents............................................ 3.1.3 Vertical and Horizontal Overflow............................................................... 3.1.4 Font .......................................................................................................... 3.1.5 Cursor P osition......................................................................................... 3.1.6 Input History L im it.................................................................................... 3.1.7 Window Exposure and Keyboard Connection......................................... 3-2 3-2 3-2 3-2 3-3 3-3 3-3 3-4 3-4 3-5 3-6 3-6 3-7 3.2 Input from a Window S tream .................................................................................... 3.2.1 Input E d itin g .............................................................................................. 3.2.1.1 Editing Without WITH-INPUT-EDITING ................................ 3.2.1.2 Using the WITH-INPUT-EDITING Macro .............................. 3.2.1.3 Using Options to WITH-INPUT-EDITING.............................. 3.2.1.4 Window Stream Editing Commands and Key Bindings . . . . 3.2.2 Recalling Input ......................................................................................... 3-7 3-7 3-8 3-8 3-10 3-11 3—13 3.3 Output to a Window S tre a m .................................................................................... 3-14 3.4 Window System D ependencies............................................................................... 3.4.1 VMS Workstation Software ...................................................................... 3.4.1.1 Native Coordinate System ...................................................... 3.4.1.2 Fonts and Font Specification................................................. 3.4.1.3 Multiple Stream R estriction................................................... 3.4.1.4 Virtual Keyboard U s e ............................................................. 3.4.1.5 Using Attribute Blocks............................................................. 3.4.1.6 Resizing W indow s.................................................................. 3.4.2 DECwindows ........................................................................................... 3.4.2.1 Native Coordinate System ................................................... 3.4.2.2 Fonts and Font Specification................................................. 3.4.2.3 Multiple Stream Restriction ................................................... 3.4.2.4 Using Graphics Contexts ..................................................... 3.4.2.5 Resizing W indow s.................................................................. 3.4.2.6 Repainting Windows ............................................................ 3-14 3-14 3-14 3-14 3-14 3-14 3-15 3-15 3-15 3-15 3-15 3-15 3-16 3-16 3-16 3.5 Chapter 4 Window Stream Functions and Macros ................................................................. ERASE-VIEWING-AREA FUNCTION........................................................................... MAKE-WINDOW-STREAM FUNCTION...................................................................... SCROLL-VIEWING-AREA FUNCTION........................................................................ SCROLL-VIEWING-AREA-CELL FUNCTION ............................................................ VIEWING-AREA-HEIGHT FUNCTION........................................................................ VIEWING-AREA-HEIGHT-CELL FUNCTION............................................................... VIEWING-AREA-WIDTH FUNCTION........................................................................... VIEWING-AREA-WIDTH-CELL FUNCTION ............................................................... WINDOW-STREAM TYPE SPECIFIER...................................................................... WINDOW-STREAM-ATTRIBUTE-BLOCK FUNCTION................................................ WINDOW-STREAM-FONT FU N C TIO N ...................................................................... WINDOW-STREAM-GCONTEXT FUNCTION............................................................ WINDOW-STREAM-HORIZONTAL-OVERFLOW FUNCTION.................................... WINDOW-STREAM-INPUT-HISTORY-LIMIT FUNCTION........................................... WINDOW-STREAM-KB FUNCTION ........................................................................... WINDOW-STREAM-P FUNCTION ............................................................................. WINDOW-STREAM-SHOW-ON FUNCTION.............................................................. WINDOW-STREAM-VERTICAL-OVERFLOW FUNCTION......................................... WINDOW-STREAM-VIEWING-AREA FU N C TIO N ..................................................... WINDOW-STREAM-WINDOW FUNCTION................................................................. WINDOW-STREAM-X-POSITION FUNCTION............................................................ WINDOW-STREAM-X-POSITION-CELL FUNCTION ................................................ WINDOW-STREAM-Y-POSITION FUNCTION............................................................ WINDOW-STREAM-Y-POSITION-CELL FUNCTION................................................... WITH-INPUT-EDITING M A C R O .................................................................................. WITH-WINDOW-STREAM MACRO............................................................................. 3-16 3-17 3-17 3-18 3-19 3-20 3-20 3-21 3-21 3-22 3-22 3-22 3-23 3-23 3-23 3-24 3-24 3-24 3-25 3-25 3-26 3-26 3-27 3-27 3-28 3-28 3-30 Pretty-Printing and Using Extensions to FORMAT 4.1 Pretty-Printing with D e fa u lts ..................................................................................... 4-2 4.2 Pretty-Printing with Control Variables ..................................................................... 4.2.1 Explicitly Enabling Pretty-Printing............................................................ 4.2.2 Limiting Output by L in e s ........................................................................... 4.2.3 Controlling Margins .................................................................................. 4.2.4 Conserving Space with Miser Mode ....................................................... 4-2 4—3 4-3 4-3 4—4 4.3 Extensions to the FORMAT F u n c tio n ...................................................................... 4.3.1 Using the Write FORMAT Directive.......................................................... 4.3.2 Controlling the Arrangement of Output..................................................... 4.3.3 Controlling Where New Lines Begin ....................................................... 4.3.4 Controlling Indentation ............................................................................. 4.3.5 Producing Prefixes and Suffixes............................................................... 4.3.6 Using T a b s ................................................................................................ 4.3.7 Directives for Handling Lists ................................................................... 4-4 4-6 4-7 4—9 4-11 4—12 4—13 4-13 4.4 Defining Your Own Format Directives .................................................................... 4-15 4.5 Defining Print Functions for L is t s ........................................................................... 4—16 4.6 Defining Generalized Print F u n ctio n s...................................................................... 4-17 v 4.7 Abbreviating Printed O u tp u t...................................................................................... 4.7.1 Abbreviating Output Le n g th ...................................................................... 4.7.2 Abbreviating Output Depth........................................................................ 4.7.3 Abbreviating Output by L in e s................................................................... 4—19 4-19 4-20 4-20 4.8 Using Miser Mode ..................................................................................................... 4-21 4.9 Handling Improperly Formed Argument L is t s ........................................................ 4-23 Chapter 5 Error Handling 5.1 Error H andler.............................................................................................................. 5-1 5.2 VAX LISP Error Types................................................................................................ 5.2.1 Fatal Errors................................................................................................ 5.2.2 Continuable E rrors.................................................................................... 5.2.3 W arnings.................................................................................................. 5-1 5—2 5-2 5-3 5.3 Creating an Error H a ndler......................................................................................... 5.3.1 Defining an Error H andler........................................................................ 5.3.1.1 Function N a m e ....................................................................... 5.3.1.2 Error-Signaling Function......................................................... 5.3.1.3 A rgum ents.............................................................................. 5.3.2 Binding the ‘ UNIVERSAL-ERROR-HANDLER* V ariable........................ 5-4 5-4 5-5 5-5 5-5 5-5 3-1 Using the WITH-INPUT-EDITING Macro ................................................................... 3-9 3 -1 Text Misalignment As a Result of Changing Fonts...................................................... 3-5 4—1 Variables Governing Miser Mode ................................................................................. 4-22 1-1 VAX LISP Floating-Point Numbers .............................................................................. 1-2 Index Examples Figures Tables 1—2 Floating-Point Constants............................................................................................... 1-3 1- 3 Summary of Implementation-Dependent Functions and M a cro s................................. 1-16 2- 1 I/O Request S pecifiers.................................................................................................. 2-3 2-2 Stream Data Types and Predicates.............................................................................. 2—4 2- 3 Stream Informational Functions ................................................................................... 2-5 3- 1 Window Stream Editing Commands and Key Bindings............................................... 3-12 3- 2 Keyword Options to WITH-INPUT-EDITING................................................................ 3-29 4- 1 FORMAT Directives Provided by VAX L IS P ................................................................ 4—5 5- 1 Error-Signaling Functions ............................................................................................. 5-5 Preface VAX LISP is an extended implementation of Common LISP. The Common LISP language is described in Common LISP: The Language * The VAX LISP Implementation and Extensions to Common LISP manual describes the ways in which VAX LISP differs from Common LISP. Some Common LISP language elements are not fully specified in Common LISP. The Language. This manual describes VAX LISP’ s implementation-specific details. VAX LISP extends the Common LISP language in some areas, such as input and output and the definition of window streams. This manual describes VAX LISP’ s extensions to Common LISP. Intended Audience This manual is for programmers with a working knowledge of LISP. Detailed knowledge of VMS is helpful but not essential; familiarity with the Introduction to VMS is recommended. Detailed knowledge of ULTRIX—32 is helpful but not essential. Some sections of this manual require more extensive understanding of the oper ating system. In such sections, you are directed to the appropriate manual(s) for additional information. Structure This manual is organized as follows: • Chapter 1, VAX LISP Implementation Notes, describes the features of LISP that are defined by or are dependent on the VAX implementation of Common LISP. • Chapter 2, VAX LISP Extensions to I/O, describes VAX LISP extensions to the Common LISP I/O system. • Chapter 3, Window Streams, explains how to use the VAX LISP window streams facility. • Chapter 4, Pretty-Printing and Using Extensions to FORMAT, explains how to use the VAX LISP pretty-printer. • Chapter 5, Error Handling, describes the VAX LISP error-handling facility. * Guy L. Steele, Jr., Common LISP: The Language, Digital Press (1984), Burlington, Massachusetts. vii Associated Documents The following documents are relevant to VAX LISP/VMS programming: • VAX LISP/VMS Program Development Guide • VAX LISP/VMS System Access Guide • VAX LISP/VMS System-Building Guide • VAX LISP/VMS DECwindows Programming Guide • VAX LISP Editor Programming Guide • VAX LISP/VMS Interface to VWS Graphics • Introduction to VMS • VMS DCL Dictionary • VMS System Services Reference Manual • VMS I/O User’ s Reference Manual: Part I • VMS RTL Library (LIB$) Manual The following documents are relevant to VAX LISP/ULTRIX programming: • VAX LISP/ULTRIX User’ s Guide • VAX LISP/ULTRIX System Access Guide • VAX LISP/ULTRIX System-Building Guide • ULTRIX-32 Programmer’ s Manual • ULTRIX-32 Supplementary Documentation The following documents are always relevant: • Common LISP: The Language • VAX Architecture Handbook For a complete list of VMS software documents, see the Overview of VMS Documentation. Conventions The following conventions are used in this manual: C o n v e n tio n M e a n in g UPPERCASE DCL comm ands and qualifiers and VMS file names are printed in uppercase characters; however, you can enter them in uppercase, lowercase, or a combination of uppercase and lowercase characters. For example: The exam ples directory (SYS$SYSROOT:[VAXLISP.EXAMPLES] by default) contains sam ple LISP source files. U PPER CA SE TYPEWRITER Defined LISP functions, macros, variables, constants, and other symbol names are printed in uppercase TY PE WRITE R charac ters; however, you can enter them in uppercase, lowercase, or a combination of uppercase and lowercase characters. For example: The CALL-OUT m acro calls a defined external routine . . . . lo w e r c a s e ty p e w r ite r LISP forms are printed in the text in lowercase t y p e w r i t e r characters; however, you can enter them in uppercase, lowercase, or a combination o f uppercase and lowercase characters. For example: ( s e t f exam ple-1 SANS SERIF ( m a k e- sp a ce) ) Format specifications o f LISP functions and m acros are printed in a s a n s serif typeface. For example: CALL-OUT external-routine &REST routine-arguments ita lics Lowercase ita lics in format specifications and in text indicate argu ments that you supply; however, you can enter them in lowercase, uppercase, or a combination o f lowercase and uppercase characters. For example: The routine-argum ents m ust be com patible with the argum ents d e f i n e d in the call to the D E F IN E - E X T E R N A L - R O U T IN E macro. () Parentheses used in exam ples o f LISP code and in form at spec ifications indicate the beginning and end o f a LISP form. For example: ( s e t q name l i s p ) [] Square brackets in format specifications enclose optional elements. For example: [doc-string] Square brackets do not indicate optional elem ents when they are used in the syntax o f a directory name in a VMS file specification. Here, the square bracket characters m ust be included in the syntax. For example: (pathname " M I A M I : : D B A 1 : [ S M I T H ] L O G I N . C O M ;4 " ) U In function and m acro format specifications, braces enclose elements that are considered one unit o f code. For example: {keyword value} C o n v e n tio n M ea n in g {}* In function and macro form at specifications, braces followed by an asterisk enclose elem ents that are considered one unit of code, which can be repeated zero or m ore times. For example: {keyword value}* &OPTIONAL In function and m acro format specifications, the word &OPTIONAL indicates that the argum ents that follow it are optional. For exam ple: PPRINT object &OPTIONAL stream Do not specify &OPTIONAL when you invoke a function or macro whose definition includes &OPTIONAL. &REST In function and m acro format specifications, the word &REST indicates that an indefinite number of argum ents may appear. For example: CALL-OUT external-routine &REST routine-arguments Do not specify &REST when you invoke a function or m acro whose definition includes &REST. &KEY In function and m acro format specifications, the word &KEY indi cates that keyword argum ents are accepted. For example: COMPILE-FILE input-pathname &KEY LISTING :MACHINE-CODE OPTIMIZE :OUTPUT-FILE :VERBOSE WARNINGS Do not specify &KEY when you invoke a function or macro whose definition includes &KEY. A horizontal ellipsis in a format specification m eans that the ele m ent preceding the ellipsis can be repeated. For example: function-name . . . A vertical ellipsis in a code exam ple indicates that all the informa tion that the system would display in response to the function call is not shown; or, that all the information a user is to enter is not shown. |R e t u r n | A word inside a box indicates that you press a key on the keyboard. For example: | R e tu rn |or |Tab| In code examples, carriage returns are im plied at the end o f each line. However, IR e tu rn |is used in som e exam ples to em phasize carriage returns. [ c t f fic l Two key names enclosed in a box indicate a control key sequence in which you hold down Ctrl while you press another key. For example: |C trl/C E3H |or |C trl/S | A sequence such as [pfT] [xj indicates that you m ust first press and release the key labeled PF1, then press and release another key. C o n v e n tio n M e a n in g m ouse The term mouse refers to any pointing device, such as a mouse, a puck, or a stylus. MB1, MB2, MB3 By default, MB1 indicates the left m ouse button, MB2 indicates the m iddle m ouse button, and MB3 indicates the right m ouse button. You can rebind the m ouse buttons. Red print In interactive examples, user input is shown in red. For example: Lisp> (cdr ' (a b c) ) (B C) Lisp> xi Chapter 1 VAX LISP Implementation Notes VAX LISP is an implementation of LISP that is based on Common LISP as described in Common LISP: The Language. This chapter describes how implementation-dependent aspects of Common LISP are implemented on the VMS and ULTRIX—32/32w operating systems. This chapter does not describe all the implementation differences between VAX LISP/VMS (VAX LISP as implemented on VMS) and VAX LISP/ULTRIX (VAX LISP as implemented on ULTRIX). For a complete list of such differences, see the VAX LISP Release Notes. These release notes are on line in the file SYS$HELP:LISPrcrm.RELEASE_ NOTES (on VMS systems) or /usr/lib/vaxlisp/lispnnn.mem (on ULTRIX systems), where nnn is the VAX LISP version number. For example, LISP030.RELEASE_ NOTES or Iisp030.mem is the file containing the release notes for Version 3.0. Most of the information in this chapter refers to subjects that Common LISP: The Language refers to as implementation dependent. The purpose of this chapter is to clarify the implementation specifics for the following topics: • Data representation • The garbage collector • Input and output • Interrupt functions (on VMS systems only) and keyboard functions that execute asynchronously when you type a control character • Functions and macros NOTE VAX LISP/VMS su p p orts only sym bols that are in the p ack ages nam ed common- l i s p , v ax - l i s p , e d it o r , clx , dwt, and UIS. VAX LISP/ULTRIX su p p orts only sym bols that are in the p ack ages nam ed common- l i s p , vax- l i s p , cl x , and dwt. 1.1 Data Representation Common LISP defines the data types implemented in VAX LISP but Common LISP does not define implementation-dependent information related to the data types. This section provides data type information specific to VAX LISP. Complete descriptions of data types are provided in Common LISP: The Language. The following data types require VAX LISP implementation information: • Numbers • Characters VAX LISP Implementation Notes 1-1 • Arrays • Strings 1.1.1 Numbers Sections 1.1.1.1 through 1.1.1.3 explain how VAX LISP implements the integer, floating-point, and complex number data types. 1.1.1.1 Integers Common LISP defines two subtypes of integers: fixnums and bignums. In VAX LISP, the integers in the range -2**28 to 2**28-l are represented as fixnums; integers not in the fixnum range are represented as bignums. VAX LISP stores bignums as two’ s complement bit sequences. In VAX LISP, the e q function returns T when it is called with two fixnums with the same value. The values of the Common LISP integer constants are implementation dependent. The names of the constants and the corresponding VAX LISP values follow: M OST-POSITIV E-FIXN U M 268435455 M O ST - N E G A T IV E - F IX N U M -26 84 35 45 6 NOTE The range of integers represented as fixnums has been reduced by half from the old range o f -2**29 to 2**29-l. Descriptions of these constants are provided in Common LISP: The Language. 1.1.1.2 Floating-Point Numbers Common LISP defines the following types of floating-point numbers: • Short floating-point numbers • S in g le flo a tin g- p o in t n u m b e r s • Double floating-point numbers • Long floating-point numbers In VAX LISP, these four types are implemented with VAX floating data types. Table 1-1 lists the types of Common LISP floating-point numbers, the corre sponding VAX data types, and the number of bits allocated for the exponent and significand of each floating-point type. For information on the VAX floating data types, see the VAX Architecture Handbook. Table 1-1: 1-2 VAX LISP Floating-Point Numbers C o m m o n L IS P T y p e VAX T y p e E xpon ent S ig n ific a n d SHORT-FLOAT F_floating 8 24 SINGLE-FLOAT F_floating 8 24 DOUBLE-FLOAT G_floating 11 53 LONG-FLOAT ELfloating 15 113 VAX LISP Implementation Notes On ULTRIX Systems If your system does not have G and H floating-point instructions, see the ULTRIX-32 Programmer’ s Manual Binder IIIA “ System Managers”for infor mation on how to configure your system to use the g/h floating-point emulator. The values of the Common LISP floating-point constants are implementation dependent. You can use the values of these constants to compare the range of values and the degrees of precision of the VAX LISP floating-point types. Table 1-2 lists the names of the constants and provides the actual hexadecimal values and the decimal approximations for VAX LISP. Table 1-2: Floating-Point Constants C o n s ta n t H e x a d e c im a l R e p r e s e n t a t io n A p p r o x im a te D e c im a l V alue DOUBLE-FLOAT-EPSILON 00000000 00003CC0 l.lld-16 DOUBLE-FLOAT-NEGATIVE-EPSILON 00010000 00003CB0 5.55d-17 LEAST-NEGATIVE-DOUBLE-FLOAT 00000000 00008010 -5.5d-309 LEAST-NEGATIVE-LONG-FLOAT 00000000 00000000 00000000 00008001 -8.41L-4933 LEAST-NEGATIVE-SHORT-FLOAT 00008080 -2.94e-39 LEAST-NEGATIVE-SINGLE-FLOAT 00008080 -2.94e-39 LEAST-POSITIVE-DOUBLE-FLOAT 00000000 00000010 5.56d-309 LEAST-POSITIVE-LONG-FLOAT 00000000 00000000 0000000C 00000001 8.41L-4933 LEAST-POSITIVE-SHORT-FLOAT 00000080 2.94e-39 LEAST-POSITIVE-SINGLE-FLOAT 00000080 2.94e-39 LONG-FLOAT-EPSILON 00000000 00000000 00000000 00003F90 9.63L-35 LONG-FLOAT-NEGATIVE-EPSILON 00010000 00000000 00000000 00003F8F 4.81L-35 MOST-NEGATIVE-DOUBLE-FLOAT FFFFFFFF FFFFFFFF -8.99d307 MOST-NEGATIVE-LONG-FLOAT FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF -5.95L4931 MOST-NEGATIVE-SHORT-FLOAT FFFFFFFF -1.70e38 MOST-NEGATIVE-SINGLE-FLOAT FFFFFFFF -1.70e38 MOST-POSITIVE-DOUBLE-FLOAT FFFFFFFF FFFF7FFF 8.99d307 MOST-POSITIVE-LONG-FLOAT FFFFFFFF FFFFFFFF FFFFFFFF FFFF7FFF 5.95L4931 MOST-POSITIVE-SHORT-FLOAT FFFF7FFF 1.70e38 MOST-POSITIVE-SINGLE-FLOAT FFFF7FFF 1.70e38 SHORT-FLOAT-EPSILON 00003480 5.96e-8 SHORT-FLOAT-NEGATIVE-EPSILON 00013400 2.98e-8 SINGLE-FLOAT-EP SILON 00003480 5.96e-8 SINGLE-FLOAT-NEGATIVE-EPSILON 00013400 2.98e-8 Descriptions of these constants are provided in Common LISP: The Language. Common LISP allows an implementation to define a floating-point minus zero. In VAX LISP, floating-point minus zero does not exist. VAX LISP Implementation Notes 1-3 1.1.1.3 Complex Numbers VAX LISP Version 3.0 supports complex numbers of types r a t i o n a l and f l o a t , with subtypes s i n g l e -f l o a t , d o u b l e -f l o a t , and l o n g -f l o a t .A s specified in Common LISP: The Language, both parts of a complex number must be of the same type. 1.1.2 Characters Common LISP defines characters as objects that have three attributes: code, bits, and font. The code attribute is a numerical representation of the character itself. The bits attribute allows extra flags (such as c o n t r o l or m e t a ) to be associated with a character. The font attribute permits a typographical style (such as italic) or font to be associated with a character. Common LISP does not require that an implementation honor bits or font attributes. VAX LISP implements characters with eight bits for the code attribute, which is encoded using the extended ASCII character set. The bits and font attributes are no longer supported. The types c h a r a c t e r and s t r i n g -c h a r are now the same. For compatibility, characters with bits attributes can still be read and printed, but, if they are put into a string, they lose their bits attribute. The bits attribute consists of the four Common LISP bits: c o n t r o l , h y p e r , m e t a , and s u p e r . Note that the c o n t r o l bits attribute is not associated with control characters in the ASCII character set. The VAX LISP implementation of Common LISP functions that take a font argument ignores it. The VAX LISP implementation of Common LISP functions that compare char acters uses the numeric values that correspond to the extended 8-bit ASCII character set. The character predicate functions and the rules that the functions use to compare characters are described in Common LISP: The Language. The ordering of two characters that have the same character code but different bits and font attributes is undefined in VAX LISP. The Common LISP character constants that are the exclusive upper limits on the code, bits, and font attributes have the following values in VAX LISP: CHAR-CODE-LIMIT 256 CHAR-BITS-LIMIT 1 CHAR-FONT-LIMIT 1 NOTE The values of these constants have changed in this release of VAX LISP. Descriptions of these constants are provided in Common LISP: The Language. You can obtain a table of valid VAX LISP character names by calling the VAX LISP c h a r -n a m e -t a b l e function described in the VAX LISP/VMS Object Reference Manual. On ULTRIX Systems The ULTRIX operating system masks the eighth bit, which produces the same effect as having specified 7-bit characters. You can prevent this masking by setting the terminal in RAW mode, but this is not recommended (see tty(4) in the ULTRIX-32 Programmer’ s Manual). 1-4 VAX LISP Implementation Notes 1.1.3 Arrays Common LISP defines an array as an object whose components are arranged according to a Cartesian coordinate system and whose number of dimensions is called its rank. The names of the Common LISP array constants and the corresponding VAX LISP values are: A R R A Y - D IM E N S IO N - L I M IT 16777215 A RR A Y - R A N K - L IM IT 8 A R R A Y -TOTA L -SIZE-L IM IT 16777215 These constants are described in Common LISP: The Language. Common LISP defines a specialized array as an array that can contain only elements of a specific type. Specialized arrays are more space efficient than general arrays. VAX LISP creates a specialized array when you call the m a k e a r r a y function with the : e l e m e n t -t y p e keyword set to any of the types in the following set: CHARACTER BIT (UNSIGNED-BYTE 2) (UNSIGNED-BYTE 4) (UNSIGNED-BYTE 8) (UNSIGNED-BYTE 12) (UNSIGNED-BYTE 16) (UNSIGNED-BYTE 24) (UNSIGNED-BYTE 32) (UNSIGNED-BYTE 64) (SIGNED-BYTE 8) (SIGNED-BYTE 16) (SIGNED-BYTE 32) DOUBLE-FLOAT LONG-FLOAT (SIGNED-BYTE 64) SINGLE-FLOAT If the element type is neither a member of this set nor a subtype of a member, VAX LISP creates a general array (element type is t ). In VAX LISP Version 3.0, vectors of characters are implemented as strings. 1.1.4 Strings Common LISP defines a string as a vector of string characters. In VAX LISP, a string can be composed of as many as a r r a y -d i m e n s i o n -l i m i t minus one character. A string character is a character that can be stored in a string object. In VAX LISP Version 3.0, all characters are string characters. String characters cannot have the bits or font attributes. On ULTRIX Systems You can prevent the ULTRIX operating system from masking the eighth bit of a character by setting the terminal in RAW mode, but this is not recommended (see tty ( 4 ) in the ULTRIX-32 Programmer’ s Manual). 1.1.5 Functions The Common LISP constants that are the exclusive upper bounds on the number of arguments to a function, the parameters in a lambda list, and the return values of a function have the following values in VAX LISP: CALL-ARGUMENTS-LIMIT l a m b d a -p a r a m e t e r s -l i m i t MULTIPLE-VALUES-LIMIT 1000000 255 1000000 VAX LISP Implementation Notes 1-5 1.2 Garbage Collector When VAX LISP is executing, LISP objects are created dynamically in one area of the total memory pool assigned to LISP by the operating system. Some objects are always used and referred to, while others are referred to only for a short time. When the amount of memory allocated to LISP objects reaches a certain percentage of the LISP memory pool, all LISP processing is suspended. Objects that can still be referred to are copied into another area of dynamic memory, while objects that can no longer be referred to are not copied. The space that such objects occupied is thus reclaimed by the VAX LISP system. This process of reclaiming space is called garbage collection. The following sections describe aspects of the VAX LISP garbage collector: • Memory management • Types of garbage collection • Tuning garbage collection performance • Increasing available space • Garbage collection failure • Controlling messages • Effect on static space • Effect on VMS interrupt functions You can ignore garbage collections of dynamic memory space when you write LISP programs. Section 1.2.7 explains how to create objects in static rather than dynamic space. 1.2.1 Memory Management When you start a LISP session, VAX LISP requests memory from the operating system. By default, 5000 512-byte pages are assigned to LISP and 50 percent may be used to allocate LISP objects. (See Section 1.2.4 for information on how to change these defaults.) When the percentage is reached, a garbage collection occurs, copying all live data from the current dynamic allocation area into unused memory (called the unassigned area until used). The memory previously allocated is then returned to the available LISP memory pool (to the unassigned area). Objects that are not referred to are not copied. All LISP processing is suspended during garbage collection. To provide flexibility in allocation of objects and in garbage collection strategies, the VAX LISP system divides its memory pool into a number of different spaces: : r e a d -o n l y , -.STACK, :s t a t i c , and :d y n a m i c . The :r e a d -o n l y space contains much of the LISP system. This space may not be written to and is shared among multiple processes when installed properly with the VMS INSTALL utility. Users building their own LISP systems with the System Build Utility may have portions of their own application placed in : r e a d -o n l y memory as well. : s t a c k space contains control and binding stacks and tends to remain relatively stable during a LISP session. Users’objects are not allocated in : s t a c k space. : s t a t i c space is used for allocation when users require allocated LISP objects which are guaranteed not to be moved by the garbage collector during the LISP session. :s t a t i c space also contains all nonreadonly portions of user applications built with the System Build Utility. 1-6 VAX LISP Implementation Notes Garbage collection is not performed in the :r e a d -o n l y , :s t a c k , and : s t a t i c spaces, only in the :d y n a m i c space. Most LISP objects are allocated in :d y n a m i c space. When the ephemeral garbage collector is active, ephemeral areas are created within the dynamic space. 1.2.2 Types of Garbage Collection VAX LISP uses both full and ephemeral garbage collection methods. In general, full collections happen infrequently (if enough memory is available) and free large amounts of memory. However, full collections take time proportional to the amount of : s t a t i c space, which must be scanned, and the amount of live data in :d y n a m i c space, which must be copied. In full collections, all objects are scanned and any dynamic objects that can be referred to are copied. In applications with large amounts of dynamic data, the time required can be substantial. This can present annoying pauses in interactive sessions, lb remedy this, the ephemeral garbage collector may be used. Ephemeral garbage collection takes the opposite approach: frequent small collec tions rather than infrequent large garbage collections. There is some overhead in doing ephemeral collection, because of the frequency of use; applications with much live data will require more total CPU time than they would running only the full garbage collection. On the other hand, user-visible garbage collection activity is kept to a minimum. Also, ephemeral collection does not replace full garbage collection because it only partially reclaims data. Depending on your application, a full garbage collection may be required at some point. In general, however, ephemeral garbage collection can postpone full garbage collections for a long time. Besides reducing the visibility of garbage collection activity, the ephemeral collector also provides “ age tracking”of data. The ephemeral collector maintains three areas of dynamic memory: EO, El, and E2. Most allocation is done in the EO area. When EO is full, an ephemeral collection occurs and live data is copied (promoted) to El. When E l is full (presumably after many EO collections), an ephemeral collection occurs and data that is still live is promoted to E2. When E2 is full, live data is promoted to the :d y n a m i c area where it remains in place until a full collection is required. It is generally accepted that in most LISP applications, most data has a short lifetime and becomes garbage very quickly. The longer data remains live, the more likely it will never become garbage. By using separate areas, ephemeral garbage collection eventually moves long-lived data to more permanent memory. The ephemeral garbage collector is automatically enabled when you invoke VAX LISP, if enough memory is allocated (see Section 1.2.4 for details). 1.2.3 Tuning Garbage Collection Performance The frequency of garbage collection is inversely proportional to the size of the current dynamic memory space; the speed is directly proportional. The degree to which the frequency of garbage collection and the size of dynamic memory affect run-time efficiency depends on the program. If a program creates more permanent objects than short-lived objects, the garbage collector has to perform more copy operations, slowing execution. VAX LISP Implementation Notes 1-7 You can make full garbage collections occur less frequently by increasing tbe virtual memory allocated to LISP or increasing the percentage of dynamic space that must be occupied before a full collection takes place. See Section 1.2.4 for information on ways to set the amount of available memory. The d y n a m i c s p a c e -r a t i o function returns the current percentage, as a floating-point value, of dynamic space that may be used before a full garbage collection is performed. This ratio may be changed by using the s e t f macro. The new value must be greater than zero and less than or equal to one. Setting the dynamic space ratio can help the memory management system make more efficient use of memory, but the ratio is only a guideline. The ratio may be reset when the memory management system finds the current value to be inappropriate for existing conditions. You can make ephemeral collections occur less frequently by increasing the size of the ephemeral areas. However, having too large an EO area causes ephemeral garbage collections to take longer thus undoing the desired “ user-invisible” effect of frequent, fast ephemeral garbage collections. Having a large EO area and a too small E l area may make most EO collections instantly cause an E l collection. While collection of the EO area is optimized for speed, the others are used mostly for age tracking of data. It is recommended that E l be large enough to give any live but soon-to-die data that survives an EO collection a chance to die before promoting if to E2 or even :d y n a m i c space. The limits on the sizes of the ephemeral areas can be queried or changed with the a r e a -s e g m e n t -l i m i t function. For example: Lisp> (area-segment-limit 0) 10 Lisp> (setf (area-segment-limit 0) 40) Under certain circumstances, ephemeral garbage collection is counterproduc tive, as when loading files that create large amounts of permanent, live data. Disabling ephemeral collections before loading the files causes the data to be created directly in :d y n a m i c space, avoiding the overhead of promotions through the ephemeral areas However, garbage created by the loading is not discarded. You can disable or enable ephemeral collection with the g c -m o d e function. For example: (gc-mode :full) 1.2.4 Increasing Available Space Garbage collection generally occurs when a LISP object is being created. If a garbage collection occurs and enough dynamic memory space to allocate the object is not available, the LISP system grows dynamic space as needed by requesting more memory from the operating system. The LISP system requests at least the number of 64K-byte segments in the value bound to the m e m o r y a l l o c a t i o n -e x t e n t function, depending on the size of the object. You can change the allocation extent with the s e t f macro. You can increase the total memory addressable by LISP with the e n l a r g e -l i s p Its format is: m e m o r y function. ENLARGE-LISP-MEMORY segments where segments is the number of 64K-byte segments by which the amount of virtual memory available for LISP allocation should be increased by the operating system. 1-8 VAX LISP Implementation Notes You can also set the amount of memory available to LISP by specifying the /MEMORY command qualifier (on VMS systems) or the MEMORY (-m) option (on ULTRIX systems) when you invoke the LISP system. Garbage collection occurs less often if you use the memory qualifier or option to increase the size of the dynamic memory space. (See Chapter 2 of the VAX LISP /VMS Program Development Guide for more information about setting the amount of memory available to LISP.) The ephemeral garbage collector is automatically turned on when the memory allocation size is larger than approximately 10,000 pages. This size can vary according to how the image was created and how it was started. In addition, normal execution may use up free space so that there is not enough left over after a garbage collection. In this situation, the ephemeral garbage collector is automatically turned off. 1.2.5 Garbage Collection Failure The ephemeral garbage collector will be disabled when the sum of the size of the :d y n a m i c space and the ephemeral area segment limits is more than the d y n a m i c -s p a c e -r a t i o of the LISP-allocated pool. If this is caused by a user action, for example, you have enlarged an area segment limit, a warning message is printed. A full garbage collection is performed regardless of cause. You can reenable the ephemeral garbage collector by using the g c -m o d e function: (gcmode :ephemeral). This function may not enable ephemeral garbage collection if there is insufficient memory. The garbage collection process may fail to complete. If, for example, the LISP system cannot allocate enough memory to contain all the LISP objects that can be referred to without exceeding the process quota, the LISP image is terminated, and control returns to the DCL level (on VMS systems) or to the shell (on ULTRIX systems). The risk of this happening is greater when the value bound to the d y n a m i c -s p a c e -r a t i o function is large (for example, 90 percent) or if garbage collection is turned off (g c -m o d e :n o n e ). In previous versions of VAX LISP, a control stack overflow caused a garbage collection. In Version 3.0, control stack overflow is a fatal error. You can increase the allocation for control stacks with the /CSTACK qualifier to the DCL LISP command. (See Chapter 2 of the VAX LISP/VMS Program Development Guide for details.) 1.2.6 Controlling Messages During a full garbage collection, messages are displayed when the operation begins and when it is finished. You can suppress these messages by changing the value of the VAX LISP *g c -v e r b o s e * variable to n i l .When the value is n i l , messages are not displayed. You can also specify the contents of the messages by changing the values of the VAX LISP *p r e -g c -m e s s a g e * and *p o s t -g c -m e s s a g e * variables. The *g c v e r b o s e *, *p r e -g c -m e s s a g e *, and *p o s t -g c -m e s s a g e * variables are described in the VAX LISP /VMS Object Reference Manual. VAX LISP Implementation Notes 1-9 1.2.7 Effect on Static Space LISP objects that are created in static space are not collected by the garbage collector. These objects do not move and they are not deleted, even if they can no longer be referred to. You can create objects in static space by using the :a l l o c a t i o n keyword with the m a k e -a r r a y function or by using the constructor functions that are defined by the d e f i n e -a l i e n -s t r u c t u r e macro for alien structures. (See the VAX LISP /VMS Object Reference Manual for details.) 1.2.8 Effect on VMS Interrupt Functions LISP processing is suspended during a garbage collection. The VMS operating system queues interrupt functions, such as those defined by the VAX LISP BIND-KEYBOARD-FUNCTION and INSTATE-INTERRUPT-FUNCTION functions, for delivery after garbage collection is finished. Interrupt functions are discussed in Section 1.4. 1.3 Input and Output On VMS systems, VAX LISP I/O is implemented with two sets of low level functions. One set of functions handles terminal I/O, using direct QIOs to the terminal driver. The other set of functions handles all other I/O (particularly to disk files), using calls to VAX Record Management Services (RMS). See the VMS Record Management Services Manual for information about VAX RMS. On ULTRIX systems, VAX LISP terminal I/O and file I/O are implemented by low level ULTRIX system I/O routines. See the ULTRIX-32 Programmer’ s Manual for a description of ULTRIX I/O. The following sections cover the specific VAX LISP I/O implementations of: • Newline character • Terminal input • Terminal output (on ULTRIX systems) • End-of-file operations • Record length (on VMS systems) • File organization • Functions 1.3.1 Newline Character Common LISP defines the #\n e w l i n e character as a character that is returned from the READ-CHAR function as an end-of-line indicator. In VAX LISP, the character code for the #\n e w l i n e character has an integer value of 255. In VAX LISP, the w r i t e -c h a r and w r i t e -s t r i n g functions interpret the #\ n e w l i n e character as follows: • When the w r i t e -c h a r function is called with the #\n e w l i n e character as its argument value, the function starts writing a new line. This call is equivalent to a call to the t e r p r i function (see Common LISP: The Language). 1-10 VAX LISP Implementation Notes • When the write-string function is called with an argument string that contains the #\newline character, the function divides the string into multiple lines. The following example shows the output that is displayed by the write-string function when the #\newline character is not used: Lisp> (write-string (concatenate 'string "NEW" "LINE")) NEWLINE "NEWLINE" Both strings, "new" and "line", are displayed on the same line. A call to the write-string function with a string argument that d oes include the #\newline character, produces the following output: Lisp> (write-string (concatenate 'string "NEW" (string #\newline) "LINE")) NEW LINE "NEW LINE" This call to the w r i t e -s t r i n g function displays the strings "NEW" and "l i n e " on separate lines. The #\n e w l i n e character is the only character that moves the cursor to the beginning of the next line. #\l i n e f e e d moves the cursor down one line; #\r e t u r n moves the cursor to the beginning of the current line. 1.3.2 Terminal Input In VAX LISP, terminals perform input operations in line mode. Input is returned by the r e a d -c h a r function only after you press the Return key. On VMS Systems The r e a d -c h a r function returns ASCII characters as data unless one of the following conditions exists: 1. A character is used by the VMS terminal driver for terminal control. 2. A character is defined to invoke an interrupt function. See the VMS I/O U ser’ s Reference Manual: Part I for information on terminal control characters, and see Section 1.4 of this manual for information about interrupt functions. You can change the mode in which your terminal performs input operations by invoking the VAX LISP s e t -t e r m i n a l -m o d e s function with the :PASS-t h r o u g h keyword set to t (see the 'VAX'LISP/VMS Object Reference Manual). If the value of the :p a s s -t h r o u g h keyword is t , then the VAX LISP system does not recognize control characters processed by the VMS system and characters de fined to invoke interrupt functions. In addition, the r e a d -c h a r function performs input operations differently than it does when the terminal is in line mode. In line mode, the r e a d -c h a r function does not return a character until you press the Return key; in pass-through mode, that function returns a character as soon as the character is typed. See Common LISP: The Language for a description of the r e a d -c h a r function. VAX LISP Implementation Notes 1-11 To put your terminal back into line mode, invoke s e t -t e r m i n a l -m o d e s with :PASS-THROUGH set to NIL. On ULTRIX Systems The read-char function returns ASCII characters as data unless a character is used by the ULTRIX terminal driver for terminal control. See the ULTRIX-32 Programmer’ s Manual (particularly ioctl(2), stty(l), and tty(4)) for information on terminal control characters. 1.3.3 Terminal Output on ULTRIX Systems ULTRIX truncates terminal output rather than wrapping it. To make output more readable, set the *p r i n t -p r e t t y * variable to T or *p r i n t -r i g h t -m a r g i n * to the width of the screen. 1.3.4 End-of-File Operations In VAX LISP, read operations from a file do not indicate the end of the file until the operation after the last character in the file is performed. Read operations from a terminal do not indicate the end of a file in VAX LISP. In VAX LISP, you can close a stream that is connected to your terminal if the stream is not related to the stream bound to the *t e r m i n a l -i o * variable. If you attempt to close the stream bound to *t e r m i n a l - i o *, no action is performed. 1.3.5 Record Length on VMS Systems VAX LISP/VMS uses VAX RMS to process file I/O. Therefore, the maximum record length in VAX LISP must conform to the maximum record length in RMS. A maximum of 32,767 characters can be written to a single record of a disk file, and a maximum of 9995 characters can be written to a single record of a magnetic tape. If you exceed these record-length limits, an error is signaled and nothing is written to the file. The w r i t e -c h a r function causes an immediate operation when it is called with a terminal stream. As a result, there is no limit on the number of calls you can make to the w r i t e -c h a r function before you invoke the t e r p r i function if you are writing to a terminal. Your user-buffered I/O byte limit quota determines the maximum string length you can write to your terminal. You can find out what the quota is by invoking the VAX LISP/VMS g e t -p r o c e s s - i n f o r m a t i o n function with the :BIO-b y t e q u o t a keyword (see VAX LISP/VMS Object Reference Manual). For example: Lisp> (get-process-information "SMITH" :bio-byte-quota) (:BIO-BYTE-QUOTA 30000) NOTE You can prevent your buffered I/O byte limit quota from overflowing and avoid the RMS record length limits by including calls to the t e r p r i function, by inserting the #\n e w l i n e character in your strings, or by setting *p r i n t -r i g h t -m a r g i n * or *p r i n t -p r e t t y *. 1-12 VAX LISP Implementation Notes 1.3.6 File Organization VAX LISP/VMS reads RMS files sequentially. Character files created by VAX LISP/VMS have sequential organization, variable-length records, and the implied carriage-return attribute. Files created for binary output (with, for example, the w r i t e -b y t e function) have sequential organization, variable-length records, and no carriage-control attributes. VAX LISP/ULTRIX creates ULTRIX files that are sequential streams. 1.3.7 I/O Functions Some Common LISP functions used for I/O have VAX LISP dependencies and need further explanation: • OPEN • WRITE-CHAR • FILE-LENGTH (on VMS systems only) • f i l e -p o s i t i o n (on VMS systems only) Unless otherwise noted, the implementation information in the following sections applies to both ULTRIX and VMS systems. 1.3.7.1 OPEN Function Before you can access a file, you must open it with the o p e n function or the macro. The o p e n function can be specified with keywords that determine the type of stream that is to be created and how errors are to be handled. The keywords you can specify are: w i t h -o p e n -f i l e :DIRECTION :ELEMENT-TYPE :IF-EXISTS :IF-DOES-NOT-EXIST VAX LISP restricts the values you can specify for these keywords. The rest of this section explains the restrictions. For the :i f -e x i s t s keyword values of iRENAME, :r e n a m e -a n d -d e l e t e , and :s u p e r s e d e , the old file is renamed to the same name with the string “ old” appended to the file type. On closing files opened with any of these three values, and specifying :a b o r t t , the new version is deleted and the old is restored to its former name. On closing files with :a b o r t n i l , on :r e n a m e , there is no action; with :r e n a m e -a n d -d e l e t e or : s u p e r s e d e , the old file is deleted. VAX LISP supports all the values for the : e l e m e n t -t y p e keyword specified by Common LISP. VAX LISP lets you open binary streams, but the maximum byte size for a stream is 512 8-bit bytes. On VMS Systems In VAX LISP/VMS, you can specify the : io value for the :d i r e c t i o n keyword only if the specified stream is connected to a terminal or mailbox. When you specify the : io value, the target device must exist before the o p e n function is called. Therefore, if you specify this value for the :d i r e c t i o n keyword, you cannot specify the : i f -e x i s t s keyword, and you can specify the : i f -d o e s -n o t -e x i s t keyword only with the :e r r o r value. VAX LISP Implementation Notes 1-13 The : IF-EXISTS :o v e r w r i t e option is not supported in VAX LISP/VMS. On ULTRIX Systems In VAX LISP/ULTRIX, if a file is opened with :d i r e c t i o n : io, the user must set the file position with the f i l e -p o s i t i o n function when changing from reading to writing and vice versa. Not setting the file position will cause the file to be left in an inconsistent state. 1.3.7.2 WRITE-CHAR Function The w r i t e -c h a r function disregards the bit and font attributes of characters. 1.3.7.3 FILE-LENGTH Function on VMS Systems The length of a file is measured in units of the o p e n function’ s : e l e m e n t -ty p e keyword. In VAX LISP/VMS, files cannot be measured in these units for all the supported element types. Therefore, the f i l e -l e n g t h function returns NIL. You can determine the total number of 8-bit bytes in a file by invoking the g e t f i l e - i n f o r m a t i o n function with the :e n d -o f -f i l e -b l o c k and : f i r s t -f r e e -b y t e keywords, and then performing the following steps: 1. Multiply the value returned for the :END-o f -f i l e -b l o c k keyword minus one by 512. 2. Add the value you get in step 1 to the value returned for the :FIRs t -f r e e b y t e keyword. For example: (defun size-in-bytes (file) (let ((blocks (cadr (get-file-information file :end-of-file-block))) (bytes (cadr (get-file-information file :first-free-byte)))) (+ bytes (* 512 (- blocks 1 ))))) For the more information on the g e t -f i l e -i n f o r m a t i o n function, see the VAX LISP/VMS Object Reference Manual. 1.3.7.4 FILE-POSITION Function on VMS Systems The f i l e -p o s i t i o n function returns or sets the current position within a randomaccess file. VAX LISP/VMS does not support random-access files; therefore, this function returns n i l . 1.4 VAX LISP/VMS Interrupt and Keyboard Functions An interrupt function is a function that is invoked when a specific event occurs. If an interrupt function is defined for an event, the VAX LISP/VMS system interrupts the current LISP processing and invokes the interrupt function when the event occurs. When the interrupt function exits, the VAX LISP/VMS system resumes processing at the point where it was interrupted. VAX LISP/VMS provides two functions you can use to define interrupt functions: INSTATE-INTERRUPT-FUNCTION and BIND-KEYBOARD-FUNCTION. The INSTATEINTERRUPT-FUNCTION function is part of a general mechanism that lets your program respond to asynchronous events (ASTs) in the VMS operating system. This mechanism is described in the VAX LISP/VMS System Access Guide. 1-14 VAX LISP Implementation Notes b i n d -k e y b o a r d -f u n c t i o n is a more specialized function that binds an ASCII control character to an interrupt function. Once a control character is bound to a function, you can cause the VAX LISP/VMS system to interrupt the current evaluation and call the function asynchronously by typing the control character. Functions bound using b i n d -k e y b o a r d -f u n c t i o n are also called keyboard functions. Interrupt functions are not always called as soon as the defined event occurs. If a low-level LISP function, such as w r i t e -c h a r or c o n s , is being evaluated or a garbage collection is being performed, interrupt functions are placed in a queue until they can be evaluated. Delays in interrupt function evaluation are generally not perceptible. An example of when you might perceive a delay is when the system performs a garbage collection. VAX LISP also provides a means by which you can assign different priorities for interrupt and keyboard functions. These priorities, called interrupt levels, are described in the VAX' LISP/VMS System Access Guide. If you suspend the LISP system when interrupt functions are defined, the functions that are defined by the b i n d -k e y b o a r d -f u n c t i o n function are still defined when the system is resumed. The key/function bindings are not lost. Any other interrupt functions that you may have defined are uninstated when the system is suspended and are not reinstated when the system is resumed. Besides the b i n d -k e y b o a r d -f u n c t i o n function are the VAX LISP functions g e t -k e y b o a r d -f u n c t i o n and u n b i n d -k e y b o a r d -f u n c t i o n . The g e t -k e y b o a r d f u n c t i o n function returns information about a function that is bound to a control character, and the u n b i n d -k e y b o a r d -f u n c t i o n function removes the binding of a function from a control character. Descriptions of the b i n d -k e y b o a r d -f u n c t i o n , g e t -k e y b o a r d -f u n c t i o n , and u n b i n d -k e y b o a p d -f u n c t i o n functions are provided in the VAX LISP/VMS Object Reference Manual. 1.5 VAX LISP/ULTRIX Keyboard Functions A keyboard function is a function that is invoked when the user types a particular control key. The b i n d -k e y b o a r d -f u n c t i o n function binds an ASCII control character to a function, creating a keyboard function. A keyboard function interrupts the current LISP processing when the specified control key is typed. When the keyboard function exits, the VAX LISP/ULTRIX system resumes processing at the point where it was interrupted. Note that you can use the b i n d -k e y b o a r d -f u n c t i o n to bind only three characters (Ctrl/C, CtrlA, and Ctrl/Z. See Chapter 2 of the VAX’ LISP/VMS Program Development Guide for more information on these characters. Keyboard functions are not always called as soon as the specified control key is typed. If a low-level LISP function, such as w r i t e -c h a r or c o n s , is being evaluated or a garbage collection is being performed, keyboard functions are placed in a queue until they can be evaluated. Delays in keyboard function evaluation are generally not perceptible. An example of when you might perceive a delay is when the system performs a garbage collection. VAX LISP also provides a means by which you can assign different priorities for keyboard functions. These priorities, called interrupt levels, are described in the VAX LISP/ULTRIX System Access Guide. VAX LISP Implementation Notes 1-15 If you suspend the LISP system when keyboard functions are defined, the functions are still defined when the system is resumed. The key/function bindings are not lost. Besides the b i n d -k e y b o a r d -f u n c t i o n function are the VAX LISP functions GET-KEYBOARD-FUNCTION and UNBIND-KEYBOARD-FUNCTION. The GET-KEYBOARDFUNCTION function returns information about a function that is bound to a control character, and the u n b i n d -k e y b o a r d -f u n c t i o n function removes the binding of a function from a control character. Descriptions of the b i n d -k e y b o a r d -f u n c t i o n , g e t -k e y b o a r d -f u n c t i o n , and u n b i n d -k e y b o a r d -f u n c t i o n functions are provided in the VAX LISP/VMS Object Reference Manual. 1.6 Functions and Macros Several functions and macros described in Common LISP: The Language have implementation dependencies. Table 1-3 lists the names of these functions and macros and provides a brief explanation of the type of information that is implementation dependent. For a summary description of these functions and macros, see the VAX LISP/VMS Object Reference Manual. Each description consists of the function’ s or macro’ s use, implementation-dependent information, format, applicable arguments, return value, and examples of use. See Common LISP: The Language for further information regarding these functions and macros. Table 1-3: Summary of Implementation-Dependent Functions and Macros N am e Type Im p le m e n ta tio n - D e p e n d e n t In fo r m a tio n APROPOS Function Optional argum ent and DO-SYMBOLS macro APROPOS-LIST Function Optional argum ent and DO-SYMBOLS macro BREAK Function Facility invoked COMPILE-FILE Function Keywords and return value DESCRIBE Function Displayed output DIRECTORY Function A rgum ent m erged with wildcards DRIBBLE Function Cannot nest calls On VMS systems, also terminal I/O while in the Editor is not saved ED (on VMS system s only) Function Arguments GET-INTERNAL-RUN-TIME Function M eaning o f return value LOAD Function Finds latest file LONG-SITE-NAME Function On VMS systems, the logical name and return value On ULTRIX systems, the location of informa tion for string returned MACHINE-INSTANCE Function Return value On VMS systems, also the logical name MACHINE-VERSION Function Return value (continued on next page) 1-16 VAX LISP Implementation Notes Table 1-3 (Cont.): Summary of Implementation-Dependent Functions and Macros N am e Type Im p le m e n ta tio n - D e p e n d e n t In fo r m a tio n MAKE-ARRAY Function : ALLOCATION keyword REQUIRE Function Modules ROOM Function D isplayed output SHORT-SITE-NAME Function On VMS systems, the logical name and return value On ULTRIX systems, the location o f informa tion for string returned TIME Macro Displayed output TRACE Macro Keywords WARN Function Facility invoked NOTE T, n i l , and keywords are not legal function names in VAX LISP. VAX LISP Implementation Notes 1-17 Chapter 2 VAX LISP Extensions to I/O VAX LISP provides a number of extensions to the Common LISP I/O system. These extensions fall into the following three categories: • A facility for defining new stream types. VAX LISP lets you define new types of character streams. Section 2.1 describes this facility. • Information about streams. VAX LISP data types and functions provide more information about streams than is possible using only Common LISP facilities. Section 2.2 describes these data types and functions. • New I/O functions. VAX LISP provides a number of I/O functions in addition to those defined in Common LISP. Section 2.3 describes these functions. 2.1 Defining New Types of Streams Common LISP provides several types of streams; for example, synonym streams, broadcast streams, and echo streams. VAX LISP lets you define new types of streams that have different characteristics from those defined in Common LISP. You may want to define a new type of stream when you need input or output operations to have side effects unavailable with Common LISP streams. To define a new type of stream, do the following: • Design the stream. You need to decide how instances of the stream should respond to each valid I/O function. • Define a means of creating instances of the stream. See Section 2.1.2. • Define the action of each I/O function when acting on streams of that type. See Section 2.1.3. 2.1.1 Overview of VAX LISP I/O In the VAX LISP I/O system, every instance of a stream includes a function called the stream dispatch function. Whenever an I/O function is called with a stream as its argument, the stream dispatch function for that stream executes. The stream dispatch function requires as its first argument an I/O request specifier whose value indicates the I/O function that was called. The stream dispatch function must, for every valid I/O request specifier, take the appropriate action for that I/O function operating on that type of stream. In VAX LISP, streams are implemented as structures. Every structure definition of a stream type includes the s t r e a m structure definition provided in VAX LISP. In addition, stream type definitions may contain slots specific to the type of VAX LISP Extensions to I/O 2-1 stream. For example, the structure that implements a synonym stream contains a slot for the symbol to whose value the synonym stream is equated. 2.1.2 Defining Stream Structures To define a new stream type, use the defstruct macro to create a structure definition that includes the stream structure definition. Define additional slots as needed to satisfy the requirements of the stream type you have designed. You must not use any of the following names for your slots: CLASS DISPATCH-FUNCTION DOES-INPUT-P DOES-OUTPUT-P ELEMENT-SIZE IMMEDIATE-OUTPUT-P INPUT-BUFFER INPUT-BUFFER-INDEX INPUT-BUFFER-LIMIT LINE-POS-BASE OUTPUT-BUFFER OUTPUT-BUFFER-LIMIT RIGHT-MARGIN SPECIFIC-STATE-1 SPECIFIC-STATE-2 These slots are used by the VAX LISP I/O system and must not be modified. Your structure definition must set the following slots in the STREAM structure by specifying default values in the : include stream form: • The d o e s - in pu t -p and d o e s - output -p slots, whose values indicate whether input operations and output operations, respectively, are valid on the new stream type. • The d is p a t c h -function slot, whose value is a function you write that performs each of the input and/or output operations that can result from function calls on the stream. (Section 2.1.3 describes stream dispatch functions.) The value of the d is p a t c h - function slot may also be a symbol with a function definition. The following example defines a new stream type called sample - stream : (defstruct (sample-stream (:constructor make-sample-stream (input-stream output-stream)) (:copier nil) (:include stream (does-input-p t) (does-output-p t) (dispatch-function 'sample-stream-dispatch))) (input-stream nil :type stream :read-only t) (output-stream nil ttype stream :read-only t)) This definition results in the following: • A definition for the structu re type sample - stream , in stan ces o f w hich contain the slots in pu t - stream and output - stream in addition to th ose slots inherited from the stream structu re definition • A new type, sample - stream • A new predicate, sample - stream -p • A by-position constructor function whose format is: MAKE-SAMPLE-STREAM input-stream output-stream • Accessor functions sample- stream - in pu t - stream and sample - stream -outputstream 2-2 VAX LISP Extensions to I/O 2.1.3 Stream Dispatch Functions When an I/O function is called on a stream, the dispatch function for that stream type executes. Each stream type’ s dispatch function must perform the operations for each I/O function that can be called on streams of that type. When it executes, the stream dispatch function receives at least two arguments: 1. An I/O request specifier (a keyword that corresponds to the I/O function that was called on the stream) 2. The stream on which the function was called The stream dispatch function receives additional arguments that correspond to the additional arguments with which the I/O function was called. A stream dispatch function must be able to receive any number of arguments without error, although it need not process all arguments it receives. For example, if my- sample - stream is an instance of sample- stream , the following call: (read-char my-sample-stream nil 'eof-encountered nil) results in a call to sample- stream -d is p a t c h with five arguments. The first ar gument is the I/O request specifier, :read -char in this case. The second through fifth arguments are the value of my- sample- stream , n il , ' eo f - encountered , and NIL. Table 2-1 lists the I/O request specifiers that stream dispatch functions must handle. Not all I/O functions have a corresponding specifier, because some I/O functions (such as w r ite - l in e and t e r p r i ) are defined and implemented in terms of lower level functions. Table 2-1: I/O Request Specifiers M u st B e H a n d le d b y A ll S tr e a m s : CLOSE :ELEMENT-TYPE M u st B e H a n d le d b y All In p u t S tr e a m s : CLEAR-INPUT :LISTEN2 :NREAD-LINE :READ-CHAR :READ-LINE :UNREAD-CHAR M u st B e H a n d le d b y A ll O u tp u t S tr e a m s : CLEAR-OUTPUT :FINISH-OUTPUT :FORCE-OUTPUT :FRESH-LINE : IMMEDIATE-OUTPUT-P :LINE-POSITION :RIGHT-MARGIN :WRITE-CHAR :WRITE-STRING NOTE See Section 2.3 for a description of the functions im m ediate -output - p , LINE-POSITION, LISTEN2, NREAD-LINE, and RIGHT-MARGIN. All Other fun ctions are d escribed in Common LISP: The Language. The :abort flag argument to close is passed as the first argument with the : close request. VAX LISP Extensions to I/O 2-3 The stream dispatch function s a m p l e -s t r e a m -d i s p a t c h might be written as follows. Note the use of &r e s t to ensure that s a m p l e -s t r e a m -d i s p a t c h can be called with an indefinite number of arguments without error. (defun sample-stream-dispatch (request stream Soptional argl arg2 arg3 Srest arg4) (declare (ignore arg4)) (case (the keyword request) (:read-char (let ((char (read-char (sample-stream-input-stream stream) argl arg2 arg3))) (unless (eq char arg2) (write-char char (sample-stream-output-stream stream))) char)) (:write-char (write-char argl (sample-stream-output-stream stream))) (:unread-char (unread-char argl (sample-stream-input-stream stream))) (t (error "~A does not recognize the ~A request" stream request)))) s a m p l e -s t r e a m -d i s p a t c h provides special handling when r e a d -c h a r is called on a stream of type s a m p l e - s t r e a m . For other I/O functions, s a m p l e -s t r e a m -d i s p a t c h simply calls the same function on either the input stream or the output stream. s a m p l e -s t r e a m -d i s p a t c h signals an error if it is called with an unrecognized I/O request specifier. 2.2 Getting Information About Streams VAX LISP provides access to more detailed information about streams than is called for in Common LISP: The Language. VAX LISP provides a separate data type for each stream type, a predicate for each stream type, and functions to retrieve elements that were used to construct streams. Table 2-2 lists the stream data types and predicates. The s t r e a m p predicate is satisfied by objects of any of the stream data types. Table 2-2: Stream Data Types and Predicates D a ta T y p e P r e d ic a t e F u n c t io n BROADCAST-STREAM BROADCAST-STREAM-P object CONCATENATED-STREAM CONCATENATED-STREAM-P object DRIBBLE-STREAM DRIBBLE-STREAM-P object ECHO-STREAM ECHO-STREAM-P object FILE-STREAM FILE-STREAM-P object STRING-STREAM STRING-STREAM-P object SYNONYM-STREAM SYNONYM-STREAM-P object TERMINAL-STREAM TERMINAL-STREAM-P object TWO-WAY-STREAM TWO-WAY-STREAM-P object Table 2-3 lists functions that retrieve information from streams. You cannot use s e t f with these functions. 2-4 VAX LISP Extensions to I/O Table 2-3: Stream Informational Functions F u n c t io n C a ll R e t u r n V alue BROADCAST-STREAM-STREAMS broadcast-stream L ist of streams CONCATENATED-STREAM-STREAMS concatenated-stream L ist of streams ECHO-STREAM-INPUT-STREAM echo-stream Stream ECHO-STREAM-OUTPUT-STREAM echo-stream Stream SYNONYM-STREAM-SYMBOL synonym-stream Symbol TWO-WAY-STREAM-INPUT-STREAM two-way-stream Stream TWO-WAY-STREAM-OUTPUT-STREAM two-way-stream Stream 2.3 Additional I/O Functions VAX LISP provides several I/O functions in addition to those defined in Common LISP: The Language. Most of these functions are variations on existing Common LISP functions. This section describes the functions in alphabetical order. The optional arguments input-stream and output-stream have the defaults specified in Common LISP: The Language: • input-stream defaults to *s t a n d a r d -i n p u t *. If a value of T is supplied, the value of *t e r m i n a l -io* is used. • output-stream defaults to *s t a n d a r d -o u t p u t *. If a value of T is supplied, the value of *t e r m i n a l -io* is used. The i m m e d i a t e -OUTPUT-P predicate indicates whether an output stream does not buffer its output. The VAX LISP I/O system uses this function to improve output performance by buffering output when the stream itself does not perform buffering. Its format is: IMMEDIATE-OUTPUT-P [output-stream] The l i n e -p o s i t i o n function returns the number of characters that have been output on the current line if that number can be determined and n i l otherwise. Its format is: LINE-POSITION [output-stream] The function returns a fixnum or n i l . The LISTEN2 function returns two values instead of the one returned by the Common LISP l i s t e n function, enabling you to find out if end-of-file was encountered on the input stream. You can use this function wherever you would normally use l i s t e n . LISTEN2 [input-stream] The function returns two values: • T if a character is immediately available from input-stream and NIL otherwise. • t if end-of-file was encountered on input-stream and n i l otherwise. VAX LISP Extensions to I/O 2-5 The nread- l in e function, a destructive version of the Common LISP READ-LINE function, places the characters that were read into the string supplied as its first argument, nread- l in e returns the number of characters read, a flag indicating whether end-of-file was encountered, and a string containing the line if the line could not fit into the string supplied. The format of the nread- l in e function is: NREAD-LINE string [input-stream eof-error-p eof-value-p recursive-p] The string argument is a character string, nread- l in e updates string with the line that was read. If string has a fill pointer, the fill pointer is adjusted so that string appears to contain exactly what was read from the stream. If string is adjustable and the size of the line exceeds the size of string, then string is extended. Since nread- l in e does not return string, you mu3t maintain a pointer to string. The optional arguments correspond to the arguments to read -LINE documented in Common LISP: The Language. The nread- l in e function returns three values: • A fixnum indicating the number of characters that were in the line. • T i f the line w a s term in ated by end-of-file and n il otherwise. • n il if the line fit into string: otherwise a string containing the line. The open - stream - p predicate indicates whether a stream is open. This function takes one argument, which must be a stream. The r ig h t -margin function returns the default right margin used by the pretty printer when printing to the stream. The current margin used by the pretty printer is controlled by the variable *p r in t - r ig h t -margin *. Its format is: RIGHT-MARGIN [output-stream] The function returns a nonnegative fixnum. 2-6 VAX LISP Extensions to I/O Chapter 3 Window Streams VAX LISP lets you create a stream that can receive typed input from a window and send character output to a window. This type of stream is called a window stream and has the following characteristics: • By default, it is a valid target for all Common LISP and VAX LISP input and output functions that operate on character streams. (You can restrict window streams to output operations when you create them.) • Output to the stream appears in the window. • Input from the stream is taken from the keyboard and echoed in the window. A cursor marks the place where the next input character will be echoed. • You can specify the font to be used for output and echoing to the stream. • For output-only streams, you can specify whether to wrap, scroll, or truncate overflow from the bottom of the window. • You can specify whether to wrap or truncate output beyond the right edge of the window. • You can edit input. • You can recall, edit, and reenter previous input. This chapter describes the window stream facility in the following sections: • Section 3.1 explains how to create window streams and describes their characteristics in detail. • Section 3.2 describes input from window streams and shows how to edit typed input. • Section 3.3 describes output to window streams. • Section 3.4 lists window stream features and restrictions with each window system that supports them. (For this release, the supporting window systems are VMS Workstation Software and DECwindows.) • Section 3.5 contains reference information on the window stream functions and macros. Window Streams 3-1 3.1 Creating and Changing Window Streams The m a k e -w i n d o w -s t r e a m function creates and returns a window stream. The single required argument is a window. Keyword arguments let you specify a number of characteristics. You can also create a window stream, using the w i t h -w i n d o w -s t r e a m macro. This macro creates a window stream and binds it to a variable while the body of the macro executes. When the body returns, the stream is closed. The keyword arguments taken by m a k e -w i n d o w -s t r e a m are used to specify the characteristics of the stream created by w i t h -w i n d o w -s t r e a m . The following sections describe the characteristics of window streams and ways to change these characteristics. 3.1.1 Validity for Input Operations By default, a window stream is a valid target for input and output operations. You can use the :DOES-i n p u t -p keyword with a value of n i l to make the window stream an output-only stream. Input operations on such a stream cause an error. You can use the Common LISP i n p u t -s t r e a m -p function to determine whether a window stream is valid for input operations. 3.1.2 Viewing Area A window stream’ s viewing area is the portion of the window in which windowstream output or echoing of its input appears. By default, this area is the entire window. You can use the :v i e w i n g -a r e a keyword to specify a viewing area that is smaller than the entire window, although the viewing area must be large enough to contain at least one complete text character. When the viewing area is smaller than the window, output or echoing never appears outside the viewing area. The value of the :v i e w i n g -a r e a keyword is a list of four numbers. These numbers define a rectangle in the window’ s coordinate system. The format of the list is: (xmin ymin xmax ymax) where min and max refer to numeric values, not to spatial relationships in the window. Since windows in different window systems have different coordinate systems, specifying a viewing area necessarily introduces a dependence on the window system being used. You can modify the size of the viewing area and you can also modify its contents in several ways besides input from or output to the window stream. 3.1.2.1 Viewing Area Coordinate Systems Every viewing area has two coordinate systems. One coordinate system is the native coordinate system; that is, the coordinate system used by the supporting window system. The units and origin of the native coordinate system depend on the window system. For example, you can create a window stream with a viewing area as follows: (setq *ws* (window-streamrmake-window-stream *win* :viewing-area '(100 100 200 200))) The native coordinate system of this viewing area extends from 100,100 at one comer to 200,200 at the other. 3-2 Window Streams The other coordinate system is the character-cell coordinate system. The character-cell coordinate system is independent of the window system. In the character-cell coordinate system, the viewing area is divided into character cells, each the width and height of a character. The character cell at the upper-left comer of the viewing area is 1,1, with coordinate values increasing to the right and down. Character-cell coordinate values are always positive fixnums. The dimensions and placement of the character-cell coordinate system inside the viewing area are influenced by several factors: • The font. The size of characters in the font determines the size of each char acter cell. Changing the font used by the window stream (see Section 3.1.4) may also change the dimensions of the character cells. • The relationship of the viewing area’ s size to the character cell’ s size. If the width and height of the viewing area are not exactly divisible by the width and height of a character cell, there is space at the right and bottom of the viewing area where no characters can be written. • The position of the cursor when the character-cell coordinate system is established or altered. Figure 3-1 shows this effect. 3.1.2.2 Obtaining Viewing Area Dimensions You can obtain the dimensions of the viewing area in either native coordinates or character-cell coordinates. The v i e w i n g -a r e a -h e i g h t and v i e w i n g -a r e a -w i d t h functions return the height and width in native coordinate units. The v i e w i n g a r e a -h e i g h t -c e l l and v i e w i n g -a r e a -w i d t h -c e l l functions return the height and width in chararacter-cell units. The w i n d o w -s t r e a m -v i e w i n g -a r e a function returns the list of native-coordinate values that defines the viewing area. This function always returns a list of numbers, even if the viewing area was created using NIL to specify the entire window. 3.1.2.3 Changing Viewing Area Dimensions You can use the w i n d o w -s t r e a m -v i e w i n g -a r e a function with the s e t f macro to specify a new viewing area for a window stream. Use the same values as when creating the window stream; that is, a list of four numbers or n i l to specify the entire window. You always use native coordinates to specify a new viewing area. Changing the viewing area positions the cursor to the upper-left corner of the new viewing area. The character-cell coordinate system is automatically realigned to the new viewing area. It is an error to make the viewing area so small that it cannot contain at least one character cell. 3.1.2.4 Erasing Viewing Area Contents Use the e r a s e -v i e w i n g -a r e a function to erase the contents of a window stream’ s viewing area. Erasing the viewing area repositions the cursor to the upper-left comer of the viewing area. Window Streams 3-3 3.1.2.5 Scrolling Viewing Area Contents Use the s c r o l l -v i e w i n g -a r e a and s c r o l l -v i e w i n g -a r e a -c e l l functions to scroll the contents of the viewing area horizontally or vertically, s c r o l l -v i e w i n g -a r e a scrolls by native-coordinate units, while s c r o l l -v i e w i n g -a r e a -c e l l scrolls by character cells. Without optional arguments, these functions scroll the viewing area contents up one native-coordinate unit or one line: (window-stream:scroll-viewing-area-cell *ws*) You can supply two optional arguments. The first argument specifies horizontal motion, with positive values moving viewing area contents to the left. The second argument specifies vertical motion, with positive values moving viewing area contents up. The following example moves the contents of *ws*’ s viewing area five characters to the left and down three lines: (window-stream:scroll-viewing-area-cell wc-stream 5 -3) The SCROLL-VIEWING-AREA and SCROLL-VIEWING-AREA-CELL functions may per form vertical and horizontal scrolling separately when both are specified. This assures correct results in the viewing area. Text that disappears as a result of scrolling cannot be recovered by scrolling in the opposite direction. Once it disappears from the viewing area, it is gone. Scrolling moves everything within the viewing area, not just text that results from operations on the window stream. 3.1.3 Vertical and Horizontal Overflow By default, a window stream scrolls when the output position goes past the bottom of the viewing area. That is, everything in the viewing area moves up; whatever was at the top of the viewing area disappears and is lost. The new output appears at the bottom of the viewing area. Unless you specify :DOESi n p u t -p n i l when you create the stream, this is the only available way to treat vertical overflow. Window streams that are restricted to output allow more flexible treatment of vertical overflow. With the :WRAP value for :v e r t i c a l -o v e r f l o w , you can specify that output is to wrap around to the top of the viewing area, overwriting what was there before. :t r u n c a t e discards output that would be off the bottom of the viewing area. By default, output that would go past the right edge of the viewing area is wrapped to the next line. You can change this by specifying :t r u n c a t e with the :h o r i z o n t a l -o v e r f l o w keyword. Excess output is then discarded until a #\ n e w l i n e character is encountered. You can change the horizontal and vertical overflow behaviors after the window stream has been created. Use the s e t f macro with the w i n d o w -s t r e a m -v e r t i c a l o v e r f l o w and w i n d o w -s t r e a m -h o r i z o n t a l -o v e r f l o w functions. However, for window streams capable of input, values other than : s c r o l l for w i n d o w -s t r e a m v e r t i c a l -o v e r f l o w produce an error. 3-4 Window Streams 3.1.4 Font When you create a window stream, you can use the :FONT keyword to specify a font. The value you supply for this keyword depends on the supporting window system. See Section 3.4 for information that depends on the window system. You must specify a fixed-width font in a window stream. If you specify a variablewidth font, the results are unpredictable. Specifying a font has two effects: • It establishes the appearance of output and echoing characters on the screen. • It establishes the dimensions and location of the character-cell coordinate system that is superimposed on the viewing area. You can use the w i n d o w -s t r e a m -f o n t function with the s e t f macro to change a window stream’ s font. If the character-cell size of the new font is different, the upper-left comer of the first character in the new font will be at the same place that the upper-left corner of a character in the old font would have occupied. If you change the font when the cursor is in the middle of the viewing area, the new character-cell coordinate system may not align with the left edge of the viewing area. As a result, text using the new font also will not align at its left margin with previously output text. Figure 3—1 shows this effect in a CLX-based window. Figure 3-1: Text Misalignment As a Result of Changing Fonts These lines are in a small font. These lines are in a sma 11 font. These lines are in a small font. These lines ar e in a small f o n t . These lines are in a small f o n t . Thes e lines are in a small f°n t.lJ l| ^ 0 g 0 Ü I 1 0 S cLZ? e in a large font. These ines are in a large font. These lines are in a large font. These lines are in a large font. MLO-003303 If changing to a larger font causes the viewing area to be too small for at least one complete character cell, an error results. Window Streams 3-5 3.1.5 Cursor Position A window stream’ s cursor indicates the position of the next input character in the window. You can determine the position of the cursor and change its position in the viewing area. The cursor does not appear when a window stream is not capable of input. However, you can still obtain and change the cursor position for such streams. Cursor position can be expressed in two ways: as a native-coordinate position or as a cell-coordinate position. A native-coordinate cursor position is expressed in native-coordinate units. It is always the cursor’ s position in the window, even when the stream operates in a viewing area that is smaller than the window. The cell-coordinate cursor position is always relative to the viewing area. In window systems where the distinction is meaningful, the native-coordinate cursor position corresponds to the upper-left corner of the cell-coordinate cursor position. The following accessor functions return the X or Y component of the cursor position: WINDOW-STREAM-X-POSITION WINDOW-STREAM—X-POSITION-CELL WINDOW-STREAM-Y-POSITION WINDOW-STREAM-Y-POSITION-CELL You can use the s e t f macro with each of these functions to change a window stream’ s cursor position. When you change the native-coordinate cursor position, the position you specify may not align properly with the viewing area’ s character-cell coordinate system. For example, the new native-coordinate cursor position could be in the middle of one of the old character cells. When this happens, the character-cell coordinate system is reset to align with the native-coordinate cursor position you specify. This may result in space at the top and left edges of the viewing area that is not occupied by character cells. It is an error to attempt to move the cursor position outside the viewing area. It is also an error to specify a native-coordinate cursor position that results in the viewing area no longer containing at least one complete character cell. 3.1.6 Input History Limit Each window stream that performs input operations maintains a history of the input that has been typed to it. You can recall previous input to edit and reenter. The units of input in the history may be lines terminated by the Return key, or they may be complete input forms whose syntax is determined by a parser. Section 3.2.2 describes input recall and the scope of units of input. The default number of input units maintained by the input history is 100. When you create a window stream, you can specify this number by using the : i n p u t h i s t o r y -l i m i t keyword. After a window stream has been created, you can change this number by using the s e t f macro with the w i n d o w -s t r e a m -i n p u t h i s t o r y -l i m i t function. A value of n i l specifies no limit. If you specify 0, no input history is maintained. 3-6 Window Streams 3.1.7 Window Exposure and Keyboard Connection By default, calling an input function on a window stream makes the associated window visible and connects the keyboard to the window. Calling an output function on a window stream does not affect the associated window’ s visibility. To make the window visible, the stream takes whatever action is appropriate under a particular window system. This may include bringing the window to the front of the screen, expanding it from an icon, or retrieving it from off-screen storage. When you create a window stream, you can use the : show-on keyword to specify when its window becomes visible and when the keyboard is connected to it. The : show- on keyword takes the following values: • : input req u ests the default behavior. • : io makes the window visible and tries to connect the keyboard when an input function is called; it makes the window visible when an output function is called. • : OUTPUT req u ests that the w indow be m ade v isible for output, bu t not for input. • n il k eep s w indow visibility and k eyboard conn ection from b e in g affected for eith er in p u t or output. The window- stream - show- on function returns the current setting of this value for a window stream. You can change the setting after you have created a window stream by using the setf macro with window- stream - show- on . 3.2 Input from a Window Stream Input from a window stream is the same as input from any stream defined by Common LISP, with the following additions: • Input characters are echoed in the window stream ’ s viewing area. • You can edit the input after you have typed it and before it is read by the input function. • The stream maintains a history of units of input. You can recall, edit, and reenter these input units later. Section 3.2.1 describes input editing. Section 3.2.2 describes input recall. 3.2.1 Input Editing When you type text as input to a window stream, certain keys and key sequences are bound to input editing commands. The commands reposition the cursor, delete units of text, or recall previously entered text. As you enter text or editing commands, the window stream’ s viewing area is updated to reflect the current input. The cursor shows where new characters will be inserted. Input editing is described in the following subsections: • Section 3.2.1.1 describes input editing without the w it h - in p u t - e d it in g macro. In this mode, the Return key delimits units of input. • Section 3.2.1.2 describes input editing with the w i t h - i n p u t -e d i t i n g macro. In this mode, units of input are determined by code in the body of the macro. Window Streams 3-7 Section 3.2.1.3 describes options to the w i t h - i n p u t -e d i t i n g macro. Section 3.2.1.4 lists the editing commands and their key bindings. 3.2.1.1 Editing Without WITH-INPUT-EDITING When an input function that is not enclosed by the w i t h - i n p u t -e d i t i n g macro reads from a window stream, you can edit your typed input until you press the Return key. When you press the Return key, all your input is made available to the input function. Your input is also added to the stream ’ s input history. Even though the Return key ends your input, the input may occupy more than one line in the window as a result of: • Text wrapping at the right edge of the viewing area • The insertion of a #\ n e w l i n e character with Ctrl/J or Ctrl/O An input line that wraps is considered a single line; that is, it does not contain a #\n e w l i n e character. On the other hand, input that breaks because you type Ctrl/J or Ctrl/O does contain embedded #\n e w l i n e characters, which delimit logical lines within the input. The distinction is important because you can use the up-arrow key to move the cursor to preceding logical lines, but not to text on the same, wrapped line. (However, you can move over line-wrap breaks with the left-arrow and right-arrow keys.) 3.2.1.2 Using the WITH-INPUT-EDITING Macro The w i t h -i n p u t -e d i t i n g macro lets you enter, edit, and recall units of text that are not unconditionally terminated when you press the Return key. Instead, forms in the body of the macro determine when the input unit is complete. As long as the body of the macro is still consuming input, you can edit anywhere in the input. When the last form in the body returns, all the text that was consumed by the body is added to the stream’ s input history as a single unit. The chief advantage of the w i t h - i n p u t -e d i t i n g macro is that you can specify the syntactic content of an input unit by the code in the body of the macro. Typically, this code reads characters from the stream and parses them. As soon as the input satisfies the syntactic requirements of the code in the body, the body returns. The r e a d function is an example of a parser that reads characters from a stream and does not return until it has parsed a syntactically complete unit. For the r e a d function, the unit of input is a LISP form. The following example reads complete LISP forms from the window stream *ws*: (window-stream:with-input-editing (*ws*) (read *ws*)) If you type to the stream *ws* while the r e a d function in the example is taking input, you can break your input lines with the Return key. The r e a d function does not return until you have entered a complete LISP form, followed by Return. The r e a d function then returns the LISP object it has read, and this value is the return value of the w i t h -i n p u t -e d i t i n g form. If you notice an error in a line that you have already typed while you are typing the LISP form, you can use the up-arrow key to move the cursor to a previous line, then edit within the line. You can edit all your input until you have entered a complete form. If you later recall your input, you will recall the entire LISP form that you typed, not just individual lines. 3-8 Window Streams You can write your own parser in the body of a w i t h - i n p u t -e d i t i n g macro. Example 3—1 shows a parser that reads a specified number of words from a specified window stream and returns a list of these words. For the purposes of this example, a word consists of contiguous nonwhitespace characters, where the whitespace characters are #\s p a c e and #\n e w l i n e . Example 3-1: Using the WITH-INPUT-EDITING Macro (defun read-n-words (stream n) (let ((str (make-array 40 :element-type 'string-char :adjustable t :fill-pointer t)) (whitespace ' (#\space #\newline))) ; Define whitespace (window-stream:with-input-editing (stream) (do ((word-list '()) ; Initialize list (c) ; Input characters (word-count 0 (1+ word-count))) ((= word-count n) (nreverse word-list)) ; Stop after N words (setf (fill-pointer str) 0) (loop ; Find non-whitespace (unless (member (setq c (read-char stream)) whitespace :test #'char=) (return))) (loop ; Form word (vector-push-extend c str) (when (member (setq c (read-char stream)) whitespace :test #'char=) (return))) (push (copy-seq str) word-list))))) ; Add word to list If you write your own parser, it should not perform output or other side effects during execution. (In particular, it should not perform output to the window stream, as this will disrupt the echoed input.) To understand why, it is necessary to understand how the w i t h - i n p u t -e d i t i n g macro operates. Calling an input function on a window stream invokes an input editor. The input editor takes characters from the keyboard and places them in an editing buffer, echoing them as it does so. The input editor responds to certain characters, keys, or sequences by editing within the editing buffer and displaying the edited buffer in the window. The input editor does not pass the characters in the editing buffer to the input function until a terminating character is typed. By default, the terminating character is #\r e t u r n . If w i t h -i n p u t -e d i t i n g has not been used, typing Return passes the contents of the editing buffer to the input function, adds the input to the input history, and terminates the input editor. However, if the input function is in a w i t h i n p u t -e d i t i n g macro, Return passes the contents of the editing buffer to the input function but does not add the input to the input history or terminate the input editor. Instead, if the input function exhausts the editing buffer and still wants more characters, the input editor again takes characters from the keyboard and places them in the editing buffer. This cycle continues until the body of the w i t h - i n p u t -e d i t i n g macro returns. Window Streams 3-9 While typing input, the user can move the cursor to previous lines and edit them. But those lines have already been consumed by the input function; editing them invalidates the processing performed so far by the body. Therefore, when previous lines are edited, the w ith - in pu t - e d it in g macro reexecutes its entire body, using the edited text typed thus far as input. This process is called rescanning. Because the body of a w ith - in pu t - e d it in g macro may be executed more than once, it should not perform output or other side effects as it executes. Output or side effects would occur each time the input was rescanned. Instead, the body of a w ith - in pu t - e d it in g macro should build a data structure as it parses the input characters, then return that data structure when the parse completes. The body must initialize the data structure, since it must build the data structure from the beginning each time rescanning occurs. In Example 3—1, the body of the w ith - in pu t - e d it in g macro consists of a single do macro. The DO macro initializes the list word- l i s t each time it executes. When the do terminates, indicating a successful parse, it returns word- l i s t as its value. 3.2.1.3 Using Options to WITH-INPUT-EDITING w ith - in pu t - e d it in g takes a number of options. You specify these options as keyword-value pairs following the window-stream, argument. The options let you: • Specify a prompt for input. • Specify which characters are considered terminators. • Specify whether input should be rescanned if previous lines are edited. The :prompt option lets you specify a string that is printed in the viewing area before input is echoed. For example, you could change Example 3-1 to read in part: (window-stream:with-input-editing (stream :prompt (format nil "type ~d words: " n)) The :terminators option lets you supply a list of terminating characters. When the input editor encounters a terminating character, it passes the contents of its editing buffer to the input function. By default, the only terminating character is #\RETURN. You may want to specify other characters as terminators. For example, when reading LISP forms you may want the right-parenthesis character to be a terminating character. That way, the rea d function can examine the input at every right-parenthesis, instead of waiting for Return. For example: (window-stream:with-input-editing (*ws* :terminators ' (#\return #\))) (read *ws*)) This form reads from stream *ws*. Typing the final right-parenthesis character of a LISP form immediately causes the read function to return. #\return remains a terminating character. In Example 3-1, in the second lo o p macro, you might want to have input passed to the re a d - ch a r function as soon as a whitespace character is typed, instead of waiting for Return. You could change Example 3—1 to read in part: (window-stream:with-input-editing (stream :terminators (cons #\return whitespace)) 3-10 Window Streams Note that you must specify #\r e t u r n as a terminator if you want the Return key to signal termination. The input editor receives a #\ r e t u r n character from the keyboard, even though the input function reading from the stream receives a #\NEWLINE. Do not specify NIL as the value of : t e r m i n a t o r s .If you do not specify terminating characters, the input editor can never return. The :r e s c a n option lets you specify whether your input should be subject to rescanning. The default value for this option is T. Specifying n i l defeats much of the purpose of the w i t h -i n p u t -e d i t i n g macro. You can no longer edit lines already consumed by the body, and the input units retained by the input history are lines instead of complete forms. In other words, specifying : r e s c a n n i l is much like reading from a window stream without using w i t h -i n p u t -e d i t i n g .You can, however, use the other options to w i t h -i n p u t -e d i t i n g to specify a prompt or a set of terminating characters. 3.2.1.4 Window Stream Editing Commands and Key Bindings In general, keys and key sequences that perform editing operations are bound as in the EMACS editor. Table 3-1 lists the editing commands and the keys bound to them. Table 3-1 also includes keys such as Ctrl/S and Ctrl/Q that are not editing keys, but that have the effect described when the keyboard is connected to the window associated with the window stream. The “ logical line”referred to in Table 3-1 is delimited by a #\ n e w l i n e character. A logical line can span more than one line in the viewing area as a result of line wrapping. An input unit can contain more than one logical line, either as a result of Ctrl/J or Ctrl/O or because the input is being read using w i t h - i n p u t -e d i t i n g . If you use the b i n d -k e y b o a r d -f u n c t i o n function to bind a control key, this binding overrides any editing binding for that key. For example, if you bind Ctrl/E to invoke the VAX LISP Editor, typing Ctrl/E during input to a window stream invokes the Editor, rather than moving the window stream cursor to the end of a line. The only control key bound by default, Ctrl/C, retains its binding when you are typ ing input to a window stream. That is, it clears the input and calls the condition system a b o r t function. You can use b i n d -k e y b o a r d -f u n c t i o n to override this binding. NOTE The default behavior of Ctrl/C has changed in Version 3.0. The previous default was to call the c l e a r - i n p u t function on *t e r m i n a l -i o * and throw to the current c a n c e l -c h a r a c t e r -t a g . Keypad keys 0 through 9, period (.), comma (,), and minus sign (—) insert those characters at the cursor position. Generate an Escape key by typing the combination Ctrl/[. A letter following an Escape key may be either uppercase or lowercase. Window Streams 3-11 Table 3-1: Window Stream Editing Commands and Key Bindings B in d in g N am e D e s c r ip t io n C u rso r M ovem en t C om m an d s Move Forward Character 1 Ctrl/F | Moves cursor forward one character | Moves cursor backward one character or FH Move Backward Character | Ctri/B or F F Move Forward Word | E sca p e 11f | Moves cursor forward one word Move Backward Word | E sca p e || b | Moves cursor backward one word Move to End o f Line | Ctrl/E | Moves cursor to end o f logical line Move to Beginning o f Line I Ctrl/A | Moves cursor to beginning o f logical line Move to Next Line 1 Ctrl/N I Moves cursor to next logical line o f current input unit (down arrow recalls previously recalled input unit if you are not currently editing an input unit) or m Move to Previous Line | Ctrl/P | or Moves cursor to previous logical line o f current input unit (up arrow recalls previous input unit if you are not currently editing an input unit) m Move to End o f Input | E sca p e 11> | Moves cursor to end o f current input unit Move to B eginning of Input | E sca p e 11 < | Moves cursor to beginning o f current input unit T ex t D e le t io n C o m m a n d s Delete Next Character | Ctrl/D | Deletes the character at the cursor position Delete Previous Character <3 or Deletes the character preceding the cursor position | Ctrl/H | or p iT | Delete Forward Word | E sca p e 11d | Delete Backward Word | E sca p e 11 h | or | E sca p e Deletes from the cursor position through the next end o f word Deletes from the character preceding the cursor position back to the preceding beginning o f word | Delete to End o f Line I Ctrl/K | Deletes from the cursor position to the end o f the logical line Delete to Beginning o f Line [ E s c a p e || k | Deletes from the cursor position to the beginning o f the logical line Clear Input | Ctrl/G | Deletes all input currently being entered or edited (continued on next page) 3-12 Window Streams Table 3-1 (Cont.): Window Stream Editing Commands and Key Bindings N am e B in d in g D e s c r ip t io n L in e B r e a k in g a n d In p u t T e rm in a tio n | ctri/J | Insert Newline Inserts new line, m oving cursor to beginning o f new line; does not term inate input editor or FISI Open Current Line Here Insert Newline at End and Terminate I ctri/o | | R e tu rn Inserts new line, leaving cursor at end o f current line; does not term inate input editor | Inserts new line at end of input unit and terminates input editor (unless WITH-INPOT-EDITING is used, in which case input editor may not terminate); cursor is at beginning o f new line or | ciri/M | In p u t R e c a ll Recall Previous Input m When you are not entering or editing text, recalls previ ous input units Recall Previously Recalled Input Q j When recalling input units, recalls the unit following the one currently displayed M isc e lla n e o u s Escape Generates an escape prefix rw i or CED Insert C lose Parenthesis and Match Inserts a close parenthesis and highlights the correspond ing open parenthesis, if one exists m Insert M ultiple Spaces Inserts m ultiple spaces at the cursor position and passes m ultiple spaces to the input function: does not pass a #\ TAB character to the input function Describe LISP Function | C trl/? Refresh Input 1 Ctrl/L I Clear Viewing Area | E sca p e 1 H elp on Input Editor | E sca p e || ? 3.2.2 D escribes the current LISP function | Refreshes input, including the prom pt if any; forces input editor to recalculate view ing area dim ensions 1Ctrl/L | | Clears the viewing area associated with the window stream Prints a list o f input editor key bindings Recalling Input You can recall input units that were previously entered to a window stream. Tb do so, you either must not have entered anything to the current input request, or you must clear what you have entered with Ctrl/G. You can then recall previous input units by pressing the up-arrow key. After you have pressed the up-arrow key, you can recall subsequent input units with the down-arrow key. When you reach an input unit that you want to reenter, either press Return to reenter it as is, or edit it before reentering it. Once you have started to edit an input unit, you cannot use the up-arrow or down-arrow keys to move to other input units unless you clear the current input with Ctrl/G. You can recall all the input units that were previously entered to a window stream, up to the limit set when the stream was created. The recall buffer is circular; that is, an attempt to recall the input unit preceding the oldest one recalls the input unit most recently entered. Window Streams 3-13 3.3 Output to a Window Stream Output to a window stream is the same as output to any other Common LISP stream. By default, calling an output function on a window stream does not make the stream’ s associated window visible. See Section 3.1.7 for information on changing this behavior. 3.4 Window System Dependencies This section describes aspects of window streams that depend on the window system in use. Each major subsection covers one window system on which the window stream facility is implemented. Within each subsection, the following system-dependent items are described: • Native coordinate system • Fonts and font specification Other window system dependencies, if any, are described following these two. 3.4.1 VMS Workstation Software This section covers the window stream facility running on a VAXstation using the VMS Workstation Software, also known as UIS. 3.4.1.1 Native Coordinate System The native coordinate system is the window’ s device coordinate system. Native coordinate values must be fixnums. The origin is at the lower left comer. 3.4.1.2 Fonts and Font Specification The default font is the font specified by attribute block 0. You can specify a font in the same way as with the u i s : s e t -a t t r i b u t e function. 3.4.1.3 Multiple Stream Restriction You can create multiple window streams to the same window, but only one can perform input. All other streams associated with the window must specify :DOES-INPUT-P NIL. 3.4.1.4 Virtual Keyboard Use Window streams use virtual keyboards to get input from a window. When you create a window stream that performs input, any previous association between the window and a virtual keyboard is broken. After you create a window stream, you must not associate another virtual keyboard with the window, or the associa tion between the window and the virtual keyboard that feeds the stream will be broken. The UIS:w i n d o w -s t r e a m -kb function returns the virtual keyboard used by a window stream that performs input. You cannot use the s e t f macro with this function. Do not attempt to specify a new interrupt function for a virtual keyboard used by a window stream. 3-14 Window Streams 3.4.1.5 Using Attribute Blocks Each window stream requires the use of two dedicated attribute blocks. A window stream always uses attribute block 255, and all window streams associated with windows into a single display can share attribute block 255. The other attribute block required by a window stream stores the font and, therefore, cannot be shared among streams. The first window stream associated with a window into a particular virtual display uses attribute block 254. The second stream uses attribute block 253, and so on. To summarize: Window streams require dedicated attribute blocks and they take the highest-numbered blocks in each virtual display. The highest-numbered attribute block available is 254 minus the number of window streams associated with windows into that virtual display. Do not modify the contents of either attribute block. Results may be unpredictable. The u i s :w i n d o w -s t r e a m -a t t r i b u t e -b l o c k function returns the variable attribute block used by a window stream (that is, the one that is not attribute block 255). You cannot use the s e t f macro with this function. 3.4.1.6 Resizing Windows If the user resizes a window associated with a window stream, the window stream facility does not automatically resize the viewing area for streams associated with that window. You can specify an interrupt function that resizes the viewing area or takes other appropriate action by using the u i s : s e t -r e s i z e -a c t i o n function. You can also prevent the user from resizing the window by using a value of :DISALLOW with UIS:SET-RESIZE-ACTION. 3.4.2 DECwindows This section covers the window stream facility running on a VAXstation using DECwindows and implemented in Common LISP X (CLX). 3.4.2.1 Native Coordinate System The native coordinate system in CLX is pixel coordinates with the origin at the upper-left corner. CLX does not provide world coordinates. 3.4.2.2 Fonts and Font Specification The default font is Courierl4Bold, the same as in the LISP Listener. The font is determined by the :GCONTEXT slot of the window stream structure. You can specify a value for this slot when you create a window stream or use the default value. However, changing the graphics context of an existing window stream does not affect the window stream font. You can change the window stream font only by using s e t f on the w i n d o w -s t r e a m :WINDOW-s t r e a m -f o n t function. The window stream has to know that font has changed so that it can do output. 3.4.2.3 Multiple Stream Restriction You can create multiple window streams to the same window, but only one can perform input. All other streams associated with the window must specify :DOES-INPUT-P NIL. In addition, only one window in a tree can perform input. Window Stream s 3-15 3.4.2.4 Using Graphics Contexts There is one graphics context per window stream, used for all text output opera tions to that window stream. The CLX: w i n d o w - s t r e a m -g c o n t e x t function returns the graphics context used by a window stream. You cannot use the SETF macro with this function. With the exception of the font slot, you can modify components of a window stream’ s graphics context. For example, the following code is “ legal”and will make the text blue: (let ((gc (window-stream:window-stream-gcontext v i s ) ) ) (setf (clx:gcontext-foreground gc) "blue") (format ws "Am I blue?")) 3.4.2.5 Resizing Windows If the user resizes a window associated with a window stream, the window stream facility does not automatically resize the viewing area for streams associated with that window. 3.4.2.6 Repainting Windows CLX-based windows do not automatically repaint themselves after they have been obscured. It is advisable to draw to an image or drawable and copy from there, rather than drawing directly to a window. 3.5 Window Stream Functions and Macros This section contains reference descriptions of all the functions and macros exported from the w i n d o w -s t r e a m : package. 3-16 Window Streams ERASE-VIEWING-AREA Function ERASE-VIEWING-AREA Function Erases the viewing area of a window stream, repositioning the cursor to the upper-left corner. See Chapter 4 for more information on using this function. Format WINDOW-STREAM:ERASE-VIEWING-AREA window-stream Arguments window-stream A window stream. Return Value Undefined. MAKE-WINDOW-STREAM Function Creates and returns a window stream. Keywords control the characteristics of the stream. Format WINDOW-STREAM:MAKE-WINDOW-STREAM w indow &KEY :DOES-INPUT-P :FONT :HORIZONTAL-OVERFLOW :INPUT-HISTORY-LIMIT :SHOW-ON :VERTICAL-OVERFLOW :VIEWING-AREA Arguments window A window. :DOES-INPUT-P t (the default) or n il , in dicatin g w h eth er th is stream is a valid ta rget for input fun ction calls. :FONT A font specification; the default and format depend on the window system in use. At least one complete character cell in the specified font must fit into the specified viewing area. :HORIZONTAL-OVERFLOW Either :WRAP (the default) or : truncate . Window Streams 3-17 MAKE-WINDOW-STREAM Function :INPUT-HISTORY-LIMIT A nonnegative fixnum, specifying the number of input units maintained by the window stream ’ s input history; or n i l , indicating no limit on the number of input units. A value of 0 requests that no input history be kept. The default is 100. :SHOW-ON A value indicating, for both input and output, whether windows should be made visible and (for input) whether the keyboard should be connected to the window: :INPUT m akes the window visible (and connects the keyboard) for input only. This is the default. :10 makes the window visible on input and output and connects the keyboard for input. :OUTPUT makes the window visible for output only. NIL prevents the window from being made visible (and the keyboard from connect ing) for both input and output. :VERTICAL-OVERFLOW : s c r o l l (the default), iWRAP, or :t r u n c a t e . Unless you specify .-d o e s - i n p u t -p : s c r o l l or an error results. n i l , the value of :v e r t i c a l -o v e r f l o w must be :VIEWING-AREA Either n i l , indicating that the viewing area should occupy the entire window, or a list of native-coordinate values in the form: (xmin ymin xmax ymax) n i l is the default. character cell. The viewing area must be able to contain at least one complete Return Value A window stream. SCROLL-VIEWING-AREA Function Moves the contents in the viewing area of a window stream by native-coordinate units. The contents can be moved horizontally, vertically, or both. Contents that scroll off the edge of the viewing area are lost and cannot be recovered by scrolling in the opposite direction. Calling this function without optional arguments scrolls up the contents of the viewing area by one native-coordinate unit. Format WINDOW-STREAM:SCROLL-VIEWING-AREA window-stream &OPTIONAL x y 3-18 W indow Stream s SCROLL-VIEWING-AREA Function Arguments window-stream A window stream. x A number specifying how many native-coordinate units to scroll horizontally. Positive values move viewing area contents to the left. The default is 0. y A number specifying how many native-coordinate units to scroll vertically. Positive values move up the viewing area contents. The default is 1. Return Value Undefined. SCROLL-VIEWING-AREA-CELL Function Moves the contents in the viewing area of a window stream by cell-coordinate units. Contents can be moved horizontally, vertically, or both. Contents that scroll off the edge of the viewing area are lost and cannot be recovered by scrolling in the opposite direction. Calling this function without optional arguments scrolls up the contents of the viewing area by one line. Format WINDOW-STREAM:SCROLL-VIEWING-AREA-CELL window-stream &OPTIONAL x y Arguments window-stream A window stream. x A fixnum specifying how many cell-coordinate units to scroll horizontally. Positive values move viewing area contents to the left. The default is 0. y A fixnum specifying how many cell-coordinate units (lines) to scroll vertically. Positive values move up the viewing area contents. The default is 1. Window Streams 3-19 SCROLL-VIEWING-AREA-CELL Function Return Value Undefined. VIEWING-AREA-HEIGHT Function Returns the height of a window stream’ s viewing area in native-coordinate units. You cannot use the s e t f macro with this function. Use the w i n d o w -s t r e a m v i e w i n g -a r e a function to change the size of the viewing area. Format WINDOW-STREAM:VIEWING-AREA-HEIGHT window-stream Arguments window-stream A window stream. Return Value A number. VIEWING-AREA-HEIGHT-CELL Function Returns the height of a window stream’ s viewing area in character-cell units. You cannot use the setf macro with this function. Use the WINDOW-STREAM-VIEWINGarea function to change the size of the viewing area. Format WINDOW-STREAM:VIEWING-AREA-HEIGHT-CELL w indow-stream Arguments window-stream A window stream. Return Value A fixnum. 3-20 Window Stream s VIEWING-AREA-WIDTH Function VIEWING-AREA-WIDTH Function Returns the width of a window stream ’ s viewing area in native-coordinate units. You cannot use the s e t f macro with this function. Use the w i n d o w -s t r e a m v i e w i n g -a r e a function to change the size of the viewing area. Format WINDOW-STREAM:VIEWING-AREA-WIDTH window-stream Arguments window-stream A window stream. Return Value A number. VIEWING-AREA-WIDTH-CELL Function Returns the width of a window stream’ s viewing area in character-cell units. You cannot use the s e t f macro with this function. Use the w i n d o w -s t r e a m -v i e w i n g a r e a function to change the size of the viewing area. Format WINDOW-STREAM:VIEWING-AREA-WIDTH-CELL window-stream Arguments window-stream A window stream. Return Value A fixnum. Window Streams 3-21 WINDOW-STREAM Type Specifier WINDOW-STREAM Type Specifier Designates objects of type w i n d o w -s t r e a m created by the m a k e -w i n d o w -s t r e a m function. Format WINDOW-STREAM: WINDOW-STREAM Arguments None. Return Value None. WINDOW-STREAM-ATTRIBUTE-BLOCK Function See the description of u i s :w i n d o w -s t r e a m -a t t r i b u t e -b l o c k in Part II of VAX LISP/VMS Interface to VWS Graphics. WINDOW-STREAM-FONT Function Returns a window system-dependent value indicating the font used by a window stream. You can use the macro with this function to change the font. If the size of the new fon t is different, the viewing area’ s character-cell coordinate system is realigned; the upper-left comer of the first character output in the new font is placed at the native-coordinate cursor position. If changing to a larger font causes the viewing area to be too small for a complete character cell, an error results. s e t f See Sections 3.1.4 and 3.4.2.2 for information on using this function. Format WINDOW-STREAM:WINDOW-STREAM-FONT window-stream Arguments window-stream A window stream. 3-22 Window Stream s WINDOW-STREAM-FONT Function Return Value Depends on the window system in use. WINDOW-STREAM-GCONTEXT Function See the description of CLX: w i n d o w -s t r e a m -g c o n t e x t in Part IV of DECwindows Programming Guide. WINDOW-STREAM-HORIZONTAL-OVERFLOW Function Returns the horizontal overflow action for a window stream. You can use the se tf macro with this function to change the horizontal overflow action. See Section 3.1.3 for information on using this function. Format WINDOW-STREAM:WINDOW-STREAM-HORIZONTAL-OVERFLOW window-stream Arguments window-stream A window stream. Return Value :WRAP Or :TRUNCATE. WINDOW-STREAM-INPUT-HISTORY-LIMIT Function Returns the maximum number of input units maintained by a window stream’ s input history or n il if there is no limit. You can use the SETF macro with this function to change the input history limit. Reducing the limit truncates the window stream ’ s input history. If you set the limit to 0, no input history is maintained. See Section 3.1.6 for information on using this function. Format WINDOW-STREAM:WINDOW-STREAM-INPUT-HISTORY-LIMIT window-stream Window Stream s 3-23 WINDOW-STREAM-INPUT-HISTORY-LIMIT Function Arguments window-stream A window stream. Return Value A n on negative fixnum or NIL. WINDOW-STREAM-KB Function See the description of u i s :window- stream -kb in Part II of VAX LISP/VMS Interface to VWS Graphics or the description of CLX: window- stream - kb in Part IV of DECwindows Programming Guide. WINDOW-STREAM-P Function Returns T if its argument is a window stream or n il otherwise. Format WINDOW-STREAM:WINDOW-STREAM-P object Arguments object Any LISP object. Return Value T or NIL. WINDOW-STREAM-SHOW-ON Function Returns the type of operation that makes a window stream ’ s window visible and (for input operations) connects the keyboard to the window. You can use the setf macro with this function. See Section 3.1.7 for information on using this function. Format WINDOW-STREAM:WINDOW-STREAM-SHOW-ON window-stream 3-24 Window Stream s WINDOW-STREAM-SHOW-ON Function Arguments window-stream A window stream. Return Value : INPUT, : 10, :OUTPUT, or NIL. WINDOW-STREAM-VERTICAL-OVERFLOW Function Returns the vertical overflow action for a window stream. You can use the SETF macro with this function to change a stream’ s vertical overflow behavior. However, unless you created the stream with :DOES-in p u t -p n il , any value other than : scroll results in an error. See Section 3.1.3 for information on using this function. Format WINDOW-STREAM:WINDOW-STREAM-VERTICAL-OVERFLOW window-stream Arguments window-stream A window stream. Return Value : SCROLL, :WRAP, or :TRUNCATE. WINDOW-STREAM-VIEWING-AREA Function Returns a list of four numbers representing the native-coordinate viewing area of a window stream. This function returns a list even if the viewing area was specified with n il and thus occupies the entire window. You can use the setf macro with this function to change a window stream’ s viewing area. Changing the viewing area moves the cursor to the upper-left corner of the new viewing area and resets the viewing area’ s character-cell coordinate system. An error results if the specified viewing area is too small to contain at least one complete character cell. See Section 3.1.2.3 for information on using this function. Window Streams 3-25 WINDOW-STREAM-VIEWING-AREA Function Format WINDOW-STREAM:WINDOW-STREAM-VIEWING-AREA window-stream Arguments window-stream A window stream. Return Value A list of four native-coordinate values in the form: (xmin ymin xmax ymax) See Section 3.1.2 for details. WINDOW-STREAM-WINDOW Function Returns the window associated with a window stream. You cannot use the s e tf macro with this function. Format WINDOW-STREAM:WINDOW-STREAM-WINDOW window-stream Arguments window-stream A window stream. Return Value A window in the representation of the supporting window system. WINDOW-STREAM-X-POSITION Function Returns the horizontal component of a window stream ’ s native-coordinate cursor position. You can use the s e t f macro with this function to change the cursor position. It is an error to specify a cursor position that results in the viewing area no longer containing at least one complete character cell. See Section 3.1.5 for information on using this function. 3-26 Window Streams WINDOW-STREAM-X-POSITION Function Format WINDOW-STREAM:WINDOW-STREAM-X-POSITION window-stream Arguments window-stream A window stream. Return Value A number. WINDOW-STREAM-X-POSITION-CELL Function Returns the horizontal component of a window stream’ s character-cell coordinate cursor position. You can use the s e t f macro with this function to change the cursor position. See Section 3.1.5 for information on using this function. Format WINDOW-STREAM:WINDOW-STREAM-X-POSITION-CELL window-stream Arguments window-stream A window stream. Return Value A fixnum. WINDOW-STREAM-Y-POSITION Function Returns the vertical component of a window stream’ s native-coordinate cursor position. You can use the s e t f macro with this function to change the cursor position. It is an error to specify a cursor position that results in the viewing area no longer containing at least one complete character cell. See Section 3.1.5 for information on using this function. Window Streams 3-27 WINDOW-STREAM-Y-POSITION Function Format WINDOW-STREAM:WINDOW-STREAM-Y-POSITION window-stream Arguments window-stream A window stream. Return Value A number. WINDOW-STREAM-Y-POSITION-CELL Function Returns the vertical component of a window stream’ s character-cell coordinate cursor position. You can use the s e t f macro with this function to change the cursor position. See Section 3.1.5 for information on using this function. Format WINDOW-STREAM:WINDOW-STREAM-Y-POSITION-CELL window-stream Arguments window-stream A window stream. Return Value A fixnum. WITH-INPUT-EDITING Macro Establishes a context in which code in the body of the macro determines when a complete input unit has been entered. An input unit is the unit of text that can be recalled and edited. See Section 3.2.1.2 for more information about using this macro. 3-28 Window Streams WITH-INPUT-EDITING Macro Format WINDOW-STREAM:WITH-INPUT-EDITING ( w indow-stream {option}*) {form }* Arguments window-stream A window stream. option Keyword-value pairs. Table 3-2 lists the keywords and the meanings of their values. Table 3-2: Keyword Options to WITH-INPUT-EDITING K eyw ord V alu es a n d M e a n in g :PROMPT A string, a function of no arguments, or NIL. The string or return value o f the function is printed in the viewing area before the input editor is called. I f NIL, "Lisp>" is used. By default, no prom pt is printed. :RESCAN T (the default) or NIL. If T, the input editor can rescan input that has already been consum ed by the body o f the macro. Rescanning, which occurs when the user edits lines already typed, forces reexecution o f the body o f the macro. NIL disables rescanning and prevents the user from editing input already consumed. :TERMINATORS A list of term inating characters. When the input editor encounters a term inating character, it performs the action specified by the character (if any), then passes the contents of the input buffer to the input function requesting input from the stream. The default value is (#\ RETURN). Do not specify NIL as the value o f : TERMINATORS. If no terminating characters are specified, the input editor can never return. form One or more forms that make up the body of the macro. Usually, the body consumes and parses input from window-stream. Since the body is reexecuted whenever rescanning takes place, it should not perform output or have other side effects. The input consumed by the body is added to the input history. Return Value The value returned by the last form. Window Streams 3-29 WITH-WINDOW-STREAM Macro WITH-WINDOW-STREAM Macro Creates a window stream associated with a specified window, binds a variable to the stream, and executes forms with the variable bound to the stream. The stream is automatically closed upon exit from the w ith -window- stream form, and the value of the last form executed in the body is returned as the value of the macro. Format WINDOW-STREAM:WITH-WINDOW-STREAM ( var w indow {option}*) {form }* Arguments var window A window stream associated with window is created and bound to var. option Keyword-value pairs that specify characteristics of the window stream. The keywords are the same ones you specify with make- window- stream . form Forms that execute while the window stream is open. Return Value The value of the last form executed. 3-30 Window Streams Chapter 4 Pretty-Printing and Using Extensions to FORMAT Pretty-printing clarifies the meanings of LISP objects by modifying their printed representations. It inserts indentation and line breaks at appropriate places, making pretty-printed output easier to read than output produced with standard print functions. Pretty-printing is an alternative to standard printing for all LISP objects, but is particularly useful for printing LISP code, complex data lists, and arrays.* When pretty-printing is enabled, any function that prints output can potentially perform pretty-printing. The following example contrasts the standard and pretty-printed treatments of a c o n d structure: Lisp> (setf t-question ' (cond ((equal terminal 'vt240) start) (t (prinl ' (what terminal type are you using?))))) (COND ((EQUAL TERMINAL (QUOTE VT240)) START) (T (PRIN1 (QUOTE (WHAT TERMINAL TYPE ARE YOU USING?))))) Lisp> (pprint t-question) (COND ((EQUAL TERMINAL 'VT240) START) (T (PRIN1 '(WHAT TERMINAL TYPE ARE YOU USING?)))) The first version (produced by the standard read-eval-print loop) breaks the line at an awkward place and provides no indentation. Only one line is being printed. The line is either wrapped or truncated, depending on the operating system (VMS or ULTRIX—32) and the setting of the terminal. The pretty-printed (p p r i n t ) version is more readable because it starts a new line at the beginning of a nested list, indenting the list to line up with the structure nested to the equivalent level in the first line. This chapter describes four ways to print LISP objects: • Section 4.1 tells how to pretty-print objects. • Section 4.2 tells how to control the format of pretty-printed objects, using print control variables. • Section 4.3 tells how to use the VAX LISP f o r m a t directives that support pretty-printing. • Sections 4.4 through 4.9 tell how you can extend the VAX LISP print functions to handle specific structures and types of structures by defining new print functions. * VAX LISP pretty-printing and the extensions to FORMAT are based on a program described in the paper P P : A L is p P r e tty P r in t in g S y s te m , A.I. Memo No. 816, December 1984. The paper and the program were written by Richard C. Waters, Ph.D., of the MIT Artificial Intelligence Laboratory. Pretty-Printing and Using Extensions to FORMAT 4-1 4.1 Pretty-Printing with Defaults Three print functions let you pretty-print without explicitly using print control variables: • p p r in t form ats an object and prin ts it to a stream. • p p r in t - d e f in it io n form ats the function object o f a sym bol and prin ts it to a stream. • p p r in t - p l i s t form ats the p roperty list o f a sym bol and prin ts it to a stream. Use p p r in t when you want to let the system decide how best to format an object. The cond structure at the beginning of this chapter is an example of the output format specified for lists starting with a particular symbol. p p r in t prints whatever object is given as its argument. You can use p p r in t -d e f in it io n to print the definition of a LISP function. Supply the function name as the argument, as follows: Lisp> (defun belongs (this pile) (cond ((null pile) nil) this (car pile)) pile) (t (belongs this (cdr pile))))) BELONGS Lisp> (pprint-definition 'belongs) (DEFUN BELONGS (THIS PILE) (COND ((NULL PILE) NIL) ((EQUAL THIS (CAR PILE)) PILE) (T (BELONGS THIS (CDR PILE))))) ((equal If the object to be printed is the property list of a symbol, use p p r in t -p l i s t , as shown in the following example: Lisp> (setf (get 'places 'cities) ' (augusta Sacramento)) (AUGUSTA SACRAMENTO) Lisp> (setf (get 'places 'states) ' (maine California)) (MAINE CALIFORNIA) Lisp> (pprint-plist 'places) (STATES (MAINE CALIFORNIA) CITIES (AUGUSTA SACRAMENTO)) PPRINT-PLIST prints only indicator-value p airs for w h ich the in dicator is a ccessib le in the current package, p p r in t - p l i s t e m p h a size s the relation sh ips betw een the indicator-value pairs. 4.2 Pretty-Printing with Control Variables VAX LISP supports the global print control variables included in Common LISP and provides three additional variables: • *PRINT-RIGHT-MARGIN* • *PRINT-MISER-WIDTH* • *PRINT-LINES* By changing the values of these variables, you can adjust printed output to suit a variety of situations. Note that *p r in t -m is e r -w idth * and *p r in t - l in e s * affect pretty-printed output only. You can also specify values for these three variables in calls to the write and These functions have been extended to accept the following keyword arguments: w r ite - to - str in g functions. 4-2 Pretty-Printing and Using Extensions to FORMAT RIGHT-MARGIN MISER-WIDTH LINES If you specify any of these arguments, the corresponding special variable is bound to the value you supply with the argument before any output is produced. 4.2.1 Explicitly Enabling Pretty-Printing When the Common LISP variable *print-pretty* is non-NiL, it enables pretty printing. If you set *print-pretty* to t, you can pretty-print by calling any print function. The LISP read-eval-print loop will also pretty-print when *printPRETTY* is non-NIL. The following example shows the effect of a prini function call when pretty printing is enabled: Lisp> (setf *print-pretty* t) T Lisp> (prini ' ( (tiger tiger burning bright) (in the forests of the night) (what immortal hand or eye) (could frame thy fearful symmetry))) ((TIGER TIGER BURNING BRIGHT) (IN THE FORESTS OF THE NIGHT) (WHAT IMMORTAL HAND OR EYE) (COULD FRAME THY FEARFUL SYMMETRY)) You can also enable pretty-printing by specifying a non-NiL value for the :pretty keyword in functions such as write and write-to-string. 4.2.2 Limiting Output by Lines Pretty-printing lets you abbreviate output by controlling the number of lines printed. With the variable *p r i n t -l i n e s * set to any integer value, the print function you use stops after printing the specified number of lines. The output stream replaces omitted output with the characters “. . . ” . Abbreviation by number of lines occurs only when pretty-printing is enabled. See Section 4.7 for more details on abbreviating output. The following example shows pretty-printed output with *p r i n t -l i n e s * set to l: Lisp> (setf *print-lines* 1) 1 Lisp> (setf *print-pretty* t) T Lisp> (PRINT '((in what distant deeps or skies) (burnt the fire of thine eyes) (on what wings dare he aspire) (what the hand dare seize the fire))) , ((IN WHAT DISTANT DEEPS OR SKIES) (BURNT THE FIRE OF THINE EYES) ... 4.2.3 Controlling Margins The *p r i n t -r i g h t -m a r g i n * variable lets you adjust the width of printed output. An integer value of *p r i n t -r i g h t -m a r g i n * specifies how wide to print, even if not pretty-printing. With the left margin at 0, *p r i n t -r i g h t -m a r g i n * specifies the approximate number of columns in which the print function will try to print. The default value, n i l , causes the print functions to query the output stream for the right margin value. There needs to be a reasonable right margin value when pretty-printing and *p r i n t -r i g h t -m a r g i n * are n i l .The default varies, but is always appropriate to the output device. Pretty-Printing and Using Extensions to FORMAT 4-3 The example below shows how setting *p r i n t -r i g h t -m a r g i n * affects the width of pretty-printed output: Lisp> (setf *print-pretty* t) T Lisp> (setf *print-right-margin* 38) 38 Lisp> (prinl '((and what shoulder, & what art) (could twist the sinews of thy heart) (and when thy heart began to beat) (what dread hand & what dread feet))) ((AND WHAT SHOULDER, & WHAT ART) (COULD TWIST THE SINEWS OF THY HEART) (AND WHEN THY HEART BEGAN TO BEAT) (WHAT DREAD HAND & WHAT DREAD FEET)) Output may exceed the right margin if the printer encounters a long symbol name or string. The left margin is normally 0, but you can change it by using logical blocks with the f o r m a t function to indent (see Section 4.3). 4.2.4 Conserving Space with Miser Mode Miser mode can help you avoid running out of horizontal space when you print complicated structures. Pretty-printing adds line breaks and indentation to output to indicate levels of nesting, so that deeply nested structures often use up much of the line width. Miser mode conserves line width by minimizing indentation and inserting new lines where possible. You can use this feature by setting the variable *p r i n t -m i s e r -w i d t h * to an integer value two or three times the length of the longest symbol in the output (usually a value around 40 is appropriate). The system subtracts the value of *p r in t -m is e r -w idth * from the right margin of the output stream to determine the column at which miser mode takes effect. In other words, miser mode becomes effective when the total line width available for printing after indentation is less than the value of *p r in t -m is e r -w idth * . You can set *p r in t -m is e r -w idth * to n il to disable miser mode. See Section 4.8 for more details. The default value of *p r in t - m is e r -w idth * is 40. 4.3 Extensions to the FORMAT Function VAX LISP provides nine f o r m a t directives in addition to those specified in Common LISP. The added directives allow you to specify: • Logical blocks, which are groupings of related output tokens • Multiline mode new lines, which result in new lines if output cannot fit on one line • Indentation, which aids in indenting portions of a form Table 4-1 lists and briefly describes the f o r m a t directives that VAX LISP provides. This section provides a guide to their use. The section presupposes a thorough knowledge of the LISP f o r m a t function as described in Common LISP: The Language. 4-4 Pretty-Printing and Using Extensions to FORMAT Table 4-1: FORMAT Directives Provided by VAX LISP D ir e c t iv e E ffe c t ~w Prints the corresponding argum ent under direction o f the current print control variable values. Sim ilar to ~A and ~S in Com m on LISP. -! Begins a logical block. Without modifiers, this directive causes FORMAT to print a single argum ent following the control string, which should be a list. I f the argum ent is not a list, the entire logical block is effectively a ~W. ~: ! The colon m odifier sets values o f the print control variables: *PRINT-PRETTY* =>•T *PRINT-ESCAPE* =J> T »PRINT-LENGTH* =>■NIL »PRINT-LEVEL* => NIL »PRINT-LINES* =*- NIL ~0 ! The at-sign modifier causes directives within the logical block to print successive elem ents from the argum ent that follows the control string. ~1! The numeral one modifier specifies parentheses for the print prefix and suffix. Ends a logical block. . The at-sign modifier effectively inserts an if-needed newline directive (~ : ) before each w hitespace in the logical block. Specifies a m ultiline m ode new line. This directive is effective only in a logical block. ~: The colon m odifier specifies a conditional, or if-needed, newline. ~Q The at-sign modifier specifies a miser-mode newline. This is the least likely to split lines. ~r Marks the end o f the print prefix or the beginning o f the print suffix. (The prefix also sets indentation.) ~0; The at-sign modifier causes the prefix to be printed on every line. ~nl Sets indentation to n colum ns after the beginning print column o f the logical block. This directive is effective only in a logical block. ~n: I The colon modifier sets indentation to n columns after the current print column. ~n/FILL/ Prints the elem ents o f a list with as many elem ents as possible on each line. If n is 1, FORMAT encloses the printed list in parentheses. This directive is effective only in a logical block. ~n/LINEAR/ If the elem ents o f the list to be printed cannot be printed on a single line, this directive prints each elem ent on a separate line. I f n is 1, FORMAT encloses the printed list in parentheses. This directive is effective only in a logical block. ~ n , m / TABULAR/ Prints the list in tabular form. If n is 1, FORMAT encloses the printed list in parentheses, m specifies the colum n spacing; the default is 16. This directive is effective only in a logical block. Use the format function a s follows: FORMAT destination control-string &REST arguments This function prints the arguments according to the format you specify with directives in the control-string. destination specifies the output stream. Pretty-Printing and Using Extensions to FORMAT 4-5 The format directives provide the sole means of performing pretty-printing in VAX LISP. All functions that explicitly perform pretty-printing (for example, p p r in t and p p r in t - d e f in it io n ) do so by using these directives. Objects printed with format are printed normally unless pretty-printing is enabled. Pretty printing is enabled when both the following conditions exist: • A logical block is started. • *p r in t - pretty * is non-NiL, or the colon m odifier is specified in the logical block directive (~:! ). Nothing prevents you from starting a logical block when *p r in t - pr etty * is n i l . However, any conditional new lines or indentation specified within the logical block will be ignored. This feature results in normal output, as opposed to pretty-printed output. By allowing this flexibility, format lets you use one control string to format data, and the data is either printed normally or pretty-printed, according to the value of *p r in t - pretty * . The sections that follow describe the application of the nine VAX LISP format directives and the effects of the colon and at-sign modifiers on them. 4.3.1 Using the Write FORMAT Directive Use the ~w format directive to print an element when you want to use the current values of the print control variables. The argument for ~w can be any LISP object. In contrast, ~a and ~s specify the values of print control variables. You can use up to four prefix parameters with ~w to pad the printed object: ~mincol, colinc, minpad, padchatSN For an explanation of these parameters, see the description under “format Directives Provided with VAX LISP”in the VAX LISP/VMS Object Reference Manual. The colon modifier (~:w) binds the following print control variables for the duration of the w r ite : *p r in t -e sc a p e * to T, *p r in t -pr etty * to T, ♦p r in t length * to n il , *p r in t - lev el * to n il , and *p r in t -l i n e s * to n il . The following example contrasts the effects of using ~w and ~:w: Lisp> (setf *print-pretty* nil) NIL Lisp> (setf ‘print-escape* nil) NIL Lisp> (setf *print-length* 2) 2 Lisp> (setf colors '(("Yellow" "Purple" "Orange" "Green") ("Aqua" "Pink" "Beige" "Buff") ("Peach" "Violet" "Chartreuse"))) ((Yellow Purple ...) (Aqua Pink ...) ...) Lisp> (format t "~W" colors) ((Yellow Purple ...) (Aqua Pink ...) ...) NIL Lisp> (format t "~:W" colors) (("Yellow" "Purple" "Orange" "Green") ("Aqua" "Pink" "Beige" "Buff") ("Peach" "Violet" "Chartreuse")) The first format call truncates the first two sublists to two colors and truncates the outer list to two sublists. This truncation occurs because *p r in t - length * is 2. The first format call omits quotation marks because *p r in t -e s c a p e * is n il . The second format call produces the full list of colors and includes quotation marks, because it implicitly sets *p r in t - length * to n il and *p r in t - e sc a p e * to T. The second format call also indents the lists because it implicitly sets *p r in t -pretty * to T. 4-6 Pretty-Printing and Using Extensions to FORMAT 4.3.2 Controlling the Arrangement of Output Two concepts support the dynamic arrangement of output for pretty-printing: logical blocks and conditional new lines. Logical block directives divide the total output into hierarchical groupings, which are referred to as logical blocks or subblocks. The goal of f o r m a t is to print an entire logical block (including all its subblocks) on one line. If pretty-printing is enabled, the logical block is printed on one line only if the logical block fits between the current left and right margins. Printing all the output on one line is referred to as single-line mode printing. The output for a logical block may not fit on one line when pretty-printing. In this case, the block must be subdivided into sections at points where it may be split into multiple lines. Conditional new line directives specify these points. Multiline mode printing is the name given to the condition where a logical block must occupy multiple lines. When pretty-printing is enabled, f o r m a t buffers the contents of a logical block until it can decide whether to use single-line mode or multiline mode printing. A third mode, miser mode, is described briefly in Section 4.2.4 and in detail in Section 4.8. Use the ~! and ~. directives to specify a logical block in the form: ~! block-. where block can include any f o r m a t directives. A logical block takes one argu ment from the f o r m a t argument list. If that argument is a list, any directives within the logical block that take arguments take elements from that list, as shown in the following example: Lisp> (setf *print-pretty* t) T Lisp> (setf *print-miser-width* nil) NIL Lisp> (setf *print-right-marg±n* 40) 40 Lisp> (format t ' ((stars (betelgeuse deneb sirius)) (planets (mercury venus earth mars jupiter saturn uranus neptune pluto)))) (STARS (BETELGEUSE DENEB SIRIUS)) NIL The logical block takes the entire list as its argument. The list contains two elements but, since there is only one ~w directive, only the first element is printed. With two Write directives (~w) and a multiline mode new line directive (~_), both elements of the list are printed: Lisp> (format t "~!~w~_~W~." ' ((stars (betelgeuse deneb sirius)) (planets (mercury venus earth mars jupiter saturn uranus neptune pluto)))) (STARS (BETELGEUSE DENEB SIRIUS)) (PLANETS (MERCURY VENUS EARTH MARS JUPITER SATURN URANUS NEPTUNE PLUTO)) NIL (See the next section for more information on new line directives.) If the argument is not a list, the logical block is effectively replaced by the ~w directive. Pretty-Printing and Using Extensions to FORMAT 4-7 You can alter the directive to start a logical block (~! ) by adding two modifiers. When the directive includes a colon (~:! ), the directive sets *p r i n t -p r e t t y * and *PRINT-ESCAPE* to T and *PRINT-LENGTH*, *PRINT-LEVEL*, and *PRINT-LINES* to n i l for all the printing controlled by the logical block. When the ~! directive includes an at sign ( ~0 !), the directives within the logical block take successive arguments from the f o r m a t argument list. The logical block uses up all the arguments, not just a single list argument. Therefore, no directives that take arguments from the argument list can appear after a logical block modified by an at sign in the logical block directive (see the last example in this section). You can use the ~~ directive inside a logical block to check whether the logical block arguments have been reduced to a non-NiL atom. See Section 4.9 for information on handling improperly formed argument lists. The output associated with any format directive is subject to pretty-printing when the directive occurs within a logical block and *print-pretty* is non-NiL. A logical block defines an indentation level and can define a prefix and a suffix. By default, when pretty-printing is enabled, the indentation level is the position of the first character in the logical block. Each line following the first line in the logical block is printed preserving indentation and per-line prefixes, so that the first character in the line normally lines up with the first character in the block following the prefix. However, no default prefix or suffix is associated with a logical block. You can create nested logical blocks within a logical block, using the ~\biock~. directive. For example: Lisp> (setf *print-right-margin* 70) 70 Lisp> (setf *print-pretty* t) T Lisp> (format t "~!Stars: ~!~S ~S~. Planets: ~!~S ~S~.~ " ' ((betelgeuse deneb) (mars jupiter))) Stars: BETELGEUSE DENEB Planets: MARS JUPITER In this example, two logical blocks are created within the principal logical block. Each logical block uses the next argument for printing: • The enclosing logical block uses the elements of the principal list ((BETELGEUSE d e n e b ) (m a r s j u p i t e r )) as its arguments. • The first inner logical block uses the elements of the list (b e t e l g e u s e d e n e b ) as its arguments. • The second inner logical block uses the elements of the list (m a r s j u p i t e r ) as its arguments. Lisp> (setf *print-pretty* nil) NIL Lisp> (format t "~:!Stars: ~ !~S ~S~. Planets: ~ !~S ~S~.~." ' ((betelgeuse deneb) (mars jupiter))) Stars: BETELGEUSE DENEB Planets: MARS JUPITER In this example, the colon in the ~:! directive enables pretty-printing implicitly, producing the same output as the previous example. 4-8 Pretty-Printing and Using Extensions to FORMAT Lisp> T Lisp> (setf *print-pretty* t) (format t "~@!~S ~%~S ~%~S ' (betelgeuse deneb sirius) 'polaris 'vega 'algol 'aldebaran) (BETELGEUSE DENEB SIRIUS) POLARIS VEGA ALGOL In this example, the at sign causes the logical block to use all following argu ments. Unneeded arguments are used up by the logical block but not printed. The first ~s applies to the first argument (the list (b e t e l g e u s e d e n e b s i r i u s )). The remaining three ~s directives apply to p o l a r i s , v e g a , and a l g o l .a l d e b a r a n goes unprinted, because there is no corresponding directive. Lisp> (format t "~0!Stars: ~ !~S ~S~. Planets: ~ !~S ~S~.~." ' (betelgeuse deneb) ' (mars jupiter)) Stars: BETELGEUSE DENEB Planets: MARS JUPITER In this example, the at sign in the outermost logical block directive (~@!) directs the logical block to use all the arguments. The first inner logical block uses the elements of the list (b e t e l g e u s e d e n e b ); the second inner logical block uses the elements of the list (m a r s j u p i t e r ). 4.3.3 Controlling Where New Lines Begin Five f o r m a t directives let you specify places where new lines can start according to the demands of the situation. Each directive delimits a section in a logical block. • The ~% directive produces an unconditional new line. When used within a logical block, the directive preserves indentation and per-line prefixes. • The directive produces a fresh line. When used within a logical block, the directive preserves indentation and per-line prefixes. • The directive produces a multiline mode new line when used within a logical block. • The ~:_ directive produces an if-needed new line when used within a logical block. • The ~0_ directive produces a miser-mode new line when used within a logical block. You can specify unconditional new lines (~%) and fresh lines ( ~&) if you know in advance how the text should be laid out. If a new line is produced by one of these directives when the f o r m a t function is printing a logical block, f o r m a t prints the logical block in the multiline mode, preserving indentation and per-line prefixes. The directive specifies a fresh line, whether or not pretty-printing is enabled. If the directive occurs inside a logical block when pretty-printing is enabled and any output is on the line other than prefixes and indentation, the FORMAT call starts a fresh line, preserving indentation and per-line prefixes. Pretty-Printing and Using Extensions to FORMAT 4-9 The following examples show the use of the ~% and directives: Lisp> (format t "Stars-:!;~0;~%~S ~%~S ' (betelgeuse deneb sirius)) Stars; ;BETELGEUSE ;DENEB ;SIRIUS NIL Lisp> (format t "Stars-:!;-0;-&-S ~&~S ' (betelgeuse deneb sirius)) Stars;BETELGEUSE ;DENEB ;SIRIUS The first f o r m a t call starts a new line after the prefix because the ~% directive starts a new line wherever the directive occurs. Replacing the ~% directive with the directive changes the output, because the fresh line is not needed after the prefix. The remaining three new line directives offer flexibility because they are condi tional. However, they have no effect on output (except length abbreviation—see Section 4.7.1) when pretty-printing is not enabled. The directive (multiline mode new line) starts a new line if the output for the enclosing logical block is too long to fit on one line or if any other directive in the logical block causes a new line. When the output is too long, f o r m a t uses multiline mode, and every directive in a logical block starts a new line. The directive (if-needed new line) produces a new line if it is needed: if the following section of output is too long to fit on the current line. The ~@_ directive (miser-mode new line) produces a new line if pretty-printing is enabled with miser mode in effect (see Section 4.8 for details). The f o r m a t function ignores the three conditional new line directives when they occur outside a logical block. The following example shows how you can specify a multiline mode new line and an if-needed new line: Lisp> (setf *print—miser-width* nil) NIL Lisp> (setf *print-right-margin* 16) 16 Lisp> (format t "— : !~S —_—S — :_~S —_—S— ." ' (mercury venus earth mars)) MERCURY VENUS EARTH MARS NIL This f o r m a t function produces output in the multiline mode, because the output will not fit on one line with the right margin set to 16. The multiline mode new line directives (~_) produce new lines for v e n u s and m a r s .The if-needed new line directive (~:_) directs f o r m a t to start a new line before e a r t h if needed (but no new line is needed). You can produce printed output that fills up the space available in each line by using the at-sign (@) modifier with the directive that ends the logical block (~<block~Q.). This modifier causes FORMAT to start a new line if needed following 4-10 Pretty-Printing and Using Extensions to FORMAT every blank space or tab and is equivalent to inserting a ~ d i r e c t i v e after each element to be printed, as shown in the following example: Lisp> (setf *print-right-margin* 25) 25 Lisp> (setf *print-miser-mode* nil) NIL Lisp> (format t "~0:!antares alphecca albireo canopus castor pollux mirzam algol bellatrix capella mira mirfak dubhe polaris ) ANTARES ALPHECCA ALBIREO CANOPUS CASTOR POLLUX MIRZAM ALGOL BELLATRIX CAPELLA MIRA MIRFAK DUBHE POLARIS NIL 4.3.4 Controlling Indentation With pretty-printing enabled, a call to f o r m a t indents the output for a logical block so that the first character in each succeeding line falls under the first character following the prefix in the first line. When pretty-printing is not enabled, the f o r m a t call does not produce indentation, and the indentation directive has no effect. Use the ~ni or the ~n:i directive if you want to change the standard prettyprinted indentation. The ~ni directive causes f o r m a t to indent subsequent lines n spaces from the position of the first character in the logical block. The ~n:i directive, on the other hand, causes f o r m a t to indent subsequent lines n spaces from the output column corresponding to the position of the directive. If you omit the parameter n, the default is 0. Although this parameter can be less than 0 when used with the colon, the indentation cannot move to the left of the first character in the logical block. An indentation directive affects only indentation produced on subsequent new lines. The following example shows several variations of the indentation directive: Lisp> (setf *print-miser-mode* nil) NIL Lisp> (setf *print-right-margin* 15) 15 Lisp> (format t "~:!~S ~2I~:_~S ~:I~S ~_~S ~1I~_~S~." ' (betelgeuse deneb sirius vega aldebaran)) BETELGEUSE DENEB SIRIUS VEGA ALDEBARAN NIL d e n e b lines up under the t in b e t e l g e u s e , because the directive produces a new line and ~2i causes an indentation of two spaces past the beginning of the block. The ~: I directive sets the indentation to the column one space after the end of the second argument. This indentation takes effect on the next new line, so that v e g a lines up under s i r i u s .a l d e b a r a n lines up with the first E in b e t e l g e u s e , because the ~ll directive resets the indentation to one column past the first character in the logical block. The ~i directives only set the indentation. They do not start new lines and they do not take effect until new lines begin. Therefore, in the directives for d e n e b and a l d e b a r a n , the indentation directives precede the new line directives. Pretty-Printing and Using Extensions to FORMAT 4-11 4.3.5 Producing Prefixes and Suffixes You can specify f o r m a t control strings that add prefixes and suffixes to the printed output produced for a logical block. Several options are available. If you divide the format control string into three sections by inserting the separator directive twice, the string will specify a prefix and a suffix, as follows: - \prefix-;body-;su ffix - .. The first directive marks the end of the prefix; the second marks the beginning of the suffix. If you omit the second directive, no suffix is specified. Although the body can be any f o r m a t control string, the prefix and suffix cannot include f o r m a t directives. When a f o r m a t call prints output for a logical block that includes a prefix and pretty-printing is enabled, the second line of the output is indented so that the second line lines up with the first character in the block following the prefix. When the logical block includes a suffix, the f o r m a t call always prints the suffix at the end, even if abbreviation directives eliminate some of the body of the block. In the following examples, “ Stars <”forms the prefix, and “ >”forms the suffix. Lisp> (setf *print-pretty* t) T Lisp> (format t "~!Stars <~;~S ~%~S ' (sirius vega deneb)) Stars <SIRIUS VEGA DENEB> NIL Lisp> (setf *print-length* 2) 2 Lisp> (format t "~!Stars <~;~S ~%~S ' (sirius vega deneb)) Stars <SIRIUS VEGA ...> NIL In the second example, f o r m a t truncates the list to two elements, because *p r i n t -l e n g t h * is set to 2 (see Section 4.7) but it still adds the suffix after the last list element, v e g a lines up under s i r i u s in the first column for the body of the logical block. You can specify the prefix parameter l in the logical block directive (-1 [block-. ), causing the f o r m a t call to use parentheses for the prefix and suffix, as shown below. Lisp> (format t "~1:!~S ~%~S~." ' (castor pollux)) (CASTOR POLLUX) NIL You can create per-line prefixes in a logical block by specifying the at-sign modifier in the directive used to indicate the end of the prefix ( ). This modifier causes f o r m a t to repeat the prefix at the beginning of each line, as shown in the following example: Lisp> (format t "~:!«~0;~S ~ % ~ S ~ _ ~ S ~_~S~;»~." ' (algol antares albireo alphecca)) «ALGOL «ANTARES «ALBIREO «ALPHECCA» The prefixes and the list elements line up. 4-12 Pretty-Printing and Using Extensions to FORMAT If you nest logical blocks, you can specify a prefix with each block, as shown: Lisp> (format t (Bright stars»; ~0!«~@;~S ~S ~%~S ~ ~S~;»~.~;still twinkle. ' (sirius vega deneb algol)) Bright stars «SIRIUS VEGA «DENEB A L GOL» still twinkle. The prefix and suffix for the outer logical block are “ Bright stars”and “ still twinkle” . The prefix for the inner logical block, “ «” , is printed on each line after the indentation required by the prefix for the first logical block. The suffix for the inner logical block, “ »” , is printed once at the end of the block. 4.3.6 Using Tabs You can use the tab directive to arrange output in columns. When pretty-printing is enabled, the ~n,mT tab directive counts spaces, beginning with the indentation of the immediately enclosing logical block. The integer n specifies a number of columns. The integer m specifies an increment: the number of columns to be added at one time until the column width is at least n columns. The at-sign modifier makes the tab directive relative, so that ~n,m@T counts spaces beginning with the current output column. When pretty-printing is not enabled, on the other hand, the ~n,mT directive counts spaces from the beginning of the line, as specified in Common LISP. The default for n and m is l (see Common LISP: The Language for details). In the iterative example that follows, the tab directive precedes the if-needed new line directive: Lisp> (setf *print-pretty* t) T Lisp> (setf *print-right-margin* 29) 29 Lisp> (format t "Stars: ~:0!~{~S~-' ~11T~S ' (polaris dubhe mira mirfak bellatrix capella algol mirzam pollux canopus albireo castor alphecca antares)) POLARIS DUBHE MIRA MIRFAK BELLATRIX CAPELLA ALGOL MIRZAM CANOPUS POLLUX ALBIREO CASTOR ALPHECCA ANTARES NIL Since the tabs are counted from the indentation of the logical block, the tab directives do not have to account for the fact that the whole block is shifted seven columns to the right. 4.3.7 Directives for Handling Lists VAX LISP provides th ree format directives that sim plify the prin tin g o f lists. Each implicitly uses the ~w directive repeatedly to print elements. • If pretty-printing is enabled, the ~n/FiLL/ directive causes f o r m a t to fill the available line width by inserting a space and an if-needed new line after each list element except the last, f o r m a t encloses the list in parentheses if n is l. If pretty-printing is not enabled, ~n/FiLL/ causes f o r m a t to print the output in single-line mode. Pretty-Printing and Using Extensions to FORMAT 4-13 • If pretty-printing is enabled, the ~n/L i n e a r / directive causes f o r m a t to print the list on a single line if the list fits. Otherwise, f o r m a t prints each element on a separate line, f o r m a t encloses the list in parentheses if n is l. If pretty printing is not enabled, ~n/LiNEAR/ causes f o r m a t to print the output in single-line mode. • If pretty-printing is enabled, the ~n, m / tabular/ directive causes format to print the list as a table, using columns of m spaces for list elements. The default value for m is 16 . format encloses the list in parentheses if n is l. If pretty-printing is not enabled, ~ n , m l tabular causes format to print the output in single-line mode. The following examples show the kinds of formats you can produce with the list-handling directives: Lisp> (setf *print-miser-width* nil) NIL Lisp> (setf *print-right-margin* 36) 36 Lisp> (format t "Stars: :!~/FILL/~." ' (polaris dubhe mira mirfak bellatrix capella algol mirzam pollux canopus albireo castor alphecca antares)) Stars: POLARIS DUBHE MIRA MIRFAK BELLATRIX CAPELLA ALGOL MIRZAM POLLUX CANOPUS ALBIREO CASTOR ALPHECCA ANTARES NIL Lisp> (setf *print-right-margin* nil) NIL Lisp> (format t "Stars: ~@:!-/LINEAR/-." ' (polaris dubhe mira mirfak bellatrix capella algol mirzam pollux canopus albireo castor alphecca antares)) Stars: POLARIS DUBHE MIRA MIRFAK BELLATRIX CAPELLA ALGOL MIRZAM POLLUX CANOPUS ALBIREO CASTOR ALPHECCA ANTARES NIL Lisp> (format t "Stars: -6:!-0,20/TABULAR/-. ' (polaris dubhe mira mirfak bellatrix capella algol mirzam pollux canopus albireo castor alphecca antares)) MIRA DUBHE Stars: POLARIS CAPELLA BELLATRIX MIRFAK POLLUX MIRZAM ALGOL CASTOR ALBIREO CANOPUS ANTARES ALPHECCA NIL 4-14 Pretty-Printing and Using Extensions to FORMAT 4.4 Defining Your Own Format Directives VAX LISP lets you define your own format directives to supplement the directives supplied with the system. Any format directive that you define you can use in the control string argument to a format call. (DEFINE-FORMAT-DIRECTIVE name (arg stream colon at-sign &OPTIONAL (parameterl default) (parameter default) ... ) &BODY forms) This macro defines a directive named name. After you define a format directive, you can use it (whether or not pretty-printing is enabled) by including -/name/ in a format control string. NOTE If you do not specify a package with name when you define the directive, name is placed in the current package. If you do not specify a package when you refer to the directive, the form at directive looks in the USER package for the directive definition. For the body of the macro call, the symbols you supply for arg, stream, colon, and at-sign are bound as follows: • arg is bound to the argu m en t list for the format directive you define. • stream is bound to the stream on which the printing is to be done. • The colon and at-sign arguments are bound to n i l unless the colon and at-sign modifiers are used with the directive. There must be one optional argument for each prefix parameter that is allowed in the directive. A parameter argument will receive the corresponding prefix parameter if it was specified in the directive. Otherwise, the default value will be used, as with all optional arguments. The body is evaluated to print the argument arg on the output stream. A userdefined format directive can be useful because it provides a level of indirection. In addition, you can call the directive repeatedly, which may save you some time coding and debugging. The following example shows a format directive used to produce error messages: Lisp> (define-format-directive evaluation-error (symbol stream colon-p atsign-p Soptional (severity 0)) (declare (ignore atsign-p)) (fresh-line stream) (princ (case severity (0 "Warning: ") (1 "Error: ") (2 "Severe Error: ")) stream) (format stream "~0:!The symbol ~S ~:_does not have an ~ integer value.~%Its value is: ~:_~S~." symbol (symbol-value symbol)) (when colon-p (write-char #\BELL stream))) EVALUATION-ERROR Pretty-Printing and Using Extensions to FORMAT 4-15 Lisp> (setf process nil) NIL Lisp> (format t "~1:/evaluation-error/" 'process) Error: The symbol PROCESS does not have an integer value. Its value is: NIL <BEEP> NIL This example shows the definition of a f o r m a t directive, an application of the directive, and the printed output. It assumes that the current package is u s e r The prefix parameter l in "~i:/e v a l u a t i o n -e r r o r /" indicates the severity of the error being signaled. The colon in the FORMAT call produces a beep on the terminal. 4.5 Defining Print Functions for Lists You can use d e f i n e -l i s t -p r i n t -f u n c t i o n to define functions to print specific kinds of lists in formats of your choice. Functions that you define are effective only if pretty-printing is enabled. The printer checks the first element of each list that it prints. If the first element of a list matches the name of a list-print function, the list is printed according to the format you have specified. Create a list-print function according to the following format: DEFINE-LIST-PRINT-FUNCTION symbol (list stream) &BODY forms This macro defines or redefines a print function for lists for which the first element is symbol, list is bound to the list to be printed and stream is bound to the stream on which the printing is to be done. The forms are evaluated to output list. For example, if you define a list-print function for the symbol m y -s e t q , any list beginning with m y -s e t q will be printed in your format when pretty-printing is enabled: Lisp> (setf *print-pretty* nil) NIL Lisp> (define-list-print-function my-setq (list stream) (format stream " ~ 1 ! ~W~A ~ : I~@ {~W~~ list)) MY-SETQ Lisp> (setf base ' (my-setq hi 3 bye 4)) (MY-SETQ HI 3 BYE 4) Lisp> (print base) (MY-SETQ HI 3 BYE 4) (MY-SETQ HI 3 BYE 4) Lisp> (pprint base) (MY-SETQ HI 3 BYE 4) When pretty-printing is not enabled, the value of b a s e is printed without regard to the list-print function defined for m y -s e t q . p p r i n t enables pretty-printing, producing a representation of the value of b a s e using the specified list-print function. VAX LISP pretty-printing incorporates predefined list-print functions for many standard LISP functions. However, if you define a list-print function for a LISP keyword, your function will override the one built into the system. 4-16 Pretty-Printing and Using Extensions to FORMAT NOTE When you use d e f i n e -l i s t -p r i n t -f u n c t i o n , you may encounter two kinds of output that you do not expect: • In most cases, a list whose first element is the symbol for a defined list-print function will be printed in the format specified, even if the context and meaning of the list are irregular and the format is inappropriate. For example, if your data says (l e t i t b e ) and l e t is the symbol of a defined list-print function, the resulting output may be inappropriate. • List-print functions are not used when you print a list under control of a user-defined f o r m a t directive. You can disable any defined list-print function by using the u n d e f i n e -l i s t p r i n t -f u n c t i o n macro. Its format is: UNDEFINE-LIST-PRINT-FUNCTION symbol This macro disables the list-print function defined for symbol. The following example disables the m y -s e t q list-print function defined in the example at the beginning of this section: Lisp> (undefine-Iist-print-function my-setq) MY-SETQ 4.6 Defining Generalized Print Functions Using generalized print functions, you can specify how any object is prettyprinted, regardless of its form. Functions that you define and enable are effective only if pretty-printing is enabled. First you define a function with d e f i n e g e n e r a l iz e d -p r i n t -f u n c t i o n .Then you enable the function. You can enable it globally, using g e n e r a l i z e d -p r i n t -f u n c t i o n -e n a b l e d -p . Or you can enable it locally, using w i t h -g e n e r a l i z e d -p r i n t -f u n c t i o n . Use the following format when you define a generalized print function: DEFINE-GENERALIZED-PRINT-FUNCTION name (object stream) predicate &BODY forms This macro defines or redefines a print function with the name name, object is bound to the object to be printed, stream is bound to the stream to which output is to be sent, predicate governs the application of the generalized print function. The predicate is operative on any LISP object. A generalized print function will be used if it is enabled and the predicate evaluates to true on the object to be printed, n u l l o b j e c t is the predicate in the sample generalized print function shown at the end of this section. The pretty-printer uses your generalized print function to print any object for which the predicate does not evaluate to n i l . Evaluation of the specified forms must write a representation of object to stream. If a generalized print function and a list-print function for the same symbol are both enabled, the generalized print function will be used. A related function lets you test whether a specific generalized print function is enabled: GENERALIZED-PRINT-FUNCTION-ENABLED-P name Pretty-Printing and Using Extensions to FORMAT 4-17 You can also use this function to globally change the status of the function, using s e t f as shown: (SETF (GENERALIZED-PRINT-FUNCTION-ENABLED-P name) T) or (SETF (GENERALIZED-PRINT-FUNCTION-ENABLED-P name) NIL) Use the w i t h -g e n e r a l i z e d -p r i n t -f u n c t i o n macro to locally enable a generalized print function in the following format: WITH-GENERALIZED-PRINT-FUNCTION name &BODY forms This macro locally enables the generalized print function named name when it evaluates the specified forms. The printer checks generalized print functions that have been enabled in reverse order from the order of their enabling. This means that in cases where two or more generalized print functions apply, the most recently enabled function is used. Enabling a generalized print function globally is less efficient than enabling it locally, because the printer must check the predicate of globally enabled print functions against every object to be printed. If you enable the generalized print function locally, the printer checks the function’ s predicate against the object being printed only during execution of the code within the macro, instead of on every call to a print function. Since the read-eval-print loop is used often, the difference in efficiency can be significant. Consider the following examples: Lisp> NIL Lisp> 25 Lisp> NIL Lisp> (setf *print-pretty* nil) (setf *print-right-margin* 25) (generalized-print-function-enabled-p 'print-nil-as-list) (define-generalized-print-function print-nil-as-list (object stream) (null object) (princ "( )" stream)) PRINT-NIL-AS-LIST Lisp> (print nil) NIL NIL Lisp> (pprint NIL) NIL Lisp> (with-generalized-print-function 'print-nil-as-list (print nil) (pprint nil)) NIL ( ) Lisp> (setf (generalized-print-function-enabled-p 'print-nil-as-list) t) T Lisp> (pprint nil) ( ) The first p r i n t call prints n i l , because pretty-printing is not enabled. The first p p r i n t call prints n i l ,because the generalized print function p r i n t -n i l -a s -l i s t is not enabled. The second p r i n t call prints n i l , because pretty-printing is again not enabled. The second p p r i n t call prints ( ), because the generalized print function is enabled locally and pretty-printing is enabled. The third p p r i n t call prints ( ), because the generalized print function is enabled globally and pretty-printing is enabled. 4-18 Pretty-Printing and Using Extensions to FORMAT NOTE A generalized print function controls the pretty-printing of an object only if the following conditions exist: • The generalized print function is enabled globally or locally. • The predicate specified with d e f i n e -g e n e r a l i z e d -p r i n t -f u n c t i o n is true. • The object to be printed does not come under control of a userdefined f o r m a t directive. In cases where two or more generalized print functions are applicable, only one is chosen. The one chosen is the most recently enabled (globally or locally) generalized print function for which the predicate specified with d e f i n e -g e n e r a l i z e d -p r i n t -f u n c t i o n is true. Generalized print functions are not used when you print an object under control of a user-defined f o r m a t directive. 4.7 Abbreviating Printed Output You can abbreviate printed output according to: • The length of the object to be printed • The depth of nested logical blocks • The number of lines in the output Length and depth abbreviation are supported in Common LISP and are effective whether or not pretty-printing is enabled. In addition, abbreviation based on the number of lines of output is supported in VAX LISP; this is effective only when pretty-printing is enabled. 4.7.1 Abbreviating Output Length You can control the number of sections of printed output by setting the *PRINTl e n g t h * variable. The value you supply specifies the number of sections to be printed for any affected logical block. The directives ~%, and mark the sections of a logical block (see Section 4.3.3 for details). After the output stream prints *p r i n t -l e n g t h * sections of a logical block, it prints an ellipsis ( . . . ) and stops processing the logical block. If the logical block is nested with other logical blocks, the output stream terminates only the processing of the immediately enclosing logical block. Output is not truncated if the value of *p r i n t -l e n g t h * is NIL. The following example shows output abbreviation based on length: Lisp> (setf *print-pretty* t) T Lisp> (setf *print-right-margin* 47) 47 Lisp> (setf *print-length* 11) 11 Pretty-Printing and Using Extensions to FORMAT 4-19 Lisp> (format t "Stars: ~@!~{~W~A ' (polaris dubhe mira mirfak bellatrix capella algol mirzam pollux canopus albireo castor alphecca antares)) Stars: POLARIS DUBHE MIRA MIRFAK BELLATRIX CAPELLA ALGOL MIRZAM POLLUX CANOPUS ALBIREO ... NIL Each star name in the list constitutes a separate logical block section, f o r m a t prints “. . . ”after the eleventh star name to indicate that the list has been abbreviated at that point. 4.7.2 Abbreviating Output Depth Use the variable *p r i n t -l e v e l * to control the depth of printed output. *p r i n t - l e v e l * specifies the lowest level of dynamically nested logical blocks to be printed. When your program calls f o r m a t recursively, the output stream keeps track of the actual nesting level and abbreviates output when the level reaches *p r i n t l e v e l * . The printed character # indicates where the stream has truncated the output. You can prevent depth abbreviation by setting *p r i n t -l e v e l * to NIL. Dynamic nesting of logical blocks occurs frequently when you print complicated structures. This nesting may not be obvious as you read the program. For example, if you have defined list-print functions for the primitives if and p r o g n , printing a program that uses a combination of these primitives would involve dynamic nesting of logical blocks, since each list-print function uses the ~w directive implicitly. The following example shows how the output stream abbreviates the printing of a structure in accord with the value of *p r i n t -l e v e l *: Lisp> (setf *print-level* 3) 3 Lisp> (pprint ' (levell (level2 (level3 (level4 (level5)))))) (LEVEL1 (LEVEL2 (LEVEL3 #))) Lisp> (setf *print-level* 2) 2 Lisp> (pprint ' (levell (level2 (level3 (level4 (level5)))))) (LEVEL1 (LEVEL2 #)) Lisp> (pprint ' (levell 4 5 6 (level2 (level3 (level4 (lev e l 5 ) ))))) (LEVEL1 4 5 6 4.7.3 (LEVEL2 #)) Abbreviating Output by Lines You can control the number of lines printed in the output by setting the *p r i n t l i n e s * variable. The value you supply specifies the number of lines to be printed for the outermost logical block. The output stream prints “ at the end of the last line to indicate where it has truncated the output. If *p r i n t -l i n e s * is n i l , the output stream will not abbreviate the number of lines printed. This abbreviation mechanism is effective only when pretty-printing is enabled. 4-20 Pretty-Printing and Using Extensions to FORMAT In the following example, printing stops at the end of the fourth line: Lisp> T Lisp> NIL Lisp> 4 Lisp> (setf *print-pretty* t) (setf *print-miser-width* nil) (setf *print-lines* 4) (format t "Stars: !~/LINEAR/~." ' (polaris dubhe mira mirfak bellatrix capella algol mirzam pollux canopus albireo castor alphecca antares)) Stars: POLARIS DUBHE MIRA MIRFAK ... NIL 4.8 Using Miser Mode If you print large structures with deeply nested logical blocks, you may find the miser mode useful. Indentation produced in the output by the nesting of logical blocks, prefixes, and the ~ni directive reduces the line length available for printing. Miser mode helps you avoid running out of space and printing beyond the right margin. Miser mode does not, however, guarantee the elimination of these problems. Pretty-printing uses single-line mode if the output fits on one line. If the f o r m a t control string permits new lines and the output requires two or more lines, pretty-printing normally uses multiline mode. The printer determines whether to print a logical block in miser mode according to the current column of the output at the beginning of the logical block and the values of two variables: • *PRINT-RIGHT-MARGIN* • *PRINT-MISER-WIDTH* *p r i n t -r i g h t -m a r g i n * specifies the location of the right margin. *p r i n t -m i s e r - w i d t h * specifies a number of columns before the i ght margin. When the current output column at the beginning of a logical block is equal to or greater than the difference between *p r i n t -r i g h t -m a r g i n * and *p r i n t -m i s e r -w i d t h *, then the logical block is printed in miser mode. This condition occurs when the total available line width is less than the value of *p r i n t -m i s e r -w i d t h *, as shown in Figure 4—1. Pretty-Printing and Using Extensions to FORMAT 4-21 Figure 4-1: Variables Governing Miser Mode Column at which printer enters miser mode ‘ PRINT-RIGHT-MARGIN* ‘ PRINT-MISER-WIDTH* M LO-003304 You can disable miser mode by setting *PRINT-MISER-WIDTH* to n i l . Miser mode saves space by: • Ignoring indentation f o r m a t directives • Starting a new line at every conditional new line directive: Multiline mode new line ( ~_) If-needed new line (~:_) Miser mode new line (~0_) The next two examples contrast pretty-printing in multiline mode and miser mode: Lisp> T Lisp> 60 Lisp> 35 Lisp> (setf *print-pretty* t) (setf *print-right-margin* 60) (setf *print-miser-width* 35) (format t "~:!Stars with Arabic names: ~S ~S ~27I~:_~S ~ ~:I~0_~S ~_~S " ' (betelgeuse (deneb sirius vega) aldebaran algol (castor pollux) bellatrix)) Stars with Arabic names: BETELGEUSE (DENEB SIRIUS VEGA) ALDEBARAN ALGOL (CASTOR POLLUX) BELLATRIX NIL Lisp> (format t "~!Stars with Arabic names: ~:0!~S ~:_~S ~ ~27I~:_~S ~:I~0_~S ~_~S ~1I~_~S~.~." ' (betelgeuse (deneb sirius vega) aldebaran algol (castor pollux) bellatrix)) Stars with Arabic names: BETELGEUSE (DENEB SIRIUS VEGA) ALDEBARAN ALGOL (CASTOR POLLUX) BELLATRIX NIL In the first output sample, f o r m a t uses multiline mode. Miser mode is never enabled, because the logical block begins at column 0 and miser mode takes effect only if the column begins at column 25 (60 —35). a l d e b a r a n lines up with the T in b e t e l g e u s e , because the ~27i directive sets the indentation for following lines at column 27 and the directive produces a new line. The -: I~@_~S directive sets the column for the next line at the level of the A in a l g o l . The ~li directive controls the last argument, b e l l a t r i x , setting the indentation to column 1. 4-22 Pretty-Printing and Using Extensions to FORMAT The second output example shows the effects of miser mode, because the text in the outer logical block, “ Stars with Arabic names:” , causes the inner logical block to begin at column 26. With *p r i n t -m i s e r -w i d t h * set to 35 and ♦p r i n t -r i g h t m a r g i n * set to 60, f o r m a t enables miser mode when the logical block begins past column 25. f o r m a t conserves space by starting a new line at every multiline mode new line directive (~_) and every if-needed new line directive (~ ) f o r m a t also inserts a new line at the miser mode new line directive (~0_) and ignores the indentation directives (~m ). 4.9 Handling Improperly Formed Argument Lists VAX LISP provides a method for gracefully handling argument lists that are improperly formed. The function of the ~Adirective, when used in a logical block, differs slightly from the corresponding function in Common LISP. In Common LISP the ~Adirective is used with the iteration directives ~{ and -} to check whether the argument list has been reduced to n i l . If the list is n i l , iteration stops. You can also use the ~Adirective to check whether the argument list for a logical block has been reduced to a non-NlL atom. If the check shows that the argument list is a non-NiL atom, the printer prints space-dot-space ( . ) and uses the ~w directive to print the value of the atom, format then stops processing the immediately enclosing logical block, after printing the suffix (if one is there). No error condition results. The following example shows the use of format to print a dotted pair: Lisp> (format t "~1:!~Q(~S~A ' (castor pollux deneb . aldebaran)) (CASTOR POLLUX DENEB . ALDEBARAN) This feature serves as a useful debugging tool, because it lets the f o r m a t function work even when the argument list is improperly formed. NOTE When the ~Adirective is included in a logical block, the format function checks whether the argument list is a non-NiL atom, even when pretty-printing is not enabled. Pretty-Printing and Using Extensions to FORMAT 4-23 Chapter 5 Error Handling The LISP system invokes the VAX LISP error handler when errors are signaled during program evaluation. This chapter explains what the error handler does when an error is signaled. Because the system ’ s error handler may not meet your programming needs, VAX LISP lets you create your own error handler. The procedure for creating an error handler is also explained in this chapter. 5.1 Error Handler The VAX LISP error handler function, u n i v e r s a l -e r r o r -h a n d l e r , performs four sequential steps: 1. Checks the number of nested errors that have occurred. If three nested errors have occurred, the error handler aborts your program, displays a message, and returns you to the top-level read-eval-print loop; otherwise, the handler continues to the next step. 2. Checks the type of error. 3. Displays an error message that provides you with information about the error. 4. Performs the appropriate operation for the type of error that was signaled. 5.2 VAX LISP Error Types T h r e e ty p e s o f e r r o r s ca n o ccu r d u r in g th e e v a lu a tio n o f a L IS P progra m : • Fatal error • Continuable error • Warning When an error is signaled, the VAX LISP system displays an error message that provides you with the following information: • The type of error that was signaled—fatal error, continuable error, or warning • The name of the function that caused the error • The name of the function that was used to signal the error—e rro r, c e r r o r , or WARN • A description of the error • If a continuable error, an explanation of what will happen if you continue the program’ s evaluation from the point at which the error occurred Error Handling 5-1 The format of an error message and the information a message provides depend on the type of error. The next three sections describe the types of errors; each description includes the error type’ s message format and the operation the error handler performs. 5.2.1 Fatal Errors When a fatal error is signaled, the error handler displays a message in the following format: Error in function-name: error-description. In this format description, function-name is the name of the function that caused the error, and error-description is a message telling why the error occurred. The message is generated from the format string and the arguments in the call to the error function; the message can be displayed on more than one line. An example of a fatal error message follows: Error in SYSTEM::MAKE-ARRAY-UK: Only vectors can have fill pointers. After the message is displayed, the error handler checks the value of the VAX LISP * error -a c t io n * variable. This value is set when you invoke VAX LISP and can be either the :EXIT or the :debug keyword. When the value is :EXIT (the default in a batch session), the error handler causes the LISP system to exit on an error; when the value is :debug (the default in an interactive session), the handler invokes the VAX LISP debugger. On VMS systems, you use a command qualifier to set the value of the *error - a c t io n * variable: $ LISP/ERROR_ACTION=va/ue On ULTRIX systems, you use an option to set the value of the *error -a c t io n * variable: % vaxlisp -V ERROR_ACTION=va/ue In eith er case, the value m u st be either EXIT or debug . If the debugger is invoked, you can use it to locate the error in your program. After you locate the error, you can correct it and restart your program’ s evalua tion. NOTE You cannot continue your program’ s evaluation from the point at which a fatal error occurred. The *error -a c t io n * variable is described in the VAX LISP/VMS Object Reference Manual, and the debugger is described in Chapter 4 of the VAX LISP/VMS Program Development Guide. 5.2.2 Continuable Errors When a continuable error is signaled, the error handler displays a message in the following format: Continuable error in function-name: error-description. Control Stack Debugger If continued: continue-explanation. 5-2 Error Handling In the preceding format description, function-name is the name of the function that caused the error, and error-description is a message telling why the error occurred. The message is generated from the format string and the arguments in the call to the c e r r o r function; the message can be displayed on more than one line. A line of text that explains what will happen if you continue your program’ s evaluation follows the error description. A n e x a m p le o f a c o n tin u a b le e r r o r m e s s a g e is: Continuable error in FACTORIAL: Too few arguments: 0 Contro Stack Debugger If continued: Proceed with unsupplied arguments defaulting to NIL. After the message is displayed, the error handler checks the value of the VAX LISP *e r r o r -a c t i o n * variable in the same way it checks the value after a fatal error (see Section 5.2.1). If the debugger is invoked, you can do one of the following: • Continue from the error; the c e r r o r function performs the corrective action that is specified in the error message. • Locate the error in your program. After you locate the error, you can correct it and restart your program’ s evaluation. The *e r r o r -a c t i o n * variable is described in the VAXLISP/VMS Object Reference Manual, and the debugger is described in Chapter 4 of your Program Development Guide. 5.2.3 Warnings A warning is an error condition that may or may not affect your program’ s evaluation. When this type of error occurs, the system displays a message for the following reasons: • You might want to correct the error later. • Your program might correct the error, but you should know that the error occurred. When a warning is signaled, the error handler displays a message in the following format: Warning in function-name: error-description. function-name is the name of the function that caused the error, and errordescription is a message telling why the error occurred. The message is generated from the format string and the arguments in the call to the w a r n function; the message can be displayed on more than one line. An example of a warning error message is: Warning in function TE: 3 is not a symbol. After the message is displayed, the error handler checks the value of the *b r e a k o n -w a r n i n g s * variable in the same way it checks the value *e r r o r -a c t i o n * variable after a fatal error (see Section 5.2.1). NOTE If the value of the *b r e a k -o n -w a r n i n g s * variable is T, the debugger is invoked when a warning is signaled. Error Handling 5-3 If the debugger is invoked, you can use it to locate the error in your program. After you locate the error, you can correct it, exit the debugger, and then continue your program’ s evaluation from the point where the error occurred. The *break—on—warnings* variable is described in Common LISP: The Language. 5.3 Creating an Error Handler The VAX LISP *univ ersal - error - handler* variable is bound to the system ’ s error handler. This binding provides you with a way to create your own error handler if the system ’ s handler does not meet your programming needs. To create an error handler you must: 1. Define the error handler. 2. Bind the *univ ersal -error -handler* variable to your defined handler. The * universal - error - handler* variable is described in the VAX LISP/VMS Object Reference Manual. 5.3.1 Defining an Error Handler To define an error handler, you must define an error handler function. This function must be able to accept two or more arguments because the LISP system passes at least two arguments to the error handler each time an error occurs in a program. Therefore, specify the arguments in an error-handler definition in the following format: (DEFUN handler (function-name error-signaling-function &REST args) . ..) The arguments provide the error handler with the following information: • The name of the function that called the error-signaling function • The name of the error-signaling function • The arguments that were passed to the error-signaling function An example of an error handler definition is: Lisp> (defun critical-error-handler (function-name error-signaling-function Srest args) (when (or (eq error-signaling-function 'error) (eq error-signaling-function 'cerror)) (flash-alarm-light)) (apply #'universal-error-handler function-name error-signaling-function args)) CRITICAL-ERROR-HANDLER This error handler checks whether a fatal or continuable error is signaled. If either type of error is signaled, the handler calls the function flash -alarm- lig h t and then passes the error signal information to the VAX LISP error handler. When you define an error handler, the definition can include a call to the univ ersal - error - handler function. If the definition does not include a call to this function and you want the handler to check the value of the *error -a c t io n * or *BREAK-ON-warnings * variable, you must include a check of the variable in the handler’ s definition. 5-4 Error Handling If you want an error handler to display error messages in the formats described in Sections 5.2.1 through 5.2.3, include a call to either the u n i v e r s a l -e r r o r h a n d l e r or p r i n t -s i g n a l e d -e r r o r function. Descriptions of these functions are provided in the VAX LISP/VMS Object Reference Manual. The next three sections describe the arguments an error handler must be able to accept. 5.3.1.1 Function Name The function-name argument is the name of the function that calls an error signaling function. This argument enables the error handler to include the function’ s name in the error message the handler displays. 5.3.1.2 Error-Signaling Function The error-signaling-function argument is the name of the error-signaling function that is called to generate the error signal. Depending on which function is called, a fatal error, continuable error, or warning is signaled. The error handler uses the error-signaling-function argument to determine the contents of the args argument. Table 5-1 lists the functions that can be passed as the error-signaling-function argument and briefly describes each function. Table 5-1: Error-Signaling Functions F u n c t io n D e s c r ip t io n CERROR Signals a continuable error ERROR Signals a fatal error WARN Signals a warning See Common LISP: The Language for detailed descriptions of the c e r r o r and See the VAX LISP/VMS Object Reference Manual for a descrip tion of the w a r n function. e r r o r functions. 5.3.1.3 Arguments The args argument is the list of arguments passed to the error-signaling function when the error-signaling function is invoked. The contents of the list depends on which function is invoked. The list can include one or two format strings and their corresponding arguments. The format strings and arguments are passed to the f o r m a t function, which produces the correct error message. 5.3.2 Binding the *UNIVERSAL-ERROR-HANDLER* Variable Once you define an error-handling function, you must bind the *u n i v e r s a l The following example shows how to bind the variable to a function: e r r o r -h a n d l e r * variable to it. Lisp> (let ((‘universal-error-handler* #'critical-error-handler) ) (perform-critical-operation)) Error Handling 5-5 The LET special form binds the *u n i v e r s a l -e r r o r -h a n d l e r * variable to the c r i t i c a l -e r r o r -h a n d l e r function that was defined in Section 5.3.1 and calls a function named p e r f o r m -c r i t i c a l -o p e r a t i o n .When the form is exited because the evaluation finished or the t h r o w function is called, the *u n i v e r s a l -ERRORh a n d l e r * variable is restored to its previous value. 5-6 Error Handling Index A________________________ ch aracter-cell, w in d ow stre a m S e e Window stream cursor D __________________________________ D ata rep resen ta tion , garbage collector, 1-10 interrupt functions, 1-15 keyboard functions, 1-15 : B I O - B Y T E - Q U O T A keyword D ata t y p e s arrays, 1-12 1-4 * B R E A K - O N - W A R N IN G S * variable c________________ Character-cell coordinate system, 3-3 and font, 3-3 realigning by changing cursor position, 3-6 by changing font, 3-5 Characters, 1-4 1—4 comparisons, 1-4 constants, 1-4 Code attribute, 1-4 Common LISP VAX LISP extensions to I/O, 2-1 to 2-6 VAX LISP implementation notes, 1-1 to 1-17 Complex numbers, 1-4 Conditional new line directives, 4-7 Constructor function allocating static space, 1-10 Control characters binding to functions, 1-15 returning information about bindings, 1-15, 1-16 unbinding from functions, 1-15, 1-16 Controlling output arrangement, 4-7 to 4-9 indentation, 4-11 margins, 4-3 to 4—4 newlines, 4-9 to 4-11 Control stack overflow, 1-9 1-1 to 1-5 1-5 co n sta n ts, 1-5 s p e c ia liz e d , 1-5 ch ara cters, 1—4 attributes, 1—4 c o m p a r is o n s, 1-4 c o n sta n ts, 1-4 defining an error handler, 5-4 attributes, 3-2 C u rsor B IN D - K E Y B O A R D - F U N C T IO N function G E T - P R O C E S S - I N F O R M A T I O N function, 3-3 for v iew in g a re a s, B________________________ Bits attribute, C on trol v a ria b le s for printing, 4—2 to 4-4 C o o r d in a t e s y s t e m s Abbreviating printed output, 4-19 to 4-21 by depth, 4-20 by length, 4-19 to 4-20 by lines, 4-3, 4-20 to 4-21 Arrays, 1-5 constants, 1-5 specialized, 1-5 c o m p le x n u m b ers, 1—4 floating-point n u m b ers, co n sta n ts, fu nctions, 1-5 in tegers, 1-2 co n sta n ts, n u m b ers, 1-2 1-3 1-2 1-2 to 1—4 strings, 1-5 D ebu gger error handler, 5-2 to 5-3 : D EBU G k ey w ord S e e * E R R O R - A C T I O N * va ria b le D efining error handler, 5-4 to 5-5 g e n e r a liz e d print fu nctions, 4-17 to 4-19 list-print fu nctions, 4-16 to 4—17 D irectiv es for h andling lists, 4-13 t o 4-14 D o u b le floating-point n u m b ers, 1-2 D y n a m ic m em o ry g a r b a g e colle ctor, 1-6, 1-8 E________________________ : E L E M E N T - T Y P E k ey w ord M A K E-A RRA Y function, O PE N function, 1-5 1-14 E n ablin g pretty-printing, 4-3 : E N D - O F - F I L E - B L O C K k ey w ord G E T - F I L E - I N F O R M A T I O N function, End-of-file o p era tion s, 1-14 1-12 lndex-1 E p h e m e ra l g a r b a g e collector, Function 1-7 k e y b o a rd (cont'd.) Error handling, 5-1 s u s p e n d e d s y s te m s , to 5-6 m essa ges error-handler definition, form at, Functions, CERROR, 5-3 ERROR, 5-2 FORMAT, 4—4 to 4-14 5-5 5-1 ty p es, 5-1 to 5-4 con tin u able, 5-2 to 5-3 fatal, error m e s s a g e s , 5-3 to 5-4 Error h an dler P P R IN T - D E F IN IT IO N , binding *UNIVERSAL-ERROR-HANDLER* WARN, (table), 5-5 E R R O R _ A C T IO N option 5-1 5-3 W R IT E , 4-2 W R IT E - T O - S T R IN G , fatal error, 5-2 / E R R O R _ A C T IO N qualifier 4-2 G______________________ fatal error, 5-2 E S C A P E k ey term inal input, 1 -12 G a r b a g e collector, 1-6 to a v a ila b le s p a c e , : E X I T k ey w ord 4-4 to 4-14 F______________________ _ File organ ization , 1-13 FILE-LENGTH function, FILE-POSITION function, d y n a m ic m em ory, 1-7 1 -1 0 ,1 -1 5 k e y b o a rd fu nctions, 1-15 1-7 run-time efficien cy, 1-14 static m em ory , 4-13 :FIRST-FREE-BYTE k ey w ord GET-FILE-INFORMATION function, 1-9 1- 6 , 1 -8 failure, 1-9 interrupt fu nctions, p e rfo rm a n ce , 1-14 1-9 con trol sta c k overflow , ep h e m e ra l, 1-10 1-8 ch a n g in g m e s s a g e s , *ERROR-ACTION* v a ria b le E x te n sio n s t o th e FORMAT function, tuning, 1-7 1-10 1-7 G e n e r a liz e d print fu nctions, 1-14 4-1 7 to 4-19 G E T - F I L E - I N F O R M A T I O N function Floating-point n u m b ers, 1-2 c o n s t a n t s (table), 1-3 (table), 5-5 U N IV E R S A L - E R R O R - H A N D L E R , E rror-signaling fu n ction s Fill d irective, 4-2 P P R I N T - P L I S T , 4-2 P R IN T - S IG N A L E D - E R R O R , variable, 5-5 defining, 5-4 to 5-5 See 5-5 GENERALIZED-PRINT-FUNCTIONENABLED -P, 4-17 PPRINT, 4-2 5-2 w arning, 1-16 1-5 n u m b er of b y t e s in a file, 1-14 G E T - K E Y B O A R D - F U N C T IO N fu nction returning inform ation a b o u t k e y bin din gs, 1-2 F ont in flu en ce on ch ara cter-cell co o r d in a t e s y ste m , F ont attribute, 1-4 F on ts sp e c ify in g for w in d o w s trea m s, 3-5 FORMAT d ir e c tiv e s in VAX L ISP (table), FORMAT fu n ction ~% directive, 4-9 directive, 4-9 3 -3 G E T - P R O C E S S - I N F O R M A T I O N fu nction r e c o r d length, 4 -5 1-15, 1-16 1 -12 H_______________________ H an dlin g lists, 4-13 to 4-14 directive, 4-9 ~ d i r e c t i v e , 4-9 I_______________________ ~ 0 _ directive, 4-9 ~ ; directive, 4-12 I/O r e q u e s t sp e cifie r s, table, 2-3 -/FILL/ directive, - I directive, 4-13 lf- n ee d ed n e w line d irective, 4-11 Im plem en tation n otes, -/LINEAR/ directive, 4-14 -/TABULAR/ directive, 4-14 ~T directive, 4-13 Indentation, 4-11 directive, 4-11 u ser- d efin ed d irectiv es, ~W directive, 4-6 Input/Output, F resh line directive, p reserv in g, 4-15 to 4—16 file organ ization , im p le m en ta tion - d e p en d en t (table), interrupt, 1-10, 1-14 t o I - 1 5 1 -15 s u s p e n d e d s y s te m s, 1-15 k ey b oa rd , 1-15 to 1-16 g a r b a g e collector, 1-15 1-16 1-14 1 -1 2 1-14 1-13 F I L E - P O S I T I O N function, fu nctions, 1-13 # \ N E W L IN E ch aracter, re c o r d length, 1 -12 term inal input, term inal output, 1-14 1-10 1-11 1 -1 2 W R IT E - C H A R function, lndex-2 1-17 4-8 1-10 to F I L E -L E N G T H function, F unction 4-9 1-1 to end-of-file op era tio n s, 4-9 g a r b a g e collector, 2-3 1-14 p Input fo r m s ed itin g typed, 3-8 P a ss-a ll m od e, INSTATE-INTERRUPT-FUNCTION fu n ction g a r b a g e collector, In tegers, 1-10 S E T - T E R M IN A L - M O D E S function, Per-line prefix, 4-12 1-2 co n sta n ts, 1-2 Interrupt fu n ction s, 1 -1 0,1 -14 to g a r b a g e collector, term inal input, pre se rv in g, 1-15 per-line, 1-15 1-11 K___________________________ K e y b o a rd fu n ction s, 1-15 to 4-19 to 4-21 b y length, 4-19 to 4-20 b y lines, 4-3, 4-20 to 4-21 P r e se r v in g per-line p refixes, Pretty-printing, 4-3 ♦ P R I N T - M I S E R - W ID T H * variable, 1-1 to 1-17 S e e Input/Output p r o c e s s in g d urin g g a r b a g e colle ction , 1-10 1-12 R ela tiv e tabbin g, 4-13 1-16 4-16 to U N D E F IN E - L IS T - P R IN T - F U N C T IO N , 4-17 W IT H - G E N E R A L IZ E D - P R IN T - F U N C T IO N , 4-18 M argin s 4-3 to 4—4 M em ory d y n a m ic g a r b a g e collector, 1-6, 1-8 g a r b a g e c olle ctor, 1-10 static s_______________ c h a n g in g term inal input m od e , D E F I N E - G E N E R A I ilZ E D —P R IN T - F U N C T IO N , 4-17 D E F IN E - L IS T - P R IN T - F U N C T IO N , 4-17 1-7 S e p a r a to r directive, 4-12 S E T - T E R M IN A L - M O D E S fu nction Macro im p le m en ta tion - d e p en d en t (table), M acros S p e c ia liz e d arrays, 1-5 S ta tic m em o ry g a r b a g e colle ctor, 1-10 S trea m d is p a tc h function, a rgu m en ts, N u m bers, 1-2 to 1—4 o O P E N function, 2-3 2-3 S tr e a m s d efin in g n ew ty p es, 2-1 inform ation about, 2—4 S trea m structure, Strin gs, 1-5 2-2 Suffix to printed output, 4—12 to 4-13 S u sp e n d e d sy stem s to 4-23 4-9 4-9 interrupt fu nctions, 1-15 k e y b o a r d fu nctions, 1-16 T____________________ 4-13 T a b s in printed output, 4-9 to 4—11 Tabular directive, Term inal input, 4-13 4-14 1-11 c h a n g in g m o d e s , p a ss- a il m od e , 1-14 1-11 S h ort floating-point n u m b ers, 1-2 S in g le floating-point n u m b ers, 1-2 T ab directive. N e w lines, 3-10 1-11 Run-tim e efficiency, 1-2 M ultiline-m ode n ew line directive, 1-10 r e c o r d length, Return k ey term inal input, M_______________________ N 4-3 1-12 R e s c a n n in g by W I T H - I N P U T - E D I T I N G , List-print fu n ction s, 4-16 to 4-17 L o g ica l block, 4—4 M ise r- m o d e n e w line d irective, Multiline m od e , 4—7 4-4 ♦ P R IN T - R IG H T - M A R G IN * variable, input/output, L o n g floating-point n u m b ers, 4-23 4-2 to 4—4 R e c o r d M a n a g e m e n t S e r v ic e s (RMS) 4-14 im p le m en ta tion n o te s, input/output 4-8 4—1 to 4-23 R e c o r d length, LISP 4-4, 4-21 4-8 R___________________ 4-20 M iser m od e , 4-12 to 4-13 P r e se r v in g indentation, with con trol v a ria b les, with defa u lts, 4-2 b y depth , controlling, 4—12 im properly fo r m e d a rgu m en t lists, L________________________ Linear directive, 4-8 Prefix to printed output, en a b lin g, 1-16 g a r b a g e colle ctor, 1-1 5 s u s p e n d e d s y s te m s, 1-16 Limiting output, 1-11 Prefix 1-15 s u s p e n d e d s y s te m s, 1-11 : P A S S - T H R O U G H k ey w ord 1-11 1-11 T erm inating c h a r a c te r s for w in d ow stre a m input editor, 3-9 lndex-3 W in d ow s tr e a m s T E R P R I fu n ction r e c o r d length, input from (con t’ d.) 1-12 Tuning, g a r b a g e co lle cto r, editing, 1-7 3-7 prom pting, u __________ U N B IN D - K E Y B O A R D - F U N C T IO N fu n ction un bin din g con trol ch ara cters, 1-15, 1-16 U n con dition al n e w line directive, d efin in g an error handler, 5-4 U se r d e fin e d FORM A T d irectiv es, 4-15 to 4-16 V__________________________ * E R R O R - A C T IO N * , print control, 5-3 5-2 4-2 t o 4-4 * P R IN T - L E N G T H \ 4-19 * P R I N T - L I N E S * , 4 - 2 ,4 - 3 ,4 - 2 0 * P R I N T - M I S E R - W I D T H * , 4-2, 4-4 * P R IN T - P R E T T Y * , 4-3, 4-6 * P R IN T - R IG H T - M A R G IN * , 4-2, 4-3 * U N IV E R S A L - E R R O R - H A N D L E R * , 5-6 V iew in g a r e a ch a n g in g, 3-3, 3-25 e ffe c t on cu rsor, 3-3 co o r d in a t e s y s te m s , 3-2 era sin g , 3-3, 3—17 ob ta in in g d im e n s io n s , 3-3 scro llin g con ten ts, sp ecify in g, 3-18 3-4 w in d o w s tre a m s, 3-2 w W in d ow s s e n d in g ch a r a c te r output to, 3-1 tak in g c h a ra cte r input from, 3-1 visibility w in d o w s trea m s, W in d ow stre a m 3-7 input history limit, scrollin g 3-6 ce ll c o o r d in a te s, 3-19 native c o o rd in a te s, 3—18 W in d ow str e a m cursor, 3-6 p o sitio n ch a n g in g, 3-6 obtainin g, 3-6 W in d ow stre a m s, 3-1 a n d k ey b oa rd , 3-7 creatin g, to 4—1 3-2 cu rsor S e e W in d ow stre a m c u r s o r fon t ch a n g in g, 3-5, 3-22 sp ecify in g, 3-5, 3-17 h orizon tal o v erflow truncating, 3-4 w rappin g, input editor, 3-4 3-9 term inating ch aracter, input from, 3-7 Index-4 3-9 and W IT H - IN P U T - E D IT IN G , limit, 3-18 vertical ov erflow scrollin g, 3-4 truncating, 3-4 w rappin g, 3-4 W R IT E - C H A R function r e c o r d length, 1-12 W rite directive, 4-6 V ariab les 5-4 to 3-8 input history output-only, 3-2 sp e c ify in g ch a ra cteristics, 4-9 U N IV E R S A L - E R R O R - H A N D L E R function * B R E A K - O N - W A R N IN G S * , 3-10 rea d in g c o m p le t e form s, 3-2 3-8 HOW T O O R D E R A D D ITIO N A L D O CU M EN TA TIO N From Call 603-884-6660 Alaska, Hawaii, or New Hampshire Rest of U.S.A. and Puerto Rico1 Write Digital Equipment Corporation P.O. Box CS2008 Nashua NH 03061 800-DIGITAL 'Prepaid orders from Puerto Rico, call Digital’ s local subsidiary (809-754-7575) Canada 800-267-6219 (for software documentation) Digital Equipment of Canada Ltd. 100 Herzberg Road Kanata, Ontario, Canada K2K 2A6 Attn: Direct Order Desk 613-592-5111 (for hardware documentation) Internal orders (for software documentation) — Software Supply Business (SSB) Digital Equipment Corporation Westminster MA 01473 Internal orders (for hardware documentation) DTN: 234-4323 508-351-4323 Publishing & Circulation Services (P&CS) NR03-1/W3 Digital Equipment Corporation Northboro MA 01532 Reader’s Comments VAX LISP Implementation and Extensions to Common LISP AA-MK70A-TE Your comm ents and suggestions will help us im prove the quality o f our future documentation. Please note that this form is for comm ents on documentation only. I r a te th is m a n u a l’ s: Accuracy (product works as described) Com pleteness (enough information) Clarity (easy to understand) Organization (structure of subject matter) Figures (useful) Exam ples (useful) Index (ability to find topic) Page layout (easy to find information) Excellent □ □ □ □ □ □ □ □ Good □ □ □ □ □ □ □ □ Fair □ □ □ □ □ □ □ □ W hat I like best about this manual: What I like least about this manual: I found the following errors in this manual: Page Description My additional com m ents or suggestions for im proving this manual: Please indicate the type of user/reader that you m ost nearly represent: □ Administrative Support □ Com puter Operator □ Educator/Trainer □ Programmer/Analyst □ Sales □ Scientist/Engineer □ Software Support □ System Manager □ Other (please specify) N a m e / T itle ________________________________________________________________ Dept. C o m p a n y ________________________________________________________________ M ailing Address Date -------------------------------------------------------- ----------------- _________________________________________________________________________ 10/87 ------ Phone ------ Poor □ □ □ □ □ □ □ □ — Do Not Tear — Fold Here and Tape SDSDDSO' NO POSTAGE NECESSARY IF MAILED IN THE UNITED STATES BUSINESS REPLY MAIL FIRST CLASS PERMIT N 0.33 M A Y N A R D MASS. POSTAGE W IL L BE PAID BY ADDRESSEE DIGITAL EQUIPMENT CORPORATION CORPORATE USER PUBLICATIONS PKO3-1/30D 129 PARKER STREET MAYNARD, MA 01754-2198 — Do Not Tear — Fold Here
Home
Privacy and Data
Site structure and layout ©2025 Majenko Technologies