This is slib.info, produced by makeinfo version 4.0 from slib.texi. INFO-DIR-SECTION The Algorithmic Language Scheme START-INFO-DIR-ENTRY * SLIB: (slib). Scheme Library END-INFO-DIR-ENTRY This file documents SLIB, the portable Scheme library. Copyright (C) 1993 Todd R. Eigenschink Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Aubrey Jaffer Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the author.  File: slib.info, Node: Top, Next: The Library System, Prev: (dir), Up: (dir) "SLIB" is a portable library for the programming language "Scheme". It provides a platform independent framework for using "packages" of Scheme procedures and syntax. As distributed, SLIB contains useful packages for all Scheme implementations. Its catalog can be transparently extended to accomodate packages specific to a site, implementation, user, or directory. * Menu: * The Library System:: How to use and customize. * Scheme Syntax Extension Packages:: * Textual Conversion Packages:: * Mathematical Packages:: * Database Packages:: * Other Packages:: * About SLIB:: Install, etc. * Index::  File: slib.info, Node: The Library System, Next: Scheme Syntax Extension Packages, Prev: Top, Up: Top The Library System ****************** * Menu: * Feature:: SLIB names. * Requesting Features:: * Library Catalogs:: * Catalog Compilation:: * Built-in Support:: * About this manual::  File: slib.info, Node: Feature, Next: Requesting Features, Prev: The Library System, Up: The Library System Feature ======= SLIB denotes "features" by symbols. SLIB maintains a list of features supported by the Scheme "session". The set of features provided by a session may change over time. Some features are properties of the Scheme implementation being used. The following features detail what sort of numbers are available from an implementation. * 'inexact * 'rational * 'real * 'complex * 'bignum Other features correspond to the presence of sets of Scheme procedures or syntax (macros). - Function: provided? feature Returns `#t' if FEATURE is supported by the current Scheme session. - Procedure: provide feature Informs SLIB that FEATURE is supported. Henceforth `(provided? FEATURE)' will return `#t'. (provided? 'foo) => #f (provide 'foo) (provided? 'foo) => #t  File: slib.info, Node: Requesting Features, Next: Library Catalogs, Prev: Feature, Up: The Library System Requesting Features =================== SLIB creates and maintains a "catalog" mapping features to locations of files introducing procedures and syntax denoted by those features. At the beginning of each section of this manual, there is a line like `(require 'FEATURE)'. The Scheme files comprising SLIB are cataloged so that these feature names map to the corresponding files. SLIB provides a form, `require', which loads the files providing the requested feature. - Procedure: require feature * If `(provided? FEATURE)' is true, then `require' just returns an unspecified value. * Otherwise, if FEATURE is found in the catalog, then the corresponding files will be loaded and an unspecified value returned. Subsequently `(provided? FEATURE)' will return `#t'. * Otherwise (FEATURE not found in the catalog), an error is signaled. The catalog can also be queried using `require:feature->path'. - Function: require:feature->path feature * If FEATURE is already provided, then returns `#t'. * Otherwise, if FEATURE is in the catalog, the path or list of paths associated with FEATURE is returned. * Otherwise, returns `#f'.  File: slib.info, Node: Library Catalogs, Next: Catalog Compilation, Prev: Requesting Features, Up: The Library System Library Catalogs ================ At the start of a session no catalog is present, but is created with the first catalog inquiry (such as `(require 'random)'). Several sources of catalog information are combined to produce the catalog: * standard SLIB packages. * additional packages of interest to this site. * packages specifically for the variety of Scheme which this session is running. * packages this user wants to always have available. This catalog is the file `homecat' in the user's "HOME" directory. * packages germane to working in this (current working) directory. This catalog is the file `usercat' in the directory to which it applies. One would typically `cd' to this directory before starting the Scheme session. Catalog files consist of one or more "association list"s. In the circumstance where a feature symbol appears in more than one list, the latter list's association is retrieved. Here are the supported formats for elements of catalog lists: `(FEATURE . )' Redirects to the feature named . `(FEATURE . "")' Loads file . `(FEATURE source "")' `slib:load's the Scheme source file . `(FEATURE compiled "" ...)' `slib:load-compiled's the files .... The various macro styles first `require' the named macro package, then just load or load-and-macro-expand as appropriate for the implementation. `(FEATURE defmacro "")' `defmacro:load's the Scheme source file . `(FEATURE macro-by-example "")' `defmacro:load's the Scheme source file . `(FEATURE macro "")' `macro:load's the Scheme source file . `(FEATURE macros-that-work "")' `macro:load's the Scheme source file . `(FEATURE syntax-case "")' `macro:load's the Scheme source file . `(FEATURE syntactic-closures "")' `macro:load's the Scheme source file . Here is an example of a `usercat' catalog. A Program in this directory can invoke the `run' feature with `(require 'run)'. ;;; "usercat": SLIB catalog additions for SIMSYNCH. -*-scheme-*- ( (simsynch . "../synch/simsynch.scm") (run . "../synch/run.scm") (schlep . "schlep.scm") )  File: slib.info, Node: Catalog Compilation, Next: Built-in Support, Prev: Library Catalogs, Up: The Library System Catalog Compilation =================== SLIB combines the catalog information which doesn't vary per user into the file `slibcat' in the implementation-vicinity. Therefore `slibcat' needs change only when new software is installed or compiled. Because the actual pathnames of files can differ from installation to installation, SLIB builds a separate catalog for each implementation it is used with. The definition of `*SLIB-VERSION*' in SLIB file `require.scm' is checked against the catalog association of `*SLIB-VERSION*' to ascertain when versions have changed. I recommend that the definition of `*SLIB-VERSION*' be changed whenever the library is changed. If multiple implementations of Scheme use SLIB, remember that recompiling one `slibcat' will fix only that implementation's catalog. The compilation scripts of Scheme implementations which work with SLIB can automatically trigger catalog compilation by deleting `slibcat' or by invoking a special form of `require': - Procedure: require 'new-catalog This will load `mklibcat', which compiles and writes a new `slibcat'. Another special form of `require' erases SLIB's catalog, forcing it to be reloaded the next time the catalog is queried. - Procedure: require #f Removes SLIB's catalog information. This should be done before saving an executable image so that, when restored, its catalog will be loaded afresh. Each file in the table below is descibed in terms of its file-system independent "vicinity" (*note Vicinity::). The entries of a catalog in the table override those of catalogs above it in the table. `implementation-vicinity' `slibcat' This file contains the associations for the packages comprising SLIB, the `implcat' and the `sitecat's. The associations in the other catalogs override those of the standard catalog. `library-vicinity' `mklibcat.scm' creates `slibcat'. `library-vicinity' `sitecat' This file contains the associations specific to an SLIB installation. `implementation-vicinity' `implcat' This file contains the associations specific to an implementation of Scheme. Different implementations of Scheme should have different `implementation-vicinity'. `implementation-vicinity' `mkimpcat.scm' if present, creates `implcat'. `implementation-vicinity' `sitecat' This file contains the associations specific to a Scheme implementation installation. `home-vicinity' `homecat' This file contains the associations specific to an SLIB user. `user-vicinity' `usercat' This file contains associations effecting only those sessions whose "working directory" is `user-vicinity'.  File: slib.info, Node: Built-in Support, Next: About this manual, Prev: Catalog Compilation, Up: The Library System Built-in Support ================ The procedures described in these sections are supported by all implementations as part of the `*.init' files or by `require.scm'. * Menu: * Require:: Module Management * Vicinity:: Pathname Management * Configuration:: Characteristics of Scheme Implementation * Input/Output:: Things not provided by the Scheme specs. * Legacy:: * System:: LOADing, EVALing, ERRORing, and EXITing  File: slib.info, Node: Require, Next: Vicinity, Prev: Built-in Support, Up: Built-in Support Require ------- - Variable: *features* Is a list of symbols denoting features supported in this implementation. *FEATURES* can grow as modules are `require'd. *FEATURES* must be defined by all implementations (*note Porting::). Here are features which SLIB (`require.scm') adds to *FEATURES* when appropriate. * 'inexact * 'rational * 'real * 'complex * 'bignum For each item, `(provided? 'FEATURE)' will return `#t' if that feature is available, and `#f' if not. - Variable: *modules* Is a list of pathnames denoting files which have been loaded. - Variable: *catalog* Is an association list of features (symbols) and pathnames which will supply those features. The pathname can be either a string or a pair. If pathname is a pair then the first element should be a macro feature symbol, `source', or `compiled'. The cdr of the pathname should be either a string or a list. In the following functions if the argument FEATURE is not a symbol it is assumed to be a pathname. - Function: provided? feature Returns `#t' if FEATURE is a member of `*features*' or `*modules*' or if FEATURE is supported by a file already loaded and `#f' otherwise. - Procedure: require feature FEATURE is a symbol. If `(provided? FEATURE)' is true `require' returns. Otherwise, if `(assq FEATURE *catalog*)' is not `#f', the associated files will be loaded and `(provided? FEATURE)' will henceforth return `#t'. An unspecified value is returned. If FEATURE is not found in `*catalog*', then an error is signaled. - Procedure: require pathname PATHNAME is a string. If PATHNAME has not already been given as an argument to `require', PATHNAME is loaded. An unspecified value is returned. - Procedure: provide feature Assures that FEATURE is contained in `*features*' if FEATURE is a symbol and `*modules*' otherwise. - Function: require:feature->path feature Returns `#t' if FEATURE is a member of `*features*' or `*modules*' or if FEATURE is supported by a file already loaded. Returns a path if one was found in `*catalog*' under the feature name, and `#f' otherwise. The path can either be a string suitable as an argument to load or a pair as described above for *catalog*.  File: slib.info, Node: Vicinity, Next: Configuration, Prev: Require, Up: Built-in Support Vicinity -------- A vicinity is a descriptor for a place in the file system. Vicinities hide from the programmer the concepts of host, volume, directory, and version. Vicinities express only the concept of a file environment where a file name can be resolved to a file in a system independent manner. Vicinities can even be used on "flat" file systems (which have no directory structure) by having the vicinity express constraints on the file name. On most systems a vicinity would be a string. All of these procedures are file system dependent. These procedures are provided by all implementations. - Function: make-vicinity path Returns the vicinity of PATH for use by `in-vicinity'. - Function: program-vicinity Returns the vicinity of the currently loading Scheme code. For an interpreter this would be the directory containing source code. For a compiled system (with multiple files) this would be the directory where the object or executable files are. If no file is currently loading it the result is undefined. *Warning:* `program-vicinity' can return incorrect values if your program escapes back into a `load'. - Function: library-vicinity Returns the vicinity of the shared Scheme library. - Function: implementation-vicinity Returns the vicinity of the underlying Scheme implementation. This vicinity will likely contain startup code and messages and a compiler. - Function: user-vicinity Returns the vicinity of the current directory of the user. On most systems this is `""' (the empty string). - Function: home-vicinity Returns the vicinity of the user's "HOME" directory, the directory which typically contains files which customize a computer environment for a user. If scheme is running without a user (eg. a daemon) or if this concept is meaningless for the platform, then `home-vicinity' returns `#f'. - Function: in-vicinity vicinity filename Returns a filename suitable for use by `slib:load', `slib:load-source', `slib:load-compiled', `open-input-file', `open-output-file', etc. The returned filename is FILENAME in VICINITY. `in-vicinity' should allow FILENAME to override VICINITY when FILENAME is an absolute pathname and VICINITY is equal to the value of `(user-vicinity)'. The behavior of `in-vicinity' when FILENAME is absolute and VICINITY is not equal to the value of `(user-vicinity)' is unspecified. For most systems `in-vicinity' can be `string-append'. - Function: sub-vicinity vicinity name Returns the vicinity of VICINITY restricted to NAME. This is used for large systems where names of files in subsystems could conflict. On systems with directory structure `sub-vicinity' will return a pathname of the subdirectory NAME of VICINITY.  File: slib.info, Node: Configuration, Next: Input/Output, Prev: Vicinity, Up: Built-in Support Configuration ------------- These constants and procedures describe characteristics of the Scheme and underlying operating system. They are provided by all implementations. - Constant: char-code-limit An integer 1 larger that the largest value which can be returned by `char->integer'. - Constant: most-positive-fixnum In implementations which support integers of practically unlimited size, MOST-POSITIVE-FIXNUM is a large exact integer within the range of exact integers that may result from computing the length of a list, vector, or string. In implementations which do not support integers of practically unlimited size, MOST-POSITIVE-FIXNUM is the largest exact integer that may result from computing the length of a list, vector, or string. - Constant: slib:tab The tab character. - Constant: slib:form-feed The form-feed character. - Function: software-type Returns a symbol denoting the generic operating system type. For instance, `unix', `vms', `macos', `amiga', or `ms-dos'. - Function: slib:report-version Displays the versions of SLIB and the underlying Scheme implementation and the name of the operating system. An unspecified value is returned. (slib:report-version) => slib "2d2" on scm "5b1" on unix | - Function: slib:report Displays the information of `(slib:report-version)' followed by almost all the information neccessary for submitting a problem report. An unspecified value is returned. - Function: slib:report #t provides a more verbose listing. - Function: slib:report filename Writes the report to file `filename'. (slib:report) => slib "2d2" on scm "5b1" on unix | (implementation-vicinity) is "/home/jaffer/scm/" (library-vicinity) is "/home/jaffer/slib/" (scheme-file-suffix) is ".scm" loaded *features* : trace alist qp sort common-list-functions macro values getopt compiled implementation *features* : bignum complex real rational inexact vicinity ed getenv tmpnam abort transcript with-file ieee-p1178 rev4-report rev4-optional-procedures hash object-hash delay eval dynamic-wind multiarg-apply multiarg/and- logical defmacro string-port source current-time record rev3-procedures rev2-procedures sun-dl string-case array dump char-ready? full-continuation system implementation *catalog* : (i/o-extensions compiled "/home/jaffer/scm/ioext.so") ...  File: slib.info, Node: Input/Output, Next: Legacy, Prev: Configuration, Up: Built-in Support Input/Output ------------ These procedures are provided by all implementations. - Procedure: file-exists? filename Returns `#t' if the specified file exists. Otherwise, returns `#f'. If the underlying implementation does not support this feature then `#f' is always returned. - Procedure: delete-file filename Deletes the file specified by FILENAME. If FILENAME can not be deleted, `#f' is returned. Otherwise, `#t' is returned. - Procedure: tmpnam Returns a pathname for a file which will likely not be used by any other process. Successive calls to `(tmpnam)' will return different pathnames. - Procedure: current-error-port Returns the current port to which diagnostic and error output is directed. - Procedure: force-output - Procedure: force-output port Forces any pending output on PORT to be delivered to the output device and returns an unspecified value. The PORT argument may be omitted, in which case it defaults to the value returned by `(current-output-port)'. - Procedure: output-port-width - Procedure: output-port-width port Returns the width of PORT, which defaults to `(current-output-port)' if absent. If the width cannot be determined 79 is returned. - Procedure: output-port-height - Procedure: output-port-height port Returns the height of PORT, which defaults to `(current-output-port)' if absent. If the height cannot be determined 24 is returned.  File: slib.info, Node: Legacy, Next: System, Prev: Input/Output, Up: Built-in Support Legacy ------ These procedures are provided by all implementations. - Function: identity x IDENTITY returns its argument. Example: (identity 3) => 3 (identity '(foo bar)) => (foo bar) (map identity LST) == (copy-list LST) The following procedures were present in Scheme until R4RS (*note Language changes: (r4rs)Notes.). They are provided by all SLIB implementations. - Constant: t Derfined as `#t'. - Constant: nil Defined as `#f'. - Function: last-pair l Returns the last pair in the list L. Example: (last-pair (cons 1 2)) => (1 . 2) (last-pair '(1 2)) => (2) == (cons 2 '())  File: slib.info, Node: System, Prev: Legacy, Up: Built-in Support System ------ These procedures are provided by all implementations. - Procedure: slib:load-source name Loads a file of Scheme source code from NAME with the default filename extension used in SLIB. For instance if the filename extension used in SLIB is `.scm' then `(slib:load-source "foo")' will load from file `foo.scm'. - Procedure: slib:load-compiled name On implementations which support separtely loadable compiled modules, loads a file of compiled code from NAME with the implementation's filename extension for compiled code appended. - Procedure: slib:load name Loads a file of Scheme source or compiled code from NAME with the appropriate suffixes appended. If both source and compiled code are present with the appropriate names then the implementation will load just one. It is up to the implementation to choose which one will be loaded. If an implementation does not support compiled code then `slib:load' will be identical to `slib:load-source'. - Procedure: slib:eval obj `eval' returns the value of OBJ evaluated in the current top level environment. *Note Eval:: provides a more general evaluation facility. - Procedure: slib:eval-load filename eval FILENAME should be a string. If filename names an existing file, the Scheme source code expressions and definitions are read from the file and EVAL called with them sequentially. The `slib:eval-load' procedure does not affect the values returned by `current-input-port' and `current-output-port'. - Procedure: slib:warn arg1 arg2 ... Outputs a warning message containing the arguments. - Procedure: slib:error arg1 arg2 ... Outputs an error message containing the arguments, aborts evaluation of the current form and responds in a system dependent way to the error. Typical responses are to abort the program or to enter a read-eval-print loop. - Procedure: slib:exit n - Procedure: slib:exit Exits from the Scheme session returning status N to the system. If N is omitted or `#t', a success status is returned to the system (if possible). If N is `#f' a failure is returned to the system (if possible). If N is an integer, then N is returned to the system (if possible). If the Scheme session cannot exit an unspecified value is returned from `slib:exit'.  File: slib.info, Node: About this manual, Prev: Built-in Support, Up: The Library System About this manual ================= * Entries that are labeled as Functions are called for their return values. Entries that are labeled as Procedures are called primarily for their side effects. * Examples in this text were produced using the `scm' Scheme implementation. * At the beginning of each section, there is a line that looks like `(require 'feature)'. Include this line in your code prior to using the package.  File: slib.info, Node: Scheme Syntax Extension Packages, Next: Textual Conversion Packages, Prev: The Library System, Up: Top Scheme Syntax Extension Packages ******************************** * Menu: * Defmacro:: Supported by all implementations * R4RS Macros:: 'macro * Macro by Example:: 'macro-by-example * Macros That Work:: 'macros-that-work * Syntactic Closures:: 'syntactic-closures * Syntax-Case Macros:: 'syntax-case Syntax extensions (macros) included with SLIB. | * Fluid-Let:: 'fluid-let * Yasos:: 'yasos, 'oop, 'collect  File: slib.info, Node: Defmacro, Next: R4RS Macros, Prev: Scheme Syntax Extension Packages, Up: Scheme Syntax Extension Packages Defmacro ======== Defmacros are supported by all implementations. - Function: gentemp Returns a new (interned) symbol each time it is called. The symbol names are implementation-dependent (gentemp) => scm:G0 (gentemp) => scm:G1 - Function: defmacro:eval e Returns the `slib:eval' of expanding all defmacros in scheme expression E. - Function: defmacro:load filename FILENAME should be a string. If filename names an existing file, the `defmacro:load' procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain defmacro definitions. The `macro:load' procedure does not affect the values returned by `current-input-port' and `current-output-port'. - Function: defmacro? sym Returns `#t' if SYM has been defined by `defmacro', `#f' otherwise. - Function: macroexpand-1 form - Function: macroexpand form If FORM is a macro call, `macroexpand-1' will expand the macro call once and return it. A FORM is considered to be a macro call only if it is a cons whose `car' is a symbol for which a `defmacro' has been defined. `macroexpand' is similar to `macroexpand-1', but repeatedly expands FORM until it is no longer a macro call. - Macro: defmacro name lambda-list form ... When encountered by `defmacro:eval', `defmacro:macroexpand*', or `defmacro:load' defines a new macro which will henceforth be expanded when encountered by `defmacro:eval', `defmacro:macroexpand*', or `defmacro:load'. Defmacroexpand -------------- `(require 'defmacroexpand)' - Function: defmacro:expand* e Returns the result of expanding all defmacros in scheme expression E.  File: slib.info, Node: R4RS Macros, Next: Macro by Example, Prev: Defmacro, Up: Scheme Syntax Extension Packages R4RS Macros =========== `(require 'macro)' is the appropriate call if you want R4RS high-level macros but don't care about the low level implementation. If an SLIB R4RS macro implementation is already loaded it will be used. Otherwise, one of the R4RS macros implemetations is loaded. The SLIB R4RS macro implementations support the following uniform interface: - Function: macro:expand sexpression Takes an R4RS expression, macro-expands it, and returns the result of the macro expansion. - Function: macro:eval sexpression Takes an R4RS expression, macro-expands it, evals the result of the macro expansion, and returns the result of the evaluation. - Procedure: macro:load filename FILENAME should be a string. If filename names an existing file, the `macro:load' procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The `macro:load' procedure does not affect the values returned by `current-input-port' and `current-output-port'.  File: slib.info, Node: Macro by Example, Next: Macros That Work, Prev: R4RS Macros, Up: Scheme Syntax Extension Packages Macro by Example ================ `(require 'macro-by-example)' A vanilla implementation of `Macro by Example' (Eugene Kohlbecker, R4RS) by Dorai Sitaram, (dorai @ cs.rice.edu) using `defmacro'. * generating hygienic global `define-syntax' Macro-by-Example macros *cheaply*. * can define macros which use `...'. * needn't worry about a lexical variable in a macro definition clashing with a variable from the macro use context * don't suffer the overhead of redefining the repl if `defmacro' natively supported (most implementations) Caveat ------ These macros are not referentially transparent (*note Macros: (r4rs)Macros.). Lexically scoped macros (i.e., `let-syntax' and `letrec-syntax') are not supported. In any case, the problem of referential transparency gains poignancy only when `let-syntax' and `letrec-syntax' are used. So you will not be courting large-scale disaster unless you're using system-function names as local variables with unintuitive bindings that the macro can't use. However, if you must have the full `r4rs' macro functionality, look to the more featureful (but also more expensive) versions of syntax-rules available in slib *Note Macros That Work::, *Note Syntactic Closures::, and *Note Syntax-Case Macros::. - Macro: define-syntax keyword transformer-spec The KEYWORD is an identifier, and the TRANSFORMER-SPEC should be an instance of `syntax-rules'. The top-level syntactic environment is extended by binding the KEYWORD to the specified transformer. (define-syntax let* (syntax-rules () ((let* () body1 body2 ...) (let () body1 body2 ...)) ((let* ((name1 val1) (name2 val2) ...) body1 body2 ...) (let ((name1 val1)) (let* (( name2 val2) ...) body1 body2 ...))))) - Macro: syntax-rules literals syntax-rule ... LITERALS is a list of identifiers, and each SYNTAX-RULE should be of the form `(PATTERN TEMPLATE)' where the PATTERN and TEMPLATE are as in the grammar above. An instance of `syntax-rules' produces a new macro transformer by specifying a sequence of hygienic rewrite rules. A use of a macro whose keyword is associated with a transformer specified by `syntax-rules' is matched against the patterns contained in the SYNTAX-RULEs, beginning with the leftmost SYNTAX-RULE. When a match is found, the macro use is trancribed hygienically according to the template. Each pattern begins with the keyword for the macro. This keyword is not involved in the matching and is not considered a pattern variable or literal identifier.  File: slib.info, Node: Macros That Work, Next: Syntactic Closures, Prev: Macro by Example, Up: Scheme Syntax Extension Packages Macros That Work ================ `(require 'macros-that-work)' `Macros That Work' differs from the other R4RS macro implementations in that it does not expand derived expression types to primitive expression types. - Function: macro:expand expression - Function: macwork:expand expression Takes an R4RS expression, macro-expands it, and returns the result of the macro expansion. - Function: macro:eval expression - Function: macwork:eval expression `macro:eval' returns the value of EXPRESSION in the current top level environment. EXPRESSION can contain macro definitions. Side effects of EXPRESSION will affect the top level environment. - Procedure: macro:load filename - Procedure: macwork:load filename FILENAME should be a string. If filename names an existing file, the `macro:load' procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The `macro:load' procedure does not affect the values returned by `current-input-port' and `current-output-port'. References: The `Revised^4 Report on the Algorithmic Language Scheme' Clinger and Rees [editors]. To appear in LISP Pointers. Also available as a technical report from the University of Oregon, MIT AI Lab, and Cornell. Macros That Work. Clinger and Rees. POPL '91. The supported syntax differs from the R4RS in that vectors are allowed as patterns and as templates and are not allowed as pattern or template data. transformer spec ==> (syntax-rules literals rules) rules ==> () | (rule . rules) rule ==> (pattern template) pattern ==> pattern_var ; a symbol not in literals | symbol ; a symbol in literals | () | (pattern . pattern) | (ellipsis_pattern) | #(pattern*) ; extends R4RS | #(pattern* ellipsis_pattern) ; extends R4RS | pattern_datum template ==> pattern_var | symbol | () | (template2 . template2) | #(template*) ; extends R4RS | pattern_datum template2 ==> template | ellipsis_template pattern_datum ==> string ; no vector | character | boolean | number ellipsis_pattern ==> pattern ... ellipsis_template ==> template ... pattern_var ==> symbol ; not in literals literals ==> () | (symbol . literals) Definitions ----------- Scope of an ellipsis Within a pattern or template, the scope of an ellipsis (`...') is the pattern or template that appears to its left. Rank of a pattern variable The rank of a pattern variable is the number of ellipses within whose scope it appears in the pattern. Rank of a subtemplate The rank of a subtemplate is the number of ellipses within whose scope it appears in the template. Template rank of an occurrence of a pattern variable The template rank of an occurrence of a pattern variable within a template is the rank of that occurrence, viewed as a subtemplate. Variables bound by a pattern The variables bound by a pattern are the pattern variables that appear within it. Referenced variables of a subtemplate The referenced variables of a subtemplate are the pattern variables that appear within it. Variables opened by an ellipsis template The variables opened by an ellipsis template are the referenced pattern variables whose rank is greater than the rank of the ellipsis template. Restrictions ------------ No pattern variable appears more than once within a pattern. For every occurrence of a pattern variable within a template, the template rank of the occurrence must be greater than or equal to the pattern variable's rank. Every ellipsis template must open at least one variable. For every ellipsis template, the variables opened by an ellipsis template must all be bound to sequences of the same length. The compiled form of a RULE is rule ==> (pattern template inserted) pattern ==> pattern_var | symbol | () | (pattern . pattern) | ellipsis_pattern | #(pattern) | pattern_datum template ==> pattern_var | symbol | () | (template2 . template2) | #(pattern) | pattern_datum template2 ==> template | ellipsis_template pattern_datum ==> string | character | boolean | number pattern_var ==> #(V symbol rank) ellipsis_pattern ==> #(E pattern pattern_vars) ellipsis_template ==> #(E template pattern_vars) inserted ==> () | (symbol . inserted) pattern_vars ==> () | (pattern_var . pattern_vars) rank ==> exact non-negative integer where V and E are unforgeable values. The pattern variables associated with an ellipsis pattern are the variables bound by the pattern, and the pattern variables associated with an ellipsis template are the variables opened by the ellipsis template. If the template contains a big chunk that contains no pattern variables or inserted identifiers, then the big chunk will be copied unnecessarily. That shouldn't matter very often.  File: slib.info, Node: Syntactic Closures, Next: Syntax-Case Macros, Prev: Macros That Work, Up: Scheme Syntax Extension Packages Syntactic Closures ================== `(require 'syntactic-closures)' - Function: macro:expand expression - Function: synclo:expand expression Returns scheme code with the macros and derived expression types of EXPRESSION expanded to primitive expression types. - Function: macro:eval expression - Function: synclo:eval expression `macro:eval' returns the value of EXPRESSION in the current top level environment. EXPRESSION can contain macro definitions. Side effects of EXPRESSION will affect the top level environment. - Procedure: macro:load filename - Procedure: synclo:load filename FILENAME should be a string. If filename names an existing file, the `macro:load' procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The `macro:load' procedure does not affect the values returned by `current-input-port' and `current-output-port'. Syntactic Closure Macro Facility -------------------------------- A Syntactic Closures Macro Facility by Chris Hanson 9 November 1991 This document describes "syntactic closures", a low-level macro facility for the Scheme programming language. The facility is an alternative to the low-level macro facility described in the `Revised^4 Report on Scheme.' This document is an addendum to that report. The syntactic closures facility extends the BNF rule for TRANSFORMER SPEC to allow a new keyword that introduces a low-level macro transformer: TRANSFORMER SPEC := (transformer EXPRESSION) Additionally, the following procedures are added: make-syntactic-closure capture-syntactic-environment identifier? identifier=? The description of the facility is divided into three parts. The first part defines basic terminology. The second part describes how macro transformers are defined. The third part describes the use of "identifiers", which extend the syntactic closure mechanism to be compatible with `syntax-rules'. Terminology ........... This section defines the concepts and data types used by the syntactic closures facility. * "Forms" are the syntactic entities out of which programs are recursively constructed. A form is any expression, any definition, any syntactic keyword, or any syntactic closure. The variable name that appears in a `set!' special form is also a form. Examples of forms: 17 #t car (+ x 4) (lambda (x) x) (define pi 3.14159) if define * An "alias" is an alternate name for a given symbol. It can appear anywhere in a form that the symbol could be used, and when quoted it is replaced by the symbol; however, it does not satisfy the predicate `symbol?'. Macro transformers rarely distinguish symbols from aliases, referring to both as identifiers. * A "syntactic" environment maps identifiers to their meanings. More precisely, it determines whether an identifier is a syntactic keyword or a variable. If it is a keyword, the meaning is an interpretation for the form in which that keyword appears. If it is a variable, the meaning identifies which binding of that variable is referenced. In short, syntactic environments contain all of the contextual information necessary for interpreting the meaning of a particular form. * A "syntactic closure" consists of a form, a syntactic environment, and a list of identifiers. All identifiers in the form take their meaning from the syntactic environment, except those in the given list. The identifiers in the list are to have their meanings determined later. A syntactic closure may be used in any context in which its form could have been used. Since a syntactic closure is also a form, it may not be used in contexts where a form would be illegal. For example, a form may not appear as a clause in the cond special form. A syntactic closure appearing in a quoted structure is replaced by its form. Transformer Definition ...................... This section describes the `transformer' special form and the procedures `make-syntactic-closure' and `capture-syntactic-environment'. - Syntax: transformer expression Syntax: It is an error if this syntax occurs except as a TRANSFORMER SPEC. Semantics: The EXPRESSION is evaluated in the standard transformer environment to yield a macro transformer as described below. This macro transformer is bound to a macro keyword by the special form in which the `transformer' expression appears (for example, `let-syntax'). A "macro transformer" is a procedure that takes two arguments, a form and a syntactic environment, and returns a new form. The first argument, the "input form", is the form in which the macro keyword occurred. The second argument, the "usage environment", is the syntactic environment in which the input form occurred. The result of the transformer, the "output form", is automatically closed in the "transformer environment", which is the syntactic environment in which the `transformer' expression occurred. For example, here is a definition of a push macro using `syntax-rules': (define-syntax push (syntax-rules () ((push item list) (set! list (cons item list))))) Here is an equivalent definition using `transformer': (define-syntax push (transformer (lambda (exp env) (let ((item (make-syntactic-closure env '() (cadr exp))) (list (make-syntactic-closure env '() (caddr exp)))) `(set! ,list (cons ,item ,list)))))) In this example, the identifiers `set!' and `cons' are closed in the transformer environment, and thus will not be affected by the meanings of those identifiers in the usage environment `env'. Some macros may be non-hygienic by design. For example, the following defines a loop macro that implicitly binds `exit' to an escape procedure. The binding of `exit' is intended to capture free references to `exit' in the body of the loop, so `exit' must be left free when the body is closed: (define-syntax loop (transformer (lambda (exp env) (let ((body (cdr exp))) `(call-with-current-continuation (lambda (exit) (let f () ,@(map (lambda (exp) (make-syntactic-closure env '(exit) exp)) body) (f)))))))) To assign meanings to the identifiers in a form, use `make-syntactic-closure' to close the form in a syntactic environment. - Function: make-syntactic-closure environment free-names form ENVIRONMENT must be a syntactic environment, FREE-NAMES must be a list of identifiers, and FORM must be a form. `make-syntactic-closure' constructs and returns a syntactic closure of FORM in ENVIRONMENT, which can be used anywhere that FORM could have been used. All the identifiers used in FORM, except those explicitly excepted by FREE-NAMES, obtain their meanings from ENVIRONMENT. Here is an example where FREE-NAMES is something other than the empty list. It is instructive to compare the use of FREE-NAMES in this example with its use in the `loop' example above: the examples are similar except for the source of the identifier being left free. (define-syntax let1 (transformer (lambda (exp env) (let ((id (cadr exp)) (init (caddr exp)) (exp (cadddr exp))) `((lambda (,id) ,(make-syntactic-closure env (list id) exp)) ,(make-syntactic-closure env '() init)))))) `let1' is a simplified version of `let' that only binds a single identifier, and whose body consists of a single expression. When the body expression is syntactically closed in its original syntactic environment, the identifier that is to be bound by `let1' must be left free, so that it can be properly captured by the `lambda' in the output form. To obtain a syntactic environment other than the usage environment, use `capture-syntactic-environment'. - Function: capture-syntactic-environment procedure `capture-syntactic-environment' returns a form that will, when transformed, call PROCEDURE on the current syntactic environment. PROCEDURE should compute and return a new form to be transformed, in that same syntactic environment, in place of the form. An example will make this clear. Suppose we wanted to define a simple `loop-until' keyword equivalent to (define-syntax loop-until (syntax-rules () ((loop-until id init test return step) (letrec ((loop (lambda (id) (if test return (loop step))))) (loop init))))) The following attempt at defining `loop-until' has a subtle bug: (define-syntax loop-until (transformer (lambda (exp env) (let ((id (cadr exp)) (init (caddr exp)) (test (cadddr exp)) (return (cadddr (cdr exp))) (step (cadddr (cddr exp))) (close (lambda (exp free) (make-syntactic-closure env free exp)))) `(letrec ((loop (lambda (,id) (if ,(close test (list id)) ,(close return (list id)) (loop ,(close step (list id))))))) (loop ,(close init '()))))))) This definition appears to take all of the proper precautions to prevent unintended captures. It carefully closes the subexpressions in their original syntactic environment and it leaves the `id' identifier free in the `test', `return', and `step' expressions, so that it will be captured by the binding introduced by the `lambda' expression. Unfortunately it uses the identifiers `if' and `loop' within that `lambda' expression, so if the user of `loop-until' just happens to use, say, `if' for the identifier, it will be inadvertently captured. The syntactic environment that `if' and `loop' want to be exposed to is the one just outside the `lambda' expression: before the user's identifier is added to the syntactic environment, but after the identifier loop has been added. `capture-syntactic-environment' captures exactly that environment as follows: (define-syntax loop-until (transformer (lambda (exp env) (let ((id (cadr exp)) (init (caddr exp)) (test (cadddr exp)) (return (cadddr (cdr exp))) (step (cadddr (cddr exp))) (close (lambda (exp free) (make-syntactic-closure env free exp)))) `(letrec ((loop ,(capture-syntactic-environment (lambda (env) `(lambda (,id) (,(make-syntactic-closure env '() `if) ,(close test (list id)) ,(close return (list id)) (,(make-syntactic-closure env '() `loop) ,(close step (list id))))))))) (loop ,(close init '()))))))) In this case, having captured the desired syntactic environment, it is convenient to construct syntactic closures of the identifiers `if' and the `loop' and use them in the body of the `lambda'. A common use of `capture-syntactic-environment' is to get the transformer environment of a macro transformer: (transformer (lambda (exp env) (capture-syntactic-environment (lambda (transformer-env) ...)))) Identifiers ........... This section describes the procedures that create and manipulate identifiers. Previous syntactic closure proposals did not have an identifier data type - they just used symbols. The identifier data type extends the syntactic closures facility to be compatible with the high-level `syntax-rules' facility. As discussed earlier, an identifier is either a symbol or an "alias". An alias is implemented as a syntactic closure whose "form" is an identifier: (make-syntactic-closure env '() 'a) => an "alias" Aliases are implemented as syntactic closures because they behave just like syntactic closures most of the time. The difference is that an alias may be bound to a new value (for example by `lambda' or `let-syntax'); other syntactic closures may not be used this way. If an alias is bound, then within the scope of that binding it is looked up in the syntactic environment just like any other identifier. Aliases are used in the implementation of the high-level facility `syntax-rules'. A macro transformer created by `syntax-rules' uses a template to generate its output form, substituting subforms of the input form into the template. In a syntactic closures implementation, all of the symbols in the template are replaced by aliases closed in the transformer environment, while the output form itself is closed in the usage environment. This guarantees that the macro transformation is hygienic, without requiring the transformer to know the syntactic roles of the substituted input subforms. - Function: identifier? object Returns `#t' if OBJECT is an identifier, otherwise returns `#f'. Examples: (identifier? 'a) => #t (identifier? (make-syntactic-closure env '() 'a)) => #t (identifier? "a") => #f (identifier? #\a) => #f (identifier? 97) => #f (identifier? #f) => #f (identifier? '(a)) => #f (identifier? '#(a)) => #f The predicate `eq?' is used to determine if two identifers are "the same". Thus `eq?' can be used to compare identifiers exactly as it would be used to compare symbols. Often, though, it is useful to know whether two identifiers "mean the same thing". For example, the `cond' macro uses the symbol `else' to identify the final clause in the conditional. A macro transformer for `cond' cannot just look for the symbol `else', because the `cond' form might be the output of another macro transformer that replaced the symbol `else' with an alias. Instead the transformer must look for an identifier that "means the same thing" in the usage environment as the symbol `else' means in the transformer environment. - Function: identifier=? environment1 identifier1 environment2 identifier2 ENVIRONMENT1 and ENVIRONMENT2 must be syntactic environments, and IDENTIFIER1 and IDENTIFIER2 must be identifiers. `identifier=?' returns `#t' if the meaning of IDENTIFIER1 in ENVIRONMENT1 is the same as that of IDENTIFIER2 in ENVIRONMENT2, otherwise it returns `#f'. Examples: (let-syntax ((foo (transformer (lambda (form env) (capture-syntactic-environment (lambda (transformer-env) (identifier=? transformer-env 'x env 'x))))))) (list (foo) (let ((x 3)) (foo)))) => (#t #f) (let-syntax ((bar foo)) (let-syntax ((foo (transformer (lambda (form env) (capture-syntactic-environment (lambda (transformer-env) (identifier=? transformer-env 'foo env (cadr form)))))))) (list (foo foo) (foobar)))) => (#f #t) Acknowledgements ................ The syntactic closures facility was invented by Alan Bawden and Jonathan Rees. The use of aliases to implement `syntax-rules' was invented by Alan Bawden (who prefers to call them "synthetic names"). Much of this proposal is derived from an earlier proposal by Alan Bawden.  File: slib.info, Node: Syntax-Case Macros, Next: Fluid-Let, Prev: Syntactic Closures, Up: Scheme Syntax Extension Packages Syntax-Case Macros ================== `(require 'syntax-case)' - Function: macro:expand expression - Function: syncase:expand expression Returns scheme code with the macros and derived expression types of EXPRESSION expanded to primitive expression types. - Function: macro:eval expression - Function: syncase:eval expression `macro:eval' returns the value of EXPRESSION in the current top level environment. EXPRESSION can contain macro definitions. Side effects of EXPRESSION will affect the top level environment. - Procedure: macro:load filename - Procedure: syncase:load filename FILENAME should be a string. If filename names an existing file, the `macro:load' procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The `macro:load' procedure does not affect the values returned by `current-input-port' and `current-output-port'. This is version 2.1 of `syntax-case', the low-level macro facility proposed and implemented by Robert Hieb and R. Kent Dybvig. This version is further adapted by Harald Hanche-Olsen to make it compatible with, and easily usable with, SLIB. | Mainly, these adaptations consisted of: | * Removing white space from `expand.pp' to save space in the distribution. This file is not meant for human readers anyway... * Removed a couple of Chez scheme dependencies. * Renamed global variables used to minimize the possibility of name conflicts. * Adding an SLIB-specific initialization file. * Removing a couple extra files, most notably the documentation (but see below). If you wish, you can see exactly what changes were done by reading the shell script in the file `syncase.sh'. The two PostScript files were omitted in order to not burden the SLIB distribution with them. If you do intend to use `syntax-case', however, you should get these files and print them out on a PostScript printer. They are available with the original `syntax-case' distribution by anonymous FTP in `cs.indiana.edu:/pub/scheme/syntax-case'. In order to use syntax-case from an interactive top level, execute: (require 'syntax-case) (require 'repl) (repl:top-level macro:eval) See the section Repl (*note Repl::) for more information. To check operation of syntax-case get `cs.indiana.edu:/pub/scheme/syntax-case', and type (require 'syntax-case) (syncase:sanity-check) Beware that `syntax-case' takes a long time to load - about 20s on a SPARCstation SLC (with SCM) and about 90s on a Macintosh SE/30 (with Gambit). Notes ----- All R4RS syntactic forms are defined, including `delay'. Along with `delay' are simple definitions for `make-promise' (into which `delay' expressions expand) and `force'. `syntax-rules' and `with-syntax' (described in `TR356') are defined. `syntax-case' is actually defined as a macro that expands into calls to the procedure `syntax-dispatch' and the core form `syntax-lambda'; do not redefine these names. Several other top-level bindings not documented in TR356 are created: * the "hooks" in `hooks.ss' * the `build-' procedures in `output.ss' * `expand-syntax' (the expander) The syntax of define has been extended to allow `(define ID)', which assigns ID to some unspecified value. We have attempted to maintain R4RS compatibility where possible. The incompatibilities should be confined to `hooks.ss'. Please let us know if there is some incompatibility that is not flagged as such. Send bug reports, comments, suggestions, and questions to Kent Dybvig (dyb @ iuvax.cs.indiana.edu). Note from maintainer -------------------- Included with the `syntax-case' files was `structure.scm' which defines a macro `define-structure'. There is no documentation for this macro and it is not used by any code in SLIB.  File: slib.info, Node: Fluid-Let, Next: Yasos, Prev: Syntax-Case Macros, Up: Scheme Syntax Extension Packages Fluid-Let ========= `(require 'fluid-let)' - Syntax: fluid-let `(BINDINGS ...)' FORMS... (fluid-let ((VARIABLE INIT) ...) EXPRESSION EXPRESSION ...) The INITs are evaluated in the current environment (in some unspecified order), the current values of the VARIABLEs are saved, the results are assigned to the VARIABLEs, the EXPRESSIONs are evaluated sequentially in the current environment, the VARIABLEs are restored to their original values, and the value of the last EXPRESSION is returned. The syntax of this special form is similar to that of `let', but `fluid-let' temporarily rebinds existing VARIABLEs. Unlike `let', `fluid-let' creates no new bindings; instead it _assigns_ the values of each INIT to the binding (determined by the rules of lexical scoping) of its corresponding VARIABLE.  File: slib.info, Node: Yasos, Prev: Fluid-Let, Up: Scheme Syntax Extension Packages Yasos ===== `(require 'oop)' or `(require 'yasos)' `Yet Another Scheme Object System' is a simple object system for Scheme based on the paper by Norman Adams and Jonathan Rees: `Object Oriented Programming in Scheme', Proceedings of the 1988 ACM Conference on LISP and Functional Programming, July 1988 [ACM #552880]. Another reference is: Ken Dickey. Scheming with Objects `AI Expert' Volume 7, Number 10 (October 1992), pp. 24-33. * Menu: * Yasos terms:: Definitions and disclaimer. * Yasos interface:: The Yasos macros and procedures. * Setters:: Dylan-like setters in Yasos. * Yasos examples:: Usage of Yasos and setters.  File: slib.info, Node: Yasos terms, Next: Yasos interface, Prev: Yasos, Up: Yasos Terms ----- "Object" Any Scheme data object. "Instance" An instance of the OO system; an "object". "Operation" A METHOD. _Notes:_ The object system supports multiple inheritance. An instance can inherit from 0 or more ancestors. In the case of multiple inherited operations with the same identity, the operation used is that from the first ancestor which contains it (in the ancestor `let'). An operation may be applied to any Scheme data object--not just instances. As code which creates instances is just code, there are no "classes" and no meta-ANYTHING. Method dispatch is by a procedure call a la CLOS rather than by `send' syntax a la Smalltalk. _Disclaimer:_ There are a number of optimizations which can be made. This implementation is expository (although performance should be quite reasonable). See the L&FP paper for some suggestions.  File: slib.info, Node: Yasos interface, Next: Setters, Prev: Yasos terms, Up: Yasos Interface --------- - Syntax: define-operation `('opname self arg ...`)' DEFAULT-BODY Defines a default behavior for data objects which don't handle the operation OPNAME. The default behavior (for an empty DEFAULT-BODY) is to generate an error. - Syntax: define-predicate opname? Defines a predicate OPNAME?, usually used for determining the "type" of an object, such that `(OPNAME? OBJECT)' returns `#t' if OBJECT has an operation OPNAME? and `#f' otherwise. - Syntax: object `((NAME SELF ARG ...) BODY)' ... Returns an object (an instance of the object system) with operations. Invoking `(NAME OBJECT ARG ...' executes the BODY of the OBJECT with SELF bound to OBJECT and with argument(s) ARG.... - Syntax: object-with-ancestors `(('ancestor1 init1`)' ...`)' operation ... A `let'-like form of `object' for multiple inheritance. It returns an object inheriting the behaviour of ANCESTOR1 etc. An operation will be invoked in an ancestor if the object itself does not provide such a method. In the case of multiple inherited operations with the same identity, the operation used is the one found in the first ancestor in the ancestor list. - Syntax: operate-as component operation self arg ... Used in an operation definition (of SELF) to invoke the OPERATION in an ancestor COMPONENT but maintain the object's identity. Also known as "send-to-super". - Procedure: print obj port A default `print' operation is provided which is just `(format PORT OBJ)' (*note Format::) for non-instances and prints OBJ preceded by `#' for instances. - Function: size obj The default method returns the number of elements in OBJ if it is a vector, string or list, `2' for a pair, `1' for a character and by default id an error otherwise. Objects such as collections (*note Collections::) may override the default in an obvious way.  File: slib.info, Node: Setters, Next: Yasos examples, Prev: Yasos interface, Up: Yasos Setters ------- "Setters" implement "generalized locations" for objects associated with some sort of mutable state. A "getter" operation retrieves a value from a generalized location and the corresponding setter operation stores a value into the location. Only the getter is named - the setter is specified by a procedure call as below. (Dylan uses special syntax.) Typically, but not necessarily, getters are access operations to extract values from Yasos objects (*note Yasos::). Several setters are predefined, corresponding to getters `car', `cdr', `string-ref' and `vector-ref' e.g., `(setter car)' is equivalent to `set-car!'. This implementation of setters is similar to that in Dylan(TM) (`Dylan: An object-oriented dynamic language', Apple Computer Eastern Research and Technology). Common LISP provides similar facilities through `setf'. - Function: setter getter Returns the setter for the procedure GETTER. E.g., since `string-ref' is the getter corresponding to a setter which is actually `string-set!': (define foo "foo") ((setter string-ref) foo 0 #\F) ; set element 0 of foo foo => "Foo" - Syntax: set place new-value If PLACE is a variable name, `set' is equivalent to `set!'. Otherwise, PLACE must have the form of a procedure call, where the procedure name refers to a getter and the call indicates an accessible generalized location, i.e., the call would return a value. The return value of `set' is usually unspecified unless used with a setter whose definition guarantees to return a useful value. (set (string-ref foo 2) #\O) ; generalized location with getter foo => "FoO" (set foo "foo") ; like set! foo => "foo" - Procedure: add-setter getter setter Add procedures GETTER and SETTER to the (inaccessible) list of valid setter/getter pairs. SETTER implements the store operation corresponding to the GETTER access operation for the relevant state. The return value is unspecified. - Procedure: remove-setter-for getter Removes the setter corresponding to the specified GETTER from the list of valid setters. The return value is unspecified. - Syntax: define-access-operation getter-name Shorthand for a Yasos `define-operation' defining an operation GETTER-NAME that objects may support to return the value of some mutable state. The default operation is to signal an error. The return value is unspecified.  File: slib.info, Node: Yasos examples, Prev: Setters, Up: Yasos Examples -------- ;;; These definitions for PRINT and SIZE are ;;; already supplied by (require 'yasos) (define-operation (print obj port) (format port (if (instance? obj) "#" "~s") obj)) (define-operation (size obj) (cond ((vector? obj) (vector-length obj)) ((list? obj) (length obj)) ((pair? obj) 2) ((string? obj) (string-length obj)) ((char? obj) 1) (else (error "Operation not supported: size" obj)))) (define-predicate cell?) (define-operation (fetch obj)) (define-operation (store! obj newValue)) (define (make-cell value) (object ((cell? self) #t) ((fetch self) value) ((store! self newValue) (set! value newValue) newValue) ((size self) 1) ((print self port) (format port "#" (fetch self))))) (define-operation (discard obj value) (format #t "Discarding ~s~%" value)) (define (make-filtered-cell value filter) (object-with-ancestors ((cell (make-cell value))) ((store! self newValue) (if (filter newValue) (store! cell newValue) (discard self newValue))))) (define-predicate array?) (define-operation (array-ref array index)) (define-operation (array-set! array index value)) (define (make-array num-slots) (let ((anArray (make-vector num-slots))) (object ((array? self) #t) ((size self) num-slots) ((array-ref self index) (vector-ref anArray index)) ((array-set! self index newValue) (vector-set! anArray index newValue)) ((print self port) (format port "#" (size self)))))) (define-operation (position obj)) (define-operation (discarded-value obj)) (define (make-cell-with-history value filter size) (let ((pos 0) (most-recent-discard #f)) (object-with-ancestors ((cell (make-filtered-call value filter)) (sequence (make-array size))) ((array? self) #f) ((position self) pos) ((store! self newValue) (operate-as cell store! self newValue) (array-set! self pos newValue) (set! pos (+ pos 1))) ((discard self value) (set! most-recent-discard value)) ((discarded-value self) most-recent-discard) ((print self port) (format port "#" (fetch self)))))) (define-access-operation fetch) (add-setter fetch store!) (define foo (make-cell 1)) (print foo #f) => "#" (set (fetch foo) 2) => (print foo #f) => "#" (fetch foo) => 2  File: slib.info, Node: Textual Conversion Packages, Next: Mathematical Packages, Prev: Scheme Syntax Extension Packages, Up: Top Textual Conversion Packages *************************** * Menu: * Precedence Parsing:: * Format:: Common-Lisp Format * Standard Formatted I/O:: Posix printf and scanf * Programs and Arguments:: * HTML:: * HTML Tables:: Databases meet HTML * HTTP and CGI:: Serve WWW sites * URI:: Uniform Resource Identifier * Printing Scheme:: Nicely * Time and Date:: * Vector Graphics:: * Schmooz:: Documentation markup for Scheme programs  File: slib.info, Node: Precedence Parsing, Next: Format, Prev: Textual Conversion Packages, Up: Textual Conversion Packages Precedence Parsing ================== `(require 'precedence-parse)' or `(require 'parse)' This package implements: * a Pratt style precedence parser; * a "tokenizer" which congeals tokens according to assigned classes of constituent characters; * procedures giving direct control of parser rulesets; * procedures for higher level specification of rulesets. * Menu: * Precedence Parsing Overview:: * Ruleset Definition and Use:: * Token definition:: * Nud and Led Definition:: * Grammar Rule Definition::  File: slib.info, Node: Precedence Parsing Overview, Next: Ruleset Definition and Use, Prev: Precedence Parsing, Up: Precedence Parsing Precedence Parsing Overview --------------------------- This package offers improvements over previous parsers. * Common computer language constructs are concisely specified. * Grammars can be changed dynamically. Operators can be assigned different meanings within a lexical context. * Rulesets don't need compilation. Grammars can be changed incrementally. * Operator precedence is specified by integers. * All possibilities of bad input are handled (1) and return as much structure as was parsed when the error occured; The symbol `?' is substituted for missing input. Here are the higher-level syntax types and an example of each. Precedence considerations are omitted for clarity. See *Note Grammar Rule Definition:: for full details. - Grammar: nofix bye exit bye calls the function `exit' with no arguments. - Grammar: prefix - negate - 42 Calls the function `negate' with the argument `42'. - Grammar: infix - difference x - y Calls the function `difference' with arguments `x' and `y'. - Grammar: nary + sum x + y + z Calls the function `sum' with arguments `x', `y', and `y'. - Grammar: postfix ! factorial 5 ! Calls the function `factorial' with the argument `5'. - Grammar: prestfix set set! set foo bar Calls the function `set!' with the arguments `foo' and `bar'. - Grammar: commentfix /* */ /* almost any text here */ Ignores the comment delimited by `/*' and `*/'. - Grammar: matchfix { list } {0, 1, 2} Calls the function `list' with the arguments `0', `1', and `2'. - Grammar: inmatchfix ( funcall ) f(x, y) Calls the function `funcall' with the arguments `f', `x', and `y'. - Grammar: delim ; set foo bar; delimits the extent of the restfix operator `set'. ---------- Footnotes ---------- (1) How do I know this? I parsed 250kbyte of random input (an e-mail file) with a non-trivial grammar utilizing all constructs.  File: slib.info, Node: Ruleset Definition and Use, Next: Token definition, Prev: Precedence Parsing Overview, Up: Precedence Parsing Ruleset Definition and Use -------------------------- - Variable: *syn-defs* A grammar is built by one or more calls to `prec:define-grammar'. The rules are appended to *SYN-DEFS*. The value of *SYN-DEFS* is the grammar suitable for passing as an argument to `prec:parse'. - Constant: *syn-ignore-whitespace* Is a nearly empty grammar with whitespace characters set to group 0, which means they will not be made into tokens. Most rulesets will want to start with `*syn-ignore-whitespace*' In order to start defining a grammar, either (set! *syn-defs* '()) or (set! *syn-defs* *syn-ignore-whitespace*) - Function: prec:define-grammar rule1 ... Appends RULE1 ... to *SYN-DEFS*. `prec:define-grammar' is used to define both the character classes and rules for tokens. Once your grammar is defined, save the value of `*syn-defs*' in a variable (for use when calling `prec:parse'). (define my-ruleset *syn-defs*) - Function: prec:parse ruleset delim - Function: prec:parse ruleset delim port The RULESET argument must be a list of rules as constructed by `prec:define-grammar' and extracted from *SYN-DEFS*. The token DELIM may be a character, symbol, or string. A character DELIM argument will match only a character token; i.e. a character for which no token-group is assigned. A symbols or string will match only a token string; i.e. a token resulting from a token group. `prec:parse' reads a RULESET grammar expression delimited by DELIM from the given input PORT. `prec:parse' returns the next object parsable from the given input PORT, updating PORT to point to the first character past the end of the external representation of the object. If an end of file is encountered in the input before any characters are found that can begin an object, then an end of file object is returned. If a delimiter (such as DELIM) is found before any characters are found that can begin an object, then `#f' is returned. The PORT argument may be omitted, in which case it defaults to the value returned by `current-input-port'. It is an error to parse from a closed port.  File: slib.info, Node: Token definition, Next: Nud and Led Definition, Prev: Ruleset Definition and Use, Up: Precedence Parsing Token definition ---------------- - Function: tok:char-group group chars chars-proc The argument CHARS may be a single character, a list of characters, or a string. Each character in CHARS is treated as though `tok:char-group' was called with that character alone. The argument CHARS-PROC must be a procedure of one argument, a list of characters. After `tokenize' has finished accumulating the characters for a token, it calls CHARS-PROC with the list of characters. The value returned is the token which `tokenize' returns. The argument GROUP may be an exact integer or a procedure of one character argument. The following discussion concerns the treatment which the tokenizing routine, `tokenize', will accord to characters on the basis of their groups. When GROUP is a non-zero integer, characters whose group number is equal to or exactly one less than GROUP will continue to accumulate. Any other character causes the accumulation to stop (until a new token is to be read). The GROUP of zero is special. These characters are ignored when parsed pending a token, and stop the accumulation of token characters when the accumulation has already begun. Whitespace characters are usually put in group 0. If GROUP is a procedure, then, when triggerd by the occurence of an initial (no accumulation) CHARS character, this procedure will be repeatedly called with each successive character from the input stream until the GROUP procedure returns a non-false value. The following convenient constants are provided for use with `tok:char-group'. - Constant: tok:decimal-digits Is the string `"0123456789"'. - Constant: tok:upper-case Is the string consisting of all upper-case letters ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"). - Constant: tok:lower-case Is the string consisting of all lower-case letters ("abcdefghijklmnopqrstuvwxyz"). - Constant: tok:whitespaces Is the string consisting of all characters between 0 and 255 for which `char-whitespace?' returns true.  File: slib.info, Node: Nud and Led Definition, Next: Grammar Rule Definition, Prev: Token definition, Up: Precedence Parsing Nud and Led Definition ---------------------- This section describes advanced features. You can skip this section on first reading. The "Null Denotation" (or "nud") of a token is the procedure and arguments applying for that token when "Left", an unclaimed parsed expression is not extant. The "Left Denotation" (or "led") of a token is the procedure, arguments, and lbp applying for that token when there is a "Left", an unclaimed parsed expression. In his paper, Pratt, V. R. Top Down Operator Precendence. `SIGACT/SIGPLAN Symposium on Principles of Programming Languages', Boston, 1973, pages 41-51 the "left binding power" (or "lbp") was an independent property of tokens. I think this was done in order to allow tokens with NUDs but not LEDs to also be used as delimiters, which was a problem for statically defined syntaxes. It turns out that _dynamically binding_ NUDs and LEDs allows them independence. For the rule-defining procedures that follow, the variable TK may be a character, string, or symbol, or a list composed of characters, strings, and symbols. Each element of TK is treated as though the procedure were called for each element. Character TK arguments will match only character tokens; i.e. characters for which no token-group is assigned. Symbols and strings will both match token strings; i.e. tokens resulting from token groups. - Function: prec:make-nud tk sop arg1 ... Returns a rule specifying that SOP be called when TK is parsed. If SOP is a procedure, it is called with TK and ARG1 ... as its arguments; the resulting value is incorporated into the expression being built. Otherwise, `(list SOP ARG1 ...)' is incorporated. If no NUD has been defined for a token; then if that token is a string, it is converted to a symbol and returned; if not a string, the token is returned. - Function: prec:make-led tk sop arg1 ... Returns a rule specifying that SOP be called when TK is parsed and LEFT has an unclaimed parsed expression. If SOP is a procedure, it is called with LEFT, TK, and ARG1 ... as its arguments; the resulting value is incorporated into the expression being built. Otherwise, LEFT is incorporated. If no LED has been defined for a token, and LEFT is set, the parser issues a warning.  File: slib.info, Node: Grammar Rule Definition, Prev: Nud and Led Definition, Up: Precedence Parsing Grammar Rule Definition ----------------------- Here are procedures for defining rules for the syntax types introduced in *Note Precedence Parsing Overview::. For the rule-defining procedures that follow, the variable TK may be a character, string, or symbol, or a list composed of characters, strings, and symbols. Each element of TK is treated as though the procedure were called for each element. For procedures prec:delim, ..., prec:prestfix, if the SOP argument is `#f', then the token which triggered this rule is converted to a symbol and returned. A false SOP argument to the procedures prec:commentfix, prec:matchfix, or prec:inmatchfix has a different meaning. Character TK arguments will match only character tokens; i.e. characters for which no token-group is assigned. Symbols and strings will both match token strings; i.e. tokens resulting from token groups. - Function: prec:delim tk Returns a rule specifying that TK should not be returned from parsing; i.e. TK's function is purely syntactic. The end-of-file is always treated as a delimiter. - Function: prec:nofix tk sop Returns a rule specifying the following actions take place when TK is parsed: * If SOP is a procedure, it is called with no arguments; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP is incorporated. - Function: prec:prefix tk sop bp rule1 ... Returns a rule specifying the following actions take place when TK is parsed: * The rules RULE1 ... augment and, in case of conflict, override rules currently in effect. * `prec:parse1' is called with binding-power BP. * If SOP is a procedure, it is called with the expression returned from `prec:parse1'; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP and the expression returned from `prec:parse1' is incorporated. * The ruleset in effect before TK was parsed is restored; RULE1 ... are forgotten. - Function: prec:infix tk sop lbp bp rule1 ... Returns a rule declaring the left-binding-precedence of the token TK is LBP and specifying the following actions take place when TK is parsed: * The rules RULE1 ... augment and, in case of conflict, override rules currently in effect. * One expression is parsed with binding-power LBP. If instead a delimiter is encountered, a warning is issued. * If SOP is a procedure, it is applied to the list of LEFT and the parsed expression; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP, the LEFT expression, and the parsed expression is incorporated. * The ruleset in effect before TK was parsed is restored; RULE1 ... are forgotten. - Function: prec:nary tk sop bp Returns a rule declaring the left-binding-precedence of the token TK is BP and specifying the following actions take place when TK is parsed: * Expressions are parsed with binding-power BP as far as they are interleaved with the token TK. * If SOP is a procedure, it is applied to the list of LEFT and the parsed expressions; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP, the LEFT expression, and the parsed expressions is incorporated. - Function: prec:postfix tk sop lbp Returns a rule declaring the left-binding-precedence of the token TK is LBP and specifying the following actions take place when TK is parsed: * If SOP is a procedure, it is called with the LEFT expression; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP and the LEFT expression is incorporated. - Function: prec:prestfix tk sop bp rule1 ... Returns a rule specifying the following actions take place when TK is parsed: * The rules RULE1 ... augment and, in case of conflict, override rules currently in effect. * Expressions are parsed with binding-power BP until a delimiter is reached. * If SOP is a procedure, it is applied to the list of parsed expressions; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP and the parsed expressions is incorporated. * The ruleset in effect before TK was parsed is restored; RULE1 ... are forgotten. - Function: prec:commentfix tk stp match rule1 ... Returns rules specifying the following actions take place when TK is parsed: * The rules RULE1 ... augment and, in case of conflict, override rules currently in effect. * Characters are read until and end-of-file or a sequence of characters is read which matches the _string_ MATCH. * If STP is a procedure, it is called with the string of all that was read between the TK and MATCH (exclusive). * The ruleset in effect before TK was parsed is restored; RULE1 ... are forgotten. Parsing of commentfix syntax differs from the others in several ways. It reads directly from input without tokenizing; It calls STP but does not return its value; nay any value. I added the STP argument so that comment text could be echoed. - Function: prec:matchfix tk sop sep match rule1 ... Returns a rule specifying the following actions take place when TK is parsed: * The rules RULE1 ... augment and, in case of conflict, override rules currently in effect. * A rule declaring the token MATCH a delimiter takes effect. * Expressions are parsed with binding-power `0' until the token MATCH is reached. If the token SEP does not appear between each pair of expressions parsed, a warning is issued. * If SOP is a procedure, it is applied to the list of parsed expressions; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP and the parsed expressions is incorporated. * The ruleset in effect before TK was parsed is restored; RULE1 ... are forgotten. - Function: prec:inmatchfix tk sop sep match lbp rule1 ... Returns a rule declaring the left-binding-precedence of the token TK is LBP and specifying the following actions take place when TK is parsed: * The rules RULE1 ... augment and, in case of conflict, override rules currently in effect. * A rule declaring the token MATCH a delimiter takes effect. * Expressions are parsed with binding-power `0' until the token MATCH is reached. If the token SEP does not appear between each pair of expressions parsed, a warning is issued. * If SOP is a procedure, it is applied to the list of LEFT and the parsed expressions; the resulting value is incorporated into the expression being built. Otherwise, the list of SOP, the LEFT expression, and the parsed expressions is incorporated. * The ruleset in effect before TK was parsed is restored; RULE1 ... are forgotten.  File: slib.info, Node: Format, Next: Standard Formatted I/O, Prev: Precedence Parsing, Up: Textual Conversion Packages Format (version 3.0) ==================== `(require 'format)' * Menu: * Format Interface:: * Format Specification::  File: slib.info, Node: Format Interface, Next: Format Specification, Prev: Format, Up: Format Format Interface ---------------- - Function: format destination format-string . arguments An almost complete implementation of Common LISP format description according to the CL reference book `Common LISP' from Guy L. Steele, Digital Press. Backward compatible to most of the available Scheme format implementations. Returns `#t', `#f' or a string; has side effect of printing according to FORMAT-STRING. If DESTINATION is `#t', the output is to the current output port and `#t' is returned. If DESTINATION is `#f', a formatted string is returned as the result of the call. NEW: If DESTINATION is a string, DESTINATION is regarded as the format string; FORMAT-STRING is then the first argument and the output is returned as a string. If DESTINATION is a number, the output is to the current error port if available by the implementation. Otherwise DESTINATION must be an output port and `#t' is returned. FORMAT-STRING must be a string. In case of a formatting error format returns `#f' and prints a message on the current output or error port. Characters are output as if the string were output by the `display' function with the exception of those prefixed by a tilde (~). For a detailed description of the FORMAT-STRING syntax please consult a Common LISP format reference manual. For a test suite to verify this format implementation load `formatst.scm'. Please send bug reports to `lutzeb@cs.tu-berlin.de'. Note: `format' is not reentrant, i.e. only one `format'-call may be executed at a time.  File: slib.info, Node: Format Specification, Prev: Format Interface, Up: Format Format Specification (Format version 3.0) ----------------------------------------- Please consult a Common LISP format reference manual for a detailed description of the format string syntax. For a demonstration of the implemented directives see `formatst.scm'. This implementation supports directive parameters and modifiers (`:' and `@' characters). Multiple parameters must be separated by a comma (`,'). Parameters can be numerical parameters (positive or negative), character parameters (prefixed by a quote character (`''), variable parameters (`v'), number of rest arguments parameter (`#'), empty and default parameters. Directive characters are case independent. The general form of a directive is: DIRECTIVE ::= ~{DIRECTIVE-PARAMETER,}[:][@]DIRECTIVE-CHARACTER DIRECTIVE-PARAMETER ::= [ [-|+]{0-9}+ | 'CHARACTER | v | # ] Implemented CL Format Control Directives ........................................ Documentation syntax: Uppercase characters represent the corresponding control directive characters. Lowercase characters represent control directive parameter descriptions. `~A' Any (print as `display' does). `~@A' left pad. `~MINCOL,COLINC,MINPAD,PADCHARA' full padding. `~S' S-expression (print as `write' does). `~@S' left pad. `~MINCOL,COLINC,MINPAD,PADCHARS' full padding. `~D' Decimal. `~@D' print number sign always. `~:D' print comma separated. `~MINCOL,PADCHAR,COMMACHARD' padding. `~X' Hexadecimal. `~@X' print number sign always. `~:X' print comma separated. `~MINCOL,PADCHAR,COMMACHARX' padding. `~O' Octal. `~@O' print number sign always. `~:O' print comma separated. `~MINCOL,PADCHAR,COMMACHARO' padding. `~B' Binary. `~@B' print number sign always. `~:B' print comma separated. `~MINCOL,PADCHAR,COMMACHARB' padding. `~NR' Radix N. `~N,MINCOL,PADCHAR,COMMACHARR' padding. `~@R' print a number as a Roman numeral. `~:@R' print a number as an "old fashioned" Roman numeral. `~:R' print a number as an ordinal English number. `~R' print a number as a cardinal English number. `~P' Plural. `~@P' prints `y' and `ies'. `~:P' as `~P but jumps 1 argument backward.' `~:@P' as `~@P but jumps 1 argument backward.' `~C' Character. `~@C' prints a character as the reader can understand it (i.e. `#\' prefixing). `~:C' prints a character as emacs does (eg. `^C' for ASCII 03). `~F' Fixed-format floating-point (prints a flonum like MMM.NNN). `~WIDTH,DIGITS,SCALE,OVERFLOWCHAR,PADCHARF' `~@F' If the number is positive a plus sign is printed. `~E' Exponential floating-point (prints a flonum like MMM.NNN`E'EE). `~WIDTH,DIGITS,EXPONENTDIGITS,SCALE,OVERFLOWCHAR,PADCHAR,EXPONENTCHARE' `~@E' If the number is positive a plus sign is printed. `~G' General floating-point (prints a flonum either fixed or exponential). `~WIDTH,DIGITS,EXPONENTDIGITS,SCALE,OVERFLOWCHAR,PADCHAR,EXPONENTCHARG' `~@G' If the number is positive a plus sign is printed. `~$' Dollars floating-point (prints a flonum in fixed with signs separated). `~DIGITS,SCALE,WIDTH,PADCHAR$' `~@$' If the number is positive a plus sign is printed. `~:@$' A sign is always printed and appears before the padding. `~:$' The sign appears before the padding. `~%' Newline. `~N%' print N newlines. `~&' print newline if not at the beginning of the output line. `~N&' prints `~&' and then N-1 newlines. `~|' Page Separator. `~N|' print N page separators. `~~' Tilde. `~N~' print N tildes. `~' Continuation Line. `~:' newline is ignored, white space left. `~@' newline is left, white space ignored. `~T' Tabulation. `~@T' relative tabulation. `~COLNUM,COLINCT' full tabulation. `~?' Indirection (expects indirect arguments as a list). `~@?' extracts indirect arguments from format arguments. `~(STR~)' Case conversion (converts by `string-downcase'). `~:(STR~)' converts by `string-capitalize'. `~@(STR~)' converts by `string-capitalize-first'. `~:@(STR~)' converts by `string-upcase'. `~*' Argument Jumping (jumps 1 argument forward). `~N*' jumps N arguments forward. `~:*' jumps 1 argument backward. `~N:*' jumps N arguments backward. `~@*' jumps to the 0th argument. `~N@*' jumps to the Nth argument (beginning from 0) `~[STR0~;STR1~;...~;STRN~]' Conditional Expression (numerical clause conditional). `~N[' take argument from N. `~@[' true test conditional. `~:[' if-else-then conditional. `~;' clause separator. `~:;' default clause follows. `~{STR~}' Iteration (args come from the next argument (a list)). `~N{' at most N iterations. `~:{' args from next arg (a list of lists). `~@{' args from the rest of arguments. `~:@{' args from the rest args (lists). `~^' Up and out. `~N^' aborts if N = 0 `~N,M^' aborts if N = M `~N,M,K^' aborts if N <= M <= K Not Implemented CL Format Control Directives ............................................ `~:A' print `#f' as an empty list (see below). `~:S' print `#f' as an empty list (see below). `~<~>' Justification. `~:^' (sorry I don't understand its semantics completely) Extended, Replaced and Additional Control Directives .................................................... `~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHD' `~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHX' `~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHO' `~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHB' `~N,MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHR' COMMAWIDTH is the number of characters between two comma characters. `~I' print a R4RS complex number as `~F~@Fi' with passed parameters for `~F'. `~Y' Pretty print formatting of an argument for scheme code lists. `~K' Same as `~?.' `~!' Flushes the output if format DESTINATION is a port. `~_' Print a `#\space' character `~N_' print N `#\space' characters. `~/' Print a `#\tab' character `~N/' print N `#\tab' characters. `~NC' Takes N as an integer representation for a character. No arguments are consumed. N is converted to a character by `integer->char'. N must be a positive decimal number. `~:S' Print out readproof. Prints out internal objects represented as `#<...>' as strings `"#<...>"' so that the format output can always be processed by `read'. `~:A' Print out readproof. Prints out internal objects represented as `#<...>' as strings `"#<...>"' so that the format output can always be processed by `read'. `~Q' Prints information and a copyright notice on the format implementation. `~:Q' prints format version. `~F, ~E, ~G, ~$' may also print number strings, i.e. passing a number as a string and format it accordingly. Configuration Variables ....................... Format has some configuration variables at the beginning of `format.scm' to suit the systems and users needs. There should be no modification necessary for the configuration that comes with SLIB. If modification is desired the variable should be set after the format code is loaded. Format detects automatically if the running scheme system implements floating point numbers and complex numbers. FORMAT:SYMBOL-CASE-CONV Symbols are converted by `symbol->string' so the case type of the printed symbols is implementation dependent. `format:symbol-case-conv' is a one arg closure which is either `#f' (no conversion), `string-upcase', `string-downcase' or `string-capitalize'. (default `#f') FORMAT:IOBJ-CASE-CONV As FORMAT:SYMBOL-CASE-CONV but applies for the representation of implementation internal objects. (default `#f') FORMAT:EXPCH The character prefixing the exponent value in `~E' printing. (default `#\E') Compatibility With Other Format Implementations ............................................... SLIB format 2.x: See `format.doc'. SLIB format 1.4: Downward compatible except for padding support and `~A', `~S', `~P', `~X' uppercase printing. SLIB format 1.4 uses C-style `printf' padding support which is completely replaced by the CL `format' padding style. MIT C-Scheme 7.1: Downward compatible except for `~', which is not documented (ignores all characters inside the format string up to a newline character). (7.1 implements `~a', `~s', ~NEWLINE, `~~', `~%', numerical and variable parameters and `:/@' modifiers in the CL sense). Elk 1.5/2.0: Downward compatible except for `~A' and `~S' which print in uppercase. (Elk implements `~a', `~s', `~~', and `~%' (no directive parameters or modifiers)). Scheme->C 01nov91: Downward compatible except for an optional destination parameter: S2C accepts a format call without a destination which returns a formatted string. This is equivalent to a #f destination in S2C. (S2C implements `~a', `~s', `~c', `~%', and `~~' (no directive parameters or modifiers)). This implementation of format is solely useful in the SLIB context because it requires other components provided by SLIB.  File: slib.info, Node: Standard Formatted I/O, Next: Programs and Arguments, Prev: Format, Up: Textual Conversion Packages Standard Formatted I/O ====================== * Menu: * Standard Formatted Output:: 'printf * Standard Formatted Input:: 'scanf stdio ----- `(require 'stdio)' `require's `printf' and `scanf' and additionally defines the symbols: - Variable: stdin Defined to be `(current-input-port)'. - Variable: stdout Defined to be `(current-output-port)'. - Variable: stderr Defined to be `(current-error-port)'.  File: slib.info, Node: Standard Formatted Output, Next: Standard Formatted Input, Prev: Standard Formatted I/O, Up: Standard Formatted I/O Standard Formatted Output ------------------------- `(require 'printf)' - Procedure: printf format arg1 ... - Procedure: fprintf port format arg1 ... - Procedure: sprintf str format arg1 ... - Procedure: sprintf #f format arg1 ... - Procedure: sprintf k format arg1 ... Each function converts, formats, and outputs its ARG1 ... arguments according to the control string FORMAT argument and returns the number of characters output. `printf' sends its output to the port `(current-output-port)'. `fprintf' sends its output to the port PORT. `sprintf' `string-set!'s locations of the non-constant string argument STR to the output characters. Two extensions of `sprintf' return new strings. If the first argument is `#f', then the returned string's length is as many characters as specified by the FORMAT and data; if the first argument is a non-negative integer K, then the length of the returned string is also bounded by K. The string FORMAT contains plain characters which are copied to the output stream, and conversion specifications, each of which results in fetching zero or more of the arguments ARG1 .... The results are undefined if there are an insufficient number of arguments for the format. If FORMAT is exhausted while some of the ARG1 ... arguments remain unused, the excess ARG1 ... arguments are ignored. The conversion specifications in a format string have the form: % [ FLAGS ] [ WIDTH ] [ . PRECISION ] [ TYPE ] CONVERSION An output conversion specifications consist of an initial `%' character followed in sequence by: * Zero or more "flag characters" that modify the normal behavior of the conversion specification. `-' Left-justify the result in the field. Normally the result is right-justified. `+' For the signed `%d' and `%i' conversions and all inexact conversions, prefix a plus sign if the value is positive. ` ' For the signed `%d' and `%i' conversions, if the result doesn't start with a plus or minus sign, prefix it with a space character instead. Since the `+' flag ensures that the result includes a sign, this flag is ignored if both are specified. `#' For inexact conversions, `#' specifies that the result should always include a decimal point, even if no digits follow it. For the `%g' and `%G' conversions, this also forces trailing zeros after the decimal point to be printed where they would otherwise be elided. For the `%o' conversion, force the leading digit to be `0', as if by increasing the precision. For `%x' or `%X', prefix a leading `0x' or `0X' (respectively) to the result. This doesn't do anything useful for the `%d', `%i', or `%u' conversions. Using this flag produces output which can be parsed by the `scanf' functions with the `%i' conversion (*note Standard Formatted Input::). `0' Pad the field with zeros instead of spaces. The zeros are placed after any indication of sign or base. This flag is ignored if the `-' flag is also specified, or if a precision is specified for an exact converson. * An optional decimal integer specifying the "minimum field width". If the normal conversion produces fewer characters than this, the field is padded (with spaces or zeros per the `0' flag) to the specified width. This is a _minimum_ width; if the normal conversion produces more characters than this, the field is _not_ truncated. Alternatively, if the field width is `*', the next argument in the argument list (before the actual value to be printed) is used as the field width. The width value must be an integer. If the value is negative it is as though the `-' flag is set (see above) and the absolute value is used as the field width. * An optional "precision" to specify the number of digits to be written for numeric conversions and the maximum field width for string conversions. The precision is specified by a period (`.') followed optionally by a decimal integer (which defaults to zero if omitted). Alternatively, if the precision is `.*', the next argument in the argument list (before the actual value to be printed) is used as the precision. The value must be an integer, and is ignored if negative. If you specify `*' for both the field width and precision, the field width argument precedes the precision argument. The `.*' precision is an enhancement. C library versions may not accept this syntax. For the `%f', `%e', and `%E' conversions, the precision specifies how many digits follow the decimal-point character. The default precision is `6'. If the precision is explicitly `0', the decimal point character is suppressed. For the `%g' and `%G' conversions, the precision specifies how many significant digits to print. Significant digits are the first digit before the decimal point, and all the digits after it. If the precision is `0' or not specified for `%g' or `%G', it is treated like a value of `1'. If the value being printed cannot be expressed accurately in the specified number of digits, the value is rounded to the nearest number that fits. For exact conversions, if a precision is supplied it specifies the minimum number of digits to appear; leading zeros are produced if necessary. If a precision is not supplied, the number is printed with as many digits as necessary. Converting an exact `0' with an explicit precision of zero produces no characters. * An optional one of `l', `h' or `L', which is ignored for numeric conversions. It is an error to specify these modifiers for non-numeric conversions. * A character that specifies the conversion to be applied. Exact Conversions ................. `b', `B' | Print an integer as an unsigned binary number. | | _Note:_ `%b' and `%B' are SLIB extensions. | | `d', `i' Print an integer as a signed decimal number. `%d' and `%i' are synonymous for output, but are different when used with `scanf' for input (*note Standard Formatted Input::). `o' Print an integer as an unsigned octal number. `u' Print an integer as an unsigned decimal number. `x', `X' Print an integer as an unsigned hexadecimal number. `%x' prints using the digits `0123456789abcdef'. `%X' prints using the digits `0123456789ABCDEF'. Inexact Conversions ................... `f' Print a floating-point number in fixed-point notation. `e', `E' Print a floating-point number in exponential notation. `%e' prints `e' between mantissa and exponont. `%E' prints `E' between mantissa and exponont. `g', `G' Print a floating-point number in either fixed or exponential notation, whichever is more appropriate for its magnitude. Unless an `#' flag has been supplied, trailing zeros after a decimal point will be stripped off. `%g' prints `e' between mantissa and exponont. `%G' prints `E' between mantissa and exponent. `k', `K' Print a number like `%g', except that an SI prefix is output after the number, which is scaled accordingly. `%K' outputs a space between number and prefix, `%k' does not. Other Conversions ................. `c' Print a single character. The `-' flag is the only one which can be specified. It is an error to specify a precision. `s' Print a string. The `-' flag is the only one which can be specified. A precision specifies the maximum number of characters to output; otherwise all characters in the string are output. `a', `A' Print a scheme expression. The `-' flag left-justifies the output. The `#' flag specifies that strings and characters should be quoted as by `write' (which can be read using `read'); otherwise, output is as `display' prints. A precision specifies the maximum number of characters to output; otherwise as many characters as needed are output. _Note:_ `%a' and `%A' are SLIB extensions. `%' Print a literal `%' character. No argument is consumed. It is an error to specify flags, field width, precision, or type | modifiers with `%%'. |  File: slib.info, Node: Standard Formatted Input, Prev: Standard Formatted Output, Up: Standard Formatted I/O Standard Formatted Input ------------------------ `(require 'scanf)' - Function: scanf-read-list format - Function: scanf-read-list format port - Function: scanf-read-list format string - Macro: scanf format arg1 ... - Macro: fscanf port format arg1 ... - Macro: sscanf str format arg1 ... Each function reads characters, interpreting them according to the control string FORMAT argument. `scanf-read-list' returns a list of the items specified as far as the input matches FORMAT. `scanf', `fscanf', and `sscanf' return the number of items successfully matched and stored. `scanf', `fscanf', and `sscanf' also set the location corresponding to ARG1 ... using the methods: symbol `set!' car expression `set-car!' cdr expression `set-cdr!' vector-ref expression `vector-set!' substring expression `substring-move-left!' The argument to a `substring' expression in ARG1 ... must be a non-constant string. Characters will be stored starting at the position specified by the second argument to `substring'. The number of characters stored will be limited by either the position specified by the third argument to `substring' or the length of the matched string, whichever is less. The control string, FORMAT, contains conversion specifications and other characters used to direct interpretation of input sequences. The control string contains: * White-space characters (blanks, tabs, newlines, or formfeeds) that cause input to be read (and discarded) up to the next non-white-space character. * An ordinary character (not `%') that must match the next character of the input stream. * Conversion specifications, consisting of the character `%', an optional assignment suppressing character `*', an optional numerical maximum-field width, an optional `l', `h' or `L' which is ignored, and a conversion code. Unless the specification contains the `n' conversion character (described below), a conversion specification directs the conversion of the next input field. The result of a conversion specification is returned in the position of the corresponding argument points, unless `*' indicates assignment suppression. Assignment suppression provides a way to describe an input field to be skipped. An input field is defined as a string of characters; it extends to the next inappropriate character or until the field width, if specified, is exhausted. _Note:_ This specification of format strings differs from the `ANSI C' and `POSIX' specifications. In SLIB, white space before an input field is not skipped unless white space appears before the conversion specification in the format string. In order to write format strings which work identically with `ANSI C' and SLIB, prepend whitespace to all conversion specifications except `[' and `c'. The conversion code indicates the interpretation of the input field; For a suppressed field, no value is returned. The following conversion codes are legal: `%' A single % is expected in the input at this point; no value is returned. `d', `D' A decimal integer is expected. `u', `U' An unsigned decimal integer is expected. `o', `O' An octal integer is expected. `x', `X' A hexadecimal integer is expected. `i' An integer is expected. Returns the value of the next input item, interpreted according to C conventions; a leading `0' implies octal, a leading `0x' implies hexadecimal; otherwise, decimal is assumed. `n' Returns the total number of bytes (including white space) read by `scanf'. No input is consumed by `%n'. `f', `F', `e', `E', `g', `G' A floating-point number is expected. The input format for floating-point numbers is an optionally signed string of digits, possibly containing a radix character `.', followed by an optional exponent field consisting of an `E' or an `e', followed by an optional `+', `-', or space, followed by an integer. `c', `C' WIDTH characters are expected. The normal skip-over-white-space is suppressed in this case; to read the next non-space character, use `%1s'. If a field width is given, a string is returned; up to the indicated number of characters is read. `s', `S' A character string is expected The input field is terminated by a white-space character. `scanf' cannot read a null string. `[' Indicates string data and the normal skip-over-leading-white-space is suppressed. The left bracket is followed by a set of characters, called the scanset, and a right bracket; the input field is the maximal sequence of input characters consisting entirely of characters in the scanset. `^', when it appears as the first character in the scanset, serves as a complement operator and redefines the scanset as the set of all characters not contained in the remainder of the scanset string. Construction of the scanset follows certain conventions. A range of characters may be represented by the construct first-last, enabling `[0123456789]' to be expressed `[0-9]'. Using this convention, first must be lexically less than or equal to last; otherwise, the dash stands for itself. The dash also stands for itself when it is the first or the last character in the scanset. To include the right square bracket as an element of the scanset, it must appear as the first character (possibly preceded by a `^') of the scanset, in which case it will not be interpreted syntactically as the closing bracket. At least one character must match for this conversion to succeed. The `scanf' functions terminate their conversions at end-of-file, at the end of the control string, or when an input character conflicts with the control string. In the latter case, the offending character is left unread in the input stream.  File: slib.info, Node: Programs and Arguments, Next: HTML, Prev: Standard Formatted I/O, Up: Textual Conversion Packages Program and Arguments ===================== * Menu: * Getopt:: Command Line option parsing * Command Line:: A command line reader for Scheme shells * Parameter lists:: 'parameters * Getopt Parameter lists:: 'getopt-parameters * Filenames:: 'glob or 'filename * Batch:: 'batch  File: slib.info, Node: Getopt, Next: Command Line, Prev: Programs and Arguments, Up: Programs and Arguments Getopt ------ `(require 'getopt)' This routine implements Posix command line argument parsing. Notice that returning values through global variables means that `getopt' is _not_ reentrant. - Variable: *optind* Is the index of the current element of the command line. It is initially one. In order to parse a new command line or reparse an old one, *OPTING* must be reset. - Variable: *optarg* Is set by getopt to the (string) option-argument of the current option. - Procedure: getopt argc argv optstring Returns the next option letter in ARGV (starting from `(vector-ref argv *optind*)') that matches a letter in OPTSTRING. ARGV is a vector or list of strings, the 0th of which getopt usually ignores. ARGC is the argument count, usually the length of ARGV. OPTSTRING is a string of recognized option characters; if a character is followed by a colon, the option takes an argument which may be immediately following it in the string or in the next element of ARGV. *OPTIND* is the index of the next element of the ARGV vector to be processed. It is initialized to 1 by `getopt.scm', and `getopt' updates it when it finishes with each element of ARGV. `getopt' returns the next option character from ARGV that matches a character in OPTSTRING, if there is one that matches. If the option takes an argument, `getopt' sets the variable *OPTARG* to the option-argument as follows: * If the option was the last character in the string pointed to by an element of ARGV, then *OPTARG* contains the next element of ARGV, and *OPTIND* is incremented by 2. If the resulting value of *OPTIND* is greater than or equal to ARGC, this indicates a missing option argument, and `getopt' returns an error indication. * Otherwise, *OPTARG* is set to the string following the option character in that element of ARGV, and *OPTIND* is incremented by 1. If, when `getopt' is called, the string `(vector-ref argv *optind*)' either does not begin with the character `#\-' or is just `"-"', `getopt' returns `#f' without changing *OPTIND*. If `(vector-ref argv *optind*)' is the string `"--"', `getopt' returns `#f' after incrementing *OPTIND*. If `getopt' encounters an option character that is not contained in OPTSTRING, it returns the question-mark `#\?' character. If it detects a missing option argument, it returns the colon character `#\:' if the first character of OPTSTRING was a colon, or a question-mark character otherwise. In either case, `getopt' sets the variable GETOPT:OPT to the option character that caused the error. The special option `"--"' can be used to delimit the end of the options; `#f' is returned, and `"--"' is skipped. RETURN VALUE `getopt' returns the next option character specified on the command line. A colon `#\:' is returned if `getopt' detects a missing argument and the first character of OPTSTRING was a colon `#\:'. A question-mark `#\?' is returned if `getopt' encounters an option character not in OPTSTRING or detects a missing argument and the first character of OPTSTRING was not a colon `#\:'. Otherwise, `getopt' returns `#f' when all command line options have been parsed. Example: #! /usr/local/bin/scm ;;;This code is SCM specific. (define argv (program-arguments)) (require 'getopt) (define opts ":a:b:cd") (let loop ((opt (getopt (length argv) argv opts))) (case opt ((#\a) (print "option a: " *optarg*)) ((#\b) (print "option b: " *optarg*)) ((#\c) (print "option c")) ((#\d) (print "option d")) ((#\?) (print "error" getopt:opt)) ((#\:) (print "missing arg" getopt:opt)) ((#f) (if (< *optind* (length argv)) (print "argv[" *optind* "]=" (list-ref argv *optind*))) (set! *optind* (+ *optind* 1)))) (if (< *optind* (length argv)) (loop (getopt (length argv) argv opts)))) (slib:exit) Getopt- ------- - Function: getopt- argc argv optstring The procedure `getopt--' is an extended version of `getopt' which parses "long option names" of the form `--hold-the-onions' and `--verbosity-level=extreme'. `Getopt--' behaves as `getopt' except for non-empty options beginning with `--'. Options beginning with `--' are returned as strings rather than characters. If a value is assigned (using `=') to a long option, `*optarg*' is set to the value. The `=' and value are not returned as part of the option string. No information is passed to `getopt--' concerning which long options should be accepted or whether such options can take arguments. If a long option did not have an argument, `*optarg' will be set to `#f'. The caller is responsible for detecting and reporting errors. (define opts ":-:b:") (define argc 5) (define argv '("foo" "-b9" "--f1" "--2=" "--g3=35234.342" "--")) (define *optind* 1) (define *optarg* #f) (require 'qp) (do ((i 5 (+ -1 i))) ((zero? i)) (define opt (getopt-- argc argv opts)) (print *optind* opt *optarg*))) -| 2 #\b "9" 3 "f1" #f 4 "2" "" 5 "g3" "35234.342" 5 #f "35234.342"  File: slib.info, Node: Command Line, Next: Parameter lists, Prev: Getopt, Up: Programs and Arguments Command Line ------------ `(require 'read-command)' - Function: read-command port - Function: read-command `read-command' converts a "command line" into a list of strings suitable for parsing by `getopt'. The syntax of command lines supported resembles that of popular "shell"s. `read-command' updates PORT to point to the first character past the command delimiter. If an end of file is encountered in the input before any characters are found that can begin an object or comment, then an end of file object is returned. The PORT argument may be omitted, in which case it defaults to the value returned by `current-input-port'. The fields into which the command line is split are delimited by whitespace as defined by `char-whitespace?'. The end of a command is delimited by end-of-file or unescaped semicolon (<;>) or . Any character can be literally included in a field by escaping it with a backslach (<\>). The initial character and types of fields recognized are: `\' The next character has is taken literally and not interpreted as a field delimiter. If <\> is the last character before a , that is just ignored. Processing continues from the characters after the as though the backslash and were not there. `"' The characters up to the next unescaped <"> are taken literally, according to [R4RS] rules for literal strings (*note Strings: (r4rs)Strings.). `(', `%'' One scheme expression is `read' starting with this character. The `read' expression is evaluated, converted to a string (using `display'), and replaces the expression in the returned field. `;' Semicolon delimits a command. Using semicolons more than one command can appear on a line. Escaped semicolons and semicolons inside strings do not delimit commands. The comment field differs from the previous fields in that it must be the first character of a command or appear after whitespace in order to be recognized. <#> can be part of fields if these conditions are not met. For instance, `ab#c' is just the field ab#c. `#' Introduces a comment. The comment continues to the end of the line on which the semicolon appears. Comments are treated as whitespace by `read-dommand-line' and backslashes before s in comments are also ignored. - Function: read-options-file filename `read-options-file' converts an "options file" into a list of strings suitable for parsing by `getopt'. The syntax of options files is the same as the syntax for command lines, except that s do not terminate reading (only <;> or end of file). If an end of file is encountered before any characters are found that can begin an object or comment, then an end of file object is returned.  File: slib.info, Node: Parameter lists, Next: Getopt Parameter lists, Prev: Command Line, Up: Programs and Arguments Parameter lists --------------- `(require 'parameters)' Arguments to procedures in scheme are distinguished from each other by their position in the procedure call. This can be confusing when a procedure takes many arguments, many of which are not often used. A "parameter-list" is a way of passing named information to a procedure. Procedures are also defined to set unused parameters to default values, check parameters, and combine parameter lists. A PARAMETER has the form `(parameter-name value1 ...)'. This format allows for more than one value per parameter-name. A PARAMETER-LIST is a list of PARAMETERs, each with a different PARAMETER-NAME. - Function: make-parameter-list parameter-names Returns an empty parameter-list with slots for PARAMETER-NAMES. - Function: parameter-list-ref parameter-list parameter-name PARAMETER-NAME must name a valid slot of PARAMETER-LIST. `parameter-list-ref' returns the value of parameter PARAMETER-NAME of PARAMETER-LIST. - Function: remove-parameter parameter-name parameter-list Removes the parameter PARAMETER-NAME from PARAMETER-LIST. `remove-parameter' does not alter the argument PARAMETER-LIST. If there are more than one PARAMETER-NAME parameters, an error is signaled. - Procedure: adjoin-parameters! parameter-list parameter1 ... Returns PARAMETER-LIST with PARAMETER1 ... merged in. - Procedure: parameter-list-expand expanders parameter-list EXPANDERS is a list of procedures whose order matches the order of the PARAMETER-NAMEs in the call to `make-parameter-list' which created PARAMETER-LIST. For each non-false element of EXPANDERS that procedure is mapped over the corresponding parameter value and the returned parameter lists are merged into PARAMETER-LIST. This process is repeated until PARAMETER-LIST stops growing. The value returned from `parameter-list-expand' is unspecified. - Function: fill-empty-parameters defaulters parameter-list DEFAULTERS is a list of procedures whose order matches the order of the PARAMETER-NAMEs in the call to `make-parameter-list' which created PARAMETER-LIST. `fill-empty-parameters' returns a new parameter-list with each empty parameter replaced with the list returned by calling the corresponding DEFAULTER with PARAMETER-LIST as its argument. - Function: check-parameters checks parameter-list CHECKS is a list of procedures whose order matches the order of the PARAMETER-NAMEs in the call to `make-parameter-list' which created PARAMETER-LIST. `check-parameters' returns PARAMETER-LIST if each CHECK of the corresponding PARAMETER-LIST returns non-false. If some CHECK returns `#f' a warning is signaled. In the following procedures ARITIES is a list of symbols. The elements of `arities' can be: `single' Requires a single parameter. `optional' A single parameter or no parameter is acceptable. `boolean' A single boolean parameter or zero parameters is acceptable. `nary' Any number of parameters are acceptable. `nary1' One or more of parameters are acceptable. - Function: parameter-list->arglist positions arities parameter-list Returns PARAMETER-LIST converted to an argument list. Parameters of ARITY type `single' and `boolean' are converted to the single value associated with them. The other ARITY types are converted to lists of the value(s). POSITIONS is a list of positive integers whose order matches the order of the PARAMETER-NAMEs in the call to `make-parameter-list' which created PARAMETER-LIST. The integers specify in which argument position the corresponding parameter should appear.  File: slib.info, Node: Getopt Parameter lists, Next: Filenames, Prev: Parameter lists, Up: Programs and Arguments Getopt Parameter lists ---------------------- `(require 'getopt-parameters)' - Function: getopt->parameter-list argc argv optnames arities types aliases desc ... Returns ARGV converted to a parameter-list. OPTNAMES are the parameter-names. ARITIES and TYPES are lists of symbols corresponding to OPTNAMES. ALIASES is a list of lists of strings or integers paired with elements of OPTNAMES. Each one-character string will be treated as a single `-' option by `getopt'. Longer strings will be treated as long-named options (*note getopt-: Getopt.). If the ALIASES association list has only strings as its `car's, then all the option-arguments after an option (and before the next option) are adjoined to that option. If the ALIASES association list has integers, then each (string) option will take at most one option-argument. Unoptioned arguments are collected in a list. A `-1' alias will take the last argument in this list; `+1' will take the first argument in the list. The aliases -2 then +2; -3 then +3; ... are tried so long as a positive or negative consecutive alias is found and arguments remain in the list. Finally a `0' alias, if found, absorbs any remaining arguments. In all cases, if unclaimed arguments remain after processing, a warning is signaled and #f is returned. - Function: getopt->arglist argc argv optnames positions arities types defaulters checks aliases desc ... Like `getopt->parameter-list', but converts ARGV to an argument-list as specified by OPTNAMES, POSITIONS, ARITIES, TYPES, DEFAULTERS, CHECKS, and ALIASES. If the options supplied violate the ARITIES or CHECKS constraints, then a warning is signaled and #f is returned. These `getopt' functions can be used with SLIB relational databases. For an example, *Note make-command-server: Database Utilities. If errors are encountered while processing options, directions for using the options (and argument strings DESC ...) are printed to `current-error-port'. (begin (set! *optind* 1) (getopt->parameter-list 2 '("cmd" "-?") '(flag number symbols symbols string flag2 flag3 num2 num3) '(boolean optional nary1 nary single boolean boolean nary nary) '(boolean integer symbol symbol string boolean boolean integer integer) '(("flag" flag) ("f" flag) ("Flag" flag2) ("B" flag3) ("optional" number) ("o" number) ("nary1" symbols) ("N" symbols) ("nary" symbols) ("n" symbols) ("single" string) ("s" string) ("a" num2) ("Abs" num3)))) -| Usage: cmd [OPTION ARGUMENT ...] ... -f, --flag -o, --optional= -n, --nary= ... -N, --nary1= ... -s, --single= --Flag -B -a ... --Abs= ... ERROR: getopt->parameter-list "unrecognized option" "-?"  File: slib.info, Node: Filenames, Next: Batch, Prev: Getopt Parameter lists, Up: Programs and Arguments Filenames --------- `(require 'filename)' or `(require 'glob)' - Function: filename:match?? pattern - Function: filename:match-ci?? pattern Returns a predicate which returns a non-false value if its string argument matches (the string) PATTERN, false otherwise. Filename matching is like "glob" expansion described the bash manpage, except that names beginning with `.' are matched and `/' characters are not treated specially. These functions interpret the following characters specially in PATTERN strings: `*' Matches any string, including the null string. `?' Matches any single character. `[...]' Matches any one of the enclosed characters. A pair of characters separated by a minus sign (-) denotes a range; any character lexically between those two characters, inclusive, is matched. If the first character following the `[' is a `!' or a `^' then any character not enclosed is matched. A `-' or `]' may be matched by including it as the first or last character in the set. - Function: filename:substitute?? pattern template - Function: filename:substitute-ci?? pattern template Returns a function transforming a single string argument according to glob patterns PATTERN and TEMPLATE. PATTERN and TEMPLATE must have the same number of wildcard specifications, which need not be identical. PATTERN and TEMPLATE may have a different number of literal sections. If an argument to the function matches PATTERN in the sense of `filename:match??' then it returns a copy of TEMPLATE in which each wildcard specification is replaced by the part of the argument matched by the corresponding wildcard specification in PATTERN. A `*' wildcard matches the longest leftmost string possible. If the argument does not match PATTERN then false is returned. TEMPLATE may be a function accepting the same number of string arguments as there are wildcard specifications in PATTERN. In the case of a match the result of applying TEMPLATE to a list of the substrings matched by wildcard specifications will be returned, otherwise TEMPLATE will not be called and `#f' will be returned. ((filename:substitute?? "scm_[0-9]*.html" "scm5c4_??.htm") "scm_10.html") => "scm5c4_10.htm" ((filename:substitute?? "??" "beg?mid?end") "AZ") => "begAmidZend" ((filename:substitute?? "*na*" "?NA?") "banana") => "banaNA" ((filename:substitute?? "?*?" (lambda (s1 s2 s3) (string-append s3 s1))) "ABZ") => "ZA" - Function: replace-suffix str old new STR can be a string or a list of strings. Returns a new string (or strings) similar to `str' but with the suffix string OLD removed and the suffix string NEW appended. If the end of STR does not match OLD, an error is signaled. (replace-suffix "/usr/local/lib/slib/batch.scm" ".scm" ".c") => "/usr/local/lib/slib/batch.c"  File: slib.info, Node: Batch, Prev: Filenames, Up: Programs and Arguments Batch ----- `(require 'batch)' The batch procedures provide a way to write and execute portable scripts for a variety of operating systems. Each `batch:' procedure takes as its first argument a parameter-list (*note Parameter lists::). This parameter-list argument PARMS contains named associations. Batch currently uses 2 of these: `batch-port' The port on which to write lines of the batch file. `batch-dialect' The syntax of batch file to generate. Currently supported are: * unix * dos * vms * amigados * system * *unknown* `batch.scm' uses 2 enhanced relational tables (*note Database Utilities::) to store information linking the names of `operating-system's to `batch-dialect'es. - Function: batch:initialize! database Defines `operating-system' and `batch-dialect' tables and adds the domain `operating-system' to the enhanced relational database DATABASE. - Variable: batch:platform Is batch's best guess as to which operating-system it is running under. `batch:platform' is set to `(software-type)' (*note Configuration::) unless `(software-type)' is `unix', in which case finer distinctions are made. - Function: batch:call-with-output-script parms file proc PROC should be a procedure of one argument. If FILE is an output-port, `batch:call-with-output-script' writes an appropriate header to FILE and then calls PROC with FILE as the only argument. If FILE is a string, `batch:call-with-output-script' opens a output-file of name FILE, writes an appropriate header to FILE, and then calls PROC with the newly opened port as the only argument. Otherwise, `batch:call-with-output-script' acts as if it was called with the result of `(current-output-port)' as its third argument. The rest of the `batch:' procedures write (or execute if `batch-dialect' is `system') commands to the batch port which has been added to PARMS or `(copy-tree PARMS)' by the code: (adjoin-parameters! PARMS (list 'batch-port PORT)) - Function: batch:command parms string1 string2 ... Calls `batch:try-command' (below) with arguments, but signals an error if `batch:try-command' returns `#f'. These functions return a non-false value if the command was successfully translated into the batch dialect and `#f' if not. In the case of the `system' dialect, the value is non-false if the operation suceeded. - Function: batch:try-command parms string1 string2 ... Writes a command to the `batch-port' in PARMS which executes the program named STRING1 with arguments STRING2 .... - Function: batch:try-chopped-command parms arg1 arg2 ... list breaks the last argument LIST into chunks small enough so that the command: ARG1 ARG2 ... CHUNK fits withing the platform's maximum command-line length. `batch:try-chopped-command' calls `batch:try-command' with the command and returns non-false only if the commands all fit and `batch:try-command' of each command line returned non-false. - Function: batch:run-script parms string1 string2 ... Writes a command to the `batch-port' in PARMS which executes the batch script named STRING1 with arguments STRING2 .... _Note:_ `batch:run-script' and `batch:try-command' are not the same for some operating systems (VMS). - Function: batch:comment parms line1 ... Writes comment lines LINE1 ... to the `batch-port' in PARMS. - Function: batch:lines->file parms file line1 ... Writes commands to the `batch-port' in PARMS which create a file named FILE with contents LINE1 .... - Function: batch:delete-file parms file Writes a command to the `batch-port' in PARMS which deletes the file named FILE. - Function: batch:rename-file parms old-name new-name Writes a command to the `batch-port' in PARMS which renames the file OLD-NAME to NEW-NAME. In addition, batch provides some small utilities very useful for writing scripts: - Function: truncate-up-to path char - Function: truncate-up-to path string - Function: truncate-up-to path charlist PATH can be a string or a list of strings. Returns PATH sans any prefixes ending with a character of the second argument. This can be used to derive a filename moved locally from elsewhere. (truncate-up-to "/usr/local/lib/slib/batch.scm" "/") => "batch.scm" - Function: string-join joiner string1 ... Returns a new string consisting of all the strings STRING1 ... in order appended together with the string JOINER between each adjacent pair. - Function: must-be-first list1 list2 Returns a new list consisting of the elements of LIST2 ordered so that if some elements of LIST1 are `equal?' to elements of LIST2, then those elements will appear first and in the order of LIST1. - Function: must-be-last list1 list2 Returns a new list consisting of the elements of LIST1 ordered so that if some elements of LIST2 are `equal?' to elements of LIST1, then those elements will appear last and in the order of LIST2. - Function: os->batch-dialect osname Returns its best guess for the `batch-dialect' to be used for the operating-system named OSNAME. `os->batch-dialect' uses the tables added to DATABASE by `batch:initialize!'. Here is an example of the use of most of batch's procedures: (require 'database-utilities) (require 'parameters) (require 'batch) (require 'glob) (define batch (create-database #f 'alist-table)) (batch:initialize! batch) (define my-parameters (list (list 'batch-dialect (os->batch-dialect batch:platform)) (list 'platform batch:platform) (list 'batch-port (current-output-port)))) ;gets filled in later (batch:call-with-output-script my-parameters "my-batch" (lambda (batch-port) (adjoin-parameters! my-parameters (list 'batch-port batch-port)) (and (batch:comment my-parameters "================ Write file with C program.") (batch:rename-file my-parameters "hello.c" "hello.c~") (batch:lines->file my-parameters "hello.c" "#include " "int main(int argc, char **argv)" "{" " printf(\"hello world\\n\");" " return 0;" "}" ) (batch:command my-parameters "cc" "-c" "hello.c") (batch:command my-parameters "cc" "-o" "hello" (replace-suffix "hello.c" ".c" ".o")) (batch:command my-parameters "hello") (batch:delete-file my-parameters "hello") (batch:delete-file my-parameters "hello.c") (batch:delete-file my-parameters "hello.o") (batch:delete-file my-parameters "my-batch") ))) Produces the file `my-batch': #!/bin/sh # "my-batch" script created by SLIB/batch Sun Oct 31 18:24:10 1999 # ================ Write file with C program. mv -f hello.c hello.c~ rm -f hello.c echo '#include '>>hello.c echo 'int main(int argc, char **argv)'>>hello.c echo '{'>>hello.c echo ' printf("hello world\n");'>>hello.c echo ' return 0;'>>hello.c echo '}'>>hello.c cc -c hello.c cc -o hello hello.o hello rm -f hello rm -f hello.c rm -f hello.o rm -f my-batch When run, `my-batch' prints: bash$ my-batch mv: hello.c: No such file or directory hello world  File: slib.info, Node: HTML, Next: HTML Tables, Prev: Programs and Arguments, Up: Textual Conversion Packages HTML ==== `(require 'html-form)' - Function: html:atval txt Returns a string with character substitutions appropriate to send TXT as an "attribute-value". - Function: html:plain txt Returns a string with character substitutions appropriate to send TXT as an "plain-text". - Function: html:meta name content Returns a tag of meta-information suitable for passing as the third argument to `html:head'. The tag produced is `'. The string or symbol NAME can be `author', `copyright', `keywords', `description', `date', `robots', .... - Function: html:http-equiv name content Returns a tag of HTTP information suitable for passing as the third argument to `html:head'. The tag produced is `'. The string or symbol NAME can be `Expires', `PICS-Label', `Content-Type', `Refresh', .... - Function: html:meta-refresh delay uri - Function: html:meta-refresh delay Returns a tag suitable for passing as the third argument to `html:head'. If URI argument is supplied, then DELAY seconds after displaying the page with this tag, Netscape or IE browsers will fetch and display URI. Otherwise, DELAY seconds after displaying the page with this tag, Netscape or IE browsers will fetch and redisplay this page. - Function: html:head title backlink tags ... - Function: html:head title backlink - Function: html:head title Returns header string for an HTML page named TITLE. If BACKLINK is a string, it is used verbatim between the `H1' tags; otherwise TITLE is used. If string arguments TAGS ... are supplied, then they are included verbatim within the section. - Function: html:body body ... Returns HTML string to end a page. - Function: html:pre line1 line ... Returns the strings LINE1, LINES as "PRE"formmated plain text (rendered in fixed-width font). Newlines are inserted between LINE1, LINES. HTML tags (`') within LINES will be visible verbatim. - Function: html:comment line1 line ... Returns the strings LINE1 as HTML comments. HTML Forms ========== - Function: html:form method action body ... The symbol METHOD is either `get', `head', `post', `put', or `delete'. The strings BODY form the body of the form. `html:form' returns the HTML "form". - Function: html:hidden name value Returns HTML string which will cause NAME=VALUE in form. - Function: html:checkbox pname default Returns HTML string for check box. - Function: html:text pname default size ... Returns HTML string for one-line text box. - Function: html:text-area pname default-list Returns HTML string for multi-line text box. - Function: html:select pname arity default-list foreign-values Returns HTML string for pull-down menu selector. - Function: html:buttons pname arity default-list foreign-values Returns HTML string for any-of selector. - Function: form:submit submit-label command - Function: form:submit submit-label The string or symbol SUBMIT-LABEL appears on the button which submits the form. If the optional second argument COMMAND is given, then `*command*=COMMAND' and `*button*=SUBMIT-LABEL' are set in the query. Otherwise, `*command*=SUBMIT-LABEL' is set in the query. - Function: form:image submit-label image-src The IMAGE-SRC appears on the button which submits the form. - Function: form:reset Returns a string which generates a "reset" button. - Function: form:element pname arity default-list foreign-values Returns a string which generates an INPUT element for the field named PNAME. The element appears in the created form with its representation determined by its ARITY and domain. For domains which are foreign-keys: `single' select menu `optional' select menu `nary' check boxes `nary1' check boxes If the foreign-key table has a field named `visible-name', then the contents of that field are the names visible to the user for those choices. Otherwise, the foreign-key itself is visible. For other types of domains: `single' text area `optional' text area `boolean' check box `nary' text area `nary1' text area - Function: form:delimited pname doc aliat arity default-list foreign-values Returns a HTML string for a form element embedded in a line of a delimited list. Apply map `form:delimited' to the list returned by `command->p-specs'. - Function: command->p-specs rdb command-table command The symbol COMMAND-TABLE names a command table in the RDB relational database. The symbol COMMAND names a key in COMMAND-TABLE. `command->p-specs' returns a list of lists of PNAME, DOC, ALIAT, ARITY, DEFAULT-LIST, and FOREIGN-VALUES. The returned list has one element for each parameter of command COMMAND. This example demonstrates how to create a HTML-form for the `build' command. (require (in-vicinity (implementation-vicinity) "build.scm")) (call-with-output-file "buildscm.html" (lambda (port) (display (string-append (html:head 'commands) (html:body (sprintf #f "

%s:

%s
\\n" (html:plain 'build) (html:plain ((comtab 'get 'documentation) 'build))) (html:form 'post (or "http://localhost:8081/buildscm" "/cgi-bin/build.cgi") (apply html:delimited-list (apply map form:delimited (command->p-specs build '*commands* 'build))) (form:submit 'build) (form:reset)))) port)))  File: slib.info, Node: HTML Tables, Next: HTTP and CGI, Prev: HTML, Up: Textual Conversion Packages HTML Tables =========== `(require 'db->html)' - Function: html:table options row ... - Function: html:caption caption align - Function: html:caption caption ALIGN can be `top' or `bottom'. - Function: html:heading columns Outputs a heading row for the currently-started table. - Function: html:href-heading columns uris Outputs a heading row with column-names COLUMNS linked to URIs URIS. - Function: html:linked-row-converter k foreigns The positive integer K is the primary-key-limit (number of primary-keys) of the table. FOREIGNS is a list of the filenames of foreign-key field pages and #f for non foreign-key fields. `html:linked-row-converter' returns a procedure taking a row for its single argument. This returned procedure returns the html string for that table row. - Function: table-name->filename table-name Returns the symbol TABLE-NAME converted to a filename. - Function: table->linked-html caption db table-name match-key1 ... Returns HTML string for DB table TABLE-NAME. Every foreign-key value is linked to the page (of the table) defining that key. The optional MATCH-KEY1 ... arguments restrict actions to a subset of the table. *Note match-key: Table Operations. - Function: table->linked-page db table-name index-filename arg ... Returns a complete HTML page. The string INDEX-FILENAME names the page which refers to this one. The optional ARGS ... arguments restrict actions to a subset of the table. *Note match-key: Table Operations. - Function: catalog->html db caption arg ... Returns HTML string for the catalog table of DB. HTML editing tables ------------------- A client can modify one row of an editable table at a time. For any change submitted, these routines check if that row has been modified during the time the user has been editing the form. If so, an error page results. The behavior of edited rows is: * If no fields are changed, then no change is made to the table. * If the primary keys equal null-keys (parameter defaults), and no other user has modified that row, then that row is deleted. * If only primary keys are changed, there are non-key fields, and no row with the new keys is in the table, then the old row is deleted and one with the new keys is inserted. * If only non-key fields are changed, and that row has not been modified by another user, then the row is changed to reflect the fields. * If both keys and non-key fields are changed, and no row with the new keys is in the table, then a row is created with the new keys and fields. * If fields are changed, all fields are primary keys, and no row with the new keys is in the table, then a row is created with the new keys. After any change to the table, a `sync-database' of the database is performed. - Function: command:modify-table table-name null-keys update delete retrieve - Function: command:modify-table table-name null-keys update delete - Function: command:modify-table table-name null-keys update - Function: command:modify-table table-name null-keys Returns procedure (of DB) which returns procedure to modify row of TABLE-NAME. NULL-KEYS is the list of "null" keys which indicate that the row is to be deleted. Optional arguments UPDATE, DELETE, and RETRIEVE default to the `row:update', `row:delete', and `row:retrieve' of TABLE-NAME in DB. - Function: command:make-editable-table rdb table-name arg ... Given TABLE-NAME in RDB, creates parameter and `*command*' tables for editing one row of TABLE-NAME at a time. `command:make-editable-table' returns a procedure taking a row argument which returns the HTML string for editing that row. Optional ARGS are expressions (lists) added to the call to `command:modify-table'. The domain name of a column determines the expected arity of the data stored in that column. Domain names ending in: `*' have arity `nary'; `+' have arity `nary1'. - Function: html:editable-row-converter k names edit-point edit-converter The positive integer K is the primary-key-limit (number of primary-keys) of the table. NAMES is a list of the field-names. EDIT-POINT is the list of primary-keys denoting the row to edit (or #f). EDIT-CONVERTER is the procedure called with K, NAMES, and the row to edit. `html:editable-row-converter' returns a procedure taking a row for its single argument. This returned procedure returns the html string for that table row. Each HTML table constructed using `html:editable-row-converter' has first K fields (typically the primary key fields) of each row linked to a text encoding of these fields (the result of calling `row->anchor'). The page so referenced typically allows the user to edit fields of that row. HTML databases -------------- - Function: db->html-files db dir index-filename caption DB must be a relational database. DIR must be #f or a non-empty string naming an existing sub-directory of the current directory. `db->html-files' creates an html page for each table in the database DB in the sub-directory named DIR, or the current directory if DIR is #f. The top level page with the catalog of tables (captioned CAPTION) is written to a file named INDEX-FILENAME. - Function: db->html-directory db dir index-filename - Function: db->html-directory db dir DB must be a relational database. DIR must be a non-empty string naming an existing sub-directory of the current directory or one to be created. The optional string INDEX-FILENAME names the filename of the top page, which defaults to `index.html'. `db->html-directory' creates sub-directory DIR if neccessary, and calls `(db->html-files DB DIR INDEX-FILENAME DIR)'. The `file:' URI of INDEX-FILENAME is returned. - Function: db->netscape db dir index-filename - Function: db->netscape db dir `db->netscape' is just like `db->html-directory', but calls `browse-url-netscape' with the uri for the top page after the pages are created.  File: slib.info, Node: HTTP and CGI, Next: URI, Prev: HTML Tables, Up: Textual Conversion Packages HTTP and CGI ============ `(require 'http)' or `(require 'cgi)' - Function: http:header alist Returns a string containing lines for each element of ALIST; the `car' of which is followed by `: ', then the `cdr'. - Function: http:content alist body ... Returns the concatenation of strings BODY with the `(http:header ALIST)' and the `Content-Length' prepended. - Variable: *http:byline* String appearing at the bottom of error pages. - Function: http:error-page status-code reason-phrase html-string ... STATUS-CODE and REASON-PHRASE should be an integer and string as specified in `RFC 2068'. The returned page (string) will show the STATUS-CODE and REASON-PHRASE and any additional HTML-STRINGS ...; with *HTTP:BYLINE* or SLIB's default at the bottom. - Function: http:forwarding-page title delay uri html-string ... The string or symbol TITLE is the page title. DELAY is a non-negative integer. The HTML-STRINGS ... are typically used to explain to the user why this page is being forwarded. `http:forwarding-page' returns an HTML string for a page which automatically forwards to URI after DELAY seconds. The returned page (string) contains any HTML-STRINGS ... followed by a manual link to URI, in case the browser does not forward automatically. - Function: http:serve-query serve-proc input-port output-port reads the "URI" and "query-string" from INPUT-PORT. If the query is a valid `"POST"' or `"GET"' query, then `http:serve-query' calls SERVE-PROC with three arguments, the REQUEST-LINE, QUERY-STRING, and HEADER-ALIST. Otherwise, `http:serve-query' calls SERVE-PROC with the REQUEST-LINE, #f, and HEADER-ALIST. If SERVE-PROC returns a string, it is sent to OUTPUT-PORT. If SERVE-PROC returns a list, then an error page with number 525 and strings from the list. If SERVE-PROC returns #f, then a `Bad Request' (400) page is sent to OUTPUT-PORT. Otherwise, `http:serve-query' replies (to OUTPUT-PORT) with appropriate HTML describing the problem. This example services HTTP queries from PORT-NUMBER: (define socket (make-stream-socket AF_INET 0)) (and (socket:bind socket port-number) ; AF_INET INADDR_ANY (socket:listen socket 10) ; Queue up to 10 requests. (dynamic-wind (lambda () #f) (lambda () (do ((port (socket:accept socket) (socket:accept socket))) (#f) (let ((iport (duplicate-port port "r")) (oport (duplicate-port port "w"))) (http:serve-query build:serve iport oport) (close-port iport) (close-port oport)) (close-port port))) (lambda () (close-port socket)))) - Function: cgi:serve-query serve-proc reads the "URI" and "query-string" from `(current-input-port)'. If the query is a valid `"POST"' or `"GET"' query, then `cgi:serve-query' calls SERVE-PROC with three arguments, the REQUEST-LINE, QUERY-STRING, and HEADER-ALIST. Otherwise, `cgi:serve-query' calls SERVE-PROC with the REQUEST-LINE, #f, and HEADER-ALIST. If SERVE-PROC returns a string, it is sent to `(current-input-port)'. If SERVE-PROC returns a list, then an error page with number 525 and strings from the list. If SERVE-PROC returns #f, then a `Bad Request' (400) page is sent to `(current-input-port)'. Otherwise, `cgi:serve-query' replies (to `(current-input-port)') with appropriate HTML describing the problem. - Function: make-query-alist-command-server rdb command-table - Function: make-query-alist-command-server rdb command-table #t Returns a procedure of one argument. When that procedure is called with a QUERY-ALIST (as returned by `uri:decode-query', the value of the `*command*' association will be the command invoked in COMMAND-TABLE. If `*command*' is not in the QUERY-ALIST then the value of `*suggest*' is tried. If neither name is in the QUERY-ALIST, then the literal value `*default*' is tried in COMMAND-TABLE. If optional third argument is non-false, then the command is called with just the parameter-list; otherwise, command is called with the arguments described in its table.  File: slib.info, Node: URI, Next: Printing Scheme, Prev: HTTP and CGI, Up: Textual Conversion Packages URI === `(require 'uri)' Implements "Uniform Resource Identifiers" (URI) as described in RFC 2396. - Function: make-uri - Function: make-uri fragment - Function: make-uri query fragment - Function: make-uri path query fragment - Function: make-uri authority path query fragment - Function: make-uri scheme authority path query fragment Returns a Uniform Resource Identifier string from component arguments. - Function: html:anchor name Returns a string which defines this location in the (HTML) file as NAME. The hypertext `' will link to this point. (html:anchor "(section 7)") => "" - Function: html:link uri highlighted Returns a string which links the HIGHLIGHTED text to URI. (html:link (make-uri "(section 7)") "section 7") => "section 7" - Function: html:base uri Returns a string specifying the "base" URI of a document, for inclusion in the HEAD of the document (*note head: HTML.). - Function: html:isindex prompt Returns a string specifying the search PROMPT of a document, for inclusion in the HEAD of the document (*note head: HTML.). - Function: uri->tree uri-reference base-tree ... Returns a list of 5 elements corresponding to the parts (SCHEME AUTHORITY PATH QUERY FRAGMENT) of string URI-REFERENCE. Elements corresponding to absent parts are #f. The PATH is a list of strings. If the first string is empty, then the path is absolute; otherwise relative. If the AUTHORITY component is a "Server-based Naming Authority", then it is a list of the USERINFO, HOST, and PORT strings (or #f). For other types of AUTHORITY components the AUTHORITY will be a string. (uri->tree "http://www.ics.uci.edu/pub/ietf/uri/#Related") => (http "www.ics.uci.edu" ("" "pub" "ietf" "uri" "") #f "Related") `uric:' prefixes indicate procedures dealing with URI-components. - Function: uric:encode uri-component allows Returns a copy of the string URI-COMPONENT in which all "unsafe" octets (as defined in RFC 2396) have been `%' "escaped". `uric:decode' decodes strings encoded by `uric:encode'. - Function: uric:decode uri-component Returns a copy of the string URI-COMPONENT in which each `%' escaped characters in URI-COMPONENT is replaced with the character it encodes. This routine is useful for showing URI contents on error pages.  File: slib.info, Node: Printing Scheme, Next: Time and Date, Prev: URI, Up: Textual Conversion Packages Printing Scheme =============== * Menu: * Generic-Write:: 'generic-write * Object-To-String:: 'object->string * Pretty-Print:: 'pretty-print, 'pprint-file  File: slib.info, Node: Generic-Write, Next: Object-To-String, Prev: Printing Scheme, Up: Printing Scheme Generic-Write ------------- `(require 'generic-write)' `generic-write' is a procedure that transforms a Scheme data value (or Scheme program expression) into its textual representation and prints it. The interface to the procedure is sufficiently general to easily implement other useful formatting procedures such as pretty printing, output to a string and truncated output. - Procedure: generic-write obj display? width output OBJ Scheme data value to transform. DISPLAY? Boolean, controls whether characters and strings are quoted. WIDTH Extended boolean, selects format: #f single line format integer > 0 pretty-print (value = max nb of chars per line) OUTPUT Procedure of 1 argument of string type, called repeatedly with successive substrings of the textual representation. This procedure can return `#f' to stop the transformation. The value returned by `generic-write' is undefined. Examples: (write obj) == (generic-write obj #f #f DISPLAY-STRING) (display obj) == (generic-write obj #t #f DISPLAY-STRING) where DISPLAY-STRING == (lambda (s) (for-each write-char (string->list s)) #t)  File: slib.info, Node: Object-To-String, Next: Pretty-Print, Prev: Generic-Write, Up: Printing Scheme Object-To-String ---------------- `(require 'object->string)' - Function: object->string obj Returns the textual representation of OBJ as a string. - Function: object->limited-string obj limit Returns the textual representation of OBJ as a string of length at most LIMIT.  File: slib.info, Node: Pretty-Print, Prev: Object-To-String, Up: Printing Scheme Pretty-Print ------------ `(require 'pretty-print)' - Procedure: pretty-print obj - Procedure: pretty-print obj port `pretty-print's OBJ on PORT. If PORT is not specified, `current-output-port' is used. Example: (pretty-print '((1 2 3 4 5) (6 7 8 9 10) (11 12 13 14 15) (16 17 18 19 20) (21 22 23 24 25))) -| ((1 2 3 4 5) -| (6 7 8 9 10) -| (11 12 13 14 15) -| (16 17 18 19 20) -| (21 22 23 24 25)) - Procedure: pretty-print->string obj - Procedure: pretty-print->string obj width Returns the string of OBJ `pretty-print'ed in WIDTH columns. If WIDTH is not specified, `(output-port-width)' is used. Example: (pretty-print->string '((1 2 3 4 5) (6 7 8 9 10) (11 12 13 14 15) (16 17 18 19 20) (21 22 23 24 25))) => "((1 2 3 4 5) (6 7 8 9 10) (11 12 13 14 15) (16 17 18 19 20) (21 22 23 24 25)) " (pretty-print->string '((1 2 3 4 5) (6 7 8 9 10) (11 12 13 14 15) (16 17 18 19 20) (21 22 23 24 25)) 16) => "((1 2 3 4 5) (6 7 8 9 10) (11 12 13 14 15) (16 17 18 19 20) (21 22 23 24 25)) " `(require 'pprint-file)' - Procedure: pprint-file infile - Procedure: pprint-file infile outfile Pretty-prints all the code in INFILE. If OUTFILE is specified, the output goes to OUTFILE, otherwise it goes to `(current-output-port)'. - Function: pprint-filter-file infile proc outfile - Function: pprint-filter-file infile proc INFILE is a port or a string naming an existing file. Scheme source code expressions and definitions are read from the port (or file) and PROC is applied to them sequentially. OUTFILE is a port or a string. If no OUTFILE is specified then `current-output-port' is assumed. These expanded expressions are then `pretty-print'ed to this port. Whitepsace and comments (introduced by `;') which are not part of scheme expressions are reproduced in the output. This procedure does not affect the values returned by `current-input-port' and `current-output-port'. `pprint-filter-file' can be used to pre-compile macro-expansion and thus can reduce loading time. The following will write into `exp-code.scm' the result of expanding all defmacros in `code.scm'. (require 'pprint-file) (require 'defmacroexpand) (defmacro:load "my-macros.scm") (pprint-filter-file "code.scm" defmacro:expand* "exp-code.scm")  File: slib.info, Node: Time and Date, Next: Vector Graphics, Prev: Printing Scheme, Up: Textual Conversion Packages Time and Date ============= * Menu: * Time Zone:: * Posix Time:: 'posix-time * Common-Lisp Time:: 'common-lisp-time If `(provided? 'current-time)': The procedures `current-time', `difftime', and `offset-time' deal with a "calendar time" datatype which may or may not be disjoint from other Scheme datatypes. - Function: current-time Returns the time since 00:00:00 GMT, January 1, 1970, measured in seconds. Note that the reference time is different from the reference time for `get-universal-time' in *Note Common-Lisp Time::. - Function: difftime caltime1 caltime0 Returns the difference (number of seconds) between twe calendar times: CALTIME1 - CALTIME0. CALTIME0 may also be a number. - Function: offset-time caltime offset Returns the calendar time of CALTIME offset by OFFSET number of seconds `(+ caltime offset)'.  File: slib.info, Node: Time Zone, Next: Posix Time, Prev: Time and Date, Up: Time and Date Time Zone --------- (require 'time-zone) - Data Format: TZ-string POSIX standards specify several formats for encoding time-zone rules. : If the first character of is `/', then specifies the absolute pathname of a tzfile(5) format time-zone file. Otherwise, is interpreted as a pathname within TZFILE:VICINITY (/usr/lib/zoneinfo/) naming a tzfile(5) format time-zone file. The string consists of 3 or more alphabetic characters. specifies the time difference from GMT. The is positive if the local time zone is west of the Prime Meridian and negative if it is east. can be the number of hours or hours and minutes (and optionally seconds) separated by `:'. For example, `-4:30'. is the at least 3 alphabetic characters naming the local daylight-savings-time. specifies the offset from the Prime Meridian when daylight-savings-time is in effect. The non-tzfile formats can optionally be followed by transition times specifying the day and time when a zone changes from standard to daylight-savings and back again. ,/